Work on uniques

This commit is contained in:
jamesagnew 2020-03-30 05:36:24 -04:00
parent 62d867902f
commit 8e714b6b14
14 changed files with 214 additions and 54 deletions

View File

@ -871,7 +871,7 @@ public class SearchBuilder implements ISearchBuilder {
.add(StorageProcessingMessage.class, msg);
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_INFO, params);
addPredicateCompositeStringUnique(theParams, indexString);
addPredicateCompositeStringUnique(theParams, indexString, myPartitionId);
}
}
}
@ -886,9 +886,16 @@ public class SearchBuilder implements ISearchBuilder {
}
}
private void addPredicateCompositeStringUnique(@Nonnull SearchParameterMap theParams, String theIndexedString) {
myQueryRoot.setHasIndexJoins(true);
private void addPredicateCompositeStringUnique(@Nonnull SearchParameterMap theParams, String theIndexedString, PartitionId thePartitionId) {
Join<ResourceTable, ResourceIndexedCompositeStringUnique> join = myQueryRoot.join("myParamsCompositeStringUnique", JoinType.LEFT);
if (thePartitionId != null) {
Integer partitionId = thePartitionId.getPartitionId();
Predicate predicate = myCriteriaBuilder.equal(join.get("myPartitionIdValue").as(Integer.class), partitionId);
myQueryRoot.addPredicate(predicate);
}
myQueryRoot.setHasIndexJoins(true);
Predicate predicate = myCriteriaBuilder.equal(join.get("myIndexString"), theIndexedString);
myQueryRoot.addPredicate(predicate);

View File

@ -24,9 +24,11 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndex;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.model.entity.PartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.SearchParamPresent;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
@ -203,6 +205,14 @@ abstract class BasePredicateBuilder {
return combineParamIndexPredicateWithParamNamePredicate(theResourceName, theParamName, theFrom, num);
}
void addPartitionIdPredicate(PartitionId thePartitionId, Join<ResourceTable, ? extends BaseResourceIndex> theJoin, List<Predicate> theCodePredicates) {
if (thePartitionId != null) {
Integer partitionId = thePartitionId.getPartitionId();
Predicate partitionPredicate = myCriteriaBuilder.equal(theJoin.get("myPartitionIdValue").as(Integer.class), partitionId);
myQueryRoot.addPredicate(partitionPredicate);
}
}
static String createLeftAndRightMatchLikeExpression(String likeExpression) {
return "%" + likeExpression.replace("%", "[%]") + "%";
}

View File

@ -55,40 +55,40 @@ public class PredicateBuilder {
myPredicateBuilderUri = thePredicateBuilderFactory.newPredicateBuilderUri(theSearchBuilder);
}
void addPredicateCoords(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd) {
myPredicateBuilderCoords.addPredicate(theResourceName, theParamName, theNextAnd, null);
void addPredicateCoords(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, PartitionId thePartitionId) {
myPredicateBuilderCoords.addPredicate(theResourceName, theParamName, theNextAnd, null, thePartitionId);
}
Predicate addPredicateDate(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation) {
return myPredicateBuilderDate.addPredicate(theResourceName, theParamName, theNextAnd, theOperation);
Predicate addPredicateDate(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation, PartitionId thePartitionId) {
return myPredicateBuilderDate.addPredicate(theResourceName, theParamName, theNextAnd, theOperation, thePartitionId);
}
Predicate addPredicateNumber(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation) {
return myPredicateBuilderNumber.addPredicate(theResourceName, theParamName, theNextAnd, theOperation);
Predicate addPredicateNumber(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation, PartitionId thePartitionId) {
return myPredicateBuilderNumber.addPredicate(theResourceName, theParamName, theNextAnd, theOperation, thePartitionId);
}
Predicate addPredicateQuantity(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation) {
return myPredicateBuilderQuantity.addPredicate(theResourceName, theParamName, theNextAnd, theOperation);
Predicate addPredicateQuantity(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation, PartitionId thePartitionId) {
return myPredicateBuilderQuantity.addPredicate(theResourceName, theParamName, theNextAnd, theOperation, thePartitionId);
}
void addPredicateString(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd) {
myPredicateBuilderString.addPredicate(theResourceName, theParamName, theNextAnd, SearchFilterParser.CompareOperation.sw);
void addPredicateString(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, PartitionId thePartitionId) {
myPredicateBuilderString.addPredicate(theResourceName, theParamName, theNextAnd, SearchFilterParser.CompareOperation.sw, thePartitionId);
}
Predicate addPredicateString(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation) {
return myPredicateBuilderString.addPredicate(theResourceName, theParamName, theNextAnd, theOperation);
Predicate addPredicateString(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation, PartitionId thePartitionId) {
return myPredicateBuilderString.addPredicate(theResourceName, theParamName, theNextAnd, theOperation, thePartitionId);
}
void addPredicateTag(List<List<IQueryParameterType>> theAndOrParams, String theParamName) {
myPredicateBuilderTag.addPredicateTag(theAndOrParams, theParamName);
}
Predicate addPredicateToken(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation) {
return myPredicateBuilderToken.addPredicate(theResourceName, theParamName, theNextAnd, theOperation);
Predicate addPredicateToken(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation, PartitionId thePartitionId) {
return myPredicateBuilderToken.addPredicate(theResourceName, theParamName, theNextAnd, theOperation, thePartitionId);
}
Predicate addPredicateUri(String theResourceName, String theName, List<? extends IQueryParameterType> theSingletonList, SearchFilterParser.CompareOperation theOperation) {
return myPredicateBuilderUri.addPredicate(theResourceName, theName, theSingletonList, theOperation);
Predicate addPredicateUri(String theResourceName, String theName, List<? extends IQueryParameterType> theSingletonList, SearchFilterParser.CompareOperation theOperation, PartitionId thePartitionId) {
return myPredicateBuilderUri.addPredicate(theResourceName, theName, theSingletonList, theOperation, thePartitionId);
}
public void searchForIdsWithAndOr(String theResourceName, String theNextParamName, List<List<IQueryParameterType>> theAndOrParams, RequestDetails theRequest, PartitionId thePartitionId) {

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.predicate;
*/
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.PartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.util.CoordCalculator;
@ -147,15 +148,18 @@ public class PredicateBuilderCoords extends BasePredicateBuilder implements IPre
public Predicate addPredicate(String theResourceName,
String theParamName,
List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation theOperation) {
SearchFilterParser.CompareOperation theOperation,
PartitionId thePartitionId) {
Join<ResourceTable, ResourceIndexedSearchParamCoords> join = createJoin(SearchBuilderJoinEnum.COORDS, theParamName);
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join);
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
List<Predicate> codePredicates = new ArrayList<Predicate>();
List<Predicate> codePredicates = new ArrayList<>();
addPartitionIdPredicate(thePartitionId, join, codePredicates);
for (IQueryParameterType nextOr : theList) {
Predicate singleCode = createPredicateCoords(nextOr,

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.predicate;
*/
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.PartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.model.api.IQueryParameterType;
@ -58,7 +59,8 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
public Predicate addPredicate(String theResourceName,
String theParamName,
List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation operation) {
SearchFilterParser.CompareOperation operation,
PartitionId thePartitionId) {
boolean newJoin = false;
if (myJoinMap == null) {
@ -75,11 +77,13 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
if (theList.get(0).getMissing() != null) {
Boolean missing = theList.get(0).getMissing();
addPredicateParamMissing(theResourceName, theParamName, missing, join);
addPredicateParamMissing(theResourceName, theParamName, missing, join, thePartitionId);
return null;
}
List<Predicate> codePredicates = new ArrayList<>();
addPartitionIdPredicate(thePartitionId, join, codePredicates);
for (IQueryParameterType nextOr : theList) {
IQueryParameterType params = nextOr;
Predicate p = createPredicateDate(params,

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.predicate;
*/
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.PartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.model.api.IQueryParameterType;
@ -53,16 +54,19 @@ class PredicateBuilderNumber extends BasePredicateBuilder implements IPredicateB
public Predicate addPredicate(String theResourceName,
String theParamName,
List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation operation) {
SearchFilterParser.CompareOperation operation,
PartitionId thePartitionId) {
Join<ResourceTable, ResourceIndexedSearchParamNumber> join = createJoin(SearchBuilderJoinEnum.NUMBER, theParamName);
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join);
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
List<Predicate> codePredicates = new ArrayList<>();
addPartitionIdPredicate(thePartitionId, join, codePredicates);
for (IQueryParameterType nextOr : theList) {
if (nextOr instanceof NumberParam) {

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao.predicate;
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.model.entity.PartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.model.api.IQueryParameterType;
@ -51,16 +52,19 @@ class PredicateBuilderQuantity extends BasePredicateBuilder implements IPredicat
public Predicate addPredicate(String theResourceName,
String theParamName,
List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation operation) {
SearchFilterParser.CompareOperation theOperation,
PartitionId thePartitionId) {
Join<ResourceTable, ResourceIndexedSearchParamQuantity> join = createJoin(SearchBuilderJoinEnum.QUANTITY, theParamName);
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join);
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
List<Predicate> codePredicates = new ArrayList<Predicate>();
addPartitionIdPredicate(thePartitionId, join, codePredicates);
for (IQueryParameterType nextOr : theList) {
Predicate singleCode = createPredicateQuantity(nextOr,
@ -68,7 +72,7 @@ class PredicateBuilderQuantity extends BasePredicateBuilder implements IPredicat
theParamName,
myCriteriaBuilder,
join,
operation);
theOperation);
codePredicates.add(singleCode);
}

View File

@ -188,6 +188,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
}
List<Predicate> codePredicates = new ArrayList<>();
addPartitionIdPredicate(thePartitionId, join, codePredicates);
// Resources by ID
List<ResourcePersistentId> targetPids = myIdHelperService.resolveResourcePersistentIds(targetIds, theRequest);
@ -538,12 +539,12 @@ class PredicateBuilderReference extends BasePredicateBuilder {
switch (nextParamDef.getParamType()) {
case DATE:
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
myPredicateBuilder.addPredicateDate(theResourceName, theParamName, nextAnd, null);
myPredicateBuilder.addPredicateDate(theResourceName, theParamName, nextAnd, null, thePartitionId);
}
break;
case QUANTITY:
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
myPredicateBuilder.addPredicateQuantity(theResourceName, theParamName, nextAnd, null);
myPredicateBuilder.addPredicateQuantity(theResourceName, theParamName, nextAnd, null, thePartitionId);
}
break;
case REFERENCE:
@ -553,21 +554,21 @@ class PredicateBuilderReference extends BasePredicateBuilder {
break;
case STRING:
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
myPredicateBuilder.addPredicateString(theResourceName, theParamName, nextAnd, SearchFilterParser.CompareOperation.sw);
myPredicateBuilder.addPredicateString(theResourceName, theParamName, nextAnd, SearchFilterParser.CompareOperation.sw, thePartitionId);
}
break;
case TOKEN:
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
if ("Location.position".equals(nextParamDef.getPath())) {
myPredicateBuilder.addPredicateCoords(theResourceName, theParamName, nextAnd);
myPredicateBuilder.addPredicateCoords(theResourceName, theParamName, nextAnd, thePartitionId);
} else {
myPredicateBuilder.addPredicateToken(theResourceName, theParamName, nextAnd, null);
myPredicateBuilder.addPredicateToken(theResourceName, theParamName, nextAnd, null, thePartitionId);
}
}
break;
case NUMBER:
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
myPredicateBuilder.addPredicateNumber(theResourceName, theParamName, nextAnd, null);
myPredicateBuilder.addPredicateNumber(theResourceName, theParamName, nextAnd, null, thePartitionId);
}
break;
case COMPOSITE:
@ -577,14 +578,14 @@ class PredicateBuilderReference extends BasePredicateBuilder {
break;
case URI:
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
myPredicateBuilder.addPredicateUri(theResourceName, theParamName, nextAnd, SearchFilterParser.CompareOperation.eq);
myPredicateBuilder.addPredicateUri(theResourceName, theParamName, nextAnd, SearchFilterParser.CompareOperation.eq, thePartitionId);
}
break;
case HAS:
case SPECIAL:
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
if ("Location.position".equals(nextParamDef.getPath())) {
myPredicateBuilder.addPredicateCoords(theResourceName, theParamName, nextAnd);
myPredicateBuilder.addPredicateCoords(theResourceName, theParamName, nextAnd, thePartitionId);
}
}
break;
@ -688,13 +689,13 @@ class PredicateBuilderReference extends BasePredicateBuilder {
} else {
RestSearchParameterTypeEnum typeEnum = searchParam.getParamType();
if (typeEnum == RestSearchParameterTypeEnum.URI) {
return myPredicateBuilder.addPredicateUri(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new UriParam(theFilter.getValue())), theFilter.getOperation());
return myPredicateBuilder.addPredicateUri(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new UriParam(theFilter.getValue())), theFilter.getOperation(), thePartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.STRING) {
return myPredicateBuilder.addPredicateString(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new StringParam(theFilter.getValue())), theFilter.getOperation());
return myPredicateBuilder.addPredicateString(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new StringParam(theFilter.getValue())), theFilter.getOperation(), thePartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.DATE) {
return myPredicateBuilder.addPredicateDate(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new DateParam(theFilter.getValue())), theFilter.getOperation());
return myPredicateBuilder.addPredicateDate(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new DateParam(theFilter.getValue())), theFilter.getOperation(), thePartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.NUMBER) {
return myPredicateBuilder.addPredicateNumber(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new NumberParam(theFilter.getValue())), theFilter.getOperation());
return myPredicateBuilder.addPredicateNumber(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new NumberParam(theFilter.getValue())), theFilter.getOperation(), thePartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.REFERENCE) {
String paramName = theFilter.getParamPath().getName();
SearchFilterParser.CompareOperation operation = theFilter.getOperation();
@ -704,7 +705,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
ReferenceParam referenceParam = new ReferenceParam(resourceType, chain, value);
return addPredicate(theResourceName, paramName, Collections.singletonList(referenceParam), operation, theRequest, thePartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.QUANTITY) {
return myPredicateBuilder.addPredicateQuantity(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new QuantityParam(theFilter.getValue())), theFilter.getOperation());
return myPredicateBuilder.addPredicateQuantity(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(new QuantityParam(theFilter.getValue())), theFilter.getOperation(), thePartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.COMPOSITE) {
throw new InvalidRequestException("Composite search parameters not currently supported with _filter clauses");
} else if (typeEnum == RestSearchParameterTypeEnum.TOKEN) {
@ -713,7 +714,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
null,
null,
theFilter.getValue());
return myPredicateBuilder.addPredicateToken(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(param), theFilter.getOperation());
return myPredicateBuilder.addPredicateToken(theResourceName, theFilter.getParamPath().getName(), Collections.singletonList(param), theFilter.getOperation(), thePartitionId);
}
}
return null;
@ -754,6 +755,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
qp = new SpecialParam();
break;
}
throw new InternalErrorException("Don't know how to convert param type: " + theParam.getParamType());
case URI:
case HAS:
default:

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao.predicate;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.PartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.util.StringNormalizer;
@ -56,16 +57,19 @@ class PredicateBuilderString extends BasePredicateBuilder implements IPredicateB
public Predicate addPredicate(String theResourceName,
String theParamName,
List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation operation) {
SearchFilterParser.CompareOperation theOperation,
PartitionId thePartitionId) {
Join<ResourceTable, ResourceIndexedSearchParamString> join = createJoin(SearchBuilderJoinEnum.STRING, theParamName);
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join);
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
List<Predicate> codePredicates = new ArrayList<>();
addPartitionIdPredicate(thePartitionId, join, codePredicates);
for (IQueryParameterType nextOr : theList) {
IQueryParameterType theParameter = nextOr;
Predicate singleCode = createPredicateString(theParameter,
@ -73,7 +77,7 @@ class PredicateBuilderString extends BasePredicateBuilder implements IPredicateB
theParamName,
myCriteriaBuilder,
join,
operation);
theOperation);
codePredicates.add(singleCode);
}

View File

@ -43,6 +43,7 @@ import java.util.List;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
// FIXME: add partition
@Component
@Scope("prototype")
class PredicateBuilderTag extends BasePredicateBuilder {

View File

@ -26,6 +26,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.model.entity.PartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
@ -70,22 +71,24 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
public Predicate addPredicate(String theResourceName,
String theParamName,
List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation operation) {
SearchFilterParser.CompareOperation theOperation,
PartitionId thePartitionId) {
if (theList.get(0).getMissing() != null) {
Join<ResourceTable, ResourceIndexedSearchParamToken> join = createJoin(SearchBuilderJoinEnum.TOKEN, theParamName);
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join);
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
List<Predicate> codePredicates = new ArrayList<>();
List<IQueryParameterType> tokens = new ArrayList<>();
for (IQueryParameterType nextOr : theList) {
if (nextOr instanceof TokenParam) {
TokenParam id = (TokenParam) nextOr;
if (id.isText()) {
myPredicateBuilder.addPredicateString(theResourceName, theParamName, theList);
myPredicateBuilder.addPredicateString(theResourceName, theParamName, theList, thePartitionId);
break;
}
}
@ -98,7 +101,9 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
}
Join<ResourceTable, ResourceIndexedSearchParamToken> join = createJoin(SearchBuilderJoinEnum.TOKEN, theParamName);
Collection<Predicate> singleCode = createPredicateToken(tokens, theResourceName, theParamName, myCriteriaBuilder, join, operation);
addPartitionIdPredicate(thePartitionId, join, codePredicates);
Collection<Predicate> singleCode = createPredicateToken(tokens, theResourceName, theParamName, myCriteriaBuilder, join, theOperation);
assert singleCode != null;
codePredicates.addAll(singleCode);

View File

@ -67,10 +67,7 @@ class PredicateBuilderUri extends BasePredicateBuilder implements IPredicateBuil
}
List<Predicate> codePredicates = new ArrayList<>();
if (thePartitionId != null) {
Predicate partitionPredicate = myCriteriaBuilder.like(join.get("myUri").as(String.class), createLeftMatchLikeExpression(value));
codePredicates.add(partitionPredicate);
}
addPartitionIdPredicate(thePartitionId, join, codePredicates);
for (IQueryParameterType nextOr : theList) {
@ -185,4 +182,5 @@ class PredicateBuilderUri extends BasePredicateBuilder implements IPredicateBuil
myQueryRoot.addPredicate(outerPredicate);
return outerPredicate;
}
}

View File

@ -8,6 +8,8 @@ import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.TestUtil;
@ -379,6 +381,107 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
assertEquals(1, StringUtils.countMatches(searchSql, "PARTITION_ID"));
}
@Test
public void testSearch_StringParam_SearchAllTenants() {
IIdType patientIdNull = createPatient(null, withFamily("FAMILY"));
IIdType patientId1 = createPatient(1, withFamily("FAMILY"));
IIdType patientId2 = createPatient(2, withFamily("FAMILY"));
addReadTenant(null);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_FAMILY, new StringParam("FAMILY"));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
assertThat(ids, Matchers.contains(patientIdNull, patientId1, patientId2));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(0, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "SP_VALUE_NORMALIZED"));
}
@Test
public void testSearch_StringParam_SearchOneTenant() {
createPatient(null, withFamily("FAMILY"));
IIdType patientId1 = createPatient(1, withFamily("FAMILY"));
createPatient(2, withFamily("FAMILY"));
addReadTenant(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_FAMILY, new StringParam("FAMILY"));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
assertThat(ids, Matchers.contains(patientId1));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(1, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "SP_VALUE_NORMALIZED"));
}
@Test
public void testSearch_UniqueParam_SearchAllTenants() {
createUniqueCompositeSp();
IIdType id = createPatient(1, withBirthdate("2020-01-01"));
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-01"));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
assertThat(ids, Matchers.contains(id));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(0, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "IDX_STRING='Patient?birthdate=2020-01-01'"));
}
@Test
public void testSearch_UniqueParam_SearchOneTenant() {
createUniqueCompositeSp();
IIdType id = createPatient(1, withBirthdate("2020-01-01"));
addReadTenant(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-01"));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
assertThat(ids, Matchers.contains(id));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(1, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "IDX_STRING='Patient?birthdate=2020-01-01'"));
// Same query, different partition
addReadTenant(2);
myCaptureQueriesListener.clear();
map = new SearchParameterMap();
map.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-01"));
map.setLoadSynchronous(true);
results = myPatientDao.search(map);
ids = toUnqualifiedVersionlessIds(results);
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
assertThat(ids, Matchers.empty());
}
private void createUniqueCompositeSp() {
SearchParameter sp = new SearchParameter();
sp.setId("SearchParameter/patient-birthdate");
@ -447,6 +550,14 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
return t -> t.setActive(true);
}
private Consumer<Patient> withFamily(String theFamily) {
return t -> t.addName().setFamily(theFamily);
}
private Consumer<Patient> withBirthdate(String theBirthdate) {
return t -> t.getBirthDateElement().setValueAsString(theBirthdate);
}
private Consumer<Patient> withId(String theId) {
return t -> {
assertThat(theId, matchesPattern("[a-zA-Z0-9]+"));

View File

@ -50,6 +50,12 @@ public class ResourceIndexedCompositeStringUnique implements Comparable<Resource
private String myIndexString;
@Embedded
private PartitionId myPartitionId;
/**
* This is here to support queries only, do not set this field directly
*/
@SuppressWarnings("unused")
@Column(name = PartitionId.PARTITION_ID, insertable = false, updatable = false, nullable = true)
private Integer myPartitionIdValue;
/**
* Constructor