From 660c2bde72a0090507030c05a8aad09a23304db4 Mon Sep 17 00:00:00 2001
From: James Agnew
Date: Thu, 6 Apr 2017 22:23:20 -0400
Subject: [PATCH] More work on perf
---
.editorconfig | 11 +
.../java/ca/uhn/fhir/model/api/Include.java | 6 +-
.../java/ca/uhn/fhir/model/api/TagList.java | 4 +-
.../ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java | 50 ++--
.../ca/uhn/fhir/jpa/dao/SearchBuilder.java | 218 +++++-------------
.../jpa/dao/data/ISearchParamPresentDao.java | 2 +-
.../ca/uhn/fhir/jpa/entity/ResourceTable.java | 3 +
.../ca/uhn/fhir/jpa/entity/SearchParam.java | 2 +-
.../fhir/jpa/entity/SearchParamPresent.java | 10 +-
.../jpa/sp/SearchParamPresenceSvcImpl.java | 38 +--
.../java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java | 26 +--
.../FhirResourceDaoDstu3SearchNoFtTest.java | 20 +-
12 files changed, 148 insertions(+), 242 deletions(-)
diff --git a/.editorconfig b/.editorconfig
index c15d04c8487..499513576f9 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -3,19 +3,30 @@ root = true
[*]
end_of_line = lf
insert_final_newline = true
+tab_width = 3
+indent_size = 3
[*.java]
charset = utf-8
indent_style = tab
+tab_width = 3
+indent_size = 3
[*.xml]
charset = utf-8
indent_style = tab
+tab_width = 3
+indent_size = 3
[*.json]
charset = utf-8
indent_style = tab
+tab_width = 3
+indent_size = 3
[*.vm]
charset = utf-8
indent_style = tab
+tab_width = 3
+indent_size = 3
+
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Include.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Include.java
index f1fa8ea571c..d4f7cbfb469 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Include.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Include.java
@@ -3,6 +3,8 @@ package ca.uhn.fhir.model.api;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
+import java.io.Serializable;
+
import org.apache.commons.lang3.builder.ToStringBuilder;
/*
@@ -33,8 +35,10 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
* upgrading servers.
*
*/
-public class Include {
+public class Include implements Serializable {
+ private static final long serialVersionUID = 1L;
+
private final boolean myImmutable;
private boolean myRecurse;
private String myValue;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TagList.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TagList.java
index 9571ca98845..d0f7da498bc 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TagList.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/TagList.java
@@ -104,9 +104,9 @@ public class TagList implements Set, Serializable, IBase {
* Add a new tag instance
*
* @param theScheme
- * The tag scheme
+ * The tag scheme (the system)
* @param theTerm
- * The tag term
+ * The tag term (the code)
* @return Returns the newly created tag instance. Note that the tag is added to the list by this method, so you
* generally do not need to interact directly with the added tag.
*/
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java
index 0b9f21725aa..8e95ba357e8 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java
@@ -1235,6 +1235,7 @@ public abstract class BaseHapiFhirDao implements IDao {
Set coordsParams = null;
Set links = null;
+ Set populatedResourceLinkParameters = null;
if (theDeletedTimestampOrNull != null) {
stringParams = Collections.emptySet();
@@ -1334,7 +1335,7 @@ public abstract class BaseHapiFhirDao implements IDao {
}
links = new HashSet();
- Set populatedResourceLinkParameters = extractResourceLinks(theEntity, theResource, links, theUpdateTime);
+ populatedResourceLinkParameters = extractResourceLinks(theEntity, theResource, links, theUpdateTime);
/*
* If the existing resource already has links and those match links we still want, use them instead of removing them and re adding them
@@ -1374,28 +1375,6 @@ public abstract class BaseHapiFhirDao implements IDao {
theEntity.setIndexStatus(INDEX_STATUS_INDEXED);
populateFullTextFields(theResource, theEntity);
- /*
- * Update the "search param present" table which is used for the
- * ?foo:missing=true queries
- */
- Map presentSearchParams = new HashMap();
- for (String nextKey : populatedResourceLinkParameters) {
- presentSearchParams.put(nextKey, Boolean.TRUE);
- }
- updateSearchParamPresent(presentSearchParams, stringParams);
- updateSearchParamPresent(presentSearchParams, tokenParams);
- updateSearchParamPresent(presentSearchParams, numberParams);
- updateSearchParamPresent(presentSearchParams, quantityParams);
- updateSearchParamPresent(presentSearchParams, dateParams);
- updateSearchParamPresent(presentSearchParams, uriParams);
- updateSearchParamPresent(presentSearchParams, coordsParams);
- Set activeSearchParamNames = mySearchParamRegistry.getActiveSearchParams(theEntity.getResourceType()).keySet();
- for (String nextSpName : activeSearchParamNames) {
- if (!presentSearchParams.containsKey(nextSpName)) {
- presentSearchParams.put(nextSpName, Boolean.FALSE);
- }
- }
- mySearchParamPresenceSvc.updatePresence(theEntity, presentSearchParams);
} else {
@@ -1426,6 +1405,31 @@ public abstract class BaseHapiFhirDao implements IDao {
postUpdate(theEntity, (T) theResource);
}
+ /*
+ * Update the "search param present" table which is used for the
+ * ?foo:missing=true queries
+ */
+ if (thePerformIndexing) {
+ Map presentSearchParams = new HashMap();
+ for (String nextKey : populatedResourceLinkParameters) {
+ presentSearchParams.put(nextKey, Boolean.TRUE);
+ }
+ updateSearchParamPresent(presentSearchParams, stringParams);
+ updateSearchParamPresent(presentSearchParams, tokenParams);
+ updateSearchParamPresent(presentSearchParams, numberParams);
+ updateSearchParamPresent(presentSearchParams, quantityParams);
+ updateSearchParamPresent(presentSearchParams, dateParams);
+ updateSearchParamPresent(presentSearchParams, uriParams);
+ updateSearchParamPresent(presentSearchParams, coordsParams);
+ Set activeSearchParamNames = mySearchParamRegistry.getActiveSearchParams(theEntity.getResourceType()).keySet();
+ for (String nextSpName : activeSearchParamNames) {
+ if (!presentSearchParams.containsKey(nextSpName)) {
+ presentSearchParams.put(nextSpName, Boolean.FALSE);
+ }
+ }
+ mySearchParamPresenceSvc.updatePresence(theEntity, presentSearchParams);
+ }
+
/*
* Create history entry
*/
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java
index c7ab8d61158..216aa983ffa 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java
@@ -88,8 +88,6 @@ public class SearchBuilder {
private EntityManager myEntityManager;
private IForcedIdDao myForcedIdDao;
private SearchParameterMap myParams;
- private Collection myPids;
- private PlatformTransactionManager myPlatformTransactionManager;
private IResourceIndexedSearchParamUriDao myResourceIndexedSearchParamUriDao;
private String myResourceName;
private Class extends IBaseResource> myResourceType;
@@ -97,16 +95,12 @@ public class SearchBuilder {
private Search mySearchEntity;
private ISearchResultDao mySearchResultDao;
private ISearchParamRegistry mySearchParamRegistry;
-
private IHapiTerminologySvc myTerminologySvc;
-
private Root myResourceTableRoot;
-
private ArrayList myPredicates;
-
private CriteriaBuilder myBuilder;
-
private CriteriaQuery myResourceTableQuery;
+ private PlatformTransactionManager myPlatformTransactionManager;
public SearchBuilder(FhirContext theFhirContext, EntityManager theEntityManager, PlatformTransactionManager thePlatformTransactionManager, IFulltextSearchSvc theFulltextSearchSvc,
ISearchResultDao theSearchResultDao, BaseHapiFhirDao> theDao,
@@ -158,8 +152,8 @@ public class SearchBuilder {
private void addPredicateDate(String theParamName, List extends IQueryParameterType> theList) {
- if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
- addPredicateParamMissing("myParamsDate", theParamName, ResourceIndexedSearchParamDate.class);
+ if (theList.get(0).getMissing() != null) {
+ addPredicateParamMissing(theParamName, theList.get(0).getMissing());
return;
}
@@ -167,10 +161,6 @@ public class SearchBuilder {
List codePredicates = new ArrayList();
for (IQueryParameterType nextOr : theList) {
- if (addPredicateMissingFalseIfPresent(myBuilder, theParamName, join, codePredicates, nextOr)) {
- continue;
- }
-
IQueryParameterType params = nextOr;
Predicate p = createPredicateDate(myBuilder, join, params);
codePredicates.add(p);
@@ -304,40 +294,10 @@ public class SearchBuilder {
return;
}
- private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, From, ? extends BaseResourceIndexedSearchParam> from, List codePredicates,
- IQueryParameterType nextOr) {
- boolean missingFalse = false;
- if (nextOr.getMissing() != null) {
- if (nextOr.getMissing().booleanValue() == true) {
- throw new InvalidRequestException(myContext.getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
- }
- Predicate singleCode = from.get("myId").isNotNull();
- Predicate name = theBuilder.equal(from.get("myParamName"), theParamName);
- codePredicates.add(theBuilder.and(name, singleCode));
- missingFalse = true;
- }
- return missingFalse;
- }
-
- private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, From,? extends ResourceLink> from, List codePredicates,
- IQueryParameterType nextOr) {
- boolean missingFalse = false;
- if (nextOr.getMissing() != null) {
- if (nextOr.getMissing().booleanValue() == true) {
- throw new InvalidRequestException(myContext.getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
- }
- Predicate singleCode = from.get("mySourceResource").isNotNull();
- Predicate name = createResourceLinkPathPredicate(theParamName, from);
- codePredicates.add(theBuilder.and(name, singleCode));
- missingFalse = true;
- }
- return missingFalse;
- }
-
private void addPredicateNumber(String theParamName, List extends IQueryParameterType> theList) {
- if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
- addPredicateParamMissing("myParamsNumber", theParamName, ResourceIndexedSearchParamNumber.class);
+ if (theList.get(0).getMissing() != null) {
+ addPredicateParamMissing(theParamName, theList.get(0).getMissing());
return;
}
@@ -347,10 +307,6 @@ public class SearchBuilder {
for (IQueryParameterType nextOr : theList) {
IQueryParameterType params = nextOr;
- if (addPredicateMissingFalseIfPresent(myBuilder, theParamName, join, codePredicates, nextOr)) {
- continue;
- }
-
if (params instanceof NumberParam) {
NumberParam param = (NumberParam) params;
@@ -376,62 +332,18 @@ public class SearchBuilder {
myPredicates.add(myBuilder.or(toArray(codePredicates)));
}
- private void addPredicateParamMissing(String joinName, String theParamName, Class extends BaseResourceIndexedSearchParam> theParamTable) {
- CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
- CriteriaQuery cq = builder.createQuery(Long.class);
- Root from = cq.from(ResourceTable.class);
- cq.select(from.get("myId").as(Long.class));
+ private void addPredicateParamMissing(String theParamName, boolean theMissing) {
+ Join paramPresentJoin = myResourceTableRoot.join("mySearchParamPresents", JoinType.LEFT);
+ Join paramJoin = paramPresentJoin.join("mySearchParam", JoinType.LEFT);
- Subquery subQ = cq.subquery(Long.class);
- Root extends BaseResourceIndexedSearchParam> subQfrom = subQ.from(theParamTable);
- subQ.select(subQfrom.get("myResourcePid").as(Long.class));
- Predicate subQname = builder.equal(subQfrom.get("myParamName"), theParamName);
- Predicate subQtype = builder.equal(subQfrom.get("myResourceType"), myResourceName);
- subQ.where(builder.and(subQtype, subQname));
-
- List predicates = new ArrayList();
- predicates.add(builder.not(builder.in(from.get("myId")).value(subQ)));
- predicates.add(builder.equal(from.get("myResourceType"), myResourceName));
- predicates.add(builder.isNull(from.get("myDeleted")));
- createPredicateResourceId(builder, cq, predicates, from.get("myId").as(Long.class));
-
- cq.where(builder.and(toArray(predicates)));
-
- ourLog.info("Adding :missing qualifier for parameter '{}'", theParamName);
-
- TypedQuery q = myEntityManager.createQuery(cq);
- doSetPids(q.getResultList());
- }
-
- private void addPredicateParamMissingResourceLink(String joinName, String theParamName) {
- CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
- CriteriaQuery cq = builder.createQuery(Long.class);
- Root from = cq.from(ResourceTable.class);
- cq.select(from.get("myId").as(Long.class));
-
- Subquery subQ = cq.subquery(Long.class);
- Root subQfrom = subQ.from(ResourceLink.class);
- subQ.select(subQfrom.get("mySourceResourcePid").as(Long.class));
-
- // subQ.where(builder.equal(subQfrom.get("myParamName"), theParamName));
- Predicate path = createResourceLinkPathPredicate(theParamName, subQfrom);
- subQ.where(path);
-
- List predicates = new ArrayList();
- createPredicateResourceId(builder, cq, predicates, from.get("myId").as(Long.class));
- predicates.add(builder.not(builder.in(from.get("myId")).value(subQ)));
- predicates.add(builder.equal(from.get("myResourceType"), myResourceName));
-
- cq.where(builder.and(toArray(predicates)));
-
- TypedQuery q = myEntityManager.createQuery(cq);
- List resultList = q.getResultList();
- doSetPids(new HashSet(resultList));
+ myPredicates.add(myBuilder.equal(paramJoin.get("myResourceName"), myResourceName));
+ myPredicates.add(myBuilder.equal(paramJoin.get("myParamName"), theParamName));
+ myPredicates.add(myBuilder.equal(paramPresentJoin.get("myPresent"), !theMissing));
}
private void addPredicateQuantity(String theParamName, List extends IQueryParameterType> theList) {
- if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
- addPredicateParamMissing("myParamsQuantity", theParamName, ResourceIndexedSearchParamQuantity.class);
+ if (theList.get(0).getMissing() != null) {
+ addPredicateParamMissing(theParamName, theList.get(0).getMissing());
return;
}
@@ -439,9 +351,6 @@ public class SearchBuilder {
List codePredicates = new ArrayList();
for (IQueryParameterType nextOr : theList) {
- if (addPredicateMissingFalseIfPresent(myBuilder, theParamName, join, codePredicates, nextOr)) {
- continue;
- }
Predicate singleCode = createPredicateQuantity(myBuilder, join, nextOr);
codePredicates.add(singleCode);
@@ -453,8 +362,8 @@ public class SearchBuilder {
private void addPredicateReference(String theParamName, List extends IQueryParameterType> theList) {
assert theParamName.contains(".") == false;
- if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
- addPredicateParamMissingResourceLink("myResourceLinks", theParamName);
+ if (theList.get(0).getMissing() != null) {
+ addPredicateParamMissing(theParamName, theList.get(0).getMissing());
return;
}
@@ -465,10 +374,6 @@ public class SearchBuilder {
for (IQueryParameterType nextOr : theList) {
IQueryParameterType params = nextOr;
- if (addPredicateMissingFalseIfPresentForResourceLink(myBuilder, theParamName, join, codePredicates, nextOr)) {
- continue;
- }
-
if (params instanceof ReferenceParam) {
ReferenceParam ref = (ReferenceParam) params;
@@ -585,34 +490,34 @@ public class SearchBuilder {
}
foundChainMatch = true;
-// Set pids = dao.searchForIds(chain, chainValue);
+ // Set pids = dao.searchForIds(chain, chainValue);
Subquery subQ = myResourceTableQuery.subquery(Long.class);
Root subQfrom = subQ.from(ResourceTable.class);
subQ.select(subQfrom.get("myId").as(Long.class));
-
+
List> andOrParams = new ArrayList>();
andOrParams.add(Collections.singletonList(chainValue));
/*
* We're doing a chain call, so push the current query root
* and predicate list down and put new ones at the top of the
- * stack and run a subuery
+ * stack and run a subuery
*/
Root stackRoot = myResourceTableRoot;
ArrayList stackPredicates = myPredicates;
myResourceTableRoot = subQfrom;
myPredicates = new ArrayList();
-
+
searchForIdsWithAndOr(chain, andOrParams);
subQ.where(toArray(myPredicates));
-
+
/*
* Pop the old query root and predicate list back
*/
myResourceTableRoot = stackRoot;
myPredicates = stackPredicates;
-
+
Predicate eq = join.get("myTargetResourcePid").in(subQ);
codePredicates.add(eq);
@@ -633,20 +538,16 @@ public class SearchBuilder {
}
private void addPredicateString(String theParamName, List extends IQueryParameterType> theList) {
- if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
- addPredicateParamMissing("myParamsString", theParamName, ResourceIndexedSearchParamString.class);
+ if (theList.get(0).getMissing() != null) {
+ addPredicateParamMissing(theParamName, theList.get(0).getMissing());
return;
}
Join join = myResourceTableRoot.join("myParamsString", JoinType.LEFT);
-
+
List codePredicates = new ArrayList();
for (IQueryParameterType nextOr : theList) {
IQueryParameterType theParameter = nextOr;
- if (addPredicateMissingFalseIfPresent(myBuilder, theParamName, join, codePredicates, nextOr)) {
- continue;
- }
-
Predicate singleCode = createPredicateString(theParameter, theParamName, myBuilder, join);
codePredicates.add(singleCode);
}
@@ -775,7 +676,7 @@ public class SearchBuilder {
Join tagJoin = myResourceTableRoot.join("myTags", JoinType.LEFT);
From defJoin = tagJoin.join("myTag");
-
+
List orPredicates = createPredicateTagList(defJoin, myBuilder, tagType, tokens);
myPredicates.add(myBuilder.or(toArray(orPredicates)));
@@ -785,8 +686,8 @@ public class SearchBuilder {
private void addPredicateToken(String theParamName, List extends IQueryParameterType> theList) {
- if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
- addPredicateParamMissing("myParamsToken", theParamName, ResourceIndexedSearchParamToken.class);
+ if (theList.get(0).getMissing() != null) {
+ addPredicateParamMissing(theParamName, theList.get(0).getMissing());
return;
}
@@ -794,9 +695,6 @@ public class SearchBuilder {
List codePredicates = new ArrayList();
for (IQueryParameterType nextOr : theList) {
- if (addPredicateMissingFalseIfPresent(myBuilder, theParamName, join, codePredicates, nextOr)) {
- continue;
- }
if (nextOr instanceof TokenParam) {
TokenParam id = (TokenParam) nextOr;
@@ -822,8 +720,8 @@ public class SearchBuilder {
}
private void addPredicateUri(String theParamName, List extends IQueryParameterType> theList) {
- if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
- addPredicateParamMissing("myParamsUri", theParamName, ResourceIndexedSearchParamUri.class);
+ if (theList.get(0).getMissing() != null) {
+ addPredicateParamMissing(theParamName, theList.get(0).getMissing());
return;
}
@@ -833,10 +731,6 @@ public class SearchBuilder {
for (IQueryParameterType nextOr : theList) {
IQueryParameterType params = nextOr;
- if (addPredicateMissingFalseIfPresent(myBuilder, theParamName, join, codePredicates, nextOr)) {
- continue;
- }
-
if (params instanceof UriParam) {
UriParam param = (UriParam) params;
@@ -1265,7 +1159,7 @@ public class SearchBuilder {
return singleCode;
}
- private Predicate createResourceLinkPathPredicate(String theParamName, From,? extends ResourceLink> from) {
+ private Predicate createResourceLinkPathPredicate(String theParamName, From, ? extends ResourceLink> from) {
return createResourceLinkPathPredicate(myCallingDao, myContext, theParamName, from, myResourceType);
}
@@ -1368,10 +1262,6 @@ public class SearchBuilder {
thePredicates.add(theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName()));
}
- // Predicate p = theBuilder.equal(stringJoin.get("myParamName"), theSort.getParamName());
- // Predicate pn = theBuilder.isNull(stringJoin.get("myParamName"));
- // thePredicates.add(theBuilder.or(p, pn));
-
for (String next : sortAttrName) {
if (theSort.getOrder() == null || theSort.getOrder() == SortOrderEnum.ASC) {
theOrders.add(theBuilder.asc(stringJoin.get(next)));
@@ -1565,30 +1455,30 @@ public class SearchBuilder {
mySearchEntity.setSearchType(myParams.getEverythingMode() != null ? SearchTypeEnum.EVERYTHING : SearchTypeEnum.SEARCH);
mySearchEntity.setLastUpdated(myParams.getLastUpdated());
mySearchEntity.setResourceType(myResourceName);
-
+
for (Include next : myParams.getIncludes()) {
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), false, next.isRecurse()));
}
for (Include next : myParams.getRevIncludes()) {
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), true, next.isRecurse()));
}
-
+
List firstPage = loadSearchPage(theParams, 0, 999);
mySearchEntity.setTotalCount(firstPage.size());
-
+
myEntityManager.persist(mySearchEntity);
for (SearchInclude next : mySearchEntity.getIncludes()) {
myEntityManager.persist(next);
}
-
+
IBundleProvider retVal = doReturnProvider();
-
+
ourLog.info("Search initial phase completed in {}ms", w);
return retVal;
}
public List loadSearchPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {
-
+
if (myFulltextSearchSvc == null) {
if (theParams.containsKey(Constants.PARAM_TEXT)) {
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_TEXT);
@@ -1613,28 +1503,28 @@ public class SearchBuilder {
myPredicates = new ArrayList();
myPredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), myResourceName));
myPredicates.add(myBuilder.isNull(myResourceTableRoot.get("myDeleted")));
-
+
DateRangeParam lu = theParams.getLastUpdated();
List lastUpdatedPredicates = createLastUpdatedPredicates(lu, myBuilder, myResourceTableRoot);
myPredicates.addAll(lastUpdatedPredicates);
-
+
searchForIdsWithAndOr(theParams);
-
+
myResourceTableQuery.where(myBuilder.and(SearchBuilder.toArray(myPredicates)));
myResourceTableQuery.multiselect(myResourceTableRoot.get("myId").as(Long.class));
TypedQuery query = myEntityManager.createQuery(myResourceTableQuery);
query.setFirstResult(theFromIndex);
query.setMaxResults(theToIndex - theFromIndex);
-
+
List pids = new ArrayList();
for (Tuple next : query.getResultList()) {
pids.add(next.get(0, Long.class));
}
- return pids;
+ return pids;
}
-
+
public IBundleProvider loadPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {
StopWatch sw = new StopWatch();
DateRangeParam lu = theParams.getLastUpdated();
@@ -1702,9 +1592,8 @@ public class SearchBuilder {
}
}
-
if (!theParams.isEmpty()) {
-// searchForIdsWithAndOr(theParams, lu);
+ // searchForIdsWithAndOr(theParams, lu);
}
}
@@ -1729,7 +1618,7 @@ public class SearchBuilder {
return doReturnProvider();
}
-
+
private void searchForIdsWithAndOr(SearchParameterMap theParams) {
SearchParameterMap params = theParams;
if (params == null) {
@@ -1810,7 +1699,7 @@ public class SearchBuilder {
addPredicateUri(nextParamName, nextAnd);
}
break;
- case HAS:
+ case HAS:
// should not happen
break;
}
@@ -1834,21 +1723,20 @@ public class SearchBuilder {
orPids.add(entity.getId());
}
} catch (ResourceNotFoundException e) {
- /*
+ /*
* This isn't an error, just means no result found
* that matches the ID the client provided
*/
}
}
}
-
- if (orPids.size() > 0) {
- Predicate nextPredicate = myResourceTableRoot.get("myId").as(Long.class).in(orPids);
- myPredicates.add(nextPredicate);
- }
-
}
-
+
+ if (orPids.size() > 0) {
+ Predicate nextPredicate = myResourceTableRoot.get("myId").as(Long.class).in(orPids);
+ myPredicates.add(nextPredicate);
+ }
+
}
}
@@ -1942,7 +1830,7 @@ public class SearchBuilder {
return likeExpression.replace("%", "[%]") + "%";
}
- private static Predicate createResourceLinkPathPredicate(IDao theCallingDao, FhirContext theContext, String theParamName, From,? extends ResourceLink> from,
+ private static Predicate createResourceLinkPathPredicate(IDao theCallingDao, FhirContext theContext, String theParamName, From, ? extends ResourceLink> from,
Class extends IBaseResource> resourceType) {
RuntimeResourceDefinition resourceDef = theContext.getResourceDefinition(resourceType);
RuntimeSearchParam param = theCallingDao.getSearchParamByName(resourceDef, theParamName);
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ISearchParamPresentDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ISearchParamPresentDao.java
index 1290e524da1..dceaf04331c 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ISearchParamPresentDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ISearchParamPresentDao.java
@@ -32,7 +32,7 @@ import ca.uhn.fhir.jpa.entity.SearchParamPresent;
public interface ISearchParamPresentDao extends JpaRepository {
- @Query("SELECT s FROM SearchParamPresent s WHERE s.myResourceTable = :res")
+ @Query("SELECT s FROM SearchParamPresent s WHERE s.myResource = :res")
public Collection findAllForResource(@Param("res") ResourceTable theResource);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTable.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTable.java
index 4a4250a57c1..5757cbb64dd 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTable.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceTable.java
@@ -236,6 +236,9 @@ public class ResourceTable extends BaseHasResource implements Serializable {
@OneToMany(mappedBy = "myResource", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private Set myTags;
+ @OneToMany(mappedBy = "myResource", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
+ private Collection mySearchParamPresents;
+
@Column(name = "RES_VER")
private long myVersion;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SearchParam.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SearchParam.java
index 548e83ebee2..1c5d55cc8f3 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SearchParam.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SearchParam.java
@@ -11,7 +11,7 @@ public class SearchParam {
@Id
@SequenceGenerator(name = "SEQ_SEARCHPARM_ID", sequenceName = "SEQ_SEARCHPARM_ID")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SEARCHPARM_ID")
- @Column(name = "RES_ID")
+ @Column(name = "PID")
private Long myId;
@Column(name="PARAM_NAME", length=BaseResourceIndexedSearchParam.MAX_SP_NAME, nullable=false, updatable=false)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SearchParamPresent.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SearchParamPresent.java
index 1b7b283f6f6..7db7d707f32 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SearchParamPresent.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SearchParamPresent.java
@@ -25,14 +25,14 @@ public class SearchParamPresent implements Serializable {
@ManyToOne()
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, foreignKey = @ForeignKey(name = "FK_RESPARMPRES_RESID"))
- private ResourceTable myResourceTable;
+ private ResourceTable myResource;
@ManyToOne()
@JoinColumn(name = "SP_ID", referencedColumnName = "PID", nullable = false, foreignKey = @ForeignKey(name = "FK_RESPARMPRES_SPID"))
private SearchParam mySearchParam;
- public ResourceTable getResourceTable() {
- return myResourceTable;
+ public ResourceTable getResource() {
+ return myResource;
}
public SearchParam getSearchParam() {
@@ -47,8 +47,8 @@ public class SearchParamPresent implements Serializable {
myPresent = thePresent;
}
- public void setResourceTable(ResourceTable theResourceTable) {
- myResourceTable = theResourceTable;
+ public void setResource(ResourceTable theResourceTable) {
+ myResource = theResourceTable;
}
public void setSearchParam(SearchParam theSearchParam) {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/sp/SearchParamPresenceSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/sp/SearchParamPresenceSvcImpl.java
index ad5ffe15030..55d5e846012 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/sp/SearchParamPresenceSvcImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/sp/SearchParamPresenceSvcImpl.java
@@ -16,23 +16,29 @@ import ca.uhn.fhir.jpa.entity.SearchParamPresent;
public class SearchParamPresenceSvcImpl implements ISearchParamPresenceSvc {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamPresenceSvcImpl.class);
-
- private Map, SearchParam> myResourceTypeToSearchParamToEntity = new ConcurrentHashMap, SearchParam>();
-
+
+ private Map, SearchParam> myResourceTypeToSearchParamToEntity = new ConcurrentHashMap, SearchParam>();
+
@Autowired
private ISearchParamDao mySearchParamDao;
-
+
@Autowired
private ISearchParamPresentDao mySearchParamPresentDao;
@Override
public void updatePresence(ResourceTable theResource, Map theParamNameToPresence) {
-
+
Map presenceMap = new HashMap(theParamNameToPresence);
List entitiesToSave = new ArrayList();
List entitiesToDelete = new ArrayList();
-
- Collection existing = mySearchParamPresentDao.findAllForResource(theResource);
+
+ Collection existing;
+// if (theResource.getId() != null) {
+ existing = mySearchParamPresentDao.findAllForResource(theResource);
+// } else {
+// existing = Collections.emptyList();
+// }
+
for (SearchParamPresent nextExistingEntity : existing) {
String nextSearchParamName = nextExistingEntity.getSearchParam().getParamName();
Boolean existingValue = presenceMap.remove(nextSearchParamName);
@@ -45,12 +51,12 @@ public class SearchParamPresenceSvcImpl implements ISearchParamPresenceSvc {
entitiesToSave.add(nextExistingEntity);
}
}
-
+
for (Entry next : presenceMap.entrySet()) {
- String resourceType = theResource.getResourceType();
+ String resourceType = theResource.getResourceType();
String paramName = next.getKey();
Pair key = Pair.of(resourceType, paramName);
-
+
SearchParam searchParam = myResourceTypeToSearchParamToEntity.get(key);
if (searchParam == null) {
searchParam = mySearchParamDao.findForResource(resourceType, paramName);
@@ -63,19 +69,19 @@ public class SearchParamPresenceSvcImpl implements ISearchParamPresenceSvc {
mySearchParamDao.save(searchParam);
// Don't add the newly saved entity to the map in case the save fails
}
-
+
SearchParamPresent present = new SearchParamPresent();
- present.setResourceTable(theResource);
+ present.setResource(theResource);
present.setSearchParam(searchParam);
present.setPresent(next.getValue());
entitiesToSave.add(present);
}
-
+
mySearchParamPresentDao.deleteInBatch(entitiesToDelete);
mySearchParamPresentDao.save(entitiesToSave);
-
+
}
-
+
}
-
+
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java
index fab33bd1fc7..fc57677dbbf 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java
@@ -30,28 +30,7 @@ import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.jpa.entity.ForcedId;
-import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
-import ca.uhn.fhir.jpa.entity.ResourceHistoryTag;
-import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
-import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
-import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
-import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
-import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
-import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
-import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
-import ca.uhn.fhir.jpa.entity.ResourceLink;
-import ca.uhn.fhir.jpa.entity.ResourceTable;
-import ca.uhn.fhir.jpa.entity.ResourceTag;
-import ca.uhn.fhir.jpa.entity.SearchInclude;
-import ca.uhn.fhir.jpa.entity.SearchResult;
-import ca.uhn.fhir.jpa.entity.SubscriptionFlaggedResource;
-import ca.uhn.fhir.jpa.entity.SubscriptionTable;
-import ca.uhn.fhir.jpa.entity.TagDefinition;
-import ca.uhn.fhir.jpa.entity.TermCodeSystem;
-import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
-import ca.uhn.fhir.jpa.entity.TermConcept;
-import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
+import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
import ca.uhn.fhir.jpa.term.VersionIndependentConcept;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
@@ -225,6 +204,9 @@ public abstract class BaseJpaTest {
txTemplate.execute(new TransactionCallback() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
+ entityManager.createQuery("DELETE from " + SearchParamPresent.class.getSimpleName() + " d").executeUpdate();
+ entityManager.createQuery("DELETE from " + SearchParam.class.getSimpleName() + " d").executeUpdate();
+ entityManager.createQuery("DELETE from " + SubscriptionFlaggedResource.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + SubscriptionFlaggedResource.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ForcedId.class.getSimpleName() + " d").executeUpdate();
entityManager.createQuery("DELETE from " + ResourceIndexedSearchParamDate.class.getSimpleName() + " d").executeUpdate();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java
index 7c2c8e25845..d49b07b899d 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java
@@ -1747,27 +1747,27 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
String methodName = "testSearchValueQuantity";
String id1;
- {
+ {
Observation o = new Observation();
o.getCode().addCoding().setSystem("urn:foo").setCode(methodName + "code");
Quantity q = new Quantity().setSystem("urn:bar:" + methodName).setCode(methodName + "units").setValue(100);
o.setValue(q);
id1 = myObservationDao.create(o, mySrd).getId().toUnqualifiedVersionless().getValue();
}
-
+
String id2;
- {
+ {
Observation o = new Observation();
o.getCode().addCoding().setSystem("urn:foo").setCode(methodName + "code");
Quantity q = new Quantity().setSystem("urn:bar:" + methodName).setCode(methodName + "units").setValue(5);
o.setValue(q);
id2 = myObservationDao.create(o, mySrd).getId().toUnqualifiedVersionless().getValue();
}
-
+
Map map = new HashMap();
IBundleProvider found;
QuantityParam param;
-
+
param = new QuantityParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
map.put(Observation.SP_VALUE_QUANTITY, param);
found = myObservationDao.search(map);
@@ -2146,8 +2146,8 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
param.setMissing(false);
params.put(Patient.SP_BIRTHDATE, param);
List patients = toUnqualifiedVersionlessIds(myPatientDao.search(params));
- assertThat(patients, not(containsInRelativeOrder(missing)));
assertThat(patients, containsInRelativeOrder(notMissing));
+ assertThat(patients, not(containsInRelativeOrder(missing)));
}
{
Map params = new HashMap();
@@ -2158,6 +2158,14 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
assertThat(patients, containsInRelativeOrder(missing));
assertThat(patients, not(containsInRelativeOrder(notMissing)));
}
+ // {
+ // Map params = new HashMap();
+ // DateParam param = new DateParam();
+ // param.setMissing(true);
+ // params.put(Patient.SP_DECEASED, param);
+ // List patients = toUnqualifiedVersionlessIds(myPatientDao.search(params));
+ // assertThat(patients, containsInRelativeOrder(missing, notMissing));
+ // }
}
@Test