Fix #198 - Sorting should only sort on the individual parameter searched on, not all params of the same type

This commit is contained in:
jamesagnew 2015-07-18 15:29:24 -04:00
parent 57ee1fe220
commit 626f4677e7
6 changed files with 99 additions and 14 deletions

View File

@ -283,7 +283,7 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
BaseServerResponseException bsre = (BaseServerResponseException)theException; BaseServerResponseException bsre = (BaseServerResponseException)theException;
if (bsre.getOperationOutcome() == null) { if (bsre.getOperationOutcome() == null) {
return super.handleException(theRequestDetails, theException, theServletRequest, theServletResponse);
} }
streamResponse(theRequestDetails, theServletRequest, theServletResponse, bsre.getOperationOutcome()); streamResponse(theRequestDetails, theServletRequest, theServletResponse, bsre.getOperationOutcome());

View File

@ -1050,7 +1050,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
return type; return type;
} }
private void createSort(CriteriaBuilder theBuilder, Root<ResourceTable> theFrom, SortSpec theSort, List<Order> theOrders) { private void createSort(CriteriaBuilder theBuilder, Root<ResourceTable> theFrom, SortSpec theSort, List<Order> theOrders, List<Predicate> thePredicates) {
if (theSort == null || isBlank(theSort.getParamName())) { if (theSort == null || isBlank(theSort.getParamName())) {
return; return;
} }
@ -1065,7 +1065,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
theOrders.add(theBuilder.desc(theFrom.get("myId"))); theOrders.add(theBuilder.desc(theFrom.get("myId")));
} }
createSort(theBuilder, theFrom, theSort.getChain(), theOrders); createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
return; return;
} }
@ -1096,6 +1096,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
} }
From<?, ?> stringJoin = theFrom.join(joinAttrName, JoinType.INNER); From<?, ?> stringJoin = theFrom.join(joinAttrName, JoinType.INNER);
thePredicates.add(theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName()));
// Predicate p = theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName()); // Predicate p = theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName());
// Predicate pn = theBuilder.isNull(stringJoin.get("myParamName")); // Predicate pn = theBuilder.isNull(stringJoin.get("myParamName"));
// thePredicates.add(theBuilder.or(p, pn)); // thePredicates.add(theBuilder.or(p, pn));
@ -1106,7 +1108,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
theOrders.add(theBuilder.desc(stringJoin.get(sortAttrName))); theOrders.add(theBuilder.desc(stringJoin.get(sortAttrName)));
} }
createSort(theBuilder, theFrom, theSort.getChain(), theOrders); createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
} }
@Override @Override
@ -1715,7 +1717,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
CriteriaQuery<Tuple> cq = builder.createTupleQuery(); CriteriaQuery<Tuple> cq = builder.createTupleQuery();
Root<ResourceTable> from = cq.from(ResourceTable.class); Root<ResourceTable> from = cq.from(ResourceTable.class);
predicates.add(from.get("myId").in(loadPids)); predicates.add(from.get("myId").in(loadPids));
createSort(builder, from, theParams.getSort(), orders); createSort(builder, from, theParams.getSort(), orders, predicates);
if (orders.size() > 0) { if (orders.size() > 0) {
Set<Long> originalPids = loadPids; Set<Long> originalPids = loadPids;
loadPids = new LinkedHashSet<Long>(); loadPids = new LinkedHashSet<Long>();

View File

@ -2374,47 +2374,121 @@ public class FhirResourceDaoDstu2Test extends BaseJpaTest {
assertThat(actual.subList(2, 4), containsInAnyOrder(id1, id3)); assertThat(actual.subList(2, 4), containsInAnyOrder(id1, id3));
} }
/**
* See #198
*/
@Test @Test
public void testSortByString() { public void testSortByString02() {
Patient p;
String string = "testSortByString02";
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(string);
p.addName().addFamily("Fam1").addGiven("Giv1");
ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(string);
p.addName().addFamily("Fam2").addGiven("Giv1");
ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(string);
p.addName().addFamily("Fam2").addGiven("Giv2");
ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(string);
p.addName().addFamily("Fam1").addGiven("Giv2");
ourPatientDao.create(p).getId().toUnqualifiedVersionless();
SearchParameterMap pm;
List<String> names;
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", string));
pm.setSort(new SortSpec(Patient.SP_FAMILY));
names = extractNames(ourPatientDao.search(pm));
ourLog.info("Names: {}", names);
assertThat(names.subList(0, 2), containsInAnyOrder("Giv1 Fam1", "Giv2 Fam1"));
assertThat(names.subList(2, 4), containsInAnyOrder("Giv1 Fam2", "Giv2 Fam2"));
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", string));
pm.setSort(new SortSpec(Patient.SP_FAMILY).setChain(new SortSpec(Patient.SP_GIVEN)));
names = extractNames(ourPatientDao.search(pm));
ourLog.info("Names: {}", names);
assertThat(names.subList(0, 2), contains("Giv1 Fam1", "Giv2 Fam1"));
assertThat(names.subList(2, 4), contains("Giv1 Fam2", "Giv2 Fam2"));
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", string));
pm.setSort(new SortSpec(Patient.SP_FAMILY).setChain(new SortSpec(Patient.SP_GIVEN, SortOrderEnum.DESC)));
names = extractNames(ourPatientDao.search(pm));
ourLog.info("Names: {}", names);
assertThat(names.subList(0, 2), contains("Giv2 Fam1", "Giv1 Fam1"));
assertThat(names.subList(2, 4), contains("Giv2 Fam2", "Giv1 Fam2"));
pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", string));
pm.setSort(new SortSpec(Patient.SP_FAMILY, SortOrderEnum.DESC).setChain(new SortSpec(Patient.SP_GIVEN, SortOrderEnum.DESC)));
names = extractNames(ourPatientDao.search(pm));
ourLog.info("Names: {}", names);
assertThat(names.subList(0, 2), contains("Giv2 Fam2", "Giv1 Fam2"));
assertThat(names.subList(2, 4), contains("Giv2 Fam1", "Giv1 Fam1"));
}
private List<String> extractNames(IBundleProvider theSearch) {
ArrayList<String> retVal = new ArrayList<String>();
for (IBaseResource next : theSearch.getResources(0, theSearch.size())) {
Patient nextPt = (Patient)next;
retVal.add(nextPt.getNameFirstRep().getNameAsSingleString());
}
return retVal;
}
@Test
public void testSortByString01() {
Patient p = new Patient(); Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString"); String string = "testSortByString01";
p.addIdentifier().setSystem("urn:system").setValue(string);
p.addName().addFamily("testSortF1").addGiven("testSortG1"); p.addName().addFamily("testSortF1").addGiven("testSortG1");
IIdType id1 = ourPatientDao.create(p).getId().toUnqualifiedVersionless(); IIdType id1 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
// Create out of order // Create out of order
p = new Patient(); p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString"); p.addIdentifier().setSystem("urn:system").setValue(string);
p.addName().addFamily("testSortF3").addGiven("testSortG3"); p.addName().addFamily("testSortF3").addGiven("testSortG3");
IIdType id3 = ourPatientDao.create(p).getId().toUnqualifiedVersionless(); IIdType id3 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient(); p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString"); p.addIdentifier().setSystem("urn:system").setValue(string);
p.addName().addFamily("testSortF2").addGiven("testSortG2"); p.addName().addFamily("testSortF2").addGiven("testSortG2");
IIdType id2 = ourPatientDao.create(p).getId().toUnqualifiedVersionless(); IIdType id2 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
p = new Patient(); p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testSortByString"); p.addIdentifier().setSystem("urn:system").setValue(string);
IIdType id4 = ourPatientDao.create(p).getId().toUnqualifiedVersionless(); IIdType id4 = ourPatientDao.create(p).getId().toUnqualifiedVersionless();
SearchParameterMap pm; SearchParameterMap pm;
List<IIdType> actual; List<IIdType> actual;
pm = new SearchParameterMap(); pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testSortByString")); pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", string));
pm.setSort(new SortSpec(Patient.SP_FAMILY)); pm.setSort(new SortSpec(Patient.SP_FAMILY));
actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm)); actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(4, actual.size()); assertEquals(4, actual.size());
assertThat(actual, contains(id1, id2, id3, id4)); assertThat(actual, contains(id1, id2, id3, id4));
pm = new SearchParameterMap(); pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testSortByString")); pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", string));
pm.setSort(new SortSpec(Patient.SP_FAMILY).setOrder(SortOrderEnum.ASC)); pm.setSort(new SortSpec(Patient.SP_FAMILY).setOrder(SortOrderEnum.ASC));
actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm)); actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(4, actual.size()); assertEquals(4, actual.size());
assertThat(actual, contains(id1, id2, id3, id4)); assertThat(actual, contains(id1, id2, id3, id4));
pm = new SearchParameterMap(); pm = new SearchParameterMap();
pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", "testSortByString")); pm.add(Patient.SP_IDENTIFIER, new TokenParam("urn:system", string));
pm.setSort(new SortSpec(Patient.SP_FAMILY).setOrder(SortOrderEnum.DESC)); pm.setSort(new SortSpec(Patient.SP_FAMILY).setOrder(SortOrderEnum.DESC));
actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm)); actual = toUnqualifiedVersionlessIds(ourPatientDao.search(pm));
assertEquals(4, actual.size()); assertEquals(4, actual.size());

View File

@ -18,7 +18,7 @@
<appender-ref ref="STDOUT" /> <appender-ref ref="STDOUT" />
</logger> </logger>
<logger name="org.hibernate.SQL" additivity="false" level="info"> <logger name="org.hibernate.SQL" additivity="false" level="trace">
<appender-ref ref="STDOUT" /> <appender-ref ref="STDOUT" />
</logger> </logger>

View File

@ -30,6 +30,11 @@
<artifactId>hapi-fhir-structures-dstu2</artifactId> <artifactId>hapi-fhir-structures-dstu2</artifactId>
<version>1.2-SNAPSHOT</version> <version>1.2-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId> <artifactId>hapi-fhir-testpage-overlay</artifactId>

View File

@ -28,6 +28,10 @@
count extensions exported in the Conformance statement by the JPA count extensions exported in the Conformance statement by the JPA
server. server.
</action> </action>
<action type="fix" issue="198">
JPA server sorting often returned unexpected orders when multiple
indexes of the same type were found on the same resource (e.g. multiple string indexed fields). Thanks to Travis Cummings for reporting!
</action>
</release> </release>
<release version="1.1" date="2015-07-13"> <release version="1.1" date="2015-07-13">
<action type="add"> <action type="add">