Add tests for #877

This commit is contained in:
James Agnew 2018-03-26 10:04:49 -04:00
parent ca3e7fe38f
commit 55fc20b87e
3 changed files with 146 additions and 76 deletions

View File

@ -17,9 +17,9 @@ import java.util.*;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -60,6 +60,9 @@ public class DaoConfig {
* update setter javadoc if default changes
*/
private boolean myAllowExternalReferences = false;
/**
* update setter javadoc if default changes
*/
private boolean myAllowContainsSearches = true;
/**
@ -137,6 +140,7 @@ public class DaoConfig {
myTreatReferencesAsLogical.add(theTreatReferencesAsLogical);
}
/**
* Specifies the highest number that a client is permitted to use in a
* <code>Cache-Control: nostore, max-results=NNN</code>
@ -376,9 +380,9 @@ public class DaoConfig {
* of higher importance than raw write performance
* </p>
* <p>
* Note that this setting also has an impact on sorting (i.e. using the
* <code>_sort</code> parameter on searches): If the server is configured
* to not index missing field.
* Note that this setting also has an impact on sorting (i.e. using the
* <code>_sort</code> parameter on searches): If the server is configured
* to not index missing field.
* </p>
*/
public void setIndexMissingFields(IndexEnabledEnum theIndexMissingFields) {
@ -650,6 +654,26 @@ public class DaoConfig {
return this;
}
/**
* If enabled, the server will support the use of :contains searches,
* which are helpful but can have adverse effects on performance.
*
* Default is <code>true</code>
*/
public boolean isAllowContainsSearches() {
return myAllowContainsSearches;
}
/**
* If enabled, the server will support the use of :contains searches,
* which are helpful but can have adverse effects on performance.
*
* Default is <code>true</code>
*/
public void setAllowContainsSearches(boolean theAllowContainsSearches) {
this.myAllowContainsSearches = theAllowContainsSearches;
}
/**
* If set to <code>true</code> (default is <code>false</code>) the server will allow
* resources to have references to external servers. For example if this server is
@ -1099,16 +1123,6 @@ public class DaoConfig {
}
public boolean allowContainsSearches() {
return myAllowContainsSearches;
}
public void setAllowContainsSearches(boolean myAllowContainsSearches) {
this.myAllowContainsSearches = myAllowContainsSearches;
}
public enum IndexEnabledEnum {
ENABLED,
DISABLED

View File

@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -28,8 +28,6 @@ import ca.uhn.fhir.jpa.search.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.term.VersionIndependentConcept;
import ca.uhn.fhir.jpa.util.BaseIterator;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
@ -45,7 +43,9 @@ import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.UrlUtil;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
@ -1091,10 +1091,10 @@ public class SearchBuilder implements ISearchBuilder {
} else if (theParameter instanceof StringParam) {
StringParam id = (StringParam) theParameter;
rawSearchTerm = id.getValue();
if ((id.isContains()) &&
(!myCallingDao.getConfig().allowContainsSearches()))
{
throw new MethodNotAllowedException(":contains modifier is disabled on this server");
if (id.isContains()) {
if (!myCallingDao.getConfig().isAllowContainsSearches()) {
throw new MethodNotAllowedException(":contains modifier is disabled on this server");
}
}
} else if (theParameter instanceof IPrimitiveDatatype<?>) {
IPrimitiveDatatype<?> id = (IPrimitiveDatatype<?>) theParameter;
@ -1109,18 +1109,11 @@ public class SearchBuilder implements ISearchBuilder {
}
String likeExpression = BaseHapiFhirDao.normalizeString(rawSearchTerm);
if (myCallingDao.getConfig().allowContainsSearches()) {
if (theParameter instanceof StringParam) {
if (((StringParam) theParameter).isContains()) {
likeExpression = createLeftAndRightMatchLikeExpression(likeExpression);
} else {
likeExpression = createLeftMatchLikeExpression(likeExpression);
}
} else {
likeExpression = createLeftMatchLikeExpression(likeExpression);
}
}
else {
if (theParameter instanceof StringParam &&
((StringParam) theParameter).isContains() &&
myCallingDao.getConfig().isAllowContainsSearches()) {
likeExpression = createLeftAndRightMatchLikeExpression(likeExpression);
} else {
likeExpression = createLeftMatchLikeExpression(likeExpression);
}
@ -2020,14 +2013,14 @@ public class SearchBuilder implements ISearchBuilder {
return lastUpdatedPredicates;
}
private static String createLeftMatchLikeExpression(String likeExpression) {
return likeExpression.replace("%", "[%]") + "%";
}
private static String createLeftAndRightMatchLikeExpression(String likeExpression) {
return "%" + likeExpression.replace("%", "[%]") + "%";
}
private static String createLeftMatchLikeExpression(String likeExpression) {
return likeExpression.replace("%", "[%]") + "%";
}
private static Predicate createResourceLinkPathPredicate(IDao theCallingDao, FhirContext theContext, String theParamName, From<?, ? extends ResourceLink> theFrom,
String theResourceType) {
RuntimeResourceDefinition resourceDef = theContext.getResourceDefinition(theResourceType);

View File

@ -11,6 +11,7 @@ import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
@ -54,6 +55,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
public void afterResetSearchSize() {
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
myDaoConfig.setFetchSizeDefaultMaximum(new DaoConfig().getFetchSizeDefaultMaximum());
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
}
@Before
@ -1404,43 +1406,6 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
}
}
/**
* See #819
*/
@Test
public void testSearchTokenWithNotModifier() {
String male, female;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
patient.setGender(AdministrativeGender.MALE);
male = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("002");
patient.addName().setFamily("Tester").addGiven("Jane");
patient.setGender(AdministrativeGender.FEMALE);
female = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue();
}
List<String> patients;
SearchParameterMap params;
params = new SearchParameterMap();
params.add(Patient.SP_GENDER, new TokenParam(null, "male"));
params.setLoadSynchronous(true);
patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params));
assertThat(patients, contains(male));
params = new SearchParameterMap();
params.add(Patient.SP_GENDER, new TokenParam(null, "male").setModifier(TokenParamModifier.NOT));
params.setLoadSynchronous(true);
patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params));
assertThat(patients, contains(female));
}
@Test
public void testSearchNumberParam() {
ImmunizationRecommendation e1 = new ImmunizationRecommendation();
@ -2122,6 +2087,43 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
}
}
/**
* See #819
*/
@Test
public void testSearchTokenWithNotModifier() {
String male, female;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
patient.setGender(AdministrativeGender.MALE);
male = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue();
}
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("002");
patient.addName().setFamily("Tester").addGiven("Jane");
patient.setGender(AdministrativeGender.FEMALE);
female = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless().getValue();
}
List<String> patients;
SearchParameterMap params;
params = new SearchParameterMap();
params.add(Patient.SP_GENDER, new TokenParam(null, "male"));
params.setLoadSynchronous(true);
patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params));
assertThat(patients, contains(male));
params = new SearchParameterMap();
params.add(Patient.SP_GENDER, new TokenParam(null, "male").setModifier(TokenParamModifier.NOT));
params.setLoadSynchronous(true);
patients = toUnqualifiedVersionlessIdValues(myPatientDao.search(params));
assertThat(patients, contains(female));
}
@Test
public void testSearchTokenWrongParam() {
Patient p1 = new Patient();
@ -2257,6 +2259,67 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
}
@Test
public void testSearchWithContains() {
Patient pt1 = new Patient();
pt1.addName().setFamily("ABCDEFGHIJK");
String pt1id = myPatientDao.create(pt1).getId().toUnqualifiedVersionless().getValue();
Patient pt2 = new Patient();
pt2.addName().setFamily("FGHIJK");
String pt2id = myPatientDao.create(pt2).getId().toUnqualifiedVersionless().getValue();
Patient pt3 = new Patient();
pt3.addName().setFamily("ZZZZZ");
myPatientDao.create(pt3).getId().toUnqualifiedVersionless().getValue();
List<String> ids;
SearchParameterMap map;
IBundleProvider results;
// Contains = true
map = new SearchParameterMap();
map.add(Patient.SP_NAME, new StringParam("FGHIJK").setContains(true));
map.setLoadSynchronous(true);
results = myPatientDao.search(map);
ids = toUnqualifiedVersionlessIdValues(results);
assertThat(ids, containsInAnyOrder(pt1id, pt2id));
// Contains = false
map = new SearchParameterMap();
map.add(Patient.SP_NAME, new StringParam("FGHIJK").setContains(false));
map.setLoadSynchronous(true);
results = myPatientDao.search(map);
ids = toUnqualifiedVersionlessIdValues(results);
assertThat(ids, containsInAnyOrder(pt2id));
// No contains
map = new SearchParameterMap();
map.add(Patient.SP_NAME, new StringParam("FGHIJK"));
map.setLoadSynchronous(true);
results = myPatientDao.search(map);
ids = toUnqualifiedVersionlessIdValues(results);
assertThat(ids, containsInAnyOrder(pt2id));
}
@Test
public void testSearchWithContainsDisabled() {
myDaoConfig.setAllowContainsSearches(false);
SearchParameterMap map = new SearchParameterMap();
map.setLoadSynchronous(true);
map.add(Patient.SP_NAME, new StringParam("FGHIJK").setContains(true));
try {
myPatientDao.search(map);
fail();
} catch (MethodNotAllowedException e) {
assertEquals(":contains modifier is disabled on this server", e.getMessage());
}
}
@Test
public void testSearchWithDate() {
IIdType orgId = myOrganizationDao.create(new Organization(), mySrd).getId();