Add non unique combo search params (#2809)
* Start work on nonunique combo search params * Work on SQL * Version bump * A fix * Test fixes * Fixes * Undo version bump * Test fixes * Resolve fixme
This commit is contained in:
parent
6af022062f
commit
6d37749be8
|
@ -0,0 +1,28 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||
* %%
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public enum ComboSearchParamType {
|
||||
|
||||
UNIQUE,
|
||||
NON_UNIQUE
|
||||
|
||||
}
|
|
@ -416,7 +416,7 @@ class ModelScanner {
|
|||
if (theResourceDef.isStandardType()) {
|
||||
url = "http://hl7.org/fhir/SearchParameter/" + theResourceDef.getName().toLowerCase() + "-" + searchParam.name();
|
||||
}
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(null, url, searchParam.name(), searchParam.description(), searchParam.path(), paramType, providesMembershipInCompartments, toTargetList(searchParam.target()), RuntimeSearchParamStatusEnum.ACTIVE, false, components, base);
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(null, url, searchParam.name(), searchParam.description(), searchParam.path(), paramType, providesMembershipInCompartments, toTargetList(searchParam.target()), RuntimeSearchParamStatusEnum.ACTIVE, null, components, base);
|
||||
theResourceDef.addSearchParam(param);
|
||||
nameToParam.put(param.getName(), param);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hl7.fhir.instance.model.api.IBaseExtension;
|
|||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -55,7 +56,7 @@ public class RuntimeSearchParam {
|
|||
private final RuntimeSearchParamStatusEnum myStatus;
|
||||
private final String myUri;
|
||||
private final Map<String, List<IBaseExtension<?, ?>>> myExtensions = new HashMap<>();
|
||||
private final boolean myUnique;
|
||||
private final ComboSearchParamType myComboSearchParamType;
|
||||
private final List<Component> myComponents;
|
||||
private IPhoneticEncoder myPhoneticEncoder;
|
||||
|
||||
|
@ -64,20 +65,20 @@ public class RuntimeSearchParam {
|
|||
*/
|
||||
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType,
|
||||
Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, Collection<String> theBase) {
|
||||
this(theId, theUri, theName, theDescription, thePath, theParamType, theProvidesMembershipInCompartments, theTargets, theStatus, false, Collections.emptyList(), theBase);
|
||||
this(theId, theUri, theName, theDescription, thePath, theParamType, theProvidesMembershipInCompartments, theTargets, theStatus, null, Collections.emptyList(), theBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
public RuntimeSearchParam(RuntimeSearchParam theSp) {
|
||||
this(theSp.getId(), theSp.getUri(), theSp.getName(), theSp.getDescription(), theSp.getPath(), theSp.getParamType(), theSp.getProvidesMembershipInCompartments(), theSp.getTargets(), theSp.getStatus(), theSp.isUnique(), theSp.getComponents(), theSp.getBase());
|
||||
this(theSp.getId(), theSp.getUri(), theSp.getName(), theSp.getDescription(), theSp.getPath(), theSp.getParamType(), theSp.getProvidesMembershipInCompartments(), theSp.getTargets(), theSp.getStatus(), theSp.getComboSearchParamType(), theSp.getComponents(), theSp.getBase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, boolean theUnique, List<Component> theComponents, Collection<String> theBase) {
|
||||
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, ComboSearchParamType theComboSearchParamType, List<Component> theComponents, Collection<String> theBase) {
|
||||
super();
|
||||
|
||||
myId = theId;
|
||||
|
@ -110,7 +111,7 @@ public class RuntimeSearchParam {
|
|||
} else {
|
||||
myBase = Collections.unmodifiableSet(new HashSet<>(theBase));
|
||||
}
|
||||
myUnique = theUnique;
|
||||
myComboSearchParamType = theComboSearchParamType;
|
||||
if (theComponents != null) {
|
||||
myComponents = Collections.unmodifiableList(theComponents);
|
||||
} else {
|
||||
|
@ -122,8 +123,12 @@ public class RuntimeSearchParam {
|
|||
return myComponents;
|
||||
}
|
||||
|
||||
public boolean isUnique() {
|
||||
return myUnique;
|
||||
/**
|
||||
* Returns <code>null</code> if this is not a combo search param type
|
||||
*/
|
||||
@Nullable
|
||||
public ComboSearchParamType getComboSearchParamType() {
|
||||
return myComboSearchParamType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -94,7 +94,8 @@ import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
|||
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
|
||||
import ca.uhn.fhir.jpa.search.builder.QueryStack;
|
||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboNonUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ForcedIdPredicateBuilder;
|
||||
|
@ -609,8 +610,14 @@ public abstract class BaseConfig {
|
|||
|
||||
@Bean
|
||||
@Scope("prototype")
|
||||
public CompositeUniqueSearchParameterPredicateBuilder newCompositeUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return new CompositeUniqueSearchParameterPredicateBuilder(theSearchSqlBuilder);
|
||||
public ComboUniqueSearchParameterPredicateBuilder newComboUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return new ComboUniqueSearchParameterPredicateBuilder(theSearchSqlBuilder);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Scope("prototype")
|
||||
public ComboNonUniqueSearchParameterPredicateBuilder newComboNonUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return new ComboNonUniqueSearchParameterPredicateBuilder(theSearchSqlBuilder);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -23,7 +23,7 @@ package ca.uhn.fhir.jpa.config;
|
|||
import ca.uhn.fhir.i18n.HapiLocalizer;
|
||||
import ca.uhn.fhir.jpa.model.entity.ForcedId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
|
@ -81,7 +81,7 @@ public class HapiFhirHibernateJpaDialect extends HibernateJpaDialect {
|
|||
if (constraintName.contains(ResourceHistoryTable.IDX_RESVER_ID_VER)) {
|
||||
throw new ResourceVersionConflictException(messageToPrepend + myLocalizer.getMessage(HapiFhirHibernateJpaDialect.class, "resourceVersionConstraintFailure"));
|
||||
}
|
||||
if (constraintName.contains(ResourceIndexedCompositeStringUnique.IDX_IDXCMPSTRUNIQ_STRING)) {
|
||||
if (constraintName.contains(ResourceIndexedComboStringUnique.IDX_IDXCMPSTRUNIQ_STRING)) {
|
||||
throw new ResourceVersionConflictException(messageToPrepend + myLocalizer.getMessage(HapiFhirHibernateJpaDialect.class, "resourceIndexedCompositeStringUniqueConstraintFailure"));
|
||||
}
|
||||
if (constraintName.contains(ForcedId.IDX_FORCEDID_TYPE_FID)) {
|
||||
|
|
|
@ -129,7 +129,6 @@ import javax.persistence.TypedQuery;
|
|||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.validation.constraints.Null;
|
||||
import javax.xml.stream.events.Characters;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import java.util.ArrayList;
|
||||
|
@ -1404,7 +1403,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
}
|
||||
|
||||
// Synchronize composite params
|
||||
mySearchParamWithInlineReferencesExtractor.storeCompositeStringUniques(newParams, entity, existingParams);
|
||||
mySearchParamWithInlineReferencesExtractor.storeUniqueComboParameters(newParams, entity, existingParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.ComboSearchParamType;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
|
@ -42,7 +43,7 @@ import ca.uhn.fhir.jpa.entity.ResourceSearchView;
|
|||
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTag;
|
||||
|
@ -868,9 +869,11 @@ public class LegacySearchBuilder implements ISearchBuilder {
|
|||
// Since we're going to remove elements below
|
||||
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
|
||||
|
||||
List<RuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
|
||||
List<RuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet());
|
||||
if (activeUniqueSearchParams.size() > 0) {
|
||||
|
||||
Validate.isTrue(activeUniqueSearchParams.get(0).getComboSearchParamType()== ComboSearchParamType.UNIQUE, "Non unique combo parameters are not supported with the legacy search builder");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(myResourceName);
|
||||
sb.append("?");
|
||||
|
@ -943,7 +946,7 @@ public class LegacySearchBuilder implements ISearchBuilder {
|
|||
}
|
||||
|
||||
private void addPredicateCompositeStringUnique(@Nonnull SearchParameterMap theParams, String theIndexedString, RequestPartitionId theRequestPartitionId) {
|
||||
From<?, ResourceIndexedCompositeStringUnique> join = myQueryStack.createJoin(SearchBuilderJoinEnum.COMPOSITE_UNIQUE, null);
|
||||
From<?, ResourceIndexedComboStringUnique> join = myQueryStack.createJoin(SearchBuilderJoinEnum.COMPOSITE_UNIQUE, null);
|
||||
|
||||
if (!theRequestPartitionId.isAllPartitions()) {
|
||||
Integer partitionId = theRequestPartitionId.getFirstPartitionIdOrNull();
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.dao.data;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
@ -28,15 +28,15 @@ import org.springframework.data.repository.query.Param;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public interface IResourceIndexedCompositeStringUniqueDao extends JpaRepository<ResourceIndexedCompositeStringUnique, Long> {
|
||||
public interface IResourceIndexedComboStringUniqueDao extends JpaRepository<ResourceIndexedComboStringUnique, Long> {
|
||||
|
||||
@Query("SELECT r FROM ResourceIndexedCompositeStringUnique r WHERE r.myIndexString = :str")
|
||||
ResourceIndexedCompositeStringUnique findByQueryString(@Param("str") String theQueryString);
|
||||
@Query("SELECT r FROM ResourceIndexedComboStringUnique r WHERE r.myIndexString = :str")
|
||||
ResourceIndexedComboStringUnique findByQueryString(@Param("str") String theQueryString);
|
||||
|
||||
@Query("SELECT r FROM ResourceIndexedCompositeStringUnique r WHERE r.myResourceId = :resId")
|
||||
List<ResourceIndexedCompositeStringUnique> findAllForResourceIdForUnitTest(@Param("resId") Long theResourceId);
|
||||
@Query("SELECT r FROM ResourceIndexedComboStringUnique r WHERE r.myResourceId = :resId")
|
||||
List<ResourceIndexedComboStringUnique> findAllForResourceIdForUnitTest(@Param("resId") Long theResourceId);
|
||||
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedCompositeStringUnique t WHERE t.myResourceId = :resid")
|
||||
@Query("delete from ResourceIndexedComboStringUnique t WHERE t.myResourceId = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||
* %%
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface IResourceIndexedComboTokensNonUniqueDao extends JpaRepository<ResourceIndexedComboTokenNonUnique, Long> {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM ResourceIndexedComboTokenNonUnique t WHERE t.myResourceId = :res_id")
|
||||
void deleteByResourceId(@Param("res_id") Long theResourcePid);
|
||||
}
|
|
@ -50,7 +50,8 @@ import ca.uhn.fhir.jpa.model.entity.NpmPackageVersionResourceEntity;
|
|||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryProvenanceEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTag;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||
|
@ -136,7 +137,8 @@ public class ExpungeEverythingService {
|
|||
counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamToken.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamUri.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamCoords.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedCompositeStringUnique.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedComboStringUnique.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedComboTokenNonUnique.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceLink.class));
|
||||
counter.addAndGet(expungeEverythingByType(SearchResult.class));
|
||||
counter.addAndGet(expungeEverythingByType(SearchInclude.class));
|
||||
|
|
|
@ -28,7 +28,8 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
|||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTagDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboTokensNonUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamCoordsDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamDateDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamNumberDao;
|
||||
|
@ -95,7 +96,9 @@ public class ResourceExpungeService implements IResourceExpungeService {
|
|||
@Autowired
|
||||
private IResourceIndexedSearchParamNumberDao myResourceIndexedSearchParamNumberDao;
|
||||
@Autowired
|
||||
private IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
private IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
private IResourceIndexedComboTokensNonUniqueDao myResourceIndexedComboTokensNonUniqueDao;
|
||||
@Autowired
|
||||
private IResourceLinkDao myResourceLinkDao;
|
||||
@Autowired
|
||||
|
@ -289,9 +292,12 @@ public class ResourceExpungeService implements IResourceExpungeService {
|
|||
if (resource == null || resource.isParamsTokenPopulated()) {
|
||||
myResourceIndexedSearchParamTokenDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsCompositeStringUniquePresent()) {
|
||||
if (resource == null || resource.isParamsComboStringUniquePresent()) {
|
||||
myResourceIndexedCompositeStringUniqueDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsComboTokensNonUniquePresent()) {
|
||||
myResourceIndexedComboTokensNonUniqueDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (myDaoConfig.getIndexMissingFields() == DaoConfig.IndexEnabledEnum.ENABLED) {
|
||||
mySearchParamPresentDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ public class ResourceTableFKProvider {
|
|||
// SELECT FKTABLE_NAME, FKCOLUMN_NAME FROM CROSS_REFERENCES WHERE PKTABLE_NAME = 'HFJ_RESOURCE'
|
||||
retval.add(new ResourceForeignKey("HFJ_FORCED_ID", "RESOURCE_PID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", "SRC_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", "TARGET_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", "RES_ID"));
|
||||
|
|
|
@ -20,17 +20,11 @@ package ca.uhn.fhir.jpa.dao.index;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndex;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
|
||||
import ca.uhn.fhir.jpa.util.AddRemoveCount;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
@ -43,15 +37,8 @@ import java.util.List;
|
|||
|
||||
@Service
|
||||
public class DaoSearchParamSynchronizer {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(DaoSearchParamSynchronizer.class);
|
||||
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
||||
protected EntityManager myEntityManager;
|
||||
@Autowired
|
||||
private DaoConfig myDaoConfig;
|
||||
@Autowired
|
||||
private PartitionSettings myPartitionSettings;
|
||||
@Autowired
|
||||
private ModelConfig myModelConfig;
|
||||
|
||||
public AddRemoveCount synchronizeSearchParamsToDatabase(ResourceIndexedSearchParams theParams, ResourceTable theEntity, ResourceIndexedSearchParams existingParams) {
|
||||
AddRemoveCount retVal = new AddRemoveCount();
|
||||
|
@ -65,6 +52,7 @@ public class DaoSearchParamSynchronizer {
|
|||
synchronize(theEntity, retVal, theParams.myUriParams, existingParams.myUriParams);
|
||||
synchronize(theEntity, retVal, theParams.myCoordsParams, existingParams.myCoordsParams);
|
||||
synchronize(theEntity, retVal, theParams.myLinks, existingParams.myLinks);
|
||||
synchronize(theEntity, retVal, theParams.myComboTokenNonUnique, existingParams.myComboTokenNonUnique);
|
||||
|
||||
// make sure links are indexed
|
||||
theEntity.setResourceLinks(theParams.myLinks);
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.index;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.ComboSearchParamType;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
|
@ -27,17 +28,19 @@ import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
|||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||
import ca.uhn.fhir.jpa.dao.MatchResourceUrlService;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
|
||||
import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
|
@ -46,15 +49,18 @@ import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
import ca.uhn.fhir.util.StringUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.hl7.fhir.instance.model.api.IBaseReference;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
|
@ -64,8 +70,10 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
|
@ -92,7 +100,7 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
@Autowired
|
||||
private DaoSearchParamSynchronizer myDaoSearchParamSynchronizer;
|
||||
@Autowired
|
||||
private IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
private IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
private PartitionSettings myPartitionSettings;
|
||||
|
||||
|
@ -140,7 +148,7 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
}
|
||||
|
||||
/*
|
||||
* Handle composites
|
||||
* Handle combo parameters
|
||||
*/
|
||||
extractCompositeStringUniques(theEntity, theParams);
|
||||
}
|
||||
|
@ -148,86 +156,152 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
private void extractCompositeStringUniques(ResourceTable theEntity, ResourceIndexedSearchParams theParams) {
|
||||
|
||||
final String resourceType = theEntity.getResourceType();
|
||||
List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(resourceType);
|
||||
List<RuntimeSearchParam> comboSearchParams = mySearchParamRegistry.getActiveComboSearchParams(resourceType);
|
||||
|
||||
for (RuntimeSearchParam next : uniqueSearchParams) {
|
||||
for (RuntimeSearchParam next : comboSearchParams) {
|
||||
switch (Objects.requireNonNull(next.getComboSearchParamType())) {
|
||||
case UNIQUE:
|
||||
extractComboUniqueParam(theEntity, theParams, resourceType, next);
|
||||
break;
|
||||
case NON_UNIQUE:
|
||||
extractComboNonUniqueParam(theEntity, theParams, resourceType, next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<List<String>> partsChoices = new ArrayList<>();
|
||||
private void extractComboNonUniqueParam(ResourceTable theEntity, ResourceIndexedSearchParams theParams, String theResourceType, RuntimeSearchParam theParam) {
|
||||
Set<String> queryStringsToPopulate = extractParameterCombinationsForComboParam(theParams, theResourceType, theParam);
|
||||
|
||||
List<RuntimeSearchParam> compositeComponents = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, next);
|
||||
for (RuntimeSearchParam nextCompositeOf : compositeComponents) {
|
||||
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = null;
|
||||
Collection<ResourceLink> linksForCompositePart = null;
|
||||
Collection<String> linksForCompositePartWantPaths = null;
|
||||
switch (nextCompositeOf.getParamType()) {
|
||||
case NUMBER:
|
||||
paramsListForCompositePart = theParams.myNumberParams;
|
||||
break;
|
||||
case DATE:
|
||||
paramsListForCompositePart = theParams.myDateParams;
|
||||
break;
|
||||
case STRING:
|
||||
paramsListForCompositePart = theParams.myStringParams;
|
||||
break;
|
||||
case TOKEN:
|
||||
paramsListForCompositePart = theParams.myTokenParams;
|
||||
break;
|
||||
case REFERENCE:
|
||||
linksForCompositePart = theParams.myLinks;
|
||||
linksForCompositePartWantPaths = new HashSet<>(nextCompositeOf.getPathsSplit());
|
||||
break;
|
||||
case QUANTITY:
|
||||
paramsListForCompositePart = theParams.myQuantityParams;
|
||||
break;
|
||||
case URI:
|
||||
paramsListForCompositePart = theParams.myUriParams;
|
||||
break;
|
||||
case SPECIAL:
|
||||
case COMPOSITE:
|
||||
case HAS:
|
||||
break;
|
||||
}
|
||||
for (String nextQueryString : queryStringsToPopulate) {
|
||||
ourLog.trace("Adding composite unique SP: {}", nextQueryString);
|
||||
theParams.myComboTokenNonUnique.add(new ResourceIndexedComboTokenNonUnique(myPartitionSettings, theEntity, nextQueryString));
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<String> nextChoicesList = new ArrayList<>();
|
||||
partsChoices.add(nextChoicesList);
|
||||
private void extractComboUniqueParam(ResourceTable theEntity, ResourceIndexedSearchParams theParams, String theResourceType, RuntimeSearchParam theParam) {
|
||||
Set<String> queryStringsToPopulate = extractParameterCombinationsForComboParam(theParams, theResourceType, theParam);
|
||||
|
||||
String key = UrlUtil.escapeUrlParam(nextCompositeOf.getName());
|
||||
if (paramsListForCompositePart != null) {
|
||||
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
|
||||
if (nextParam.getParamName().equals(nextCompositeOf.getName())) {
|
||||
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
|
||||
String value = nextParamAsClientParam.getValueAsQueryToken(myContext);
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
for (String nextQueryString : queryStringsToPopulate) {
|
||||
ourLog.trace("Adding composite unique SP: {}", nextQueryString);
|
||||
theParams.myComboStringUniques.add(new ResourceIndexedComboStringUnique(theEntity, nextQueryString, theParam.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Set<String> extractParameterCombinationsForComboParam(ResourceIndexedSearchParams theParams, String theResourceType, RuntimeSearchParam theParam) {
|
||||
List<List<String>> partsChoices = new ArrayList<>();
|
||||
|
||||
List<RuntimeSearchParam> compositeComponents = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, theParam);
|
||||
for (RuntimeSearchParam nextCompositeOf : compositeComponents) {
|
||||
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = findParameterIndexes(theParams, nextCompositeOf);
|
||||
|
||||
Collection<ResourceLink> linksForCompositePart = null;
|
||||
switch (nextCompositeOf.getParamType()) {
|
||||
case REFERENCE:
|
||||
linksForCompositePart = theParams.myLinks;
|
||||
break;
|
||||
case NUMBER:
|
||||
case DATE:
|
||||
case STRING:
|
||||
case TOKEN:
|
||||
case QUANTITY:
|
||||
case URI:
|
||||
case SPECIAL:
|
||||
case COMPOSITE:
|
||||
case HAS:
|
||||
break;
|
||||
}
|
||||
|
||||
Collection<String> linksForCompositePartWantPaths = null;
|
||||
switch (nextCompositeOf.getParamType()) {
|
||||
case REFERENCE:
|
||||
linksForCompositePartWantPaths = new HashSet<>(nextCompositeOf.getPathsSplit());
|
||||
break;
|
||||
case NUMBER:
|
||||
case DATE:
|
||||
case STRING:
|
||||
case TOKEN:
|
||||
case QUANTITY:
|
||||
case URI:
|
||||
case SPECIAL:
|
||||
case COMPOSITE:
|
||||
case HAS:
|
||||
break;
|
||||
}
|
||||
|
||||
ArrayList<String> nextChoicesList = new ArrayList<>();
|
||||
partsChoices.add(nextChoicesList);
|
||||
|
||||
String key = UrlUtil.escapeUrlParam(nextCompositeOf.getName());
|
||||
if (paramsListForCompositePart != null) {
|
||||
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
|
||||
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
|
||||
String value = nextParamAsClientParam.getValueAsQueryToken(myContext);
|
||||
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceType, key);
|
||||
if (theParam.getComboSearchParamType() == ComboSearchParamType.NON_UNIQUE && param != null && param.getParamType() == RestSearchParameterTypeEnum.STRING) {
|
||||
value = StringUtil.normalizeStringForSearchIndexing(value);
|
||||
}
|
||||
}
|
||||
if (linksForCompositePart != null) {
|
||||
for (ResourceLink nextLink : linksForCompositePart) {
|
||||
if (linksForCompositePartWantPaths.contains(nextLink.getSourcePath())) {
|
||||
assert isNotBlank(nextLink.getTargetResourceType());
|
||||
assert isNotBlank(nextLink.getTargetResourceId());
|
||||
String value = nextLink.getTargetResourceType() + "/" + nextLink.getTargetResourceId();
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> queryStringsToPopulate = ResourceIndexedSearchParams.extractCompositeStringUniquesValueChains(resourceType, partsChoices);
|
||||
|
||||
for (String nextQueryString : queryStringsToPopulate) {
|
||||
if (isNotBlank(nextQueryString)) {
|
||||
ourLog.trace("Adding composite unique SP: {}", nextQueryString);
|
||||
theParams.myCompositeStringUniques.add(new ResourceIndexedCompositeStringUnique(theEntity, nextQueryString, next.getId()));
|
||||
if (linksForCompositePart != null) {
|
||||
for (ResourceLink nextLink : linksForCompositePart) {
|
||||
if (linksForCompositePartWantPaths.contains(nextLink.getSourcePath())) {
|
||||
assert isNotBlank(nextLink.getTargetResourceType());
|
||||
assert isNotBlank(nextLink.getTargetResourceId());
|
||||
String value = nextLink.getTargetResourceType() + "/" + nextLink.getTargetResourceId();
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ResourceIndexedSearchParams.extractCompositeStringUniquesValueChains(theResourceType, partsChoices);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Collection<? extends BaseResourceIndexedSearchParam> findParameterIndexes(ResourceIndexedSearchParams theParams, RuntimeSearchParam nextCompositeOf) {
|
||||
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = null;
|
||||
switch (nextCompositeOf.getParamType()) {
|
||||
case NUMBER:
|
||||
paramsListForCompositePart = theParams.myNumberParams;
|
||||
break;
|
||||
case DATE:
|
||||
paramsListForCompositePart = theParams.myDateParams;
|
||||
break;
|
||||
case STRING:
|
||||
paramsListForCompositePart = theParams.myStringParams;
|
||||
break;
|
||||
case TOKEN:
|
||||
paramsListForCompositePart = theParams.myTokenParams;
|
||||
break;
|
||||
case QUANTITY:
|
||||
paramsListForCompositePart = theParams.myQuantityParams;
|
||||
break;
|
||||
case URI:
|
||||
paramsListForCompositePart = theParams.myUriParams;
|
||||
break;
|
||||
case REFERENCE:
|
||||
case SPECIAL:
|
||||
case COMPOSITE:
|
||||
case HAS:
|
||||
break;
|
||||
}
|
||||
if (paramsListForCompositePart != null) {
|
||||
paramsListForCompositePart = paramsListForCompositePart
|
||||
.stream()
|
||||
.filter(t->t.getParamName().equals(nextCompositeOf.getName()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return paramsListForCompositePart;
|
||||
}
|
||||
|
||||
|
||||
|
@ -309,19 +383,21 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
myDaoSearchParamSynchronizer = theDaoSearchParamSynchronizer;
|
||||
}
|
||||
|
||||
public void storeCompositeStringUniques(ResourceIndexedSearchParams theParams, ResourceTable theEntity, ResourceIndexedSearchParams existingParams) {
|
||||
public void storeUniqueComboParameters(ResourceIndexedSearchParams theParams, ResourceTable theEntity, ResourceIndexedSearchParams theExistingParams) {
|
||||
|
||||
// Store composite string uniques
|
||||
/*
|
||||
* String Uniques
|
||||
*/
|
||||
if (myDaoConfig.isUniqueIndexesEnabled()) {
|
||||
for (ResourceIndexedCompositeStringUnique next : myDaoSearchParamSynchronizer.subtract(existingParams.myCompositeStringUniques, theParams.myCompositeStringUniques)) {
|
||||
for (ResourceIndexedComboStringUnique next : myDaoSearchParamSynchronizer.subtract(theExistingParams.myComboStringUniques, theParams.myComboStringUniques)) {
|
||||
ourLog.debug("Removing unique index: {}", next);
|
||||
myEntityManager.remove(next);
|
||||
theEntity.getParamsCompositeStringUnique().remove(next);
|
||||
theEntity.getParamsComboStringUnique().remove(next);
|
||||
}
|
||||
boolean haveNewParams = false;
|
||||
for (ResourceIndexedCompositeStringUnique next : myDaoSearchParamSynchronizer.subtract(theParams.myCompositeStringUniques, existingParams.myCompositeStringUniques)) {
|
||||
boolean haveNewStringUniqueParams = false;
|
||||
for (ResourceIndexedComboStringUnique next : myDaoSearchParamSynchronizer.subtract(theParams.myComboStringUniques, theExistingParams.myComboStringUniques)) {
|
||||
if (myDaoConfig.isUniqueIndexesCheckedBeforeSave()) {
|
||||
ResourceIndexedCompositeStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString());
|
||||
ResourceIndexedComboStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString());
|
||||
if (existing != null) {
|
||||
|
||||
String searchParameterId = "(unknown)";
|
||||
|
@ -335,12 +411,12 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
}
|
||||
ourLog.debug("Persisting unique index: {}", next);
|
||||
myEntityManager.persist(next);
|
||||
haveNewParams = true;
|
||||
haveNewStringUniqueParams = true;
|
||||
}
|
||||
if (theParams.myCompositeStringUniques.size() > 0 || haveNewParams) {
|
||||
theEntity.setParamsCompositeStringUniquePresent(true);
|
||||
if (theParams.myComboStringUniques.size() > 0 || haveNewStringUniqueParams) {
|
||||
theEntity.setParamsComboStringUniquePresent(true);
|
||||
} else {
|
||||
theEntity.setParamsCompositeStringUniquePresent(false);
|
||||
theEntity.setParamsComboStringUniquePresent(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ class QueryRootEntryResourceTable extends QueryRootEntry {
|
|||
join = myResourceTableRoot.join("mySearchParamPresents", JoinType.LEFT);
|
||||
break;
|
||||
case COMPOSITE_UNIQUE:
|
||||
join = myResourceTableRoot.join("myParamsCompositeStringUnique", JoinType.LEFT);
|
||||
join = myResourceTableRoot.join("myParamsComboStringUnique", JoinType.LEFT);
|
||||
break;
|
||||
case RESOURCE_TAGS:
|
||||
join = myResourceTableRoot.join("myTags", JoinType.LEFT);
|
||||
|
|
|
@ -34,7 +34,8 @@ import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
|||
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.BaseJoiningPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboNonUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ForcedIdPredicateBuilder;
|
||||
|
@ -1214,11 +1215,18 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public void addPredicateCompositeUnique(String theIndexString, RequestPartitionId theRequestPartitionId) {
|
||||
CompositeUniqueSearchParameterPredicateBuilder predicateBuilder = mySqlBuilder.addCompositeUniquePredicateBuilder();
|
||||
ComboUniqueSearchParameterPredicateBuilder predicateBuilder = mySqlBuilder.addComboUniquePredicateBuilder();
|
||||
Condition predicate = predicateBuilder.createPredicateIndexString(theRequestPartitionId, theIndexString);
|
||||
mySqlBuilder.addPredicate(predicate);
|
||||
}
|
||||
|
||||
public void addPredicateCompositeNonUnique(String theIndexString, RequestPartitionId theRequestPartitionId) {
|
||||
ComboNonUniqueSearchParameterPredicateBuilder predicateBuilder = mySqlBuilder.addComboNonUniquePredicateBuilder();
|
||||
Condition predicate = predicateBuilder.createPredicateHashComplete(theRequestPartitionId, theIndexString);
|
||||
mySqlBuilder.addPredicate(predicate);
|
||||
}
|
||||
|
||||
|
||||
public void addPredicateEverythingOperation(String theResourceName, Long theTargetPid) {
|
||||
ResourceLinkPredicateBuilder table = mySqlBuilder.addReferencePredicateBuilder(this, null);
|
||||
Condition predicate = table.createEverythingPredicate(theResourceName, theTargetPid);
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.search.builder;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.ComboSearchParamType;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
|
@ -85,6 +86,7 @@ import ca.uhn.fhir.rest.param.StringParam;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.StopWatch;
|
||||
import ca.uhn.fhir.util.StringUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -119,6 +121,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
@ -213,7 +216,7 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
// Attempt to lookup via composite unique key.
|
||||
if (isCompositeUniqueSpCandidate()) {
|
||||
attemptCompositeUniqueSpProcessing(theQueryStack, theParams, theRequest);
|
||||
attemptComboUniqueSpProcessing(theQueryStack, theParams, theRequest);
|
||||
}
|
||||
|
||||
SearchContainedModeEnum searchContainedMode = theParams.getSearchContainedMode();
|
||||
|
@ -366,7 +369,10 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
QueryStack queryStack3 = new QueryStack(theParams, myDaoConfig, myDaoConfig.getModelConfig(), myContext, sqlBuilder, mySearchParamRegistry, myPartitionSettings);
|
||||
|
||||
if (theParams.keySet().size() > 1 || theParams.getSort() != null || theParams.keySet().contains(Constants.PARAM_HAS)) {
|
||||
sqlBuilder.setNeedResourceTableRoot(true);
|
||||
List<RuntimeSearchParam> activeComboParams = mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet());
|
||||
if (activeComboParams.isEmpty()) {
|
||||
sqlBuilder.setNeedResourceTableRoot(true);
|
||||
}
|
||||
}
|
||||
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(myEntityManagerFactory.getDataSource());
|
||||
|
@ -1009,12 +1015,34 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private void attemptCompositeUniqueSpProcessing(QueryStack theQueryStack3, @Nonnull SearchParameterMap theParams, RequestDetails theRequest) {
|
||||
// Since we're going to remove elements below
|
||||
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
|
||||
private void attemptComboUniqueSpProcessing(QueryStack theQueryStack3, @Nonnull SearchParameterMap theParams, RequestDetails theRequest) {
|
||||
RuntimeSearchParam comboParam = null;
|
||||
List<String> comboParamNames = null;
|
||||
List<RuntimeSearchParam> exactMatchParams = mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet());
|
||||
if (exactMatchParams.size() > 0) {
|
||||
comboParam = exactMatchParams.get(0);
|
||||
comboParamNames = new ArrayList<>(theParams.keySet());
|
||||
}
|
||||
|
||||
List<RuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
|
||||
if (activeUniqueSearchParams.size() > 0) {
|
||||
if (comboParam == null) {
|
||||
List<RuntimeSearchParam> candidateComboParams = mySearchParamRegistry.getActiveComboSearchParams(myResourceName);
|
||||
for (RuntimeSearchParam nextCandidate : candidateComboParams) {
|
||||
List<String> nextCandidateParamNames = JpaParamUtil
|
||||
.resolveComponentParameters(mySearchParamRegistry, nextCandidate)
|
||||
.stream()
|
||||
.map(t -> t.getName())
|
||||
.collect(Collectors.toList());
|
||||
if (theParams.keySet().containsAll(nextCandidateParamNames)) {
|
||||
comboParam = nextCandidate;
|
||||
comboParamNames = nextCandidateParamNames;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (comboParam != null) {
|
||||
// Since we're going to remove elements below
|
||||
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(myResourceName);
|
||||
|
@ -1022,9 +1050,8 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
boolean first = true;
|
||||
|
||||
ArrayList<String> keys = new ArrayList<>(theParams.keySet());
|
||||
Collections.sort(keys);
|
||||
for (String nextParamName : keys) {
|
||||
Collections.sort(comboParamNames);
|
||||
for (String nextParamName : comboParamNames) {
|
||||
List<List<IQueryParameterType>> nextValues = theParams.get(nextParamName);
|
||||
|
||||
nextParamName = UrlUtil.escapeUrlParam(nextParamName);
|
||||
|
@ -1047,6 +1074,13 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
List<? extends IQueryParameterType> nextAnd = nextValues.remove(0);
|
||||
IQueryParameterType nextOr = nextAnd.remove(0);
|
||||
String nextOrValue = nextOr.getValueAsQueryToken(myContext);
|
||||
|
||||
if (comboParam.getComboSearchParamType() == ComboSearchParamType.NON_UNIQUE) {
|
||||
if (nextParamDef.getParamType() == RestSearchParameterTypeEnum.STRING) {
|
||||
nextOrValue = StringUtil.normalizeStringForSearchIndexing(nextOrValue);
|
||||
}
|
||||
}
|
||||
|
||||
nextOrValue = UrlUtil.escapeUrlParam(nextOrValue);
|
||||
|
||||
if (first) {
|
||||
|
@ -1061,18 +1095,25 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
if (sb != null) {
|
||||
String indexString = sb.toString();
|
||||
ourLog.debug("Checking for unique index for query: {}", indexString);
|
||||
ourLog.debug("Checking for {} combo index for query: {}", comboParam.getComboSearchParamType(), indexString);
|
||||
|
||||
// Interceptor broadcast: JPA_PERFTRACE_INFO
|
||||
StorageProcessingMessage msg = new StorageProcessingMessage()
|
||||
.setMessage("Using unique index for query for search: " + indexString);
|
||||
.setMessage("Using " + comboParam.getComboSearchParamType() + " index for query for search: " + indexString);
|
||||
HookParams params = new HookParams()
|
||||
.add(RequestDetails.class, theRequest)
|
||||
.addIfMatchesType(ServletRequestDetails.class, theRequest)
|
||||
.add(StorageProcessingMessage.class, msg);
|
||||
CompositeInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_INFO, params);
|
||||
|
||||
theQueryStack3.addPredicateCompositeUnique(indexString, myRequestPartitionId);
|
||||
switch (comboParam.getComboSearchParamType()) {
|
||||
case UNIQUE:
|
||||
theQueryStack3.addPredicateCompositeUnique(indexString, myRequestPartitionId);
|
||||
break;
|
||||
case NON_UNIQUE:
|
||||
theQueryStack3.addPredicateCompositeNonUnique(indexString, myRequestPartitionId);
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove any empty parameters remaining after this
|
||||
theParams.clean();
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package ca.uhn.fhir.jpa.search.builder.predicate;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||
* %%
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
||||
import com.healthmarketscience.sqlbuilder.BinaryCondition;
|
||||
import com.healthmarketscience.sqlbuilder.Condition;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
|
||||
|
||||
public class ComboNonUniqueSearchParameterPredicateBuilder extends BaseSearchParamPredicateBuilder {
|
||||
|
||||
private final DbColumn myColumnIndexString;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ComboNonUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
super(theSearchSqlBuilder, theSearchSqlBuilder.addTable("HFJ_IDX_CMB_TOK_NU"));
|
||||
|
||||
myColumnIndexString = getTable().addColumn("IDX_STRING");
|
||||
}
|
||||
|
||||
|
||||
public Condition createPredicateHashComplete(RequestPartitionId theRequestPartitionId, String theIndexString) {
|
||||
BinaryCondition predicate = BinaryCondition.equalTo(myColumnIndexString, generatePlaceholder(theIndexString));
|
||||
return combineWithRequestPartitionIdPredicate(theRequestPartitionId, predicate);
|
||||
}
|
||||
}
|
|
@ -26,14 +26,14 @@ import com.healthmarketscience.sqlbuilder.BinaryCondition;
|
|||
import com.healthmarketscience.sqlbuilder.Condition;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
|
||||
|
||||
public class CompositeUniqueSearchParameterPredicateBuilder extends BaseSearchParamPredicateBuilder {
|
||||
public class ComboUniqueSearchParameterPredicateBuilder extends BaseSearchParamPredicateBuilder {
|
||||
|
||||
private final DbColumn myColumnString;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public CompositeUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
public ComboUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
super(theSearchSqlBuilder, theSearchSqlBuilder.addTable("HFJ_IDX_CMP_STRING_UNIQ"));
|
||||
|
||||
myColumnString = getTable().addColumn("IDX_STRING");
|
|
@ -27,7 +27,8 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
|||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.search.builder.QueryStack;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.BaseJoiningPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboNonUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ForcedIdPredicateBuilder;
|
||||
|
@ -145,12 +146,20 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a Composite Unique search parameter
|
||||
*/
|
||||
public CompositeUniqueSearchParameterPredicateBuilder addCompositeUniquePredicateBuilder() {
|
||||
CompositeUniqueSearchParameterPredicateBuilder retVal = mySqlBuilderFactory.newCompositeUniqueSearchParameterPredicateBuilder(this);
|
||||
public ComboUniqueSearchParameterPredicateBuilder addComboUniquePredicateBuilder() {
|
||||
ComboUniqueSearchParameterPredicateBuilder retVal = mySqlBuilderFactory.newComboUniqueSearchParameterPredicateBuilder(this);
|
||||
addTable(retVal, null);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a Composite Unique search parameter
|
||||
*/
|
||||
public ComboNonUniqueSearchParameterPredicateBuilder addComboNonUniquePredicateBuilder() {
|
||||
ComboNonUniqueSearchParameterPredicateBuilder retVal = mySqlBuilderFactory.newComboNonUniqueSearchParameterPredicateBuilder(this);
|
||||
addTable(retVal, null);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a COORDS search parameter
|
||||
|
|
|
@ -21,7 +21,8 @@ package ca.uhn.fhir.jpa.search.builder.sql;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.search.builder.QueryStack;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboNonUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ForcedIdPredicateBuilder;
|
||||
|
@ -45,10 +46,15 @@ public class SqlObjectFactory {
|
|||
@Autowired
|
||||
private ApplicationContext myApplicationContext;
|
||||
|
||||
public CompositeUniqueSearchParameterPredicateBuilder newCompositeUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return myApplicationContext.getBean(CompositeUniqueSearchParameterPredicateBuilder.class, theSearchSqlBuilder);
|
||||
public ComboUniqueSearchParameterPredicateBuilder newComboUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return myApplicationContext.getBean(ComboUniqueSearchParameterPredicateBuilder.class, theSearchSqlBuilder);
|
||||
}
|
||||
|
||||
public ComboNonUniqueSearchParameterPredicateBuilder newComboNonUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return myApplicationContext.getBean(ComboNonUniqueSearchParameterPredicateBuilder.class, theSearchSqlBuilder);
|
||||
}
|
||||
|
||||
|
||||
public CoordsPredicateBuilder coordsPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return myApplicationContext.getBean(CoordsPredicateBuilder.class, theSearchSqlBuilder);
|
||||
}
|
||||
|
@ -112,4 +118,5 @@ public class SqlObjectFactory {
|
|||
public SearchQueryExecutor newSearchQueryExecutor(GeneratedSql theGeneratedSql, Integer theMaxResultsToFetch) {
|
||||
return myApplicationContext.getBean(SearchQueryExecutor.class, theGeneratedSql, theMaxResultsToFetch);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import ca.uhn.fhir.jpa.bulk.export.api.IBulkDataExportSvc;
|
|||
import ca.uhn.fhir.jpa.config.BaseConfig;
|
||||
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboTokensNonUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamDateDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamTokenDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao;
|
||||
|
@ -161,6 +162,8 @@ public abstract class BaseJpaTest extends BaseTest {
|
|||
@Autowired
|
||||
protected IResourceIndexedSearchParamDateDao myResourceIndexedSearchParamDateDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedComboTokensNonUniqueDao myResourceIndexedComboTokensNonUniqueDao;
|
||||
@Autowired
|
||||
private IdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
private MemoryCacheService myMemoryCacheService;
|
||||
|
@ -306,6 +309,12 @@ public abstract class BaseJpaTest extends BaseTest {
|
|||
});
|
||||
}
|
||||
|
||||
protected void logAllNonUniqueIndexes() {
|
||||
runInTransaction(() -> {
|
||||
ourLog.info("Non unique indexes:\n * {}", myResourceIndexedComboTokensNonUniqueDao.findAll().stream().map(t -> t.toString()).collect(Collectors.joining("\n * ")));
|
||||
});
|
||||
}
|
||||
|
||||
protected void logAllTokenIndexes() {
|
||||
runInTransaction(() -> {
|
||||
ourLog.info("Token indexes:\n * {}", myResourceIndexedSearchParamTokenDao.findAll().stream().map(t -> t.toString()).collect(Collectors.joining("\n * ")));
|
||||
|
|
|
@ -17,7 +17,7 @@ import ca.uhn.fhir.jpa.bulk.export.api.IBulkDataExportSvc;
|
|||
import ca.uhn.fhir.jpa.config.TestDstu3Config;
|
||||
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
|
||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamStringDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamTokenDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceReindexJobDao;
|
||||
|
@ -150,7 +150,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
|||
@Qualifier("myCoverageDaoDstu3")
|
||||
protected IFhirResourceDao<Coverage> myCoverageDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
protected IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
@Qualifier("myAllergyIntoleranceDaoDstu3")
|
||||
protected IFhirResourceDao<AllergyIntolerance> myAllergyIntoleranceDao;
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
||||
import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl;
|
||||
import ca.uhn.fhir.jpa.util.SpringObjectCaster;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public abstract class BaseComboParamsR4Test extends BaseJpaR4Test {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(BaseComboParamsR4Test.class);
|
||||
@Autowired
|
||||
protected ISearchParamRegistry mySearchParamRegistry;
|
||||
protected List<String> myMessages = new ArrayList<>();
|
||||
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
|
||||
myDaoConfig.setSchedulingDisabled(true);
|
||||
myDaoConfig.setUniqueIndexesEnabled(true);
|
||||
|
||||
myInterceptorBroadcaster = mock(IInterceptorBroadcaster.class);
|
||||
when(mySrd.getInterceptorBroadcaster()).thenReturn(myInterceptorBroadcaster);
|
||||
when(mySrd.getServer().getPagingProvider()).thenReturn(new DatabaseBackedPagingProvider());
|
||||
|
||||
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_WARNING))).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_INFO))).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_INFO), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("INFO " + params.get(StorageProcessingMessage.class).getMessage());
|
||||
return null;
|
||||
});
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_WARNING), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("WARN " + params.get(StorageProcessingMessage.class).getMessage());
|
||||
return null;
|
||||
});
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_SEARCH_REUSING_CACHED), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("REUSING CACHED SEARCH");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void after() throws Exception {
|
||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden());
|
||||
myDaoConfig.setUniqueIndexesCheckedBeforeSave(new DaoConfig().isUniqueIndexesCheckedBeforeSave());
|
||||
myDaoConfig.setSchedulingDisabled(new DaoConfig().isSchedulingDisabled());
|
||||
myDaoConfig.setUniqueIndexesEnabled(new DaoConfig().isUniqueIndexesEnabled());
|
||||
myDaoConfig.setReindexThreadCount(new DaoConfig().getReindexThreadCount());
|
||||
|
||||
ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class);
|
||||
svc.initExecutor();
|
||||
}
|
||||
|
||||
protected void logCapturedMessages() {
|
||||
ourLog.info("Messages:\n {}", String.join("\n ", myMessages));
|
||||
}
|
||||
|
||||
}
|
|
@ -26,7 +26,8 @@ import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
|||
import ca.uhn.fhir.jpa.dao.data.IPartitionDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTagDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboTokensNonUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamCoordsDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamDateDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamQuantityDao;
|
||||
|
@ -228,7 +229,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
|
|||
@Autowired
|
||||
protected IResourceIndexedSearchParamDateDao myResourceIndexedSearchParamDateDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
protected IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedComboTokensNonUniqueDao myResourceIndexedComboTokensNonUniqueDao;
|
||||
@Autowired
|
||||
@Qualifier("myAllergyIntoleranceDaoR4")
|
||||
protected IFhirResourceDao<AllergyIntolerance> myAllergyIntoleranceDao;
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.BooleanType;
|
||||
import org.hl7.fhir.r4.model.DateType;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.SearchParameter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class FhirResourceDaoR4ComboNonUniqueParamTest extends BaseComboParamsR4Test {
|
||||
|
||||
private void createNamesAndGenderSp() {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-family");
|
||||
sp.setType(Enumerations.SearchParamType.STRING);
|
||||
sp.setCode("family");
|
||||
sp.setExpression("Patient.name.family + '|'");
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
mySearchParameterDao.update(sp);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-given");
|
||||
sp.setType(Enumerations.SearchParamType.STRING);
|
||||
sp.setCode("given");
|
||||
sp.setExpression("Patient.name.given");
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
mySearchParameterDao.update(sp);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-gender");
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
sp.setCode("gender");
|
||||
sp.setExpression("Patient.gender");
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
mySearchParameterDao.update(sp);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-names-and-gender");
|
||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-family");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-given");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-gender");
|
||||
sp.addExtension()
|
||||
.setUrl(HapiExtensions.EXT_SP_UNIQUE)
|
||||
.setValue(new BooleanType(false));
|
||||
mySearchParameterDao.update(sp);
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
myMessages.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndUse() {
|
||||
createNamesAndGenderSp();
|
||||
|
||||
IIdType id1 = createPatient1();
|
||||
assertNotNull(id1);
|
||||
|
||||
IIdType id2 = createPatient2();
|
||||
assertNotNull(id2);
|
||||
|
||||
logAllNonUniqueIndexes();
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedComboTokenNonUnique> indexedTokens = myResourceIndexedComboTokensNonUniqueDao.findAll();
|
||||
indexedTokens.sort(Comparator.comparing(t -> t.getId()));
|
||||
assertEquals(2, indexedTokens.size());
|
||||
assertEquals(-7504889232313729794L, indexedTokens.get(0).getHashComplete().longValue());
|
||||
});
|
||||
|
||||
myMessages.clear();
|
||||
SearchParameterMap params = SearchParameterMap.newSynchronous();
|
||||
params.add("family", new StringParam("fAmIlY1|")); // weird casing to test normalization
|
||||
params.add("given", new StringParam("gIVEn1"));
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
myCaptureQueriesListener.clear();
|
||||
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||
List<String> actual = toUnqualifiedVersionlessIdValues(results);
|
||||
myCaptureQueriesListener.logSelectQueries();
|
||||
assertThat(actual, containsInAnyOrder(id1.toUnqualifiedVersionless().getValue()));
|
||||
|
||||
String sql = myCaptureQueriesListener.getSelectQueries().get(0).getSql(true, false);
|
||||
assertEquals("SELECT t0.RES_ID FROM HFJ_IDX_CMB_TOK_NU t0 WHERE (t0.IDX_STRING = 'Patient?family=FAMILY1%5C%7C&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale&given=GIVEN1')", sql);
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("[INFO Using NON_UNIQUE index for query for search: Patient?family=FAMILY1%5C%7C&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale&given=GIVEN1]"));
|
||||
myMessages.clear();
|
||||
|
||||
// Remove 1, add another
|
||||
|
||||
myPatientDao.delete(id1);
|
||||
|
||||
IIdType id3 = createPatient1();
|
||||
assertNotNull(id3);
|
||||
|
||||
params = SearchParameterMap.newSynchronous();
|
||||
params.add("family", new StringParam("fAmIlY1|")); // weird casing to test normalization
|
||||
params.add("given", new StringParam("gIVEn1"));
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
results = myPatientDao.search(params, mySrd);
|
||||
actual = toUnqualifiedVersionlessIdValues(results);
|
||||
myCaptureQueriesListener.logSelectQueries();
|
||||
assertThat(actual, containsInAnyOrder(id3.toUnqualifiedVersionless().getValue()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithExtraParameters() {
|
||||
createNamesAndGenderSp();
|
||||
|
||||
IIdType id1 = createPatient1();
|
||||
assertNotNull(id1);
|
||||
|
||||
IIdType id2 = createPatient2();
|
||||
assertNotNull(id2);
|
||||
|
||||
logAllNonUniqueIndexes();
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedComboTokenNonUnique> indexedTokens = myResourceIndexedComboTokensNonUniqueDao.findAll();
|
||||
indexedTokens.sort(Comparator.comparing(t -> t.getId()));
|
||||
assertEquals(2, indexedTokens.size());
|
||||
assertEquals(-7504889232313729794L, indexedTokens.get(0).getHashComplete().longValue());
|
||||
});
|
||||
|
||||
myMessages.clear();
|
||||
SearchParameterMap params = SearchParameterMap.newSynchronous();
|
||||
params.add("family", new StringParam("fAmIlY1|")); // weird casing to test normalization
|
||||
params.add("given", new StringParam("gIVEn1"));
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
params.add("birthdate", new DateParam("2021-02-02"));
|
||||
myCaptureQueriesListener.clear();
|
||||
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||
List<String> actual = toUnqualifiedVersionlessIdValues(results);
|
||||
myCaptureQueriesListener.logSelectQueries();
|
||||
assertThat(actual, containsInAnyOrder(id1.toUnqualifiedVersionless().getValue()));
|
||||
|
||||
String sql = myCaptureQueriesListener.getSelectQueries().get(0).getSql(true, false);
|
||||
assertEquals("SELECT t1.RES_ID FROM HFJ_RESOURCE t1 LEFT OUTER JOIN HFJ_IDX_CMB_TOK_NU t0 ON (t1.RES_ID = t0.RES_ID) LEFT OUTER JOIN HFJ_SPIDX_DATE t2 ON (t1.RES_ID = t2.RES_ID) WHERE ((t0.IDX_STRING = 'Patient?family=FAMILY1%5C%7C&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale&given=GIVEN1') AND ((t2.HASH_IDENTITY = '5247847184787287691') AND ((t2.SP_VALUE_LOW_DATE_ORDINAL >= '20210202') AND (t2.SP_VALUE_HIGH_DATE_ORDINAL <= '20210202'))))", sql);
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("[INFO Using NON_UNIQUE index for query for search: Patient?family=FAMILY1%5C%7C&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale&given=GIVEN1]"));
|
||||
myMessages.clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private IIdType createPatient2() {
|
||||
Patient pt2 = new Patient();
|
||||
pt2.getNameFirstRep().setFamily("Family2").addGiven("Given2");
|
||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt2.setBirthDateElement(new DateType("2021-02-02"));
|
||||
IIdType id2 = myPatientDao.create(pt2).getId().toUnqualified();
|
||||
return id2;
|
||||
}
|
||||
|
||||
private IIdType createPatient1() {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.getNameFirstRep().setFamily("Family1").addGiven("Given1");
|
||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt1.setBirthDateElement(new DateType("2021-02-02"));
|
||||
return myPatientDao.create(pt1).getId().toUnqualified();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,19 +1,12 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.context.ComboSearchParamType;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
||||
import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.jpa.util.SpringObjectCaster;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
|
@ -27,17 +20,12 @@ import ca.uhn.fhir.util.HapiExtensions;
|
|||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
@ -57,56 +45,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||
public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4UniqueSearchParamTest.class);
|
||||
@Autowired
|
||||
private ISearchParamRegistry mySearchParamRegistry;
|
||||
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||
private List<String> myMessages = new ArrayList<>();
|
||||
|
||||
@AfterEach
|
||||
public void after() throws Exception {
|
||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden());
|
||||
myDaoConfig.setUniqueIndexesCheckedBeforeSave(new DaoConfig().isUniqueIndexesCheckedBeforeSave());
|
||||
myDaoConfig.setSchedulingDisabled(new DaoConfig().isSchedulingDisabled());
|
||||
myDaoConfig.setUniqueIndexesEnabled(new DaoConfig().isUniqueIndexesEnabled());
|
||||
myDaoConfig.setReindexThreadCount(new DaoConfig().getReindexThreadCount());
|
||||
|
||||
ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class);
|
||||
svc.initExecutor();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
|
||||
myDaoConfig.setSchedulingDisabled(true);
|
||||
myDaoConfig.setUniqueIndexesEnabled(true);
|
||||
|
||||
myInterceptorBroadcaster = mock(IInterceptorBroadcaster.class);
|
||||
when(mySrd.getInterceptorBroadcaster()).thenReturn(myInterceptorBroadcaster);
|
||||
when(mySrd.getServer().getPagingProvider()).thenReturn(new DatabaseBackedPagingProvider());
|
||||
|
||||
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_WARNING))).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_INFO))).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_INFO), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("INFO " + params.get(StorageProcessingMessage.class).getMessage());
|
||||
return null;
|
||||
});
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_WARNING), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("WARN " + params.get(StorageProcessingMessage.class).getMessage());
|
||||
return null;
|
||||
});
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_SEARCH_REUSING_CACHED), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("REUSING CACHED SEARCH");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4ComboUniqueParamTest.class);
|
||||
|
||||
|
||||
private void createUniqueBirthdateAndGenderSps() {
|
||||
|
@ -647,7 +589,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
|
||||
// Make sure entries are saved
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedCompositeStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(2, all.size());
|
||||
});
|
||||
|
||||
|
@ -691,7 +633,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus status) {
|
||||
List<ResourceIndexedCompositeStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(2, all.size());
|
||||
}
|
||||
});
|
||||
|
@ -706,7 +648,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class);
|
||||
svc.initExecutor();
|
||||
|
||||
List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams("Observation");
|
||||
List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams("Observation");
|
||||
assertEquals(0, uniqueSearchParams.size());
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
|
@ -735,7 +677,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
|
||||
createUniqueObservationSubjectDateCode();
|
||||
|
||||
uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams("Observation");
|
||||
uniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams("Observation");
|
||||
assertEquals(1, uniqueSearchParams.size());
|
||||
assertEquals(3, uniqueSearchParams.get(0).getComponents().size());
|
||||
|
||||
|
@ -745,7 +687,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
|
||||
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
|
||||
|
@ -753,7 +695,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
myResourceIndexedCompositeStringUniqueDao.deleteAll();
|
||||
});
|
||||
|
||||
assertEquals(1, mySearchParamRegistry.getActiveUniqueSearchParams("Observation").size());
|
||||
assertEquals(1, mySearchParamRegistry.getActiveComboSearchParams("Observation").size());
|
||||
|
||||
myResourceReindexingSvc.markAllResourcesForReindexing("Observation");
|
||||
assertEquals(1, myResourceReindexingSvc.forceReindexingPass());
|
||||
|
@ -762,7 +704,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
|
||||
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
|
||||
|
@ -833,7 +775,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus status) {
|
||||
List<ResourceIndexedCompositeStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(2, all.size());
|
||||
}
|
||||
});
|
||||
|
@ -873,7 +815,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
});
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
ourLog.info("** Uniques: {}", uniques);
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertEquals("Coverage/" + id3.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||
|
@ -1042,7 +984,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus status) {
|
||||
List<ResourceIndexedCompositeStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, all.size(), all.toString());
|
||||
}
|
||||
});
|
||||
|
@ -1074,7 +1016,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1.getValue()));
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
myMessages.clear();
|
||||
|
||||
}
|
||||
|
@ -1102,7 +1044,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
String searchId = results.getUuid();
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1));
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
myMessages.clear();
|
||||
|
||||
// Other order
|
||||
|
@ -1126,7 +1068,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
results = myPatientDao.search(params, mySrd);
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results), empty());
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-03&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?birthdate=2011-01-03&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
myMessages.clear();
|
||||
|
||||
myMessages.clear();
|
||||
|
@ -1151,7 +1093,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||
assertEquals("Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale", uniques.get(0).getIndexString());
|
||||
|
@ -1161,7 +1103,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
public void testUniqueValuesAreIndexed_RefAndDateAndToken() {
|
||||
createUniqueObservationSubjectDateCode();
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(0, uniques.size(), uniques.toString());
|
||||
|
||||
|
@ -1190,7 +1132,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testUniqueValuesAreIndexed_Reference_UsingModifierSyntax() {
|
||||
createUniqueNameAndManagingOrganizationSps();
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setId("Organization/ORG");
|
||||
|
@ -1204,7 +1146,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
IIdType id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization:Organization=ORG", mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||
myMessages.clear();
|
||||
|
||||
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
|
@ -1221,7 +1163,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization:Organization=ORG", mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||
myMessages.clear();
|
||||
|
||||
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
|
@ -1231,10 +1173,6 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
|
||||
}
|
||||
|
||||
private void logCapturedMessages() {
|
||||
ourLog.info("Messages:\n {}", String.join("\n ", myMessages));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUniqueValuesAreIndexed_StringAndReference() {
|
||||
createUniqueNameAndManagingOrganizationSps();
|
||||
|
@ -1253,7 +1191,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
pt1.setManagingOrganization(new Reference("Organization/ORG"));
|
||||
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
Collections.sort(uniques);
|
||||
|
||||
assertEquals(3, uniques.size());
|
||||
|
@ -1270,7 +1208,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testUniqueValuesAreIndexed_StringAndReference_UsingConditional() {
|
||||
createUniqueNameAndManagingOrganizationSps();
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setId("Organization/ORG");
|
||||
|
@ -1303,7 +1241,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testUniqueValuesAreIndexed_StringAndReference_UsingConditionalInTransaction() {
|
||||
createUniqueNameAndManagingOrganizationSps();
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setId("Organization/ORG");
|
||||
|
@ -1385,7 +1323,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
createUniqueBirthdateAndGenderSps();
|
||||
|
||||
Patient pt;
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
|
||||
pt = new Patient();
|
||||
pt.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
|
@ -1416,7 +1354,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
org.setName("ORG");
|
||||
myOrganizationDao.update(org);
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
Patient pt;
|
||||
|
||||
pt = new Patient();
|
||||
|
@ -1464,7 +1402,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
myResourceReindexingSvc.forceReindexingPass();
|
||||
myResourceReindexingSvc.forceReindexingPass();
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertEquals("Observation/" + id2.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
|
||||
|
@ -1486,10 +1424,10 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testDetectUniqueSearchParams() {
|
||||
createUniqueBirthdateAndGenderSps();
|
||||
List<RuntimeSearchParam> params = mySearchParamRegistry.getActiveUniqueSearchParams("Patient");
|
||||
List<RuntimeSearchParam> params = mySearchParamRegistry.getActiveComboSearchParams("Patient");
|
||||
|
||||
assertEquals(1, params.size());
|
||||
assertEquals(params.get(0).isUnique(), true);
|
||||
assertEquals(ComboSearchParamType.UNIQUE, params.get(0).getComboSearchParamType());
|
||||
assertEquals(2, params.get(0).getComponents().size());
|
||||
|
||||
// Should be alphabetical order
|
||||
|
@ -1565,7 +1503,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id2.getValue()));
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
myMessages.clear();
|
||||
|
||||
}
|
|
@ -12,7 +12,7 @@ import ca.uhn.fhir.jpa.model.entity.ForcedId;
|
|||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTag;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
|
@ -435,7 +435,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
assertEquals(myPartitionDate, presents.get(0).getPartitionId().getPartitionDate());
|
||||
|
||||
// HFJ_IDX_CMP_STRING_UNIQ
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceIdForUnitTest(patientId);
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceIdForUnitTest(patientId);
|
||||
assertEquals(1, uniques.size());
|
||||
assertEquals(myPartitionId, uniques.get(0).getPartitionId().getPartitionId().intValue());
|
||||
assertEquals(myPartitionDate, uniques.get(0).getPartitionId().getPartitionDate());
|
||||
|
@ -519,7 +519,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
assertEquals(myPartitionDate, presents.get(0).getPartitionId().getPartitionDate());
|
||||
|
||||
// HFJ_IDX_CMP_STRING_UNIQ
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceIdForUnitTest(patientId);
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceIdForUnitTest(patientId);
|
||||
assertEquals(1, uniques.size());
|
||||
assertEquals(null, uniques.get(0).getPartitionId().getPartitionId());
|
||||
assertEquals(myPartitionDate, uniques.get(0).getPartitionId().getPartitionDate());
|
||||
|
|
|
@ -327,7 +327,7 @@ public class SearchParamExtractorR4Test {
|
|||
public void testExtensionContainingReference() {
|
||||
String path = "Patient.extension('http://patext').value.as(Reference)";
|
||||
|
||||
RuntimeSearchParam sp = new RuntimeSearchParam(null, null, "extpat", "Patient SP", path, RestSearchParameterTypeEnum.REFERENCE, new HashSet<>(), Sets.newHashSet("Patient"), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null);
|
||||
RuntimeSearchParam sp = new RuntimeSearchParam(null, null, "extpat", "Patient SP", path, RestSearchParameterTypeEnum.REFERENCE, new HashSet<>(), Sets.newHashSet("Patient"), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null);
|
||||
mySearchParamRegistry.addSearchParam(sp);
|
||||
|
||||
Patient patient = new Patient();
|
||||
|
@ -440,7 +440,7 @@ public class SearchParamExtractorR4Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -451,7 +451,7 @@ public class SearchParamExtractorR4Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import ca.uhn.fhir.jpa.dao.BaseJpaTest;
|
|||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamDateDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamQuantityDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamStringDao;
|
||||
|
@ -185,7 +185,7 @@ public abstract class BaseJpaR5Test extends BaseJpaTest implements ITestDataBuil
|
|||
@Autowired
|
||||
protected IResourceIndexedSearchParamDateDao myResourceIndexedSearchParamDateDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
protected IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
@Qualifier("myAllergyIntoleranceDaoR5")
|
||||
protected IFhirResourceDao<AllergyIntolerance> myAllergyIntoleranceDao;
|
||||
|
|
|
@ -102,6 +102,21 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
|
||||
version.onTable("HFJ_IDX_CMP_STRING_UNIQ")
|
||||
.modifyColumn("20210713.1","IDX_STRING").nonNullable().withType(ColumnTypeEnum.STRING, 500);
|
||||
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.addColumn("20210720.1", "SP_CMPTOKS_PRESENT").nullable().type(ColumnTypeEnum.BOOLEAN);
|
||||
|
||||
version.addIdGenerator("20210720.2", "SEQ_IDXCMBTOKNU_ID");
|
||||
|
||||
Builder.BuilderAddTableByColumns cmpToks = version
|
||||
.addTableByColumns("20210720.3", "HFJ_IDX_CMB_TOK_NU", "PID");
|
||||
cmpToks.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
cmpToks.addColumn("RES_ID").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
cmpToks.addColumn("HASH_COMPLETE").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
cmpToks.addColumn("IDX_STRING").nonNullable().type(ColumnTypeEnum.STRING, 500);
|
||||
cmpToks.addForeignKey("20210720.4", "FK_IDXCMBTOKNU_RES_ID").toColumn("RES_ID").references("HFJ_RESOURCE", "RES_ID");
|
||||
cmpToks.addIndex("20210720.5", "IDX_IDXCMBTOKNU_STR").unique(false).withColumns("IDX_STRING");
|
||||
cmpToks.addIndex("20210720.6", "IDX_IDXCMBTOKNU_RES").unique(false).withColumns("RES_ID");
|
||||
}
|
||||
|
||||
private void init540() {
|
||||
|
|
|
@ -43,6 +43,7 @@ import javax.persistence.Temporal;
|
|||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Transient;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@MappedSuperclass
|
||||
public abstract class BaseResourceIndexedSearchParam extends BaseResourceIndex {
|
||||
|
@ -182,6 +183,17 @@ public abstract class BaseResourceIndexedSearchParam extends BaseResourceIndex {
|
|||
return hash(thePartitionSettings, theRequestPartitionId, theResourceType, theParamName);
|
||||
}
|
||||
|
||||
public static long calculateHashIdentity(PartitionSettings thePartitionSettings, RequestPartitionId theRequestPartitionId, String theResourceType, String theParamName, List<String> theAdditionalValues) {
|
||||
String[] values = new String[theAdditionalValues.size() + 2];
|
||||
values[0] = theResourceType;
|
||||
values[1] = theParamName;
|
||||
for (int i = 0; i < theAdditionalValues.size(); i++) {
|
||||
values[i + 2] = theAdditionalValues.get(i);
|
||||
}
|
||||
|
||||
return hash(thePartitionSettings, theRequestPartitionId, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a fast and consistent hashing algorithm to a set of strings
|
||||
*/
|
||||
|
|
|
@ -32,10 +32,10 @@ import javax.persistence.*;
|
|||
|
||||
@Entity()
|
||||
@Table(name = "HFJ_IDX_CMP_STRING_UNIQ", indexes = {
|
||||
@Index(name = ResourceIndexedCompositeStringUnique.IDX_IDXCMPSTRUNIQ_STRING, columnList = "IDX_STRING", unique = true),
|
||||
@Index(name = ResourceIndexedCompositeStringUnique.IDX_IDXCMPSTRUNIQ_RESOURCE, columnList = "RES_ID", unique = false)
|
||||
@Index(name = ResourceIndexedComboStringUnique.IDX_IDXCMPSTRUNIQ_STRING, columnList = "IDX_STRING", unique = true),
|
||||
@Index(name = ResourceIndexedComboStringUnique.IDX_IDXCMPSTRUNIQ_RESOURCE, columnList = "RES_ID", unique = false)
|
||||
})
|
||||
public class ResourceIndexedCompositeStringUnique extends BasePartitionable implements Comparable<ResourceIndexedCompositeStringUnique> {
|
||||
public class ResourceIndexedComboStringUnique extends BasePartitionable implements Comparable<ResourceIndexedComboStringUnique> {
|
||||
|
||||
public static final int MAX_STRING_LENGTH = 500;
|
||||
public static final String IDX_IDXCMPSTRUNIQ_STRING = "IDX_IDXCMPSTRUNIQ_STRING";
|
||||
|
@ -66,14 +66,14 @@ public class ResourceIndexedCompositeStringUnique extends BasePartitionable impl
|
|||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedCompositeStringUnique() {
|
||||
public ResourceIndexedComboStringUnique() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedCompositeStringUnique(ResourceTable theResource, String theIndexString, IIdType theSearchParameterId) {
|
||||
public ResourceIndexedComboStringUnique(ResourceTable theResource, String theIndexString, IIdType theSearchParameterId) {
|
||||
setResource(theResource);
|
||||
setIndexString(theIndexString);
|
||||
setPartitionId(theResource.getPartitionId());
|
||||
|
@ -81,7 +81,7 @@ public class ResourceIndexedCompositeStringUnique extends BasePartitionable impl
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ResourceIndexedCompositeStringUnique theO) {
|
||||
public int compareTo(ResourceIndexedComboStringUnique theO) {
|
||||
CompareToBuilder b = new CompareToBuilder();
|
||||
b.append(myIndexString, theO.getIndexString());
|
||||
return b.toComparison();
|
||||
|
@ -91,11 +91,11 @@ public class ResourceIndexedCompositeStringUnique extends BasePartitionable impl
|
|||
public boolean equals(Object theO) {
|
||||
if (this == theO) return true;
|
||||
|
||||
if (!(theO instanceof ResourceIndexedCompositeStringUnique)) {
|
||||
if (!(theO instanceof ResourceIndexedComboStringUnique)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ResourceIndexedCompositeStringUnique that = (ResourceIndexedCompositeStringUnique) theO;
|
||||
ResourceIndexedComboStringUnique that = (ResourceIndexedComboStringUnique) theO;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(myIndexString, that.myIndexString)
|
|
@ -0,0 +1,190 @@
|
|||
package ca.uhn.fhir.jpa.model.entity;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Model
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||
* %%
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import static ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam.hash;
|
||||
|
||||
@Entity
|
||||
@Table(name = "HFJ_IDX_CMB_TOK_NU", indexes = {
|
||||
@Index(name = "IDX_IDXCMBTOKNU_STR", columnList = "IDX_STRING", unique = false),
|
||||
@Index(name = "IDX_IDXCMBTOKNU_RES", columnList = "RES_ID", unique = false)
|
||||
})
|
||||
public class ResourceIndexedComboTokenNonUnique extends BaseResourceIndex implements Comparable<ResourceIndexedComboTokenNonUnique> {
|
||||
|
||||
@SequenceGenerator(name = "SEQ_IDXCMBTOKNU_ID", sequenceName = "SEQ_IDXCMBTOKNU_ID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_IDXCMBTOKNU_ID")
|
||||
@Id
|
||||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_IDXCMBTOKNU_RES_ID"))
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
private Long myResourceId;
|
||||
|
||||
@Column(name = "HASH_COMPLETE", nullable = false)
|
||||
private Long myHashComplete;
|
||||
|
||||
@Column(name = "IDX_STRING", nullable = false, length = ResourceIndexedComboStringUnique.MAX_STRING_LENGTH)
|
||||
private String myIndexString;
|
||||
|
||||
@Transient
|
||||
private transient PartitionSettings myPartitionSettings;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedComboTokenNonUnique() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ResourceIndexedComboTokenNonUnique(PartitionSettings thePartitionSettings, ResourceTable theEntity, String theQueryString) {
|
||||
myPartitionSettings = thePartitionSettings;
|
||||
myResource = theEntity;
|
||||
myIndexString = theQueryString;
|
||||
}
|
||||
|
||||
public String getIndexString() {
|
||||
return myIndexString;
|
||||
}
|
||||
|
||||
public void setIndexString(String theIndexString) {
|
||||
myIndexString = theIndexString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object theO) {
|
||||
if (this == theO) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (theO == null || getClass() != theO.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ResourceIndexedComboTokenNonUnique that = (ResourceIndexedComboTokenNonUnique) theO;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(myResource, that.myResource)
|
||||
.append(myHashComplete, that.myHashComplete)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BaseResourceIndex> void copyMutableValuesFrom(T theSource) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(Long theId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateHashes() {
|
||||
PartitionSettings partitionSettings = getPartitionSettings();
|
||||
PartitionablePartitionId partitionId = getPartitionId();
|
||||
String queryString = myIndexString;
|
||||
setHashComplete(calculateHashComplete(partitionSettings, partitionId, queryString));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(myResource)
|
||||
.append(myHashComplete)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
public PartitionSettings getPartitionSettings() {
|
||||
return myPartitionSettings;
|
||||
}
|
||||
|
||||
public ResourceTable getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
public void setResource(ResourceTable theResource) {
|
||||
myResource = theResource;
|
||||
}
|
||||
|
||||
public Long getHashComplete() {
|
||||
return myHashComplete;
|
||||
}
|
||||
|
||||
public void setHashComplete(Long theHashComplete) {
|
||||
myHashComplete = theHashComplete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ResourceIndexedComboTokenNonUnique theO) {
|
||||
CompareToBuilder b = new CompareToBuilder();
|
||||
b.append(myHashComplete, theO.getHashComplete());
|
||||
return b.toComparison();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("id", myId)
|
||||
.append("resourceId", myResourceId)
|
||||
.append("hashComplete", myHashComplete)
|
||||
.append("indexString", myIndexString)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public static long calculateHashComplete(PartitionSettings partitionSettings, PartitionablePartitionId thePartitionId, String queryString) {
|
||||
RequestPartitionId requestPartitionId = PartitionablePartitionId.toRequestPartitionId(thePartitionId);
|
||||
return hash(partitionSettings, requestPartitionId, queryString);
|
||||
}
|
||||
|
||||
public static long calculateHashComplete(PartitionSettings partitionSettings, RequestPartitionId partitionId, String queryString) {
|
||||
return hash(partitionSettings, partitionId, queryString);
|
||||
}
|
||||
|
||||
}
|
|
@ -192,11 +192,20 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
// Added in 3.0.0 - Should make this a primitive Boolean at some point
|
||||
@OptimisticLock(excluded = true)
|
||||
@Column(name = "SP_CMPSTR_UNIQ_PRESENT")
|
||||
private Boolean myParamsCompositeStringUniquePresent = false;
|
||||
private Boolean myParamsComboStringUniquePresent = false;
|
||||
|
||||
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedCompositeStringUnique> myParamsCompositeStringUnique;
|
||||
private Collection<ResourceIndexedComboStringUnique> myParamsComboStringUnique;
|
||||
|
||||
// Added in 5.5.0 - Should make this a primitive Boolean at some point
|
||||
@OptimisticLock(excluded = true)
|
||||
@Column(name = "SP_CMPTOKS_PRESENT")
|
||||
private Boolean myParamsComboTokensNonUniquePresent = false;
|
||||
|
||||
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedComboTokenNonUnique> myParamsComboTokensNonUnique;
|
||||
|
||||
@OneToMany(mappedBy = "mySourceResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
|
@ -312,11 +321,18 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
myLanguage = theLanguage;
|
||||
}
|
||||
|
||||
public Collection<ResourceIndexedCompositeStringUnique> getParamsCompositeStringUnique() {
|
||||
if (myParamsCompositeStringUnique == null) {
|
||||
myParamsCompositeStringUnique = new ArrayList<>();
|
||||
public Collection<ResourceIndexedComboStringUnique> getParamsComboStringUnique() {
|
||||
if (myParamsComboStringUnique == null) {
|
||||
myParamsComboStringUnique = new ArrayList<>();
|
||||
}
|
||||
return myParamsCompositeStringUnique;
|
||||
return myParamsComboStringUnique;
|
||||
}
|
||||
|
||||
public Collection<ResourceIndexedComboTokenNonUnique> getmyParamsComboTokensNonUnique() {
|
||||
if (myParamsComboTokensNonUnique == null) {
|
||||
myParamsComboTokensNonUnique = new ArrayList<>();
|
||||
}
|
||||
return myParamsComboTokensNonUnique;
|
||||
}
|
||||
|
||||
public Collection<ResourceIndexedSearchParamCoords> getParamsCoords() {
|
||||
|
@ -494,15 +510,26 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
myHasLinks = theHasLinks;
|
||||
}
|
||||
|
||||
public boolean isParamsCompositeStringUniquePresent() {
|
||||
if (myParamsCompositeStringUniquePresent == null) {
|
||||
public boolean isParamsComboStringUniquePresent() {
|
||||
if (myParamsComboStringUniquePresent == null) {
|
||||
return false;
|
||||
}
|
||||
return myParamsCompositeStringUniquePresent;
|
||||
return myParamsComboStringUniquePresent;
|
||||
}
|
||||
|
||||
public void setParamsCompositeStringUniquePresent(boolean theParamsCompositeStringUniquePresent) {
|
||||
myParamsCompositeStringUniquePresent = theParamsCompositeStringUniquePresent;
|
||||
public void setParamsComboStringUniquePresent(boolean theParamsComboStringUniquePresent) {
|
||||
myParamsComboStringUniquePresent = theParamsComboStringUniquePresent;
|
||||
}
|
||||
|
||||
public boolean isParamsComboTokensNonUniquePresent() {
|
||||
if (myParamsComboTokensNonUniquePresent == null) {
|
||||
return false;
|
||||
}
|
||||
return myParamsComboTokensNonUniquePresent;
|
||||
}
|
||||
|
||||
public void setParamsComboTokensNonUniquePresent(boolean theParamsComboTokensNonUniquePresent) {
|
||||
myParamsComboStringUniquePresent = theParamsComboTokensNonUniquePresent;
|
||||
}
|
||||
|
||||
public boolean isParamsCoordsPopulated() {
|
||||
|
|
|
@ -93,7 +93,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
|
||||
public static final Set<String> COORDS_INDEX_PATHS;
|
||||
private static final Pattern SPLIT = Pattern.compile("\\||( or )");
|
||||
private static final Pattern SPLIT_R4 = Pattern.compile("\\|");
|
||||
private static final Pattern SPLIT_R4 = Pattern.compile("\\s+\\|");
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseSearchParamExtractor.class);
|
||||
|
||||
static {
|
||||
|
|
|
@ -26,7 +26,8 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
|||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||
|
@ -70,7 +71,8 @@ public final class ResourceIndexedSearchParams {
|
|||
final public Collection<ResourceIndexedSearchParamUri> myUriParams = new ArrayList<>();
|
||||
final public Collection<ResourceIndexedSearchParamCoords> myCoordsParams = new ArrayList<>();
|
||||
|
||||
final public Collection<ResourceIndexedCompositeStringUnique> myCompositeStringUniques = new HashSet<>();
|
||||
final public Collection<ResourceIndexedComboStringUnique> myComboStringUniques = new HashSet<>();
|
||||
final public Collection<ResourceIndexedComboTokenNonUnique> myComboTokenNonUnique = new HashSet<>();
|
||||
final public Collection<ResourceLink> myLinks = new HashSet<>();
|
||||
final public Set<String> myPopulatedResourceLinkParameters = new HashSet<>();
|
||||
|
||||
|
@ -106,8 +108,11 @@ public final class ResourceIndexedSearchParams {
|
|||
myLinks.addAll(theEntity.getResourceLinks());
|
||||
}
|
||||
|
||||
if (theEntity.isParamsCompositeStringUniquePresent()) {
|
||||
myCompositeStringUniques.addAll(theEntity.getParamsCompositeStringUnique());
|
||||
if (theEntity.isParamsComboStringUniquePresent()) {
|
||||
myComboStringUniques.addAll(theEntity.getParamsComboStringUnique());
|
||||
}
|
||||
if (theEntity.isParamsComboTokensNonUniquePresent()) {
|
||||
myComboTokenNonUnique.addAll(theEntity.getmyParamsComboTokensNonUnique());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +130,7 @@ public final class ResourceIndexedSearchParams {
|
|||
theEntity.setParamsDatePopulated(myDateParams.isEmpty() == false);
|
||||
theEntity.setParamsUriPopulated(myUriParams.isEmpty() == false);
|
||||
theEntity.setParamsCoordsPopulated(myCoordsParams.isEmpty() == false);
|
||||
theEntity.setParamsCompositeStringUniquePresent(myCompositeStringUniques.isEmpty() == false);
|
||||
theEntity.setParamsComboStringUniquePresent(myComboStringUniques.isEmpty() == false);
|
||||
theEntity.setHasLinks(myLinks.isEmpty() == false);
|
||||
}
|
||||
|
||||
|
@ -305,7 +310,8 @@ public final class ResourceIndexedSearchParams {
|
|||
", dateParams=" + myDateParams +
|
||||
", uriParams=" + myUriParams +
|
||||
", coordsParams=" + myCoordsParams +
|
||||
", compositeStringUniques=" + myCompositeStringUniques +
|
||||
", comboStringUniques=" + myComboStringUniques +
|
||||
", comboTokenNonUniques=" + myComboTokenNonUnique +
|
||||
", links=" + myLinks +
|
||||
'}';
|
||||
}
|
||||
|
@ -431,6 +437,9 @@ public final class ResourceIndexedSearchParams {
|
|||
List<String> values = new ArrayList<>();
|
||||
Set<String> queryStringsToPopulate = new HashSet<>();
|
||||
extractCompositeStringUniquesValueChains(theResourceType, thePartsChoices, values, queryStringsToPopulate);
|
||||
|
||||
values.removeIf(StringUtils::isBlank);
|
||||
|
||||
return queryStringsToPopulate;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,26 +40,25 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class JpaSearchParamCache {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(JpaSearchParamCache.class);
|
||||
|
||||
private volatile Map<String, List<RuntimeSearchParam>> myActiveUniqueSearchParams = Collections.emptyMap();
|
||||
private volatile Map<String, Map<Set<String>, List<RuntimeSearchParam>>> myActiveParamNamesToUniqueSearchParams = Collections.emptyMap();
|
||||
private volatile Map<String, List<RuntimeSearchParam>> myActiveComboSearchParams = Collections.emptyMap();
|
||||
private volatile Map<String, Map<Set<String>, List<RuntimeSearchParam>>> myActiveParamNamesToComboSearchParams = Collections.emptyMap();
|
||||
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
|
||||
List<RuntimeSearchParam> retval = myActiveUniqueSearchParams.get(theResourceName);
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
List<RuntimeSearchParam> retval = myActiveComboSearchParams.get(theResourceName);
|
||||
if (retval == null) {
|
||||
retval = Collections.emptyList();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
Map<Set<String>, List<RuntimeSearchParam>> paramNamesToParams = myActiveParamNamesToUniqueSearchParams.get(theResourceName);
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
Map<Set<String>, List<RuntimeSearchParam>> paramNamesToParams = myActiveParamNamesToComboSearchParams.get(theResourceName);
|
||||
if (paramNamesToParams == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
@ -72,8 +71,8 @@ public class JpaSearchParamCache {
|
|||
}
|
||||
|
||||
void populateActiveSearchParams(IInterceptorService theInterceptorBroadcaster, IPhoneticEncoder theDefaultPhoneticEncoder, RuntimeSearchParamCache theActiveSearchParams) {
|
||||
Map<String, List<RuntimeSearchParam>> activeUniqueSearchParams = new HashMap<>();
|
||||
Map<String, Map<Set<String>, List<RuntimeSearchParam>>> activeParamNamesToUniqueSearchParams = new HashMap<>();
|
||||
Map<String, List<RuntimeSearchParam>> resourceNameToComboSearchParams = new HashMap<>();
|
||||
Map<String, Map<Set<String>, List<RuntimeSearchParam>>> activeParamNamesToComboSearchParams = new HashMap<>();
|
||||
|
||||
Map<String, RuntimeSearchParam> idToRuntimeSearchParam = new HashMap<>();
|
||||
List<RuntimeSearchParam> jpaSearchParams = new ArrayList<>();
|
||||
|
@ -83,7 +82,7 @@ public class JpaSearchParamCache {
|
|||
*/
|
||||
for (String theResourceName : theActiveSearchParams.getResourceNameKeys()) {
|
||||
Map<String, RuntimeSearchParam> searchParamMap = theActiveSearchParams.getSearchParamMap(theResourceName);
|
||||
List<RuntimeSearchParam> uniqueSearchParams = activeUniqueSearchParams.computeIfAbsent(theResourceName, k -> new ArrayList<>());
|
||||
List<RuntimeSearchParam> comboSearchParams = resourceNameToComboSearchParams.computeIfAbsent(theResourceName, k -> new ArrayList<>());
|
||||
Collection<RuntimeSearchParam> nextSearchParamsForResourceName = searchParamMap.values();
|
||||
|
||||
ourLog.trace("Resource {} has {} params", theResourceName, searchParamMap.size());
|
||||
|
@ -99,10 +98,9 @@ public class JpaSearchParamCache {
|
|||
idToRuntimeSearchParam.put(nextCandidate.getUri(), nextCandidate);
|
||||
}
|
||||
|
||||
RuntimeSearchParam nextCandidateCasted = nextCandidate;
|
||||
jpaSearchParams.add(nextCandidateCasted);
|
||||
if (nextCandidateCasted.isUnique()) {
|
||||
uniqueSearchParams.add(nextCandidateCasted);
|
||||
jpaSearchParams.add(nextCandidate);
|
||||
if (nextCandidate.getComboSearchParamType() != null) {
|
||||
comboSearchParams.add(nextCandidate);
|
||||
}
|
||||
|
||||
setPhoneticEncoder(theDefaultPhoneticEncoder, nextCandidate);
|
||||
|
@ -137,19 +135,19 @@ public class JpaSearchParamCache {
|
|||
}
|
||||
}
|
||||
|
||||
if (next.isUnique()) {
|
||||
if (next.getComboSearchParamType() != null) {
|
||||
for (String nextBase : next.getBase()) {
|
||||
activeParamNamesToUniqueSearchParams.computeIfAbsent(nextBase, v -> new HashMap<>());
|
||||
activeParamNamesToUniqueSearchParams.get(nextBase).computeIfAbsent(paramNames, t -> new ArrayList<>());
|
||||
activeParamNamesToUniqueSearchParams.get(nextBase).get(paramNames).add(next);
|
||||
activeParamNamesToComboSearchParams.computeIfAbsent(nextBase, v -> new HashMap<>());
|
||||
activeParamNamesToComboSearchParams.get(nextBase).computeIfAbsent(paramNames, t -> new ArrayList<>());
|
||||
activeParamNamesToComboSearchParams.get(nextBase).get(paramNames).add(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ourLog.info("Have {} unique search params", activeParamNamesToUniqueSearchParams.size());
|
||||
ourLog.info("Have {} unique search params", activeParamNamesToComboSearchParams.size());
|
||||
|
||||
myActiveUniqueSearchParams = activeUniqueSearchParams;
|
||||
myActiveParamNamesToUniqueSearchParams = activeParamNamesToUniqueSearchParams;
|
||||
myActiveComboSearchParams = resourceNameToComboSearchParams;
|
||||
myActiveParamNamesToComboSearchParams = activeParamNamesToComboSearchParams;
|
||||
}
|
||||
|
||||
void setPhoneticEncoder(IPhoneticEncoder theDefaultPhoneticEncoder, RuntimeSearchParam searchParam) {
|
||||
|
|
|
@ -109,13 +109,13 @@ public class SearchParamRegistryImpl implements ISearchParamRegistry, IResourceC
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
|
||||
return myJpaSearchParamCache.getActiveUniqueSearchParams(theResourceName);
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
return myJpaSearchParamCache.getActiveComboSearchParams(theResourceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
return myJpaSearchParamCache.getActiveUniqueSearchParams(theResourceName, theParamNames);
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
return myJpaSearchParamCache.getActiveComboSearchParams(theResourceName, theParamNames);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.searchparam.registry;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.ComboSearchParamType;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.context.phonetic.PhoneticEncoderEnum;
|
||||
|
@ -148,14 +149,16 @@ public class SearchParameterCanonicalizer {
|
|||
|
||||
IIdType id = theNextSp.getIdElement();
|
||||
String uri = "";
|
||||
boolean unique = false;
|
||||
ComboSearchParamType unique = null;
|
||||
|
||||
List<ExtensionDt> uniqueExts = theNextSp.getUndeclaredExtensionsByUrl(HapiExtensions.EXT_SP_UNIQUE);
|
||||
if (uniqueExts.size() > 0) {
|
||||
IPrimitiveType<?> uniqueExtsValuePrimitive = uniqueExts.get(0).getValueAsPrimitive();
|
||||
if (uniqueExtsValuePrimitive != null) {
|
||||
if ("true".equalsIgnoreCase(uniqueExtsValuePrimitive.getValueAsString())) {
|
||||
unique = true;
|
||||
unique = ComboSearchParamType.UNIQUE;
|
||||
} else if ("false".equalsIgnoreCase(uniqueExtsValuePrimitive.getValueAsString())) {
|
||||
unique = ComboSearchParamType.NON_UNIQUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,14 +231,16 @@ public class SearchParameterCanonicalizer {
|
|||
|
||||
IIdType id = theNextSp.getIdElement();
|
||||
String uri = "";
|
||||
boolean unique = false;
|
||||
ComboSearchParamType unique = null;
|
||||
|
||||
List<Extension> uniqueExts = theNextSp.getExtensionsByUrl(HapiExtensions.EXT_SP_UNIQUE);
|
||||
if (uniqueExts.size() > 0) {
|
||||
IPrimitiveType<?> uniqueExtsValuePrimitive = uniqueExts.get(0).getValueAsPrimitive();
|
||||
if (uniqueExtsValuePrimitive != null) {
|
||||
if ("true".equalsIgnoreCase(uniqueExtsValuePrimitive.getValueAsString())) {
|
||||
unique = true;
|
||||
unique = ComboSearchParamType.UNIQUE;
|
||||
} else if ("false".equalsIgnoreCase(uniqueExtsValuePrimitive.getValueAsString())) {
|
||||
unique = ComboSearchParamType.NON_UNIQUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -311,7 +316,7 @@ public class SearchParameterCanonicalizer {
|
|||
|
||||
IIdType id = theNextSp.getIdElement();
|
||||
String uri = terser.getSinglePrimitiveValueOrNull(theNextSp, "url");
|
||||
boolean unique = false;
|
||||
ComboSearchParamType unique = null;
|
||||
|
||||
String value = ((IBaseHasExtensions) theNextSp).getExtension()
|
||||
.stream()
|
||||
|
@ -322,7 +327,9 @@ public class SearchParameterCanonicalizer {
|
|||
.findFirst()
|
||||
.orElse("");
|
||||
if ("true".equalsIgnoreCase(value)) {
|
||||
unique = true;
|
||||
unique = ComboSearchParamType.UNIQUE;
|
||||
} else if ("false".equalsIgnoreCase(value)) {
|
||||
unique = ComboSearchParamType.NON_UNIQUE;
|
||||
}
|
||||
|
||||
List<RuntimeSearchParam.Component> components = new ArrayList<>();
|
||||
|
|
|
@ -132,11 +132,11 @@ public class SearchParamExtractorDstu3Test {
|
|||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||
extractor.start();
|
||||
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
Patient resource = new Patient();
|
||||
extractor.extractSearchParamStrings(resource);
|
||||
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", null, RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", null, RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
extractor.extractSearchParamStrings(resource);
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ public class SearchParamExtractorDstu3Test {
|
|||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
|
||||
extractor.start();
|
||||
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "communication.language.coding.system | communication.language.coding.code", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "communication.language.coding.system | communication.language.coding.code", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
Patient resource = new Patient();
|
||||
resource.getCommunicationFirstRep().getLanguage().getCodingFirstRep().setCode("blah");
|
||||
Set<ResourceIndexedSearchParamString> strings = extractor.extractSearchParamStrings(resource);
|
||||
|
@ -166,37 +166,37 @@ public class SearchParamExtractorDstu3Test {
|
|||
extractor.start();
|
||||
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
Patient resource = new Patient();
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> outcome = extractor.extractSearchParamStrings(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.TOKEN, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.TOKEN, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
Patient resource = new Patient();
|
||||
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> outcome = extractor.extractSearchParamTokens(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.QUANTITY, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.QUANTITY, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
Patient resource = new Patient();
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> outcome = extractor.extractSearchParamQuantity(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.DATE, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.DATE, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
Patient resource = new Patient();
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> outcome = extractor.extractSearchParamDates(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.NUMBER, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.NUMBER, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
Patient resource = new Patient();
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> outcome = extractor.extractSearchParamNumber(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.URI, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.URI, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
Patient resource = new Patient();
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> outcome = extractor.extractSearchParamUri(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
|
@ -269,7 +269,7 @@ public class SearchParamExtractorDstu3Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -280,7 +280,7 @@ public class SearchParamExtractorDstu3Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@ public class SearchParamExtractorMegaTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -293,7 +293,7 @@ public class SearchParamExtractorMegaTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -59,13 +59,13 @@ public class InMemoryResourceMatcherR5Test {
|
|||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
RuntimeSearchParam dateSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.effective", RestSearchParameterTypeEnum.DATE, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null);
|
||||
RuntimeSearchParam dateSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.effective", RestSearchParameterTypeEnum.DATE, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "date")).thenReturn(dateSearchParam);
|
||||
|
||||
RuntimeSearchParam codeSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.code", RestSearchParameterTypeEnum.TOKEN, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null);
|
||||
RuntimeSearchParam codeSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.code", RestSearchParameterTypeEnum.TOKEN, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "code")).thenReturn(codeSearchParam);
|
||||
|
||||
RuntimeSearchParam encSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.encounter", RestSearchParameterTypeEnum.REFERENCE, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null);
|
||||
RuntimeSearchParam encSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.encounter", RestSearchParameterTypeEnum.REFERENCE, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "encounter")).thenReturn(encSearchParam);
|
||||
|
||||
myObservation = new Observation();
|
||||
|
|
|
@ -293,7 +293,7 @@ public class SearchParamRegistryImplTest {
|
|||
|
||||
@Test
|
||||
public void testGetActiveUniqueSearchParams_Empty() {
|
||||
assertThat(mySearchParamRegistry.getActiveUniqueSearchParams("Patient"), is(empty()));
|
||||
assertThat(mySearchParamRegistry.getActiveComboSearchParams("Patient"), is(empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -45,7 +45,7 @@ public class EIDHelperR4Test extends BaseR4Test {
|
|||
@BeforeEach
|
||||
public void before() {
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier"))
|
||||
.thenReturn(new RuntimeSearchParam(null, null, "identifier", "Description", "identifier", RestSearchParameterTypeEnum.STRING, new HashSet<>(), new HashSet<>(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
|
||||
.thenReturn(new RuntimeSearchParam(null, null, "identifier", "Description", "identifier", RestSearchParameterTypeEnum.STRING, new HashSet<>(), new HashSet<>(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
|
||||
myMdmSettings = new MdmSettings(new MdmRuleValidator(ourFhirContext, mySearchParamRetriever)) {
|
||||
{
|
||||
|
|
|
@ -496,7 +496,7 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
|||
Set<String> targets = Collections.emptySet();
|
||||
RuntimeSearchParam.RuntimeSearchParamStatusEnum status = RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE;
|
||||
Collection<String> base = Collections.singletonList(theSearchMethodBinding.getResourceName());
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(id, uri, nextParamName, description, path, type, providesMembershipInCompartments, targets, status, false, null, base);
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(id, uri, nextParamName, description, path, type, providesMembershipInCompartments, targets, status, null, null, base);
|
||||
theMapToPopulate.put(nextParamName, param);
|
||||
|
||||
}
|
||||
|
|
|
@ -70,11 +70,11 @@ public interface ISearchParamRegistry {
|
|||
default void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) {
|
||||
}
|
||||
|
||||
default List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
|
||||
default List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
default List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
default List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue