testing complete. Now just need pre-review cleanup.
This commit is contained in:
parent
12dfac927e
commit
6cebb56f13
|
@ -2755,74 +2755,7 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
myParams.getEverythingMode() == null &&
|
myParams.getEverythingMode() == null &&
|
||||||
myParams.isAllParametersHaveNoModifier();
|
myParams.isAllParametersHaveNoModifier();
|
||||||
if (couldBeEligibleForCompositeUniqueSpProcessing) {
|
if (couldBeEligibleForCompositeUniqueSpProcessing) {
|
||||||
|
attemptCompositeUniqueSpProcessing(theParams, theRequest);
|
||||||
// FIXME KHS method
|
|
||||||
|
|
||||||
// Since we're going to remove elements below
|
|
||||||
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
|
|
||||||
|
|
||||||
List<JpaRuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
|
|
||||||
if (activeUniqueSearchParams.size() > 0) {
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(myResourceName);
|
|
||||||
sb.append("?");
|
|
||||||
|
|
||||||
boolean first = true;
|
|
||||||
|
|
||||||
ArrayList<String> keys = new ArrayList<>(theParams.keySet());
|
|
||||||
Collections.sort(keys);
|
|
||||||
for (String nextParamName : keys) {
|
|
||||||
List<List<IQueryParameterType>> nextValues = theParams.get(nextParamName);
|
|
||||||
|
|
||||||
nextParamName = UrlUtil.escapeUrlParam(nextParamName);
|
|
||||||
if (nextValues.get(0).size() != 1) {
|
|
||||||
sb = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reference params are only eligible for using a composite index if they
|
|
||||||
// are qualified
|
|
||||||
RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(myResourceName, nextParamName);
|
|
||||||
if (nextParamDef.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
|
|
||||||
ReferenceParam param = (ReferenceParam) nextValues.get(0).get(0);
|
|
||||||
if (isBlank(param.getResourceType())) {
|
|
||||||
sb = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<? extends IQueryParameterType> nextAnd = nextValues.remove(0);
|
|
||||||
IQueryParameterType nextOr = nextAnd.remove(0);
|
|
||||||
String nextOrValue = nextOr.getValueAsQueryToken(myContext);
|
|
||||||
nextOrValue = UrlUtil.escapeUrlParam(nextOrValue);
|
|
||||||
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
sb.append('&');
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.append(nextParamName).append('=').append(nextOrValue);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sb != null) {
|
|
||||||
String indexString = sb.toString();
|
|
||||||
ourLog.debug("Checking for unique index for query: {}", indexString);
|
|
||||||
|
|
||||||
// Interceptor broadcast: JPA_PERFTRACE_INFO
|
|
||||||
StorageProcessingMessage msg = new StorageProcessingMessage()
|
|
||||||
.setMessage("Using unique index for query for search: " + indexString);
|
|
||||||
HookParams params = new HookParams()
|
|
||||||
.add(RequestDetails.class, theRequest)
|
|
||||||
.addIfMatchesType(ServletRequestDetails.class, theRequest)
|
|
||||||
.add(StorageProcessingMessage.class, msg);
|
|
||||||
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_INFO, params);
|
|
||||||
|
|
||||||
addPredicateCompositeStringUnique(theParams, indexString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle each parameter
|
// Handle each parameter
|
||||||
|
@ -2834,6 +2767,74 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void attemptCompositeUniqueSpProcessing(@Nonnull SearchParameterMap theParams, RequestDetails theRequest) {
|
||||||
|
// Since we're going to remove elements below
|
||||||
|
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
|
||||||
|
|
||||||
|
List<JpaRuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
|
||||||
|
if (activeUniqueSearchParams.size() > 0) {
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(myResourceName);
|
||||||
|
sb.append("?");
|
||||||
|
|
||||||
|
boolean first = true;
|
||||||
|
|
||||||
|
ArrayList<String> keys = new ArrayList<>(theParams.keySet());
|
||||||
|
Collections.sort(keys);
|
||||||
|
for (String nextParamName : keys) {
|
||||||
|
List<List<IQueryParameterType>> nextValues = theParams.get(nextParamName);
|
||||||
|
|
||||||
|
nextParamName = UrlUtil.escapeUrlParam(nextParamName);
|
||||||
|
if (nextValues.get(0).size() != 1) {
|
||||||
|
sb = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference params are only eligible for using a composite index if they
|
||||||
|
// are qualified
|
||||||
|
RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(myResourceName, nextParamName);
|
||||||
|
if (nextParamDef.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
|
||||||
|
ReferenceParam param = (ReferenceParam) nextValues.get(0).get(0);
|
||||||
|
if (isBlank(param.getResourceType())) {
|
||||||
|
sb = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<? extends IQueryParameterType> nextAnd = nextValues.remove(0);
|
||||||
|
IQueryParameterType nextOr = nextAnd.remove(0);
|
||||||
|
String nextOrValue = nextOr.getValueAsQueryToken(myContext);
|
||||||
|
nextOrValue = UrlUtil.escapeUrlParam(nextOrValue);
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
sb.append('&');
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(nextParamName).append('=').append(nextOrValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb != null) {
|
||||||
|
String indexString = sb.toString();
|
||||||
|
ourLog.debug("Checking for unique index for query: {}", indexString);
|
||||||
|
|
||||||
|
// Interceptor broadcast: JPA_PERFTRACE_INFO
|
||||||
|
StorageProcessingMessage msg = new StorageProcessingMessage()
|
||||||
|
.setMessage("Using unique index for query for search: " + indexString);
|
||||||
|
HookParams params = new HookParams()
|
||||||
|
.add(RequestDetails.class, theRequest)
|
||||||
|
.addIfMatchesType(ServletRequestDetails.class, theRequest)
|
||||||
|
.add(StorageProcessingMessage.class, msg);
|
||||||
|
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_INFO, params);
|
||||||
|
|
||||||
|
addPredicateCompositeStringUnique(theParams, indexString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private <T> void ensureSubListsAreWritable(List<List<T>> theListOfLists) {
|
private <T> void ensureSubListsAreWritable(List<List<T>> theListOfLists) {
|
||||||
for (int i = 0; i < theListOfLists.size(); i++) {
|
for (int i = 0; i < theListOfLists.size(); i++) {
|
||||||
List<T> oldSubList = theListOfLists.get(i);
|
List<T> oldSubList = theListOfLists.get(i);
|
||||||
|
|
|
@ -20,8 +20,8 @@ import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -49,7 +49,7 @@ public class MatchUrlServiceTest extends BaseJpaTest {
|
||||||
SearchParameterMap match = myMatchUrlService.translateMatchUrl("Condition?patient=304&_lastUpdated=>2011-01-01T11:12:21.0000Z", resourceDef);
|
SearchParameterMap match = myMatchUrlService.translateMatchUrl("Condition?patient=304&_lastUpdated=>2011-01-01T11:12:21.0000Z", resourceDef);
|
||||||
assertEquals("2011-01-01T11:12:21.0000Z", match.getLastUpdated().getLowerBound().getValueAsString());
|
assertEquals("2011-01-01T11:12:21.0000Z", match.getLastUpdated().getLowerBound().getValueAsString());
|
||||||
assertEquals(ReferenceParam.class, match.get("patient").get(0).get(0).getClass());
|
assertEquals(ReferenceParam.class, match.get("patient").get(0).get(0).getClass());
|
||||||
assertEquals("304", ((ReferenceParam)match.get("patient").get(0).get(0)).getIdPart());
|
assertEquals("304", ((ReferenceParam) match.get("patient").get(0).get(0)).getIdPart());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -68,10 +68,42 @@ public class MatchUrlServiceTest extends BaseJpaTest {
|
||||||
assertEquals(kmDistance, nearDistanceParam.getValue().doubleValue(), 0.0);
|
assertEquals(kmDistance, nearDistanceParam.getValue().doubleValue(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoDistancesAnd() {
|
||||||
|
try {
|
||||||
|
SearchParameterMap map = myMatchUrlService.translateMatchUrl(
|
||||||
|
"Location?" +
|
||||||
|
Location.SP_NEAR_DISTANCE + "=1|http://unitsofmeasure.org|km" +
|
||||||
|
"&" +
|
||||||
|
Location.SP_NEAR_DISTANCE + "=2|http://unitsofmeasure.org|km",
|
||||||
|
ourCtx.getResourceDefinition("Location"));
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
assertEquals("Only one " + Location.SP_NEAR_DISTANCE + " parameter may be present", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoDistancesOr() {
|
||||||
|
try {
|
||||||
|
SearchParameterMap map = myMatchUrlService.translateMatchUrl(
|
||||||
|
"Location?" +
|
||||||
|
Location.SP_NEAR_DISTANCE + "=1|http://unitsofmeasure.org|km" +
|
||||||
|
"," +
|
||||||
|
"2|http://unitsofmeasure.org|km",
|
||||||
|
ourCtx.getResourceDefinition("Location"));
|
||||||
|
map.setLoadSynchronous(true);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
assertEquals("Only one " + Location.SP_NEAR_DISTANCE + " parameter may be present", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FhirContext getContext() {
|
protected FhirContext getContext() {
|
||||||
return ourCtx;
|
return ourCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PlatformTransactionManager getTxManager() {
|
protected PlatformTransactionManager getTxManager() {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -118,7 +118,6 @@ public class MatchUrlService {
|
||||||
paramMap.add(nextParamName, param);
|
paramMap.add(nextParamName, param);
|
||||||
} else if (Location.SP_NEAR_DISTANCE.equals(nextParamName)) {
|
} else if (Location.SP_NEAR_DISTANCE.equals(nextParamName)) {
|
||||||
QuantityAndListParam nearDistanceAndListParam = (QuantityAndListParam) ParameterUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.QUANTITY, nextParamName, paramList);
|
QuantityAndListParam nearDistanceAndListParam = (QuantityAndListParam) ParameterUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.QUANTITY, nextParamName, paramList);
|
||||||
// FIXME KHS
|
|
||||||
paramMap.setNearDistanceParam(nearDistanceAndListParam);
|
paramMap.setNearDistanceParam(nearDistanceAndListParam);
|
||||||
} else if (nextParamName.startsWith("_")) {
|
} else if (nextParamName.startsWith("_")) {
|
||||||
// ignore these since they aren't search params (e.g. _sort)
|
// ignore these since they aren't search params (e.g. _sort)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Location;
|
||||||
import ca.uhn.fhir.rest.api.*;
|
import ca.uhn.fhir.rest.api.*;
|
||||||
import ca.uhn.fhir.rest.param.*;
|
import ca.uhn.fhir.rest.param.*;
|
||||||
import ca.uhn.fhir.util.ObjectUtil;
|
import ca.uhn.fhir.util.ObjectUtil;
|
||||||
|
@ -499,13 +500,17 @@ public class SearchParameterMap implements Serializable {
|
||||||
if (orTokens.isEmpty()) {
|
if (orTokens.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// FIXME KHS error if size > 0
|
if (orTokens.size() > 1) {
|
||||||
|
throw new IllegalArgumentException("Only one " + Location.SP_NEAR_DISTANCE + " parameter may be present");
|
||||||
|
}
|
||||||
QuantityOrListParam quantityOrListParam = orTokens.get(0);
|
QuantityOrListParam quantityOrListParam = orTokens.get(0);
|
||||||
List<QuantityParam> tokens = quantityOrListParam.getValuesAsQueryTokens();
|
List<QuantityParam> tokens = quantityOrListParam.getValuesAsQueryTokens();
|
||||||
if (tokens.isEmpty()) {
|
if (tokens.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// FIXME KHS error if size > 0
|
if (tokens.size() > 1) {
|
||||||
|
throw new IllegalArgumentException("Only one " + Location.SP_NEAR_DISTANCE + " parameter may be present");
|
||||||
|
}
|
||||||
myNearDistanceParam = tokens.get(0);
|
myNearDistanceParam = tokens.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,7 +275,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
case "Consent.source":
|
case "Consent.source":
|
||||||
// Consent#source-identifier has a path that isn't typed - This is a one-off to deal with that
|
// Consent#source-identifier has a path that isn't typed - This is a one-off to deal with that
|
||||||
return;
|
return;
|
||||||
// FIXME KHS
|
|
||||||
case "Location.position":
|
case "Location.position":
|
||||||
addCoords_Position(resourceTypeName, params, searchParam, value);
|
addCoords_Position(resourceTypeName, params, searchParam, value);
|
||||||
return;
|
return;
|
||||||
|
@ -414,12 +413,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
public SearchParamSet<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(IBaseResource theResource) {
|
public SearchParamSet<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(IBaseResource theResource) {
|
||||||
|
|
||||||
IExtractor<ResourceIndexedSearchParamQuantity> extractor = (params, searchParam, value, path) -> {
|
IExtractor<ResourceIndexedSearchParamQuantity> extractor = (params, searchParam, value, path) -> {
|
||||||
// FIXME KHS
|
|
||||||
// if (value.getClass().equals(myLocationPositionDefinition.getImplementingClass())) {
|
|
||||||
// ourLog.warn("Position search not currently supported, not indexing location");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
String nextType = toRootTypeName(value);
|
String nextType = toRootTypeName(value);
|
||||||
String resourceType = toRootTypeName(theResource);
|
String resourceType = toRootTypeName(theResource);
|
||||||
switch (nextType) {
|
switch (nextType) {
|
||||||
|
@ -723,7 +716,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME KHS split this class up
|
|
||||||
private void addCoords_Position(String theResourceType, SearchParamSet<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
private void addCoords_Position(String theResourceType, SearchParamSet<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||||
BigDecimal latitude = null;
|
BigDecimal latitude = null;
|
||||||
BigDecimal longitude = null;
|
BigDecimal longitude = null;
|
||||||
|
|
|
@ -178,11 +178,6 @@ public class SearchParamExtractorMegaTest {
|
||||||
|
|
||||||
ISearchParamExtractor.SearchParamSet<?> set;
|
ISearchParamExtractor.SearchParamSet<?> set;
|
||||||
|
|
||||||
// FIXME KHS
|
|
||||||
// set = theExtractor.extractSearchParamCoords(resource);
|
|
||||||
// assertEquals(0, set.getWarnings().size());
|
|
||||||
// theIndexesCounter.addAndGet(set.size());
|
|
||||||
|
|
||||||
set = theExtractor.extractSearchParamDates(resource);
|
set = theExtractor.extractSearchParamDates(resource);
|
||||||
assertEquals(0, set.getWarnings().size());
|
assertEquals(0, set.getWarnings().size());
|
||||||
theIndexesCounter.addAndGet(set.size());
|
theIndexesCounter.addAndGet(set.size());
|
||||||
|
|
Loading…
Reference in New Issue