wip
This commit is contained in:
parent
c3ceffbd72
commit
74fd2c1519
|
@ -42,6 +42,7 @@ import ca.uhn.fhir.rest.param.*;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -302,18 +303,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
}
|
||||
|
||||
boolean isMeta = ResourceMetaParams.RESOURCE_META_PARAMS.containsKey(chain);
|
||||
//I'm pretty sure this chunk of code can actually cause ambiguous behaviour. Consider the query:
|
||||
// Observation?subject.name=Graham.
|
||||
// Once in this chunk of code, It could be either Patient or Practitioner, as both have returned their runtime search params.
|
||||
// according to docs here : https://www.hl7.org/fhir/search.html#chaining , the server SHOULD reject these queries,
|
||||
// but does not. From the docs:
|
||||
|
||||
// Advanced Search Note: Where a chained parameter searches a resource reference that may
|
||||
// have more than one type of resource as its target, the parameter chain may end up referring to
|
||||
// search parameters with the same name on more than one kind of resource at once. Servers SHOULD reject
|
||||
// a search where the logical id refers to more than one matching resource across different types.
|
||||
// For example, the client has to specify the type explicitly using the syntax in the second example above.
|
||||
// @jagnew your thoughts?
|
||||
//TODO LOG PERF TRACE ISSUE ON AMBIGUOUS REFERENCE TARGETS
|
||||
RuntimeSearchParam param = null;
|
||||
if (!isMeta) {
|
||||
param = mySearchParamRegistry.getSearchParamByName(typeDef, chain);
|
||||
|
@ -418,7 +408,6 @@ class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
myQueryRoot.addPredicate(myCriteriaBuilder.equal(myQueryRoot.get("myResourceType"), theSubResourceName));
|
||||
myQueryRoot.addPredicate(myCriteriaBuilder.isNull(myQueryRoot.get("myDeleted")));
|
||||
|
||||
//How is it possible for us to do a chain query if we _havent_ found a chain match? @jagnew
|
||||
if (theFoundChainMatch) {
|
||||
searchForIdsWithAndOr(theSubResourceName, theChain, andOrParams, theRequest);
|
||||
subQ.where(myQueryRoot.getPredicateArray());
|
||||
|
@ -831,20 +820,35 @@ class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
|
||||
ArrayList<IQueryParameterType> orValues = Lists.newArrayList();
|
||||
|
||||
for (IQueryParameterOr<IQueryParameterType> next : parsedParam.getValuesAsQueryTokens()) {
|
||||
orValues.addAll(next.getValuesAsQueryTokens());
|
||||
for (IQueryParameterOr<IQueryParameterType> next : parsedParam.getValuesAsQueryTokens()) {
|
||||
orValues.addAll(next.getValuesAsQueryTokens());
|
||||
}
|
||||
|
||||
//Handle internal chain inside the has.
|
||||
if (parameterName.contains(".")) {
|
||||
String chainedPartOfParameter = getChainedPart(parameterName);
|
||||
orValues.stream()
|
||||
.filter(qp -> qp instanceof ReferenceParam)
|
||||
.map(qp -> (ReferenceParam)qp)
|
||||
.forEach(rp -> rp.setChain(getChainedPart(chainedPartOfParameter)));
|
||||
}
|
||||
|
||||
Subquery<Long> subQ = myPredicateBuilder.createLinkSubquery(parameterName, targetResourceType, orValues, theRequest);
|
||||
|
||||
Subquery<Long> subQ = myPredicateBuilder.createLinkSubquery(paramName, targetResourceType, orValues, theRequest);
|
||||
Join<ResourceTable, ResourceLink> join = myQueryRoot.join("myResourceLinksAsTarget", JoinType.LEFT);
|
||||
//Predicate predicate = addPredicateReferenceWithChain("Device", paramName, orValues, join, Collections.emptyList(), refere, theRequest);
|
||||
|
||||
Predicate pathPredicate = myPredicateBuilder.createResourceLinkPathPredicate(targetResourceType, paramReference, join);
|
||||
Predicate sourceTypePredicate = myCriteriaBuilder.equal(join.get("myTargetResourceType"), theResourceType);
|
||||
Predicate sourcePidPredicate = join.get("mySourceResourcePid").in(subQ);
|
||||
Predicate andPredicate = myCriteriaBuilder.and(pathPredicate, sourcePidPredicate, sourceTypePredicate);
|
||||
//Predicate andPredicate = myCriteriaBuilder.and(pathPredicate, predicate, sourceTypePredicate);
|
||||
myQueryRoot.addPredicate(andPredicate);
|
||||
}
|
||||
}
|
||||
private String getChainedPart(String parameter) {
|
||||
//replace with indexof(.) stuff.
|
||||
return parameter.replaceAll("^.+?\\.(.+)$", "$1");
|
||||
}
|
||||
|
||||
private void addPredicateComposite(String theResourceName, RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd) {
|
||||
// TODO: fail if missing is set for a composite query
|
||||
|
|
|
@ -48,6 +48,7 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
@ -350,6 +351,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
@Test
|
||||
public void testHasParameterChained() {
|
||||
IIdType pid0;
|
||||
IIdType oid0;
|
||||
{
|
||||
Device device = new Device();
|
||||
device.addIdentifier().setSystem("urn:system").setValue("DEVICEID");
|
||||
|
@ -364,35 +366,16 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
obs.setDevice(new Reference(devId));
|
||||
obs.setSubject(new Reference(pid0));
|
||||
obs.setCode(new CodeableConcept(new Coding("sys", "val", "disp")));
|
||||
myObservationDao.create(obs, mySrd).getId();
|
||||
oid0 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
SearchParameterMap standardStringQuery = new SearchParameterMap();
|
||||
SearchParameterMap hasWithChainParamQuery = new SearchParameterMap();
|
||||
|
||||
standardStringQuery.setLoadSynchronous(true);
|
||||
//params.add("_has", new HasParam("Observation", "subject", "device.identifier", "urn:system|DEVICEID"));
|
||||
standardStringQuery.add("gender", new TokenParam("male"));
|
||||
//This is the tested query:
|
||||
hasWithChainParamQuery.setLoadSynchronous(true);
|
||||
hasWithChainParamQuery.add("_has", new HasParam("Observation", "subject", "device.identifier", "urn:system|DEVICEID"));
|
||||
// Patient?_has:Observation:subject:device.identifier=urn:system|DEVICEID
|
||||
//assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(standardStringQuery)), contains(pid0.getValue()));
|
||||
|
||||
SearchParameterMap chainQuery = new SearchParameterMap();
|
||||
chainQuery.setLoadSynchronous(true);
|
||||
chainQuery.add(Observation.SP_DEVICE, new ReferenceParam("device", "urn:system|FOO").setChain("identifier"));
|
||||
myCaptureQueriesListener.clear();
|
||||
IBundleProvider chainSearch = myObservationDao.search(chainQuery);
|
||||
List<SqlQuery> selectqueriesForCurrentThread = myCaptureQueriesListener.getSelectQueriesForCurrentThread();
|
||||
assertThat(chainQuery.size(), is(equalTo(1)));
|
||||
|
||||
SearchParameterMap hasQuery = new SearchParameterMap();
|
||||
hasQuery.setLoadSynchronous(true);
|
||||
hasQuery.add("_has", new HasParam("Observation", "subject", "code", "sys|val"));
|
||||
//hasQuery.add(Observation.SP_DEVICE, new ReferenceParam("device", "urn:system|FOO").setChain("identifier"));
|
||||
myCaptureQueriesListener.clear();
|
||||
IBundleProvider hasSearch = myPatientDao.search(hasQuery);
|
||||
selectqueriesForCurrentThread = myCaptureQueriesListener.getSelectQueriesForCurrentThread();
|
||||
assertThat(hasQuery.size(), is(equalTo(1)));
|
||||
|
||||
assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(hasWithChainParamQuery)), contains(pid0.getValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue