diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index 1349fb48b41..1570fa9442c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -834,8 +834,8 @@ public class SearchBuilder implements ISearchBuilder { subQ.where(subQfrom.get("myTagId").as(Long.class).in(defJoin)); - List orPredicates = createPredicateTagList(defJoinFrom, myBuilder, tagType, tokens); - defJoin.where(toArray(orPredicates)); + Predicate tagListPredicate = createPredicateTagList(defJoinFrom, myBuilder, tagType, tokens); + defJoin.where(tagListPredicate); continue; } @@ -843,8 +843,8 @@ public class SearchBuilder implements ISearchBuilder { Join tagJoin = myResourceTableRoot.join("myTags", JoinType.LEFT); From defJoin = tagJoin.join("myTag"); - List orPredicates = createPredicateTagList(defJoin, myBuilder, tagType, tokens); - myPredicates.add(myBuilder.or(toArray(orPredicates))); + Predicate tagListPredicate = createPredicateTagList(defJoin, myBuilder, tagType, tokens); + myPredicates.add(tagListPredicate); } @@ -1334,20 +1334,21 @@ public class SearchBuilder implements ISearchBuilder { } } - private List createPredicateTagList(Path theDefJoin, CriteriaBuilder theBuilder, TagTypeEnum theTagType, List> theTokens) { - Predicate typePrediate = theBuilder.equal(theDefJoin.get("myTagType"), theTagType); + private Predicate createPredicateTagList(Path theDefJoin, CriteriaBuilder theBuilder, TagTypeEnum theTagType, List> theTokens) { + Predicate typePredicate = theBuilder.equal(theDefJoin.get("myTagType"), theTagType); List orPredicates = Lists.newArrayList(); for (Pair next : theTokens) { - Predicate codePrediate = theBuilder.equal(theDefJoin.get("myCode"), next.getRight()); + Predicate codePredicate = theBuilder.equal(theDefJoin.get("myCode"), next.getRight()); if (isNotBlank(next.getLeft())) { - Predicate systemPrediate = theBuilder.equal(theDefJoin.get("mySystem"), next.getLeft()); - orPredicates.add(theBuilder.and(typePrediate, systemPrediate, codePrediate)); + Predicate systemPredicate = theBuilder.equal(theDefJoin.get("mySystem"), next.getLeft()); + orPredicates.add(theBuilder.and(typePredicate, systemPredicate, codePredicate)); } else { - orPredicates.add(theBuilder.and(typePrediate, codePrediate)); + orPredicates.add(theBuilder.and(typePredicate, codePredicate)); } } - return orPredicates; + + return theBuilder.or(toArray(orPredicates)); } private List createPredicateToken(Collection theParameters, String theResourceName, String theParamName, CriteriaBuilder theBuilder, diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/CircularQueueCaptureQueriesListener.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/CircularQueueCaptureQueriesListener.java index 617f1025e97..56cfbd138d0 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/CircularQueueCaptureQueriesListener.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/CircularQueueCaptureQueriesListener.java @@ -158,11 +158,20 @@ public class CircularQueueCaptureQueriesListener extends BaseCaptureQueriesListe /** * Log all captured SELECT queries */ - public void logSelectQueriesForCurrentThread() { + public void logSelectQueriesForCurrentThread(int... theIndexes) { List queries = getSelectQueriesForCurrentThread() .stream() .map(CircularQueueCaptureQueriesListener::formatQueryAsSql) .collect(Collectors.toList()); + + if (theIndexes != null && theIndexes.length > 0) { + List 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)); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java index 49c00813568..9e6d89fb382 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java @@ -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 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 ids = toUnqualifiedVersionlessIdValues(results); + myCaptureQueriesListener.logSelectQueriesForCurrentThread(0); + + assertThat(ids, containsInAnyOrder(p2id)); + } + } + + @Test public void testSearchNumberParam() { RiskAssessment e1 = new RiskAssessment(); diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4d0a13adc92..332b1073f85 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -141,6 +141,11 @@ Fix a build failure thanks to Maven pom errors. Thanks to Gary Teichrow for the pull request! + + The JPA server did not correctly process searches with a + _tag:not]]> + expression containing more than one comma separated value. +