Class SearchQueryRenderer
- java.lang.Object
-
- com.ibm.fhir.persistence.jdbc.domain.SearchQueryRenderer
-
- All Implemented Interfaces:
SearchQueryVisitor<QueryData>
public class SearchQueryRenderer extends Object implements SearchQueryVisitor<QueryData>
Used to render the domain model into a physical, executable query modeled as a Select statement. The domain model knows about resources and parameters. This class is used to translate the logical structure of the query into a physical one, using the correct table names, join predicates and filter expressions.
-
-
Constructor Summary
Constructors Constructor Description SearchQueryRenderer(JDBCIdentityCache identityCache, int rowOffset, int rowsPerPage)
Public constructor
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description QueryData
addChained(QueryData queryData, QueryParameter currentParm)
Add a chain subquery element as part of a chained parameter searchQueryData
addCompositeParam(QueryData queryData, QueryParameter queryParm)
Add a composite query parameter filter to the queryQueryData
addCompositeParam(QueryData queryData, QueryParameter queryParm, boolean isMissing)
Add a composite query which only tests missing/not missing, not the actual parameter valueQueryData
addDateParam(QueryData queryData, String resourceType, QueryParameter queryParm)
Filter the query using the given date parametervoid
addFilter(QueryData queryData, QueryParameter currentParm)
Add a filter predicate to the given chained sub-query element.protected void
addIdFilter(QueryData queryData, QueryParameter queryParm)
Add a filter on the LOGICAL_ID for the given query parameter valuesQueryData
addIncludeFilter(QueryData queryData, InclusionParameter inclusionParm, List<Long> logicalResourceIds)
QueryData
addInclusionParam(QueryData queryData, String resourceType, QueryParameter queryParm)
Special case to handle inclusion related to compartment-based searchesQueryData
addLocationParam(QueryData queryData, String resourceType, QueryParameter queryParm)
Filter the query using the given location (lat/lng) paramQueryData
addLocationPosition(QueryData queryData, List<QueryParameter> queryParameters)
QueryData
addMissingParam(QueryData queryData, QueryParameter queryParm, boolean isMissing)
Add a missing (NOT EXISTS) parameter clause to the queryQueryData
addNumberParam(QueryData queryData, String resourceType, QueryParameter queryParm)
Filter the query using the given number parameterQueryData
addPagination(QueryData queryData)
Add pagination (LIMIT/OFFSET) to the queryQueryData
addQuantityParam(QueryData queryData, String resourceType, QueryParameter queryParm)
Filter the query using the given quantity parameterQueryData
addReferenceParam(QueryData queryData, String resourceType, QueryParameter queryParm)
Filter the query using the given reference parameterQueryData
addReverseChained(QueryData queryData, QueryParameter currentParm)
Add a reverse chain subquery element as part of a chained parameter searchQueryData
addRevIncludeFilter(QueryData queryData, InclusionParameter inclusionParm, List<Long> logicalResourceIds)
QueryData
addSorting(QueryData queryData, String lrAlias)
Add sorting (order by) to the queryvoid
addSortParam(QueryData queryData, String code, SearchConstants.Type type, Sort.Direction direction)
Add the given sort parameter to the sort queryQueryData
addStringParam(QueryData queryData, String resourceType, QueryParameter queryParm)
Filter the query using the given string parameterQueryData
addTokenParam(QueryData queryData, String resourceType, QueryParameter queryParm)
Filter the query using the given parameter id and token valueQueryData
countRoot(String rootResourceType)
The root query (select statement) for a count queryQueryData
dataRoot(String rootResourceType)
The root query (select statement) for the data queryprotected int
getCodeSystemId(String codeSystemName)
Get the id for the given code system name (cache lookup)protected Long
getCommonTokenValueId(String system, String code)
Get the common token value id matching the unique tuple {system, code}protected List<Long>
getCommonTokenValueIdList(String code)
Get a list of common token values matching the given codeprotected WhereFragment
getDateFilter(QueryParameter queryParm, String paramAlias)
Add a filter predicate to the given exists sub-queryprotected WhereFragment
getFilterPredicate(QueryData queryData, QueryParameter queryParm)
Get a simple filter predicate which can be used in the WHERE clause of a search query.protected WhereFragment
getLocationFilter(QueryParameter queryParm, String paramAlias)
Add a filter predicate to the given exists sub-queryprotected String
getLRAlias(int aliasIndex)
Get the string to use as a logical resource alias for the given aliasIndex valueprotected int
getNextAliasIndex()
Get the next index number to use as a parameter table aliasprotected WhereFragment
getNumberFilter(QueryParameter queryParm, String paramAlias)
Get a filter predicate for the given number query parameterprotected Operator
getOperator(QueryParameter queryParameter)
Get the operator we need to use for matching values for this parameterprotected Operator
getOperator(QueryParameter queryParm, String defaultOverride)
Map the Modifier in the passed Parameter to a supported query operator.protected String
getParamAlias(int aliasIndex)
Get the string to use as a parameter table alias for the given aliasIndex valueQueryData
getParameterBaseQuery(QueryData parent)
Get the join to which we want to attach all the parameter tables.protected int
getParameterNameId(String parameterName)
Get the id for the given parameter name (cache lookup)protected WhereFragment
getQuantityFilter(QueryParameter queryParm, String paramAlias)
Add a filter predicate to the given exists sub-queryprotected WhereFragment
getReferenceFilter(QueryParameter queryParm, String paramAlias)
Create a filter predicate for the given reference query parameterprotected String
getSortParameterTableName(String resourceType, SearchConstants.Type type)
Returns the name of the database table corresponding to the type of the passed sort parameter.protected WhereFragment
getStringFilter(QueryParameter queryParm, String paramAlias)
Add a filter expression to the given parameter sub-query (which is used as an EXISTS clause)protected WhereFragment
getTokenFilter(QueryParameter queryParm, String paramAlias)
Get the filter predicate for the given token query parameter.protected String
getTokenParamTable(ExpNode filter, String resourceType, String paramAlias)
Compute the token parameter table name we want to use to join with.QueryData
includeRoot(String rootResourceType)
The root query (select statement) for the include query.QueryData
joinResources(QueryData queryData)
Finish the data query by wrapping the root and joining the resources tableprotected int
nullCheck(Integer value)
Use -1 as a simple substitute for null literal ids because we know -1 will never exist as a value in the database (for fields populated by sequence values).protected long
nullCheck(Long value)
Use -1 as a simple substitute for null literal ids because we know -1 will never exist as a value in the database (for fields populated by sequence values).protected WhereFragment
paramFilter(QueryParameter queryParm, String paramTableAlias)
Get the filter predicate expression for the given query parameter taking into account its type, modifiers etc.String
paramValuesColumnName(SearchConstants.Type paramType)
Get the column name to use for the given paramTypeString
paramValuesTableName(String resourceType, SearchConstants.Type paramType)
Get the parameter values table name (e.g.protected String
resourceLogicalResources(String resourceType)
Get the table name for the xx_logical_resources table where xx is the resource type nameprotected String
resourceResources(String resourceType)
Get the table name for the xx_resources table where xx is the resource type nameQueryData
sortRoot(String rootResourceType)
The root of the FHIR search sort queryQueryData
wrapInclude(QueryData query)
-
-
-
Constructor Detail
-
SearchQueryRenderer
public SearchQueryRenderer(JDBCIdentityCache identityCache, int rowOffset, int rowsPerPage)
Public constructor- Parameters:
identityCache
-rowOffset
-rowsPerPage
-
-
-
Method Detail
-
getNextAliasIndex
protected int getNextAliasIndex()
Get the next index number to use as a parameter table alias- Returns:
-
resourceLogicalResources
protected String resourceLogicalResources(String resourceType)
Get the table name for the xx_logical_resources table where xx is the resource type name- Parameters:
resourceType
-- Returns:
- the table name
-
resourceResources
protected String resourceResources(String resourceType)
Get the table name for the xx_resources table where xx is the resource type name- Parameters:
resourceType
-- Returns:
-
getParameterNameId
protected int getParameterNameId(String parameterName) throws FHIRPersistenceException
Get the id for the given parameter name (cache lookup)- Parameters:
parameterName
-- Returns:
- Throws:
FHIRPersistenceException
-
getCommonTokenValueId
protected Long getCommonTokenValueId(String system, String code) throws FHIRPersistenceException
Get the common token value id matching the unique tuple {system, code}- Parameters:
system
-code
-- Returns:
- Throws:
FHIRPersistenceException
-
getCommonTokenValueIdList
protected List<Long> getCommonTokenValueIdList(String code) throws FHIRPersistenceException
Get a list of common token values matching the given code- Parameters:
code
-- Returns:
- Throws:
FHIRPersistenceException
-
getCodeSystemId
protected int getCodeSystemId(String codeSystemName) throws FHIRPersistenceException
Get the id for the given code system name (cache lookup)- Parameters:
codeSystemName
-- Returns:
- Throws:
FHIRPersistenceException
-
countRoot
public QueryData countRoot(String rootResourceType)
Description copied from interface:SearchQueryVisitor
The root query (select statement) for a count query- Specified by:
countRoot
in interfaceSearchQueryVisitor<QueryData>
- Returns:
-
dataRoot
public QueryData dataRoot(String rootResourceType)
Description copied from interface:SearchQueryVisitor
The root query (select statement) for the data query- Specified by:
dataRoot
in interfaceSearchQueryVisitor<QueryData>
- Returns:
-
getParameterBaseQuery
public QueryData getParameterBaseQuery(QueryData parent)
Description copied from interface:SearchQueryVisitor
Get the join to which we want to attach all the parameter tables. This makes it easier to build different styles of joins- Specified by:
getParameterBaseQuery
in interfaceSearchQueryVisitor<QueryData>
- Returns:
-
joinResources
public QueryData joinResources(QueryData queryData)
Description copied from interface:SearchQueryVisitor
Finish the data query by wrapping the root and joining the resources table- Specified by:
joinResources
in interfaceSearchQueryVisitor<QueryData>
- Returns:
-
includeRoot
public QueryData includeRoot(String rootResourceType)
Description copied from interface:SearchQueryVisitor
The root query (select statement) for the include query. This query is different than the data root because of the need to support version references for _include searches. For this, we join: xx_RESOURCES.LOGICAL_RESOURCE_ID = xx_LOGICAL_RESOURCES.LOGICAL_RESOURCE_ID and allow the filter to specify the version_id constraint. However, we still need to assert that the resource has not been deleted, so we keep: xx_LOGICAL_RESOURCES.IS_DELETED = 'N'- Specified by:
includeRoot
in interfaceSearchQueryVisitor<QueryData>
- Returns:
-
wrapInclude
public QueryData wrapInclude(QueryData query)
- Specified by:
wrapInclude
in interfaceSearchQueryVisitor<QueryData>
- Returns:
-
sortRoot
public QueryData sortRoot(String rootResourceType)
Description copied from interface:SearchQueryVisitor
The root of the FHIR search sort query- Specified by:
sortRoot
in interfaceSearchQueryVisitor<QueryData>
- Returns:
-
getTokenFilter
protected WhereFragment getTokenFilter(QueryParameter queryParm, String paramAlias) throws FHIRPersistenceException
Get the filter predicate for the given token query parameter.- Parameters:
queryParm
- the token query parameterparamAlias
- the alias used for the token values table- Throws:
FHIRPersistenceException
-
getStringFilter
protected WhereFragment getStringFilter(QueryParameter queryParm, String paramAlias) throws FHIRPersistenceException
Add a filter expression to the given parameter sub-query (which is used as an EXISTS clause)- Parameters:
paramExists
- the query statement to which we need to add the filter predicatequeryParm
- the query parameter for which we need to compute and add the filter predicateparamAlias
- the alias for the query parameter table- Returns:
- Throws:
FHIRPersistenceException
-
addSorting
public QueryData addSorting(QueryData queryData, String lrAlias)
Description copied from interface:SearchQueryVisitor
Add sorting (order by) to the query- Specified by:
addSorting
in interfaceSearchQueryVisitor<QueryData>
- Returns:
-
addPagination
public QueryData addPagination(QueryData queryData)
Description copied from interface:SearchQueryVisitor
Add pagination (LIMIT/OFFSET) to the query- Specified by:
addPagination
in interfaceSearchQueryVisitor<QueryData>
- Returns:
-
paramValuesTableName
public String paramValuesTableName(String resourceType, SearchConstants.Type paramType)
Get the parameter values table name (e.g. Patient_STR_VALUES) for the given resource and parameter type. Note that this is now different from the original QuerySegmentAggregator implementation - it does not differentiate on chaining...that is left up to the building logic.- Parameters:
resourceType
-paramType
-- Returns:
-
paramValuesColumnName
public String paramValuesColumnName(SearchConstants.Type paramType)
Get the column name to use for the given paramType- Parameters:
paramType
-- Returns:
-
getFilterPredicate
protected WhereFragment getFilterPredicate(QueryData queryData, QueryParameter queryParm) throws FHIRPersistenceException
Get a simple filter predicate which can be used in the WHERE clause of a search query. This is used at the "leaf level" of parameter processing, where the queryParm relates to a single parameter (i.e. it is the caller's responsibility to handle chaining and other more complex behavior.- Parameters:
queryData
-queryParm
-- Returns:
- Throws:
FHIRPersistenceException
-
addIdFilter
protected void addIdFilter(QueryData queryData, QueryParameter queryParm) throws FHIRPersistenceException
Add a filter on the LOGICAL_ID for the given query parameter values- Parameters:
queryData
-queryParm
-- Throws:
FHIRPersistenceException
-
getNumberFilter
protected WhereFragment getNumberFilter(QueryParameter queryParm, String paramAlias) throws FHIRPersistenceException
Get a filter predicate for the given number query parameter- Parameters:
queryParm
-paramAlias
-- Throws:
FHIRPersistenceException
-
getQuantityFilter
protected WhereFragment getQuantityFilter(QueryParameter queryParm, String paramAlias) throws FHIRPersistenceException
Add a filter predicate to the given exists sub-query- Parameters:
queryParm
-paramAlias
-- Throws:
FHIRPersistenceException
-
getDateFilter
protected WhereFragment getDateFilter(QueryParameter queryParm, String paramAlias)
Add a filter predicate to the given exists sub-query- Parameters:
queryParm
-paramAlias
-
-
getLocationFilter
protected WhereFragment getLocationFilter(QueryParameter queryParm, String paramAlias) throws FHIRPersistenceException
Add a filter predicate to the given exists sub-query- Parameters:
queryParm
-paramAlias
-- Throws:
FHIRPersistenceException
-
getParamAlias
protected String getParamAlias(int aliasIndex)
Get the string to use as a parameter table alias for the given aliasIndex value- Parameters:
aliasIndex
-- Returns:
-
getLRAlias
protected String getLRAlias(int aliasIndex)
Get the string to use as a logical resource alias for the given aliasIndex value- Parameters:
aliasIndex
-- Returns:
-
getTokenParamTable
protected String getTokenParamTable(ExpNode filter, String resourceType, String paramAlias)
Compute the token parameter table name we want to use to join with. This method inspects the content of the given filterExpNode
. If the filter contains a reference to the TOKEN_VALUE column, the returned table name will be based on xx_TOKEN_VALUES_V, otherwise it will be based on xx_RESOURCE_TOKEN_REFS. The latter is preferable because it eliminates an unnecessary join, improves cardinality estimation and (usually) results in a better execution plan.- Parameters:
filter
-resourceType
-paramAlias
-- Returns:
-
getReferenceFilter
protected WhereFragment getReferenceFilter(QueryParameter queryParm, String paramAlias) throws FHIRPersistenceException
Create a filter predicate for the given reference query parameter- Parameters:
queryParm
-paramAlias
-- Throws:
FHIRPersistenceException
-
nullCheck
protected int nullCheck(Integer value)
Use -1 as a simple substitute for null literal ids because we know -1 will never exist as a value in the database (for fields populated by sequence values).- Parameters:
value
-- Returns:
-
nullCheck
protected long nullCheck(Long value)
Use -1 as a simple substitute for null literal ids because we know -1 will never exist as a value in the database (for fields populated by sequence values).- Parameters:
value
-- Returns:
-
getOperator
protected Operator getOperator(QueryParameter queryParameter)
Get the operator we need to use for matching values for this parameter- Parameters:
queryParameter
-- Returns:
-
getOperator
protected Operator getOperator(QueryParameter queryParm, String defaultOverride)
Map the Modifier in the passed Parameter to a supported query operator. If the mapping results in the default operator, override the default operator with the passed operator if the passed operator is not null.- Parameters:
queryParm
- - A valid query Parameter.defaultOverride
- - An operator that should override the default operator.- Returns:
- A supported operator.
-
paramFilter
protected WhereFragment paramFilter(QueryParameter queryParm, String paramTableAlias) throws FHIRPersistenceException
Get the filter predicate expression for the given query parameter taking into account its type, modifiers etc.- Parameters:
paramTableAlias
-queryParm
-- Returns:
- a valid expression
- Throws:
FHIRPersistenceException
-
addLocationPosition
public QueryData addLocationPosition(QueryData queryData, List<QueryParameter> queryParameters) throws FHIRPersistenceException
- Specified by:
addLocationPosition
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addInclusionParam
public QueryData addInclusionParam(QueryData queryData, String resourceType, QueryParameter queryParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Special case to handle inclusion related to compartment-based searches- Specified by:
addInclusionParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addIncludeFilter
public QueryData addIncludeFilter(QueryData queryData, InclusionParameter inclusionParm, List<Long> logicalResourceIds) throws FHIRPersistenceException
- Specified by:
addIncludeFilter
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addRevIncludeFilter
public QueryData addRevIncludeFilter(QueryData queryData, InclusionParameter inclusionParm, List<Long> logicalResourceIds) throws FHIRPersistenceException
- Specified by:
addRevIncludeFilter
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addTokenParam
public QueryData addTokenParam(QueryData queryData, String resourceType, QueryParameter queryParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Filter the query using the given parameter id and token value- Specified by:
addTokenParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addStringParam
public QueryData addStringParam(QueryData queryData, String resourceType, QueryParameter queryParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Filter the query using the given string parameter- Specified by:
addStringParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addMissingParam
public QueryData addMissingParam(QueryData queryData, QueryParameter queryParm, boolean isMissing) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Add a missing (NOT EXISTS) parameter clause to the query- Specified by:
addMissingParam
in interfaceSearchQueryVisitor<QueryData>
isMissing
- true if the condition should be that the parameter does not exist- Returns:
- Throws:
FHIRPersistenceException
-
addChained
public QueryData addChained(QueryData queryData, QueryParameter currentParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Add a chain subquery element as part of a chained parameter search- Specified by:
addChained
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addFilter
public void addFilter(QueryData queryData, QueryParameter currentParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Add a filter predicate to the given chained sub-query element. This must be the last element of the chain.- Specified by:
addFilter
in interfaceSearchQueryVisitor<QueryData>
- Throws:
FHIRPersistenceException
-
addReverseChained
public QueryData addReverseChained(QueryData queryData, QueryParameter currentParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Add a reverse chain subquery element as part of a chained parameter search- Specified by:
addReverseChained
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addNumberParam
public QueryData addNumberParam(QueryData queryData, String resourceType, QueryParameter queryParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Filter the query using the given number parameter- Specified by:
addNumberParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addQuantityParam
public QueryData addQuantityParam(QueryData queryData, String resourceType, QueryParameter queryParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Filter the query using the given quantity parameter- Specified by:
addQuantityParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addDateParam
public QueryData addDateParam(QueryData queryData, String resourceType, QueryParameter queryParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Filter the query using the given date parameter- Specified by:
addDateParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addLocationParam
public QueryData addLocationParam(QueryData queryData, String resourceType, QueryParameter queryParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Filter the query using the given location (lat/lng) param- Specified by:
addLocationParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addReferenceParam
public QueryData addReferenceParam(QueryData queryData, String resourceType, QueryParameter queryParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Filter the query using the given reference parameter- Specified by:
addReferenceParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addCompositeParam
public QueryData addCompositeParam(QueryData queryData, QueryParameter queryParm) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Add a composite query parameter filter to the query- Specified by:
addCompositeParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addCompositeParam
public QueryData addCompositeParam(QueryData queryData, QueryParameter queryParm, boolean isMissing) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Add a composite query which only tests missing/not missing, not the actual parameter value- Specified by:
addCompositeParam
in interfaceSearchQueryVisitor<QueryData>
- Returns:
- Throws:
FHIRPersistenceException
-
addSortParam
public void addSortParam(QueryData queryData, String code, SearchConstants.Type type, Sort.Direction direction) throws FHIRPersistenceException
Description copied from interface:SearchQueryVisitor
Add the given sort parameter to the sort query- Specified by:
addSortParam
in interfaceSearchQueryVisitor<QueryData>
- Throws:
FHIRPersistenceException
-
getSortParameterTableName
protected String getSortParameterTableName(String resourceType, SearchConstants.Type type) throws FHIRPersistenceException
Returns the name of the database table corresponding to the type of the passed sort parameter.- Parameters:
sortParm
- A valid SortParameter- Returns:
- String - A database table name
- Throws:
FHIRPersistenceException
-
-