Failing test
This commit is contained in:
parent
20d3e6bb25
commit
55f8e85d21
|
@ -123,6 +123,7 @@ import java.util.regex.Pattern;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.jpa.search.builder.QueryStack.SearchForIdsParams.with;
|
||||
import static ca.uhn.fhir.jpa.search.builder.predicate.ResourceIdPredicateBuilder.getResourceIdColumn;
|
||||
import static ca.uhn.fhir.jpa.util.QueryParameterUtils.fromOperation;
|
||||
import static ca.uhn.fhir.jpa.util.QueryParameterUtils.getChainedPart;
|
||||
import static ca.uhn.fhir.jpa.util.QueryParameterUtils.getParamNameWithPrefix;
|
||||
|
@ -245,7 +246,7 @@ public class QueryStack {
|
|||
resourceTablePredicateBuilder = (ResourceTablePredicateBuilder) firstPredicateBuilder;
|
||||
} else {
|
||||
resourceTablePredicateBuilder =
|
||||
mySqlBuilder.addResourceTablePredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
||||
mySqlBuilder.addResourceTablePredicateBuilder(firstPredicateBuilder.getJoinColumns());
|
||||
}
|
||||
mySqlBuilder.addSortDate(resourceTablePredicateBuilder.getColumnLastUpdated(), theAscending, myUseAggregate);
|
||||
}
|
||||
|
@ -282,7 +283,7 @@ public class QueryStack {
|
|||
resourceTablePredicateBuilder = (ResourceTablePredicateBuilder) firstPredicateBuilder;
|
||||
} else {
|
||||
resourceTablePredicateBuilder =
|
||||
mySqlBuilder.addResourceTablePredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
||||
mySqlBuilder.addResourceTablePredicateBuilder(firstPredicateBuilder.getJoinColumns());
|
||||
}
|
||||
mySqlBuilder.addSortString(resourceTablePredicateBuilder.getColumnFhirId(), theAscending, myUseAggregate);
|
||||
}
|
||||
|
@ -405,7 +406,7 @@ public class QueryStack {
|
|||
double latitudeValue = location.getLatitudeValue();
|
||||
double longitudeValue = location.getLongitudeValue();
|
||||
final CoordsPredicateBuilder coordsPredicateBuilder = mySqlBuilder.addCoordsPredicateBuilder(
|
||||
resourceLinkPredicateBuilder.getColumnTargetResourceId());
|
||||
resourceLinkPredicateBuilder.getJoinColumnsForTarget());
|
||||
mySqlBuilder.addSortCoordsNear(
|
||||
coordsPredicateBuilder, latitudeValue, longitudeValue, theAscending);
|
||||
} else {
|
||||
|
@ -418,6 +419,7 @@ public class QueryStack {
|
|||
return;
|
||||
}
|
||||
}
|
||||
//noinspection fallthrough
|
||||
case NUMBER:
|
||||
case REFERENCE:
|
||||
case COMPOSITE:
|
||||
|
@ -502,7 +504,7 @@ public class QueryStack {
|
|||
@SuppressWarnings("unchecked")
|
||||
private <T extends BaseJoiningPredicateBuilder> PredicateBuilderCacheLookupResult<T> createOrReusePredicateBuilder(
|
||||
PredicateBuilderTypeEnum theType,
|
||||
DbColumn theSourceJoinColumn,
|
||||
DbColumn[] theSourceJoinColumn,
|
||||
String theParamName,
|
||||
Supplier<T> theFactoryMethod) {
|
||||
boolean cacheHit = false;
|
||||
|
@ -534,7 +536,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
private Condition createPredicateComposite(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theParamDef,
|
||||
|
@ -551,7 +553,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
private Condition createPredicateComposite(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theParamDef,
|
||||
|
@ -605,7 +607,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
private Condition createPredicateCompositePart(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theParam,
|
||||
|
@ -813,7 +815,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateCoords(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -858,7 +860,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateDate(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -877,7 +879,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateDate(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -1105,7 +1107,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
private Condition createPredicateHas(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceType,
|
||||
List<List<IQueryParameterType>> theHasParameters,
|
||||
RequestDetails theRequest,
|
||||
|
@ -1225,7 +1227,7 @@ public class QueryStack {
|
|||
resourceLinkTableJoin.getColumnSourcePath(), mySqlBuilder.generatePlaceholders(paths));
|
||||
|
||||
Condition linkedPredicate =
|
||||
searchForIdsWithAndOr(with().setSourceJoinColumn(resourceLinkTableJoin.getColumnSrcResourceId())
|
||||
searchForIdsWithAndOr(with().setSourceJoinColumn(resourceLinkTableJoin.getJoinColumnsForSource())
|
||||
.setResourceName(targetResourceType)
|
||||
.setParamName(parameterName)
|
||||
.setAndOrParams(Collections.singletonList(orValues))
|
||||
|
@ -1239,7 +1241,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateNumber(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -1258,7 +1260,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateNumber(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -1318,7 +1320,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateQuantity(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -1337,7 +1339,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateQuantity(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -1405,7 +1407,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateReference(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theParamName,
|
||||
List<String> theQualifiers,
|
||||
|
@ -1426,7 +1428,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateReference(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theParamName,
|
||||
List<String> theQualifiers,
|
||||
|
@ -1474,16 +1476,16 @@ public class QueryStack {
|
|||
|
||||
public void addGrouping() {
|
||||
BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
|
||||
mySqlBuilder.getSelect().addGroupings(firstPredicateBuilder.getResourceIdColumn());
|
||||
mySqlBuilder.getSelect().addGroupings(firstPredicateBuilder.getJoinColumns());
|
||||
}
|
||||
|
||||
public void addOrdering() {
|
||||
BaseJoiningPredicateBuilder firstPredicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
|
||||
mySqlBuilder.getSelect().addOrderings(firstPredicateBuilder.getResourceIdColumn());
|
||||
mySqlBuilder.getSelect().addOrderings(firstPredicateBuilder.getJoinColumns());
|
||||
}
|
||||
|
||||
public Condition createPredicateReferenceForEmbeddedChainedSearchResource(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
List<? extends IQueryParameterType> theList,
|
||||
|
@ -1532,7 +1534,7 @@ public class QueryStack {
|
|||
builder = mySqlBuilder;
|
||||
}
|
||||
|
||||
DbColumn previousJoinColumn = null;
|
||||
DbColumn[] previousJoinColumn = null;
|
||||
|
||||
// Create a reference link predicates to the subselect for every link but the last one
|
||||
for (String nextLink : nextReferenceLink) {
|
||||
|
@ -1543,7 +1545,7 @@ public class QueryStack {
|
|||
builder.addReferencePredicateBuilder(this, previousJoinColumn);
|
||||
builder.addPredicate(
|
||||
resourceLinkPredicateBuilder.createPredicateSourcePaths(Lists.newArrayList(nextLink)));
|
||||
previousJoinColumn = resourceLinkPredicateBuilder.getColumnTargetResourceId();
|
||||
previousJoinColumn = resourceLinkPredicateBuilder.getJoinColumnsForTarget();
|
||||
}
|
||||
|
||||
Condition containedCondition = createIndexPredicate(
|
||||
|
@ -1572,6 +1574,7 @@ public class QueryStack {
|
|||
if (wantChainedAndNormal) {
|
||||
|
||||
if (theSourceJoinColumn == null) {
|
||||
// fixme mb HERE!!!
|
||||
retVal = new InCondition(
|
||||
mySqlBuilder.getOrCreateFirstPredicateBuilder(false).getResourceIdColumn(), union);
|
||||
} else {
|
||||
|
@ -1769,7 +1772,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
private Condition createIndexPredicate(
|
||||
DbColumn theSourceJoinColumn,
|
||||
DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
String theParamName,
|
||||
|
@ -1883,7 +1886,7 @@ public class QueryStack {
|
|||
|
||||
@Nullable
|
||||
public Condition createPredicateResourceId(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
List<List<IQueryParameterType>> theValues,
|
||||
String theResourceName,
|
||||
SearchFilterParser.CompareOperation theOperation,
|
||||
|
@ -1894,7 +1897,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
private Condition createPredicateSourceForAndList(
|
||||
@Nullable DbColumn theSourceJoinColumn, List<List<IQueryParameterType>> theAndOrParams) {
|
||||
@Nullable DbColumn[] theSourceJoinColumn, List<List<IQueryParameterType>> theAndOrParams) {
|
||||
mySqlBuilder.getOrCreateFirstPredicateBuilder();
|
||||
|
||||
List<Condition> andPredicates = new ArrayList<>(theAndOrParams.size());
|
||||
|
@ -1905,7 +1908,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
private Condition createPredicateSource(
|
||||
@Nullable DbColumn theSourceJoinColumn, List<? extends IQueryParameterType> theList) {
|
||||
@Nullable DbColumn[] theSourceJoinColumn, List<? extends IQueryParameterType> theList) {
|
||||
if (myStorageSettings.getStoreMetaSourceInformation()
|
||||
== JpaStorageSettings.StoreMetaSourceInformationEnum.NONE) {
|
||||
String msg = myFhirContext.getLocalizer().getMessage(QueryStack.class, "sourceParamDisabled");
|
||||
|
@ -1948,7 +1951,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
private SourcePredicateBuilder getSourcePredicateBuilder(
|
||||
@Nullable DbColumn theSourceJoinColumn, SelectQuery.JoinType theJoinType) {
|
||||
@Nullable DbColumn[] theSourceJoinColumn, SelectQuery.JoinType theJoinType) {
|
||||
return createOrReusePredicateBuilder(
|
||||
PredicateBuilderTypeEnum.SOURCE,
|
||||
theSourceJoinColumn,
|
||||
|
@ -1958,7 +1961,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateString(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -1977,7 +1980,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateString(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -2017,7 +2020,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateTag(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
List<List<IQueryParameterType>> theList,
|
||||
String theParamName,
|
||||
RequestPartitionId theRequestPartitionId) {
|
||||
|
@ -2129,7 +2132,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateToken(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -2148,7 +2151,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateToken(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -2264,7 +2267,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateUri(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -2285,7 +2288,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public Condition createPredicateUri(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theSpnamePrefix,
|
||||
RuntimeSearchParam theSearchParam,
|
||||
|
@ -2400,9 +2403,9 @@ public class QueryStack {
|
|||
* Raw match on RES_ID
|
||||
*/
|
||||
private Condition createPredicateResourcePID(
|
||||
DbColumn theSourceJoinColumn, List<List<IQueryParameterType>> theAndOrParams) {
|
||||
DbColumn[] theSourceJoinColumn, List<List<IQueryParameterType>> theAndOrParams) {
|
||||
|
||||
DbColumn pidColumn = theSourceJoinColumn;
|
||||
DbColumn pidColumn = getResourceIdColumn(theSourceJoinColumn);
|
||||
|
||||
if (pidColumn == null) {
|
||||
BaseJoiningPredicateBuilder predicateBuilder = mySqlBuilder.getOrCreateFirstPredicateBuilder();
|
||||
|
@ -2427,7 +2430,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
private Condition createReverseSearchPredicateLastUpdated(
|
||||
List<List<IQueryParameterType>> theAndOrParams, DbColumn theSourceColumn) {
|
||||
List<List<IQueryParameterType>> theAndOrParams, DbColumn[] theSourceColumn) {
|
||||
|
||||
ResourceTablePredicateBuilder resourceTableJoin =
|
||||
mySqlBuilder.addResourceTablePredicateBuilder(theSourceColumn);
|
||||
|
@ -2448,7 +2451,7 @@ public class QueryStack {
|
|||
|
||||
@Nullable
|
||||
private Condition createPredicateSearchParameter(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theParamName,
|
||||
List<List<IQueryParameterType>> theAndOrParams,
|
||||
|
@ -2690,7 +2693,7 @@ public class QueryStack {
|
|||
* by this method
|
||||
*/
|
||||
private boolean handleFullyChainedParameter(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
String theParamName,
|
||||
RequestDetails theRequest,
|
||||
|
@ -3147,7 +3150,7 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public static class SearchForIdsParams {
|
||||
DbColumn mySourceJoinColumn;
|
||||
DbColumn[] mySourceJoinColumn;
|
||||
String myResourceName;
|
||||
String myParamName;
|
||||
List<List<IQueryParameterType>> myAndOrParams;
|
||||
|
@ -3159,11 +3162,11 @@ public class QueryStack {
|
|||
return new SearchForIdsParams();
|
||||
}
|
||||
|
||||
public DbColumn getSourceJoinColumn() {
|
||||
public DbColumn[] getSourceJoinColumn() {
|
||||
return mySourceJoinColumn;
|
||||
}
|
||||
|
||||
public SearchForIdsParams setSourceJoinColumn(DbColumn theSourceJoinColumn) {
|
||||
public SearchForIdsParams setSourceJoinColumn(DbColumn[] theSourceJoinColumn) {
|
||||
mySourceJoinColumn = theSourceJoinColumn;
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ public class MissingParameterQueryParams {
|
|||
/**
|
||||
* The column on which to join.
|
||||
*/
|
||||
private final DbColumn mySourceJoinColumn;
|
||||
private final DbColumn[] mySourceJoinColumn;
|
||||
|
||||
/**
|
||||
* The partition id
|
||||
|
@ -76,7 +76,7 @@ public class MissingParameterQueryParams {
|
|||
List<? extends IQueryParameterType> theList,
|
||||
String theParamName,
|
||||
String theResourceType,
|
||||
DbColumn theSourceJoinColumn,
|
||||
DbColumn[] theSourceJoinColumn,
|
||||
RequestPartitionId theRequestPartitionId) {
|
||||
mySqlBuilder = theSqlBuilder;
|
||||
myParamType = theParamType;
|
||||
|
@ -116,7 +116,7 @@ public class MissingParameterQueryParams {
|
|||
return myResourceType;
|
||||
}
|
||||
|
||||
public DbColumn getSourceJoinColumn() {
|
||||
public DbColumn[] getSourceJoinColumn() {
|
||||
return mySourceJoinColumn;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,20 +24,22 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
|
|||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
public class PredicateBuilderCacheKey {
|
||||
private final DbColumn myDbColumn;
|
||||
private final DbColumn[] myDbColumn;
|
||||
private final PredicateBuilderTypeEnum myType;
|
||||
private final String myParamName;
|
||||
private final int myHashCode;
|
||||
|
||||
public PredicateBuilderCacheKey(DbColumn theDbColumn, PredicateBuilderTypeEnum theType, String theParamName) {
|
||||
public PredicateBuilderCacheKey(DbColumn[] theDbColumn, PredicateBuilderTypeEnum theType, String theParamName) {
|
||||
myDbColumn = theDbColumn;
|
||||
myType = theType;
|
||||
myParamName = theParamName;
|
||||
myHashCode = new HashCodeBuilder()
|
||||
.append(myDbColumn)
|
||||
.append(myType)
|
||||
.append(myParamName)
|
||||
.toHashCode();
|
||||
HashCodeBuilder hashBuilder = new HashCodeBuilder().append(myType).append(myParamName);
|
||||
if (theDbColumn != null) {
|
||||
for (DbColumn next : theDbColumn) {
|
||||
hashBuilder.append(next);
|
||||
}
|
||||
}
|
||||
myHashCode = hashBuilder.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -51,10 +51,14 @@ public abstract class BaseJoiningPredicateBuilder extends BasePredicateBuilder {
|
|||
|
||||
public abstract DbColumn getResourceIdColumn();
|
||||
|
||||
DbColumn getPartitionIdColumn() {
|
||||
public DbColumn getPartitionIdColumn() {
|
||||
return myColumnPartitionId;
|
||||
}
|
||||
|
||||
public DbColumn[] getJoinColumns() {
|
||||
return getSearchQueryBuilder().toJoinColumns(getPartitionIdColumn(), getResourceIdColumn());
|
||||
}
|
||||
|
||||
public Condition combineWithRequestPartitionIdPredicate(
|
||||
RequestPartitionId theRequestPartitionId, Condition theCondition) {
|
||||
Condition partitionIdPredicate = createPartitionIdPredicate(theRequestPartitionId);
|
||||
|
|
|
@ -41,6 +41,10 @@ public abstract class BasePredicateBuilder {
|
|||
mySearchSqlBuilder = theSearchSqlBuilder;
|
||||
}
|
||||
|
||||
protected SearchQueryBuilder getSearchQueryBuilder() {
|
||||
return mySearchSqlBuilder;
|
||||
}
|
||||
|
||||
PartitionSettings getPartitionSettings() {
|
||||
return mySearchSqlBuilder.getPartitionSettings();
|
||||
}
|
||||
|
@ -84,7 +88,7 @@ public abstract class BasePredicateBuilder {
|
|||
return mySearchSqlBuilder.getOrCreateFirstPredicateBuilder(theIncludeResourceTypeAndNonDeletedFlag);
|
||||
}
|
||||
|
||||
public void addJoin(DbTable theFromTable, DbTable theToTable, DbColumn theFromColumn, DbColumn theToColumn) {
|
||||
public void addJoin(DbTable theFromTable, DbTable theToTable, DbColumn[] theFromColumn, DbColumn[] theToColumn) {
|
||||
mySearchSqlBuilder.addJoin(theFromTable, theToTable, theFromColumn, theToColumn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
|||
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
||||
import ca.uhn.fhir.jpa.util.QueryParameterUtils;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParamModifier;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
@ -59,7 +60,7 @@ public class ResourceIdPredicateBuilder extends BasePredicateBuilder {
|
|||
|
||||
@Nullable
|
||||
public Condition createPredicateResourceId(
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumn,
|
||||
String theResourceName,
|
||||
List<List<IQueryParameterType>> theValues,
|
||||
SearchFilterParser.CompareOperation theOperation,
|
||||
|
@ -134,8 +135,10 @@ public class ResourceIdPredicateBuilder extends BasePredicateBuilder {
|
|||
return queryRootTable.combineWithRequestPartitionIdPredicate(theRequestPartitionId, predicate);
|
||||
}
|
||||
} else {
|
||||
DbColumn resIdColumn = getResourceIdColumn(theSourceJoinColumn);
|
||||
// FIXME: find a test that lands here and make sure we have a Keep test doing the same
|
||||
return QueryParameterUtils.toEqualToOrInPredicate(
|
||||
theSourceJoinColumn,
|
||||
resIdColumn,
|
||||
generatePlaceholders(resourceIds),
|
||||
operation == SearchFilterParser.CompareOperation.ne);
|
||||
}
|
||||
|
@ -143,4 +146,23 @@ public class ResourceIdPredicateBuilder extends BasePredicateBuilder {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes 1-2 columns and returns the last one. This is useful where the input is an array of
|
||||
* join columns for SQL Search expressions. In partition key mode, there are 2 columns (partition id and resource id).
|
||||
* In non partition key mode, only the resource id column is used.
|
||||
*/
|
||||
@Nullable
|
||||
public static DbColumn getResourceIdColumn(@Nullable DbColumn[] theJoinColumns) {
|
||||
DbColumn resIdColumn;
|
||||
if (theJoinColumns == null) {
|
||||
return null;
|
||||
} else if (theJoinColumns.length == 1) {
|
||||
resIdColumn = theJoinColumns[0];
|
||||
} else {
|
||||
assert theJoinColumns.length == 2;
|
||||
resIdColumn = theJoinColumns[1];
|
||||
}
|
||||
return resIdColumn;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,9 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
private final QueryStack myQueryStack;
|
||||
private final boolean myReversed;
|
||||
|
||||
private final DbColumn myColumnTargetPartitionId;
|
||||
private final DbColumn myColumnSrcPartitionId;
|
||||
|
||||
@Autowired
|
||||
private JpaStorageSettings myStorageSettings;
|
||||
|
||||
|
@ -133,9 +136,11 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
QueryStack theQueryStack, SearchQueryBuilder theSearchSqlBuilder, boolean theReversed) {
|
||||
super(theSearchSqlBuilder, theSearchSqlBuilder.addTable("HFJ_RES_LINK"));
|
||||
myColumnSrcResourceId = getTable().addColumn("SRC_RESOURCE_ID");
|
||||
myColumnSrcPartitionId = getTable().addColumn("PARTITION_ID");
|
||||
myColumnSrcType = getTable().addColumn("SOURCE_RESOURCE_TYPE");
|
||||
myColumnSrcPath = getTable().addColumn("SRC_PATH");
|
||||
myColumnTargetResourceId = getTable().addColumn("TARGET_RESOURCE_ID");
|
||||
myColumnTargetPartitionId = getTable().addColumn("TARGET_RES_PARTITION_ID");
|
||||
myColumnTargetResourceUrl = getTable().addColumn("TARGET_RESOURCE_URL");
|
||||
myColumnTargetResourceType = getTable().addColumn("TARGET_RESOURCE_TYPE");
|
||||
|
||||
|
@ -159,10 +164,37 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
return myColumnTargetResourceId;
|
||||
}
|
||||
|
||||
public DbColumn getColumnTargetPartitionId() {
|
||||
return myColumnTargetPartitionId;
|
||||
}
|
||||
|
||||
public DbColumn[] getJoinColumnsForTarget() {
|
||||
return getSearchQueryBuilder().toJoinColumns(getColumnTargetPartitionId(), getColumnTargetResourceId());
|
||||
}
|
||||
|
||||
public DbColumn[] getJoinColumnsForSource() {
|
||||
return getSearchQueryBuilder().toJoinColumns(getPartitionIdColumn(), myColumnSrcResourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that this may return the SRC_RESOURCE_ID or TGT_RESOURCE_ID depending
|
||||
* on whether we're building a forward or reverse link. If you need a specific
|
||||
* one of these, use {@link #getJoinColumnsForSource()} or {@link #getJoinColumnsForTarget()}.
|
||||
*/
|
||||
@Override
|
||||
// fixme dig into this
|
||||
public DbColumn[] getJoinColumns() {
|
||||
return super.getJoinColumns();
|
||||
}
|
||||
|
||||
public DbColumn getColumnSrcResourceId() {
|
||||
return myColumnSrcResourceId;
|
||||
}
|
||||
|
||||
public DbColumn getColumnSrcPartitionId() {
|
||||
return myColumnSrcPartitionId;
|
||||
}
|
||||
|
||||
public DbColumn getColumnTargetResourceType() {
|
||||
return myColumnTargetResourceType;
|
||||
}
|
||||
|
@ -509,7 +541,7 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
|
||||
List<List<IQueryParameterType>> chainParamValues = Collections.singletonList(orValues);
|
||||
andPredicates.add(
|
||||
childQueryFactory.searchForIdsWithAndOr(with().setSourceJoinColumn(myColumnTargetResourceId)
|
||||
childQueryFactory.searchForIdsWithAndOr(with().setSourceJoinColumn(getJoinColumnsForTarget())
|
||||
.setResourceName(subResourceName)
|
||||
.setParamName(chain)
|
||||
.setAndOrParams(chainParamValues)
|
||||
|
|
|
@ -53,9 +53,9 @@ public class SourcePredicateBuilder extends BaseJoiningPredicateBuilder {
|
|||
* Constructor
|
||||
*/
|
||||
public SourcePredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
super(theSearchSqlBuilder, theSearchSqlBuilder.addTable("HFJ_RES_VER_PROV"));
|
||||
super(theSearchSqlBuilder, theSearchSqlBuilder.addTable("HFJ_RES_VER"));
|
||||
|
||||
myResourceIdColumn = getTable().addColumn("RES_PID");
|
||||
myResourceIdColumn = getTable().addColumn("RES_ID");
|
||||
myColumnSourceUri = getTable().addColumn("SOURCE_URI");
|
||||
myColumnRequestId = getTable().addColumn("REQUEST_ID");
|
||||
}
|
||||
|
|
|
@ -66,7 +66,9 @@ public class TagPredicateBuilder extends BaseJoiningPredicateBuilder {
|
|||
List<Triple<String, String, String>> theTokens,
|
||||
String theParamName,
|
||||
RequestPartitionId theRequestPartitionId) {
|
||||
addJoin(getTable(), myTagDefinitionTable, myColumnTagId, myTagDefinitionColumnTagId);
|
||||
addJoin(getTable(), myTagDefinitionTable, new DbColumn[] {myColumnTagId}, new DbColumn[] {
|
||||
myTagDefinitionColumnTagId
|
||||
});
|
||||
return createPredicateTagList(theTagType, theTokens);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package ca.uhn.fhir.jpa.search.builder.sql;
|
||||
|
||||
import com.healthmarketscience.common.util.AppendableExt;
|
||||
import com.healthmarketscience.sqlbuilder.SqlContext;
|
||||
import com.healthmarketscience.sqlbuilder.SqlObject;
|
||||
import com.healthmarketscience.sqlbuilder.ValidationContext;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.Column;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.Table;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class ColumnTupleObject extends SqlObject {
|
||||
|
||||
private final List<Column> myColumns;
|
||||
|
||||
public ColumnTupleObject(Column... theColumns) {
|
||||
myColumns = List.of(theColumns);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void collectSchemaObjects(ValidationContext vContext) {
|
||||
myColumns.forEach(vContext::addColumn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(AppendableExt app) throws IOException {
|
||||
app.append('(');
|
||||
|
||||
for (Iterator<Column> iter = myColumns.iterator(); iter.hasNext(); ) {
|
||||
Column column = iter.next();
|
||||
appendTableAliasPrefix(app, column.getTable());
|
||||
app.append(column.getColumnNameSQL());
|
||||
|
||||
if (iter.hasNext()) {
|
||||
app.append(',');
|
||||
}
|
||||
}
|
||||
|
||||
app.append(')');
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the table alias prefix <code>"[<tableAlias>.]"</code> for a
|
||||
* column reference if the current SqlContext specifies table aliases should
|
||||
* be used (and the table has an alias), otherwise does nothing.
|
||||
*/
|
||||
static void appendTableAliasPrefix(AppendableExt app, Table table) throws IOException {
|
||||
if (SqlContext.getContext(app).getUseTableAliases()) {
|
||||
String alias = table.getAlias();
|
||||
if (isNotBlank(alias)) {
|
||||
app.append(alias).append(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Object from(DbColumn[] theJoinColumns) {
|
||||
if (theJoinColumns.length == 1) {
|
||||
return theJoinColumns[0];
|
||||
} else {
|
||||
return new ColumnTupleObject(theJoinColumns);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package ca.uhn.fhir.jpa.search.builder.sql;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||
import com.healthmarketscience.common.util.AppendableExt;
|
||||
import com.healthmarketscience.sqlbuilder.Expression;
|
||||
import com.healthmarketscience.sqlbuilder.ValidationContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Outputs an SQL tuple for a collection of JpaPids, consisting of
|
||||
* ((resId,partitionId),(resId,partitionId),(resId,partitionId),...)
|
||||
*/
|
||||
public class JpaPidValueTupleObject extends Expression {
|
||||
|
||||
private final Collection<String> myValues;
|
||||
|
||||
public JpaPidValueTupleObject(Collection<String> theValues) {
|
||||
myValues = theValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void collectSchemaObjects(ValidationContext vContext) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(AppendableExt app) throws IOException {
|
||||
app.append('(');
|
||||
|
||||
String value;
|
||||
for (Iterator<String> iter = myValues.iterator(); iter.hasNext(); ) {
|
||||
if (hasParens()) {
|
||||
// fixme do we want the quotes? I think these are numbers.
|
||||
app.append("('");
|
||||
}
|
||||
value = iter.next();
|
||||
app.append(value);
|
||||
app.append("','");
|
||||
value = iter.next();
|
||||
app.append(value);
|
||||
app.append("')");
|
||||
if (iter.hasNext()) {
|
||||
app.append(',');
|
||||
}
|
||||
}
|
||||
if (hasParens()) {
|
||||
app.append(')');
|
||||
}
|
||||
}
|
||||
|
||||
public static JpaPidValueTupleObject from(SearchQueryBuilder theSearchQueryBuilder, JpaPid[] thePids) {
|
||||
List<String> placeholders = new ArrayList<>(thePids.length * 2);
|
||||
for (JpaPid next : thePids) {
|
||||
placeholders.add(theSearchQueryBuilder.generatePlaceholder(next.getPartitionId()));
|
||||
placeholders.add(theSearchQueryBuilder.generatePlaceholder(next.getId()));
|
||||
}
|
||||
return new JpaPidValueTupleObject(placeholders);
|
||||
}
|
||||
}
|
|
@ -111,6 +111,7 @@ public class SearchQueryBuilder {
|
|||
private boolean myNeedResourceTableRoot;
|
||||
private int myNextNearnessColumnId = 0;
|
||||
private DbColumn mySelectedResourceIdColumn;
|
||||
private DbColumn mySelectedPartitionIdColumn;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -201,7 +202,7 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a COORDS search parameter
|
||||
*/
|
||||
public CoordsPredicateBuilder addCoordsPredicateBuilder(@Nullable DbColumn theSourceJoinColumn) {
|
||||
public CoordsPredicateBuilder addCoordsPredicateBuilder(@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
CoordsPredicateBuilder retVal = mySqlBuilderFactory.coordsPredicateBuilder(this);
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -210,7 +211,7 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Create, add and return a predicate builder (or a root query if no root query exists yet) for selecting on a DATE search parameter
|
||||
*/
|
||||
public DatePredicateBuilder addDatePredicateBuilder(@Nullable DbColumn theSourceJoinColumn) {
|
||||
public DatePredicateBuilder addDatePredicateBuilder(@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
DatePredicateBuilder retVal = mySqlBuilderFactory.dateIndexTable(this);
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -226,7 +227,7 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Create, add and return a predicate builder (or a root query if no root query exists yet) for selecting on a NUMBER search parameter
|
||||
*/
|
||||
public NumberPredicateBuilder addNumberPredicateBuilder(@Nullable DbColumn theSourceJoinColumn) {
|
||||
public NumberPredicateBuilder addNumberPredicateBuilder(@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
NumberPredicateBuilder retVal = createNumberPredicateBuilder();
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -242,7 +243,7 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on the Resource table
|
||||
*/
|
||||
public ResourceTablePredicateBuilder addResourceTablePredicateBuilder(@Nullable DbColumn theSourceJoinColumn) {
|
||||
public ResourceTablePredicateBuilder addResourceTablePredicateBuilder(@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
ResourceTablePredicateBuilder retVal = mySqlBuilderFactory.resourceTable(this);
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -251,7 +252,7 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Create, add and return a predicate builder (or a root query if no root query exists yet) for selecting on a QUANTITY search parameter
|
||||
*/
|
||||
public QuantityPredicateBuilder addQuantityPredicateBuilder(@Nullable DbColumn theSourceJoinColumn) {
|
||||
public QuantityPredicateBuilder addQuantityPredicateBuilder(@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
QuantityPredicateBuilder retVal = createQuantityPredicateBuilder();
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
|
||||
|
@ -266,7 +267,7 @@ public class SearchQueryBuilder {
|
|||
}
|
||||
|
||||
public QuantityNormalizedPredicateBuilder addQuantityNormalizedPredicateBuilder(
|
||||
@Nullable DbColumn theSourceJoinColumn) {
|
||||
@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
|
||||
QuantityNormalizedPredicateBuilder retVal = mySqlBuilderFactory.quantityNormalizedIndexTable(this);
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
|
@ -278,7 +279,7 @@ public class SearchQueryBuilder {
|
|||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a <code>_source</code> search parameter
|
||||
*/
|
||||
public SourcePredicateBuilder addSourcePredicateBuilder(
|
||||
@Nullable DbColumn theSourceJoinColumn, SelectQuery.JoinType theJoinType) {
|
||||
@Nullable DbColumn[] theSourceJoinColumn, SelectQuery.JoinType theJoinType) {
|
||||
SourcePredicateBuilder retVal = mySqlBuilderFactory.newSourcePredicateBuilder(this);
|
||||
addTable(retVal, theSourceJoinColumn, theJoinType);
|
||||
return retVal;
|
||||
|
@ -288,7 +289,7 @@ public class SearchQueryBuilder {
|
|||
* Create, add and return a predicate builder (or a root query if no root query exists yet) for selecting on a REFERENCE search parameter
|
||||
*/
|
||||
public ResourceLinkPredicateBuilder addReferencePredicateBuilder(
|
||||
QueryStack theQueryStack, @Nullable DbColumn theSourceJoinColumn) {
|
||||
QueryStack theQueryStack, @Nullable DbColumn[] theSourceJoinColumn) {
|
||||
ResourceLinkPredicateBuilder retVal = createReferencePredicateBuilder(theQueryStack);
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -306,7 +307,7 @@ public class SearchQueryBuilder {
|
|||
* source and target are reversed. This is used for _has queries.
|
||||
*/
|
||||
public ResourceLinkPredicateBuilder addReferencePredicateBuilderReversed(
|
||||
QueryStack theQueryStack, DbColumn theSourceJoinColumn) {
|
||||
QueryStack theQueryStack, DbColumn[] theSourceJoinColumn) {
|
||||
ResourceLinkPredicateBuilder retVal = mySqlBuilderFactory.referenceIndexTable(theQueryStack, this, true);
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -315,7 +316,7 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Create, add and return a predicate builder (or a root query if no root query exists yet) for selecting on a STRING search parameter
|
||||
*/
|
||||
public StringPredicateBuilder addStringPredicateBuilder(@Nullable DbColumn theSourceJoinColumn) {
|
||||
public StringPredicateBuilder addStringPredicateBuilder(@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
StringPredicateBuilder retVal = createStringPredicateBuilder();
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -331,7 +332,7 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a <code>_tag</code> search parameter
|
||||
*/
|
||||
public TagPredicateBuilder addTagPredicateBuilder(@Nullable DbColumn theSourceJoinColumn) {
|
||||
public TagPredicateBuilder addTagPredicateBuilder(@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
TagPredicateBuilder retVal = mySqlBuilderFactory.newTagPredicateBuilder(this);
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -340,7 +341,7 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Create, add and return a predicate builder (or a root query if no root query exists yet) for selecting on a TOKEN search parameter
|
||||
*/
|
||||
public TokenPredicateBuilder addTokenPredicateBuilder(@Nullable DbColumn theSourceJoinColumn) {
|
||||
public TokenPredicateBuilder addTokenPredicateBuilder(@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
TokenPredicateBuilder retVal = createTokenPredicateBuilder();
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -369,7 +370,7 @@ public class SearchQueryBuilder {
|
|||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a <code>:missing</code> search parameter
|
||||
*/
|
||||
public SearchParamPresentPredicateBuilder addSearchParamPresentPredicateBuilder(
|
||||
@Nullable DbColumn theSourceJoinColumn) {
|
||||
@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
SearchParamPresentPredicateBuilder retVal = mySqlBuilderFactory.searchParamPresentPredicateBuilder(this);
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -378,7 +379,7 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Create, add and return a predicate builder (or a root query if no root query exists yet) for selecting on a URI search parameter
|
||||
*/
|
||||
public UriPredicateBuilder addUriPredicateBuilder(@Nullable DbColumn theSourceJoinColumn) {
|
||||
public UriPredicateBuilder addUriPredicateBuilder(@Nullable DbColumn[] theSourceJoinColumn) {
|
||||
UriPredicateBuilder retVal = createUriPredicateBuilder();
|
||||
addTable(retVal, theSourceJoinColumn);
|
||||
return retVal;
|
||||
|
@ -402,19 +403,19 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for an arbitrary table
|
||||
*/
|
||||
private void addTable(BaseJoiningPredicateBuilder thePredicateBuilder, @Nullable DbColumn theSourceJoinColumn) {
|
||||
private void addTable(BaseJoiningPredicateBuilder thePredicateBuilder, @Nullable DbColumn[] theSourceJoinColumn) {
|
||||
addTable(thePredicateBuilder, theSourceJoinColumn, SelectQuery.JoinType.INNER);
|
||||
}
|
||||
|
||||
private void addTable(
|
||||
BaseJoiningPredicateBuilder thePredicateBuilder,
|
||||
@Nullable DbColumn theSourceJoinColumn,
|
||||
@Nullable DbColumn[] theSourceJoinColumns,
|
||||
SelectQuery.JoinType theJoinType) {
|
||||
if (theSourceJoinColumn != null) {
|
||||
DbTable fromTable = theSourceJoinColumn.getTable();
|
||||
if (theSourceJoinColumns != null) {
|
||||
DbTable fromTable = theSourceJoinColumns[0].getTable();
|
||||
DbTable toTable = thePredicateBuilder.getTable();
|
||||
DbColumn toColumn = thePredicateBuilder.getResourceIdColumn();
|
||||
addJoin(fromTable, toTable, theSourceJoinColumn, toColumn, theJoinType);
|
||||
DbColumn[] toColumn = toJoinColumns(thePredicateBuilder);
|
||||
addJoin(fromTable, toTable, theSourceJoinColumns, toColumn, theJoinType);
|
||||
} else {
|
||||
if (myFirstPredicateBuilder == null) {
|
||||
|
||||
|
@ -446,29 +447,47 @@ public class SearchQueryBuilder {
|
|||
|
||||
DbTable fromTable = myFirstPredicateBuilder.getTable();
|
||||
DbTable toTable = thePredicateBuilder.getTable();
|
||||
DbColumn fromColumn = myFirstPredicateBuilder.getResourceIdColumn();
|
||||
DbColumn toColumn = thePredicateBuilder.getResourceIdColumn();
|
||||
DbColumn[] fromColumn = toJoinColumns(myFirstPredicateBuilder);
|
||||
DbColumn[] toColumn = toJoinColumns(thePredicateBuilder);
|
||||
addJoin(fromTable, toTable, fromColumn, toColumn, theJoinType);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbColumn[] toJoinColumns(BaseJoiningPredicateBuilder theBuilder) {
|
||||
DbColumn partitionIdColumn = theBuilder.getPartitionIdColumn();
|
||||
DbColumn resourceIdColumn = theBuilder.getResourceIdColumn();
|
||||
return toJoinColumns(partitionIdColumn, resourceIdColumn);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public DbColumn[] toJoinColumns(DbColumn partitionIdColumn, DbColumn resourceIdColumn) {
|
||||
if (isIncludePartitionIdInJoins()) {
|
||||
return new DbColumn[] {partitionIdColumn, resourceIdColumn};
|
||||
} else {
|
||||
return new DbColumn[] {resourceIdColumn};
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIncludePartitionIdInJoins() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addJoin(DbTable theFromTable, DbTable theToTable, DbColumn[] theFromColumn, DbColumn[] theToColumn) {
|
||||
addJoin(theFromTable, theToTable, theFromColumn, theToColumn, SelectQuery.JoinType.INNER);
|
||||
}
|
||||
|
||||
public void addJoin(
|
||||
DbTable theFromTable,
|
||||
DbTable theToTable,
|
||||
DbColumn theFromColumn,
|
||||
DbColumn theToColumn,
|
||||
DbColumn[] theFromColumn,
|
||||
DbColumn[] theToColumn,
|
||||
SelectQuery.JoinType theJoinType) {
|
||||
Join join = new DbJoin(
|
||||
mySpec, theFromTable, theToTable, new DbColumn[] {theFromColumn}, new DbColumn[] {theToColumn});
|
||||
assert theFromColumn.length == theToColumn.length;
|
||||
Join join = new DbJoin(mySpec, theFromTable, theToTable, theFromColumn, theToColumn);
|
||||
mySelect.addJoins(theJoinType, join);
|
||||
}
|
||||
|
||||
public void addJoin(DbTable theFromTable, DbTable theToTable, DbColumn theFromColumn, DbColumn theToColumn) {
|
||||
Join join = new DbJoin(
|
||||
mySpec, theFromTable, theToTable, new DbColumn[] {theFromColumn}, new DbColumn[] {theToColumn});
|
||||
mySelect.addJoins(SelectQuery.JoinType.INNER, join);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and return the SQL generated by this builder
|
||||
*/
|
||||
|
@ -659,7 +678,7 @@ public class SearchQueryBuilder {
|
|||
* for its generated SQL. So we work around this by replacing our contents with a string in the SQL consisting
|
||||
* of <code>[random UUID]-[value index]</code> and then
|
||||
*/
|
||||
public String generatePlaceholder(Object theValue) {
|
||||
public String generatePlaceholder(Object theValue) {
|
||||
String placeholder = myBindVariableSubstitutionBase + myBindVariableValues.size();
|
||||
myBindVariableValues.add(theValue);
|
||||
return placeholder;
|
||||
|
|
|
@ -23,6 +23,7 @@ import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
|||
import ca.uhn.fhir.rest.api.server.storage.BaseResourcePersistentId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -66,6 +67,10 @@ public class JpaPid extends BaseResourcePersistentId<Long> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public static List<Long> toLongList(JpaPid[] thePids) {
|
||||
return toLongList(Arrays.asList(thePids));
|
||||
}
|
||||
|
||||
public static List<Long> toLongList(Collection<JpaPid> thePids) {
|
||||
List<Long> retVal = new ArrayList<>(thePids.size());
|
||||
for (JpaPid next : thePids) {
|
||||
|
@ -129,4 +134,10 @@ public class JpaPid extends BaseResourcePersistentId<Long> {
|
|||
public String toString() {
|
||||
return myId.toString();
|
||||
}
|
||||
|
||||
public Integer getPartitionId() {
|
||||
// wipmb should we return null instead?
|
||||
assert getPartitionablePartitionId() != null;
|
||||
return getPartitionablePartitionId().getPartitionId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package ca.uhn.fhir.jpa.model.dao;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.fhir.jpa.model.dao.JpaPid.fromId;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class JpaPidTest {
|
||||
|
||||
@Test
|
||||
void testToLongList() {
|
||||
assertEquals(List.of(), JpaPid.toLongList(List.of()));
|
||||
assertEquals(List.of(1L, 2L), JpaPid.toLongList(List.of(fromId(1L), fromId(2L))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testArrayToLongList() {
|
||||
assertEquals(List.of(), JpaPid.toLongList(new JpaPid[0]));
|
||||
assertEquals(List.of(1L, 2L), JpaPid.toLongList(new JpaPid[]{fromId(1L), fromId(2L)}));
|
||||
}
|
||||
|
||||
}
|
|
@ -65,7 +65,7 @@ public class FhirResourceDaoR4SearchSqlTest extends BaseJpaR4Test {
|
|||
myPatientDao.search(map);
|
||||
assertEquals(1, myCaptureQueriesListener.countSelectQueries());
|
||||
String sql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(false, false);
|
||||
assertEquals("SELECT t1.RES_ID FROM HFJ_RESOURCE t1 INNER JOIN HFJ_SPIDX_STRING t0 ON (t1.RES_ID = t0.RES_ID) INNER JOIN HFJ_SPIDX_TOKEN t2 ON (t1.RES_ID = t2.RES_ID) WHERE (((t0.HASH_NORM_PREFIX = ?) AND (t0.SP_VALUE_NORMALIZED LIKE ?)) AND (t2.HASH_SYS_AND_VALUE = ?))", sql);
|
||||
assertEquals("SELECT t1.RES_ID FROM HFJ_RESOURCE t1 INNER JOIN HFJ_SPIDX_STRING t0 ON (t1.RES_ID = t0.RES_ID AND ((t1.PARTITION_ID = t0.PARTITION_ID) OR (t1.PARTITION_ID is null AND t0.PARTITION_ID is null))) INNER JOIN HFJ_SPIDX_TOKEN t2 ON (t1.RES_ID = t2.RES_ID AND ((t1.PARTITION_ID = t2.PARTITION_ID) OR (t1.PARTITION_ID is null AND t2.PARTITION_ID is null)) ) WHERE (((t0.HASH_NORM_PREFIX = ?) AND (t0.SP_VALUE_NORMALIZED LIKE ?)) AND (t2.HASH_SYS_AND_VALUE = ?))", sql);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public abstract class BaseSearchQueryBuilderDialectTest {
|
|||
when(mySqlObjectFactory.dateIndexTable(any())).thenReturn(new DatePredicateBuilder(searchQueryBuilder));
|
||||
|
||||
BaseJoiningPredicateBuilder firstPredicateBuilder = searchQueryBuilder.getOrCreateFirstPredicateBuilder();
|
||||
DatePredicateBuilder sortPredicateBuilder = searchQueryBuilder.addDatePredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
||||
DatePredicateBuilder sortPredicateBuilder = searchQueryBuilder.addDatePredicateBuilder(firstPredicateBuilder.getJoinColumns());
|
||||
|
||||
Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate("MolecularSequence", "variant-start");
|
||||
searchQueryBuilder.addPredicate(hashIdentityPredicate);
|
||||
|
|
|
@ -63,7 +63,7 @@ public class SearchQueryBuilderDialectMySqlTest extends BaseSearchQueryBuilderDi
|
|||
when(mySqlObjectFactory.stringIndexTable(any())).thenReturn(new StringPredicateBuilder(searchQueryBuilder));
|
||||
|
||||
BaseJoiningPredicateBuilder firstPredicateBuilder = searchQueryBuilder.getOrCreateFirstPredicateBuilder();
|
||||
StringPredicateBuilder sortPredicateBuilder = searchQueryBuilder.addStringPredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
||||
StringPredicateBuilder sortPredicateBuilder = searchQueryBuilder.addStringPredicateBuilder(firstPredicateBuilder.getJoinColumns());
|
||||
|
||||
Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate("patient", "family");
|
||||
searchQueryBuilder.addPredicate(hashIdentityPredicate);
|
||||
|
@ -112,7 +112,7 @@ public class SearchQueryBuilderDialectMySqlTest extends BaseSearchQueryBuilderDi
|
|||
when(mySqlObjectFactory.dateIndexTable(any())).thenReturn(new DatePredicateBuilder(searchQueryBuilder));
|
||||
|
||||
BaseJoiningPredicateBuilder firstPredicateBuilder = searchQueryBuilder.getOrCreateFirstPredicateBuilder();
|
||||
DatePredicateBuilder sortPredicateBuilder = searchQueryBuilder.addDatePredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
||||
DatePredicateBuilder sortPredicateBuilder = searchQueryBuilder.addDatePredicateBuilder(firstPredicateBuilder.getJoinColumns());
|
||||
|
||||
Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate("patient", "birthdate");
|
||||
searchQueryBuilder.addPredicate(hashIdentityPredicate);
|
||||
|
|
Loading…
Reference in New Issue