JPA server can't use OR list on _tag:not (#1362)

* Add a failing test for :not tags

* Add changelog and fix issue
This commit is contained in:
James Agnew 2019-06-26 08:44:56 -04:00 committed by GitHub
parent c14f5c1520
commit ce0c84db03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 12 deletions

View File

@ -834,8 +834,8 @@ public class SearchBuilder implements ISearchBuilder {
subQ.where(subQfrom.get("myTagId").as(Long.class).in(defJoin)); subQ.where(subQfrom.get("myTagId").as(Long.class).in(defJoin));
List<Predicate> orPredicates = createPredicateTagList(defJoinFrom, myBuilder, tagType, tokens); Predicate tagListPredicate = createPredicateTagList(defJoinFrom, myBuilder, tagType, tokens);
defJoin.where(toArray(orPredicates)); defJoin.where(tagListPredicate);
continue; continue;
} }
@ -843,8 +843,8 @@ public class SearchBuilder implements ISearchBuilder {
Join<ResourceTable, ResourceTag> tagJoin = myResourceTableRoot.join("myTags", JoinType.LEFT); Join<ResourceTable, ResourceTag> tagJoin = myResourceTableRoot.join("myTags", JoinType.LEFT);
From<ResourceTag, TagDefinition> defJoin = tagJoin.join("myTag"); From<ResourceTag, TagDefinition> defJoin = tagJoin.join("myTag");
List<Predicate> orPredicates = createPredicateTagList(defJoin, myBuilder, tagType, tokens); Predicate tagListPredicate = createPredicateTagList(defJoin, myBuilder, tagType, tokens);
myPredicates.add(myBuilder.or(toArray(orPredicates))); myPredicates.add(tagListPredicate);
} }
@ -1334,20 +1334,21 @@ public class SearchBuilder implements ISearchBuilder {
} }
} }
private List<Predicate> createPredicateTagList(Path<TagDefinition> theDefJoin, CriteriaBuilder theBuilder, TagTypeEnum theTagType, List<Pair<String, String>> theTokens) { private Predicate createPredicateTagList(Path<TagDefinition> theDefJoin, CriteriaBuilder theBuilder, TagTypeEnum theTagType, List<Pair<String, String>> theTokens) {
Predicate typePrediate = theBuilder.equal(theDefJoin.get("myTagType"), theTagType); Predicate typePredicate = theBuilder.equal(theDefJoin.get("myTagType"), theTagType);
List<Predicate> orPredicates = Lists.newArrayList(); List<Predicate> orPredicates = Lists.newArrayList();
for (Pair<String, String> next : theTokens) { for (Pair<String, String> next : theTokens) {
Predicate codePrediate = theBuilder.equal(theDefJoin.get("myCode"), next.getRight()); Predicate codePredicate = theBuilder.equal(theDefJoin.get("myCode"), next.getRight());
if (isNotBlank(next.getLeft())) { if (isNotBlank(next.getLeft())) {
Predicate systemPrediate = theBuilder.equal(theDefJoin.get("mySystem"), next.getLeft()); Predicate systemPredicate = theBuilder.equal(theDefJoin.get("mySystem"), next.getLeft());
orPredicates.add(theBuilder.and(typePrediate, systemPrediate, codePrediate)); orPredicates.add(theBuilder.and(typePredicate, systemPredicate, codePredicate));
} else { } else {
orPredicates.add(theBuilder.and(typePrediate, codePrediate)); orPredicates.add(theBuilder.and(typePredicate, codePredicate));
} }
} }
return orPredicates;
return theBuilder.or(toArray(orPredicates));
} }
private List<Predicate> createPredicateToken(Collection<IQueryParameterType> theParameters, String theResourceName, String theParamName, CriteriaBuilder theBuilder, private List<Predicate> createPredicateToken(Collection<IQueryParameterType> theParameters, String theResourceName, String theParamName, CriteriaBuilder theBuilder,

View File

@ -158,11 +158,20 @@ public class CircularQueueCaptureQueriesListener extends BaseCaptureQueriesListe
/** /**
* Log all captured SELECT queries * Log all captured SELECT queries
*/ */
public void logSelectQueriesForCurrentThread() { public void logSelectQueriesForCurrentThread(int... theIndexes) {
List<String> queries = getSelectQueriesForCurrentThread() List<String> queries = getSelectQueriesForCurrentThread()
.stream() .stream()
.map(CircularQueueCaptureQueriesListener::formatQueryAsSql) .map(CircularQueueCaptureQueriesListener::formatQueryAsSql)
.collect(Collectors.toList()); .collect(Collectors.toList());
if (theIndexes != null && theIndexes.length > 0) {
List<String> newList = new ArrayList<>();
for (int i = 0; i < theIndexes.length; i++) {
newList.add(queries.get(theIndexes[i]));
}
queries = newList;
}
ourLog.info("Select Queries:\n{}", String.join("\n", queries)); ourLog.info("Select Queries:\n{}", String.join("\n", queries));
} }

View File

@ -1839,6 +1839,52 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
} }
} }
@Test
public void testSearchNotTag() {
Patient p0 = new Patient();
p0.getMeta().addTag("http://system", "tag0", "Tag 0");
p0.setActive(true);
String p0id = myPatientDao.create(p0).getId().toUnqualifiedVersionless().getValue();
Patient p1 = new Patient();
p1.getMeta().addTag("http://system", "tag1", "Tag 1");
p1.setActive(true);
String p1id = myPatientDao.create(p1).getId().toUnqualifiedVersionless().getValue();
Patient p2 = new Patient();
p2.getMeta().addTag("http://system", "tag2", "Tag 2");
p2.setActive(true);
String p2id = myPatientDao.create(p2).getId().toUnqualifiedVersionless().getValue();
{
String criteria = "_tag:not=http://system|tag0";
SearchParameterMap map = myMatchUrlService.translateMatchUrl(criteria, myFhirCtx.getResourceDefinition(Patient.class));
map.setLoadSynchronous(true);
myCaptureQueriesListener.clear();
IBundleProvider results = myPatientDao.search(map);
List<String> ids = toUnqualifiedVersionlessIdValues(results);
myCaptureQueriesListener.logSelectQueriesForCurrentThread(0);
assertThat(ids, containsInAnyOrder(p1id, p2id));
}
{
String criteria = "_tag:not=http://system|tag0,http://system|tag1";
SearchParameterMap map = myMatchUrlService.translateMatchUrl(criteria, myFhirCtx.getResourceDefinition(Patient.class));
map.setLoadSynchronous(true);
myCaptureQueriesListener.clear();
IBundleProvider results = myPatientDao.search(map);
List<String> ids = toUnqualifiedVersionlessIdValues(results);
myCaptureQueriesListener.logSelectQueriesForCurrentThread(0);
assertThat(ids, containsInAnyOrder(p2id));
}
}
@Test @Test
public void testSearchNumberParam() { public void testSearchNumberParam() {
RiskAssessment e1 = new RiskAssessment(); RiskAssessment e1 = new RiskAssessment();

View File

@ -141,6 +141,11 @@
Fix a build failure thanks to Maven pom errors. Thanks to Gary Teichrow for Fix a build failure thanks to Maven pom errors. Thanks to Gary Teichrow for
the pull request! the pull request!
</action> </action>
<action type="fix" issue="1362">
The JPA server did not correctly process searches with a
<![CDATA[<code>_tag:not</code>]]>
expression containing more than one comma separated value.
</action>
</release> </release>
<release version="3.8.0" date="2019-05-30" description="Hippo"> <release version="3.8.0" date="2019-05-30" description="Hippo">
<action type="fix"> <action type="fix">