From f86a4c9fa1cad9b1c3e2dd39ac400812ef3568f6 Mon Sep 17 00:00:00 2001
From: Gary Graham
- * Should searches use the integer field {@code SP_VALUE_LOW_DATE_ORDINAL} and {@code SP_VALUE_HIGH_DATE_ORDINAL} in
- * {@link ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate} when resolving searches where all predicates are using
- * precision of {@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#DAY}.
- *
- * For example, if enabled, the search of {@code Observation?date=2020-02-25} will cause the date to be collapsed down to an
- * ordinal {@code 20200225}. It would then be compared against {@link ResourceIndexedSearchParamDate#getValueLowDateOrdinal()}
- * and {@link ResourceIndexedSearchParamDate#getValueHighDateOrdinal()}
- *
- * Should searches use the integer field {@code SP_VALUE_LOW_DATE_ORDINAL} and {@code SP_VALUE_HIGH_DATE_ORDINAL} in - * {@link ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate} when resolving searches where all predicates are using - * precision of {@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#DAY}. - * - * For example, if enabled, the search of {@code Observation?date=2020-02-25} will cause the date to be collapsed down to an - * integer representing the ordinal date {@code 20200225}. It would then be compared against {@link ResourceIndexedSearchParamDate#getValueLowDateOrdinal()} - * and {@link ResourceIndexedSearchParamDate#getValueHighDateOrdinal()} - *
- * Default is {@literal true} beginning in HAPI FHIR 4.3. - * - * - * @since 4.3 - */ - public boolean getUseOrdinalDatesForDayPrecisionSearches() { - return myUseOrdinalDatesForDayPrecisionSearches; - } public enum StoreMetaSourceInformationEnum { NONE(false, false), diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/BasePredicateBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/BasePredicateBuilder.java index f5c6c0480ba..6c613e684bb 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/BasePredicateBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/BasePredicateBuilder.java @@ -50,6 +50,7 @@ abstract class BasePredicateBuilder { @Autowired DaoConfig myDaoConfig; + boolean myDontUseHashesForSearch; final IDao myCallingDao; final CriteriaBuilder myBuilder; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderDate.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderDate.java index dade7a7fbbe..d8bfb3a7876 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderDate.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderDate.java @@ -171,7 +171,7 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi * If all present search parameters are of DAY precision, and {@link DaoConfig#getUseOrdinalDatesForDayPrecisionSearches()} is true, * then we attempt to use the ordinal field for date comparisons instead of the date field. */ - boolean isOrdinalComparison = isNullOrDayPrecision(lowerBound) && isNullOrDayPrecision(upperBound) && myDaoConfig.getUseOrdinalDatesForDayPrecisionSearches(); + boolean isOrdinalComparison = isNullOrDayPrecision(lowerBound) && isNullOrDayPrecision(upperBound) && myDaoConfig.getModelConfig().getUseOrdinalDatesForDayPrecisionSearches(); Predicate lt = null; Predicate gt = null; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherR4Test.java index ee88580d9d6..bb98b5de8d9 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherR4Test.java @@ -884,10 +884,10 @@ public class InMemorySubscriptionMatcherR4Test { public void testDateSearchParametersShouldBeTimezoneIndependent() { Listtrue
(default is true) the server will match incoming resources against active subscriptions
* and send them to the subscription channel. If set to false
no matching or sending occurs.
* @since 3.7.0
*/
-
-
public void setSubscriptionMatchingEnabled(boolean theSubscriptionMatchingEnabled) {
mySubscriptionMatchingEnabled = theSubscriptionMatchingEnabled;
}
@@ -388,6 +390,43 @@ public class ModelConfig {
myWebsocketContextPath = theWebsocketContextPath;
}
+ /**
+ * + * Should searches use the integer field {@code SP_VALUE_LOW_DATE_ORDINAL} and {@code SP_VALUE_HIGH_DATE_ORDINAL} in + * {@link ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate} when resolving searches where all predicates are using + * precision of {@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#DAY}. + * + * For example, if enabled, the search of {@code Observation?date=2020-02-25} will cause the date to be collapsed down to an + * ordinal {@code 20200225}. It would then be compared against {@link ResourceIndexedSearchParamDate#getValueLowDateOrdinal()} + * and {@link ResourceIndexedSearchParamDate#getValueHighDateOrdinal()} + *
+ * Default is {@literal true} beginning in HAPI FHIR 4.3. + * + * + * @since 4.3 + */ + public void setUseOrdinalDatesForDayPrecisionSearches(boolean theUseOrdinalDates) { + myUseOrdinalDatesForDayPrecisionSearches = theUseOrdinalDates; + } + + /** + *+ * Should searches use the integer field {@code SP_VALUE_LOW_DATE_ORDINAL} and {@code SP_VALUE_HIGH_DATE_ORDINAL} in + * {@link ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate} when resolving searches where all predicates are using + * precision of {@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#DAY}. + * + * For example, if enabled, the search of {@code Observation?date=2020-02-25} will cause the date to be collapsed down to an + * integer representing the ordinal date {@code 20200225}. It would then be compared against {@link ResourceIndexedSearchParamDate#getValueLowDateOrdinal()} + * and {@link ResourceIndexedSearchParamDate#getValueHighDateOrdinal()} + *
+ * Default is {@literal true} beginning in HAPI FHIR 4.3. + * + * + * @since 4.3 + */ + public boolean getUseOrdinalDatesForDayPrecisionSearches() { + return myUseOrdinalDatesForDayPrecisionSearches; + } private static void validateTreatBaseUrlsAsLocal(String theUrl) { Validate.notBlank(theUrl, "Base URL must not be null or empty"); diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamDate.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamDate.java index abb132d093d..9b2b4c93129 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamDate.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamDate.java @@ -35,7 +35,6 @@ import org.hibernate.search.annotations.Field; import org.hl7.fhir.r4.model.DateTimeType; import javax.persistence.*; -import java.text.SimpleDateFormat; import java.util.Date; @Embeddable @@ -238,21 +237,33 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar } @Override - public boolean matches(IQueryParameterType theParam) { + public boolean matches(IQueryParameterType theParam, boolean theUseOrdinalDatesForDayComparison) { if (!(theParam instanceof DateParam)) { return false; } DateParam dateParam = (DateParam) theParam; DateRangeParam range = new DateRangeParam(dateParam); + + + + boolean result; + if (theUseOrdinalDatesForDayComparison) { + result = matchesOrdinalDateBounds(range); + } else { + result = matchesDateBounds(range); + } + + return result; + } + + private boolean matchesDateBounds(DateRangeParam range) { Date lowerBound = range.getLowerBoundAsInstant(); Date upperBound = range.getUpperBoundAsInstant(); - if (lowerBound == null && upperBound == null) { // should never happen return false; } - boolean result = true; if (lowerBound != null) { result &= (myValueLow.after(lowerBound) || myValueLow.equals(lowerBound)); @@ -265,8 +276,27 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar return result; } + private boolean matchesOrdinalDateBounds(DateRangeParam range) { + boolean result = true; + Integer lowerBoundAsDateInteger = range.getLowerBoundAsDateInteger(); + Integer upperBoundAsDateInteger = range.getUpperBoundAsDateInteger(); + if (upperBoundAsDateInteger == null && lowerBoundAsDateInteger == null) { + return false; + } + if (lowerBoundAsDateInteger != null) { + result &= (myValueLowDateOrdinal.equals(lowerBoundAsDateInteger) || myValueLowDateOrdinal > lowerBoundAsDateInteger); + result &= (myValueHighDateOrdinal.equals(lowerBoundAsDateInteger) || myValueHighDateOrdinal > lowerBoundAsDateInteger); + } + if (upperBoundAsDateInteger != null) { + result &= (myValueHighDateOrdinal.equals(upperBoundAsDateInteger) || myValueHighDateOrdinal < upperBoundAsDateInteger); + result &= (myValueLowDateOrdinal.equals(upperBoundAsDateInteger) || myValueLowDateOrdinal < upperBoundAsDateInteger); + } + return result; + } + + public static Long calculateOrdinalValue(Date theDate) { return (long) DateUtils.convertDatetoDayInteger(theDate); - }; + } } diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamNumber.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamNumber.java index f88e357ccd7..bb686e6cc5f 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamNumber.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamNumber.java @@ -158,7 +158,7 @@ public class ResourceIndexedSearchParamNumber extends BaseResourceIndexedSearchP } @Override - public boolean matches(IQueryParameterType theParam) { + public boolean matches(IQueryParameterType theParam, boolean theUseOrdinalDatesForDayComparison) { if (!(theParam instanceof NumberParam)) { return false; } diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamQuantity.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamQuantity.java index 6107df7884d..8b9787a63db 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamQuantity.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamQuantity.java @@ -237,7 +237,7 @@ public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearc } @Override - public boolean matches(IQueryParameterType theParam) { + public boolean matches(IQueryParameterType theParam, boolean theUseOrdinalDatesForDayComparison) { if (!(theParam instanceof QuantityParam)) { return false; } diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamString.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamString.java index 155bf7a8da3..714c2cd6f98 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamString.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamString.java @@ -314,7 +314,7 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP } @Override - public boolean matches(IQueryParameterType theParam) { + public boolean matches(IQueryParameterType theParam, boolean theUseOrdinalDatesForDayComparison) { if (!(theParam instanceof StringParam)) { return false; } diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamToken.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamToken.java index 44a14bf41ee..f18c2d53157 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamToken.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamToken.java @@ -239,7 +239,7 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa } @Override - public boolean matches(IQueryParameterType theParam) { + public boolean matches(IQueryParameterType theParam, boolean theUseOrdinalDatesForDayComparison) { if (!(theParam instanceof TokenParam)) { return false; } diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamUri.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamUri.java index c827890d54b..6247dc668d1 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamUri.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamUri.java @@ -188,7 +188,7 @@ public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchPara } @Override - public boolean matches(IQueryParameterType theParam) { + public boolean matches(IQueryParameterType theParam, boolean theUseOrdinalDatesForDayComparison) { if (!(theParam instanceof UriParam)) { return false; } diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceIndexedSearchParams.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceIndexedSearchParams.java index 73f0df466c1..9dff7395b62 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceIndexedSearchParams.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceIndexedSearchParams.java @@ -217,7 +217,7 @@ public final class ResourceIndexedSearchParams { return myPopulatedResourceLinkParameters; } - public boolean matchParam(String theResourceName, String theParamName, RuntimeSearchParam theParamDef, IQueryParameterType theParam) { + public boolean matchParam(String theResourceName, String theParamName, RuntimeSearchParam theParamDef, IQueryParameterType theParam, boolean theUseOrdinalDatesForDayComparison) { if (theParamDef == null) { return false; } @@ -254,7 +254,7 @@ public final class ResourceIndexedSearchParams { } Predicate