Fix bug in history search (#4009)

* add failing test

* Fix history search bug and add tests for two more scenarios

* Fix history search bug and add tests for two more scenarios

* - added failing test condition

* Fix history search bug and add tests for two more scenarios

* Fix build test failures

* Fix build test failures

* Add extra verifications for scenarios of _since

* Refactor dao.history interface to add overload method and shall come back to remove old method once cdr is refactored.

* Update with new hapi interface

* Add depreciate comment

* Add depreciate comment

* Version bump to mvn 6.2.0-PRE11-SNAPSHOT

Co-authored-by: nathaniel.doef <nathaniel.doef@smilecdr.com>
This commit is contained in:
weiping202209 2022-10-03 07:00:41 -06:00 committed by GitHub
parent 43ed8ca051
commit 66baa8263d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
83 changed files with 464 additions and 103 deletions

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -0,0 +1,46 @@
package ca.uhn.fhir.rest.param;
/*-
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2022 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 java.util.Map;
public class HistorySearchDateRangeParam extends DateRangeParam {
public HistorySearchDateRangeParam(Map<String, String[]> theParameters, DateRangeParam theDateRange,
Integer theOffset){
super(theDateRange);
this.myOffset = theOffset;
this.myHistorySearchType = theParameters == null? null
: theParameters.keySet().stream().map(key -> HistorySearchStyleEnum.parse(key))
.filter(type -> type != null).findAny().orElse(null);
}
private HistorySearchStyleEnum myHistorySearchType;
private Integer myOffset;
public HistorySearchStyleEnum getHistorySearchType() {
return myHistorySearchType;
}
public Integer getOffset() {
return myOffset;
}
}

View File

@ -0,0 +1,50 @@
package ca.uhn.fhir.rest.param;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2022 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.rest.api.Constants;
import java.util.Arrays;
public enum HistorySearchStyleEnum {
AT(Constants.PARAM_AT),
SINCE(Constants.PARAM_SINCE),
COUNT(Constants.PARAM_COUNT);
public String getValue() {
return myValue;
}
private final String myValue;
HistorySearchStyleEnum(String theValue) {
this.myValue = theValue;
}
public static HistorySearchStyleEnum parse(String value){
return Arrays.stream(HistorySearchStyleEnum.values())
.filter(type -> type.myValue.equals(value)).findAny().orElse(null);
}
public boolean isAt(){
return this == HistorySearchStyleEnum.AT;
}
}

View File

@ -0,0 +1,41 @@
package ca.uhn.fhir.rest.param;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
class HistorySearchDateRangeParamTest {
private final int theOffset = 100;
private final DateRangeParam dateRangeParam = new DateRangeParam();
@Test
public void testSearchDateRangeParamWithInvalidSearchType() {
HistorySearchDateRangeParam param = new HistorySearchDateRangeParam(Map.of("Some key", new String[]{"value"}), dateRangeParam, theOffset);
assertNull(param.getHistorySearchType());
assertEquals(theOffset, param.getOffset());
}
@Test
public void testSearchDateRangeParamWithSearchTypeAsAt() {
HistorySearchDateRangeParam param = new HistorySearchDateRangeParam(Map.of("_at", new String[]{"value"}), dateRangeParam, theOffset);
assertEquals(HistorySearchStyleEnum.AT, param.getHistorySearchType());
assertEquals(theOffset, param.getOffset());
}
@Test
public void testSearchDateRangeParamWithSearchTypeAsSince() {
HistorySearchDateRangeParam param = new HistorySearchDateRangeParam(Map.of("_since", new String[]{"value"}), dateRangeParam, theOffset);
assertEquals(HistorySearchStyleEnum.SINCE, param.getHistorySearchType());
assertEquals(theOffset, param.getOffset());
}
@Test
public void testSearchDateRangeParamWithSearchTypeAsCount() {
HistorySearchDateRangeParam param = new HistorySearchDateRangeParam(Map.of("_count", new String[]{"value"}), dateRangeParam, theOffset);
assertEquals(HistorySearchStyleEnum.COUNT, param.getHistorySearchType());
assertEquals(theOffset, param.getOffset());
}
}

View File

@ -0,0 +1,26 @@
package ca.uhn.fhir.rest.param;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
class HistorySearchStyleEnumTest {
@Test
public void testParse(){
assertNull(HistorySearchStyleEnum.parse(""));
assertNull(HistorySearchStyleEnum.parse(null));
assertNull(HistorySearchStyleEnum.parse("Anything"));
assertEquals(HistorySearchStyleEnum.AT, HistorySearchStyleEnum.parse("_at"));
assertEquals(HistorySearchStyleEnum.SINCE, HistorySearchStyleEnum.parse("_since"));
assertEquals(HistorySearchStyleEnum.COUNT, HistorySearchStyleEnum.parse("_count"));
}
@Test
public void testIsAt(){
assertTrue(HistorySearchStyleEnum.AT.isAt());
assertFalse(HistorySearchStyleEnum.SINCE.isAt());
}
}

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -3,14 +3,14 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-bom</artifactId> <artifactId>hapi-fhir-bom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>HAPI FHIR BOM</name> <name>HAPI FHIR BOM</name>
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli</artifactId> <artifactId>hapi-fhir-cli</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom</relativePath> <relativePath>../../hapi-deployable-pom</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -0,0 +1,6 @@
---
type: fix
issue: 4008
jira: SMILE-4296
title: "Previously, when executing a '[base]/_history' search, '_since' and '_at' shared the same behaviour. When a user searched for the date between the records' updated date with '_at', the record of '_at' time was not returned.
This has been corrected. '_since' query parameter works as it previously did, and the '_at' query parameter returns the record of '_at' time."

View File

@ -11,7 +11,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -49,9 +49,7 @@ import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage; import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.partition.IPartitionLookupSvc; import ca.uhn.fhir.jpa.partition.IPartitionLookupSvc;
import ca.uhn.fhir.jpa.partition.RequestPartitionHelperSvc;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProviderFactory; import ca.uhn.fhir.jpa.search.PersistedJpaBundleProviderFactory;
import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc;
import ca.uhn.fhir.jpa.searchparam.extractor.LogicalReferenceHelper; import ca.uhn.fhir.jpa.searchparam.extractor.LogicalReferenceHelper;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams; import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult; import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
@ -73,11 +71,11 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.LenientErrorHandler; import ca.uhn.fhir.parser.LenientErrorHandler;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum; import ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails; 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.ResourcePersistentId;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.param.HistorySearchStyleEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
@ -516,7 +514,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
} }
protected IBundleProvider history(RequestDetails theRequest, String theResourceType, Long theResourcePid, Date theRangeStartInclusive, Date theRangeEndInclusive, Integer theOffset) { protected IBundleProvider history(RequestDetails theRequest, String theResourceType, Long theResourcePid, Date theRangeStartInclusive, Date theRangeEndInclusive, Integer theOffset) {
return history(theRequest, theResourceType, theResourcePid, theRangeStartInclusive, theRangeEndInclusive, theOffset, null);
}
protected IBundleProvider history(RequestDetails theRequest, String theResourceType, Long theResourcePid, Date theRangeStartInclusive, Date theRangeEndInclusive, Integer theOffset, HistorySearchStyleEnum searchParameterType) {
String resourceName = defaultIfBlank(theResourceType, null); String resourceName = defaultIfBlank(theResourceType, null);
Search search = new Search(); Search search = new Search();
@ -529,6 +530,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
search.setResourceId(theResourcePid); search.setResourceId(theResourcePid);
search.setSearchType(SearchTypeEnum.HISTORY); search.setSearchType(SearchTypeEnum.HISTORY);
search.setStatus(SearchStatusEnum.FINISHED); search.setStatus(SearchStatusEnum.FINISHED);
search.setHistorySearchStyle(searchParameterType);
return myPersistedJpaBundleProviderFactory.newInstance(theRequest, search); return myPersistedJpaBundleProviderFactory.newInstance(theRequest, search);
} }

View File

@ -89,6 +89,7 @@ import ca.uhn.fhir.rest.api.server.storage.IDeleteExpungeJobSubmitter;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.param.HasParam; import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.HistorySearchDateRangeParam;
import ca.uhn.fhir.rest.server.IPagingProvider; import ca.uhn.fhir.rest.server.IPagingProvider;
import ca.uhn.fhir.rest.server.IRestfulServerDefaults; import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
import ca.uhn.fhir.rest.server.RestfulServerUtils; import ca.uhn.fhir.rest.server.RestfulServerUtils;
@ -936,6 +937,25 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return retVal; return retVal;
} }
@Override
@Transactional
public IBundleProvider history(final IIdType theId, final HistorySearchDateRangeParam theHistorySearchDateRangeParam,
RequestDetails theRequest) {
StopWatch w = new StopWatch();
IIdType id = theId.withResourceType(myResourceName).toUnqualifiedVersionless();
BaseHasResource entity = readEntity(id, theRequest);
IBundleProvider retVal = super.history(theRequest, myResourceName, entity.getId(),
theHistorySearchDateRangeParam.getLowerBoundAsInstant(),
theHistorySearchDateRangeParam.getUpperBoundAsInstant(),
theHistorySearchDateRangeParam.getOffset(),
theHistorySearchDateRangeParam.getHistorySearchType());
ourLog.debug("Processed history on {} in {}ms", id, w.getMillisAndRestart());
return retVal;
}
protected boolean isPagingProviderDatabaseBacked(RequestDetails theRequestDetails) { protected boolean isPagingProviderDatabaseBacked(RequestDetails theRequestDetails) {
if (theRequestDetails == null || theRequestDetails.getServer() == null) { if (theRequestDetails == null || theRequestDetails.getServer() == null) {
return false; return false;

View File

@ -29,6 +29,7 @@ import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable; import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.param.HistorySearchStyleEnum;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
@ -43,9 +44,11 @@ import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.JoinType; import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -93,19 +96,20 @@ public class HistoryBuilder {
Root<ResourceHistoryTable> from = criteriaQuery.from(ResourceHistoryTable.class); Root<ResourceHistoryTable> from = criteriaQuery.from(ResourceHistoryTable.class);
criteriaQuery.select(cb.count(from)); criteriaQuery.select(cb.count(from));
addPredicatesToQuery(cb, thePartitionId, criteriaQuery, from); addPredicatesToQuery(cb, thePartitionId, criteriaQuery, from, null);
TypedQuery<Long> query = myEntityManager.createQuery(criteriaQuery); TypedQuery<Long> query = myEntityManager.createQuery(criteriaQuery);
return query.getSingleResult(); return query.getSingleResult();
} }
@SuppressWarnings("OptionalIsPresent") @SuppressWarnings("OptionalIsPresent")
public List<ResourceHistoryTable> fetchEntities(RequestPartitionId thePartitionId, Integer theOffset, int theFromIndex, int theToIndex) { public List<ResourceHistoryTable> fetchEntities(RequestPartitionId thePartitionId, Integer theOffset, int theFromIndex,
int theToIndex, HistorySearchStyleEnum theHistorySearchStyle) {
CriteriaBuilder cb = myEntityManager.getCriteriaBuilder(); CriteriaBuilder cb = myEntityManager.getCriteriaBuilder();
CriteriaQuery<ResourceHistoryTable> criteriaQuery = cb.createQuery(ResourceHistoryTable.class); CriteriaQuery<ResourceHistoryTable> criteriaQuery = cb.createQuery(ResourceHistoryTable.class);
Root<ResourceHistoryTable> from = criteriaQuery.from(ResourceHistoryTable.class); Root<ResourceHistoryTable> from = criteriaQuery.from(ResourceHistoryTable.class);
addPredicatesToQuery(cb, thePartitionId, criteriaQuery, from); addPredicatesToQuery(cb, thePartitionId, criteriaQuery, from, theHistorySearchStyle);
from.fetch("myProvenance", JoinType.LEFT); from.fetch("myProvenance", JoinType.LEFT);
@ -149,7 +153,8 @@ public class HistoryBuilder {
return tables; return tables;
} }
private void addPredicatesToQuery(CriteriaBuilder theCriteriaBuilder, RequestPartitionId thePartitionId, CriteriaQuery<?> theQuery, Root<ResourceHistoryTable> theFrom) { private void addPredicatesToQuery(CriteriaBuilder theCriteriaBuilder, RequestPartitionId thePartitionId, CriteriaQuery<?> theQuery,
Root<ResourceHistoryTable> theFrom, HistorySearchStyleEnum theHistorySearchStyle) {
List<Predicate> predicates = new ArrayList<>(); List<Predicate> predicates = new ArrayList<>();
if (!thePartitionId.isAllPartitions()) { if (!thePartitionId.isAllPartitions()) {
@ -175,7 +180,11 @@ public class HistoryBuilder {
} }
if (myRangeStartInclusive != null) { if (myRangeStartInclusive != null) {
predicates.add(theCriteriaBuilder.greaterThanOrEqualTo(theFrom.get("myUpdated").as(Date.class), myRangeStartInclusive)); if(HistorySearchStyleEnum.AT == theHistorySearchStyle && myResourceId != null) {
addPredicateForAtQueryParameter(theCriteriaBuilder, theQuery, theFrom, predicates);
} else {
predicates.add(theCriteriaBuilder.greaterThanOrEqualTo(theFrom.get("myUpdated").as(Date.class), myRangeStartInclusive));
}
} }
if (myRangeEndInclusive != null) { if (myRangeEndInclusive != null) {
predicates.add(theCriteriaBuilder.lessThanOrEqualTo(theFrom.get("myUpdated").as(Date.class), myRangeEndInclusive)); predicates.add(theCriteriaBuilder.lessThanOrEqualTo(theFrom.get("myUpdated").as(Date.class), myRangeEndInclusive));
@ -186,6 +195,23 @@ public class HistoryBuilder {
} }
} }
private void addPredicateForAtQueryParameter(CriteriaBuilder theCriteriaBuilder, CriteriaQuery<?> theQuery,
Root<ResourceHistoryTable> theFrom, List<Predicate> thePredicates) {
Subquery<Date> pastDateSubQuery = theQuery.subquery(Date.class);
Root<ResourceHistoryTable> subQueryResourceHistory = pastDateSubQuery.from(ResourceHistoryTable.class);
Expression<Date> myUpdatedMostRecent = theCriteriaBuilder.max(subQueryResourceHistory.get("myUpdated")).as(Date.class);
Expression<Date> myUpdatedMostRecentOrDefault = theCriteriaBuilder.coalesce(myUpdatedMostRecent,
theCriteriaBuilder.literal(myRangeStartInclusive));
pastDateSubQuery.select(myUpdatedMostRecentOrDefault)
.where(theCriteriaBuilder.lessThanOrEqualTo(subQueryResourceHistory.get("myUpdated").as(Date.class), myRangeStartInclusive)
, theCriteriaBuilder.equal(subQueryResourceHistory.get("myResourceId"), myResourceId));
Predicate updatedDatePredicate = theCriteriaBuilder.greaterThanOrEqualTo(theFrom.get("myUpdated").as(Date.class),
pastDateSubQuery);
thePredicates.add(updatedDatePredicate);
}
private void validateNotSearchingAllPartitions(RequestPartitionId thePartitionId) { private void validateNotSearchingAllPartitions(RequestPartitionId thePartitionId) {
if (myPartitionSettings.isPartitioningEnabled()) { if (myPartitionSettings.isPartitioningEnabled()) {
if (thePartitionId.isAllPartitions()) { if (thePartitionId.isAllPartitions()) {

View File

@ -6,6 +6,7 @@ import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.util.QueryParameterUtils; import ca.uhn.fhir.jpa.util.QueryParameterUtils;
import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HistorySearchStyleEnum;
import ca.uhn.fhir.rest.server.util.ICachedSearchDetails; import ca.uhn.fhir.rest.server.util.ICachedSearchDetails;
import org.apache.commons.lang3.SerializationUtils; import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
@ -158,6 +159,13 @@ public class Search implements ICachedSearchDetails, Serializable {
@Transient @Transient
private Integer mySizeModeSize; private Integer mySizeModeSize;
/**
* This isn't currently persisted in the DB. When there is search criteria defined in the
* search parameter, this is used to keep the search criteria type.
*/
@Transient
private HistorySearchStyleEnum myHistorySearchStyle;
/** /**
* Constructor * Constructor
*/ */
@ -415,6 +423,14 @@ public class Search implements ICachedSearchDetails, Serializable {
myOffset = theOffset; myOffset = theOffset;
} }
public HistorySearchStyleEnum getHistorySearchStyle() {
return myHistorySearchStyle;
}
public void setHistorySearchStyle(HistorySearchStyleEnum theHistorySearchStyle) {
this.myHistorySearchStyle = theHistorySearchStyle;
}
@Nonnull @Nonnull
public static String createSearchQueryStringForStorage(@Nonnull String theSearchQueryString, @Nonnull RequestPartitionId theRequestPartitionId) { public static String createSearchQueryStringForStorage(@Nonnull String theSearchQueryString, @Nonnull RequestPartitionId theRequestPartitionId) {
String searchQueryString = theSearchQueryString; String searchQueryString = theSearchQueryString;

View File

@ -149,10 +149,12 @@ public class PersistedJpaBundleProvider implements IBundleProvider {
*/ */
private List<IBaseResource> doHistoryInTransaction(Integer theOffset, int theFromIndex, int theToIndex) { private List<IBaseResource> doHistoryInTransaction(Integer theOffset, int theFromIndex, int theToIndex) {
HistoryBuilder historyBuilder = myHistoryBuilderFactory.newHistoryBuilder(mySearchEntity.getResourceType(), mySearchEntity.getResourceId(), mySearchEntity.getLastUpdatedLow(), mySearchEntity.getLastUpdatedHigh()); HistoryBuilder historyBuilder = myHistoryBuilderFactory.newHistoryBuilder(mySearchEntity.getResourceType(),
mySearchEntity.getResourceId(), mySearchEntity.getLastUpdatedLow(), mySearchEntity.getLastUpdatedHigh());
RequestPartitionId partitionId = getRequestPartitionIdForHistory(); RequestPartitionId partitionId = getRequestPartitionIdForHistory();
List<ResourceHistoryTable> results = historyBuilder.fetchEntities(partitionId, theOffset, theFromIndex, theToIndex); List<ResourceHistoryTable> results = historyBuilder.fetchEntities(partitionId, theOffset, theFromIndex,
theToIndex, mySearchEntity.getHistorySearchStyle());
List<IBaseResource> retVal = new ArrayList<>(); List<IBaseResource> retVal = new ArrayList<>();
for (ResourceHistoryTable next : results) { for (ResourceHistoryTable next : results) {

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -1521,10 +1521,14 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
Patient patient = new Patient(); Patient patient = new Patient();
patient.addName().setFamily(methodName); patient.addName().setFamily(methodName);
IIdType id = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
List<Date> preDates = Lists.newArrayList(); List<Date> preDates = Lists.newArrayList();
List<String> ids = Lists.newArrayList(); List<String> ids = Lists.newArrayList();
IIdType idCreated = myPatientDao.create(patient, mySrd).getId();
ids.add(idCreated.toUnqualified().getValue());
IIdType id = idCreated.toUnqualifiedVersionless();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Thread.sleep(100); Thread.sleep(100);
preDates.add(new Date()); preDates.add(new Date());
@ -1537,13 +1541,13 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
List<String> idValues; List<String> idValues;
idValues = toUnqualifiedIdValues(myPatientDao.history(id, preDates.get(0), preDates.get(3), null, mySrd)); idValues = toUnqualifiedIdValues(myPatientDao.history(id, preDates.get(0), preDates.get(3), null, mySrd));
assertThat(idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
idValues = toUnqualifiedIdValues(myPatientDao.history(preDates.get(0), preDates.get(3), null, mySrd)); idValues = toUnqualifiedIdValues(myPatientDao.history(preDates.get(0), preDates.get(3), null, mySrd));
assertThat(idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
idValues = toUnqualifiedIdValues(mySystemDao.history(preDates.get(0), preDates.get(3), null, mySrd)); idValues = toUnqualifiedIdValues(mySystemDao.history(preDates.get(0), preDates.get(3), null, mySrd));
assertThat(idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
} }
@Test @Test

View File

@ -2246,10 +2246,14 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
Patient patient = new Patient(); Patient patient = new Patient();
patient.addName().setFamily(methodName); patient.addName().setFamily(methodName);
IIdType id = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
List<Date> preDates = Lists.newArrayList(); List<Date> preDates = Lists.newArrayList();
List<String> ids = Lists.newArrayList(); List<String> ids = Lists.newArrayList();
IIdType idCreated = myPatientDao.create(patient, mySrd).getId();
ids.add(idCreated.toUnqualified().getValue());
IIdType id = idCreated.toUnqualifiedVersionless();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Thread.sleep(100); Thread.sleep(100);
preDates.add(new Date()); preDates.add(new Date());
@ -2262,13 +2266,13 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
List<String> idValues; List<String> idValues;
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + id.getIdPart() + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3))); idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + id.getIdPart() + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3)));
assertThat(idValues.toString(), idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues.toString(), idValues, contains(ids.get(3), ids.get(2), ids.get(1), ids.get(0)));
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3))); idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3)));
assertThat(idValues.toString(), idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues.toString(), idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3))); idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3)));
assertThat(idValues.toString(), idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues.toString(), idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt2060"); idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt2060");
assertThat(idValues.toString(), idValues, empty()); assertThat(idValues.toString(), idValues, empty());

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -2090,10 +2090,13 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
Patient patient = new Patient(); Patient patient = new Patient();
patient.addName().setFamily(methodName); patient.addName().setFamily(methodName);
IIdType id = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
List<Date> preDates = Lists.newArrayList(); List<Date> preDates = Lists.newArrayList();
List<String> ids = Lists.newArrayList(); List<String> ids = Lists.newArrayList();
IIdType idCreated = myPatientDao.create(patient, mySrd).getId();
ids.add(idCreated.toUnqualified().getValue());
IIdType id = idCreated.toUnqualifiedVersionless();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Thread.sleep(100); Thread.sleep(100);
preDates.add(new Date()); preDates.add(new Date());
@ -2106,13 +2109,13 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
List<String> idValues; List<String> idValues;
idValues = toUnqualifiedIdValues(myPatientDao.history(id, preDates.get(0), preDates.get(3), null, mySrd)); idValues = toUnqualifiedIdValues(myPatientDao.history(id, preDates.get(0), preDates.get(3), null, mySrd));
assertThat(idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
idValues = toUnqualifiedIdValues(myPatientDao.history(preDates.get(0), preDates.get(3), null, mySrd)); idValues = toUnqualifiedIdValues(myPatientDao.history(preDates.get(0), preDates.get(3), null, mySrd));
assertThat(idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
idValues = toUnqualifiedIdValues(mySystemDao.history(preDates.get(0), preDates.get(3), null, mySrd)); idValues = toUnqualifiedIdValues(mySystemDao.history(preDates.get(0), preDates.get(3), null, mySrd));
assertThat(idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
} }
@Test @Test

View File

@ -179,6 +179,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -3032,10 +3033,14 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
Patient patient = new Patient(); Patient patient = new Patient();
patient.addName().setFamily(methodName); patient.addName().setFamily(methodName);
IIdType id = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
List<Date> preDates = Lists.newArrayList(); List<Date> preDates = Lists.newArrayList();
List<String> ids = Lists.newArrayList(); List<String> ids = Lists.newArrayList();
IIdType idCreated = myPatientDao.create(patient, mySrd).getId();
ids.add(idCreated.toUnqualified().getValue());
IIdType id = idCreated.toUnqualifiedVersionless();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
sleepOneClick(); sleepOneClick();
preDates.add(new Date()); preDates.add(new Date());
@ -3049,13 +3054,13 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
List<String> idValues; List<String> idValues;
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + id.getIdPart() + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3))); idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + id.getIdPart() + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3)));
assertThat(idValues.toString(), idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues.toString(), idValues, contains(ids.get(3), ids.get(2), ids.get(1), ids.get(0)));
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3))); idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3)));
assertThat(idValues.toString(), idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues.toString(), idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3))); idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt" + toStr(preDates.get(0)) + "&_at=lt" + toStr(preDates.get(3)));
assertThat(idValues.toString(), idValues, contains(ids.get(2), ids.get(1), ids.get(0))); assertThat(idValues.toString(), idValues, contains(ids.get(3), ids.get(2), ids.get(1)));
idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt2060"); idValues = searchAndReturnUnqualifiedIdValues(ourServerBase + "/_history?_at=gt2060");
assertThat(idValues.toString(), idValues, empty()); assertThat(idValues.toString(), idValues, empty());
@ -7234,6 +7239,108 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
assertEquals(0, results.getEntry().size()); assertEquals(0, results.getEntry().size());
} }
@Test
public void testSearchHistoryWithAtAndGtParameters() throws Exception {
// Create Patient
Patient patient = new Patient();
patient = (Patient) myClient.create().resource(patient).execute().getResource();
Long patientId = patient.getIdElement().getIdPartAsLong();
// Update Patient after delay
int delayInMs = 1000;
TimeUnit.MILLISECONDS.sleep(delayInMs);
patient.getNameFirstRep().addGiven("Bob");
myClient.update().resource(patient).execute();
Patient unrelatedPatient = (Patient) myClient.create().resource(new Patient()).execute().getResource();
assertNotEquals(unrelatedPatient.getIdElement().getIdPartAsLong(), patientId);
// ensure the patient has the expected overall history
Bundle result = myClient.history()
.onInstance("Patient/"+patientId)
.returnBundle(Bundle.class)
.execute();
assertEquals(2, result.getEntry().size());
Patient patientV1 = (Patient) result.getEntry().get(1).getResource();
assertEquals(patientId, patientV1.getIdElement().getIdPartAsLong());
Patient patientV2 = (Patient) result.getEntry().get(0).getResource();
assertEquals(patientId, patientV2.getIdElement().getIdPartAsLong());
Date dateV1 = patientV1.getMeta().getLastUpdated();
Date dateV2 = patientV2.getMeta().getLastUpdated();
assertTrue(dateV1.before((dateV2)));
// Issue 3138 test case, verify behavior of _at
verifyAtBehaviourWhenQueriedDateDuringTwoUpdatedDates(patientId, delayInMs, dateV1, dateV2);
verifyAtBehaviourWhenQueriedDateAfterTwoUpdatedDates(patientId, delayInMs, dateV1, dateV2);
verifyAtBehaviourWhenQueriedDateBeforeTwoUpdatedDates(patientId, delayInMs, dateV1, dateV2);
// verify behavior of _since
verifySinceBehaviourWhenQueriedDateDuringTwoUpdatedDates(patientId, delayInMs, dateV1, dateV2);
verifySinceBehaviourWhenQueriedDateAfterTwoUpdatedDates(patientId, delayInMs, dateV1, dateV2);
verifySinceBehaviourWhenQueriedDateBeforeTwoUpdatedDates(patientId, delayInMs, dateV1, dateV2);
}
private void verifyAtBehaviourWhenQueriedDateDuringTwoUpdatedDates(Long patientId, int delayInMs, Date dateV1, Date dateV2) throws IOException {
Date timeBetweenUpdates = DateUtils.addMilliseconds(dateV1, delayInMs / 2);
assertTrue(timeBetweenUpdates.after(dateV1));
assertTrue(timeBetweenUpdates.before(dateV2));
List<String> resultIds = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + patientId + "/_history?_at=gt" + toStr(timeBetweenUpdates));
assertEquals(2, resultIds.size());
assertTrue(resultIds.contains("Patient/"+ patientId +"/_history/1"));
assertTrue(resultIds.contains("Patient/"+ patientId +"/_history/2"));
}
private void verifyAtBehaviourWhenQueriedDateAfterTwoUpdatedDates(Long patientId, int delayInMs, Date dateV1, Date dateV2) throws IOException {
Date timeBetweenUpdates = DateUtils.addMilliseconds(dateV2, delayInMs);
assertTrue(timeBetweenUpdates.after(dateV1));
assertTrue(timeBetweenUpdates.after(dateV2));
List<String> resultIds = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + patientId + "/_history?_at=gt" + toStr(timeBetweenUpdates));
assertEquals(1, resultIds.size());
assertTrue(resultIds.contains("Patient/"+ patientId +"/_history/2"));
}
private void verifyAtBehaviourWhenQueriedDateBeforeTwoUpdatedDates(Long patientId, int delayInMs, Date dateV1, Date dateV2) throws IOException {
Date timeBetweenUpdates = DateUtils.addMilliseconds(dateV1, - delayInMs);
assertTrue(timeBetweenUpdates.before(dateV1));
assertTrue(timeBetweenUpdates.before(dateV2));
List<String> resultIds = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + patientId + "/_history?_at=gt" + toStr(timeBetweenUpdates));
assertEquals(2, resultIds.size());
assertTrue(resultIds.contains("Patient/"+ patientId +"/_history/1"));
assertTrue(resultIds.contains("Patient/"+ patientId +"/_history/2"));
}
private void verifySinceBehaviourWhenQueriedDateDuringTwoUpdatedDates(Long patientId, int delayInMs, Date dateV1, Date dateV2) throws IOException {
Date timeBetweenUpdates = DateUtils.addMilliseconds(dateV1, delayInMs / 2);
assertTrue(timeBetweenUpdates.after(dateV1));
assertTrue(timeBetweenUpdates.before(dateV2));
List<String> resultIds = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + patientId + "/_history?_since=" + toStr(timeBetweenUpdates));
assertEquals(1, resultIds.size());
assertTrue(resultIds.contains("Patient/"+ patientId +"/_history/2"));
}
private void verifySinceBehaviourWhenQueriedDateAfterTwoUpdatedDates(Long patientId, int delayInMs, Date dateV1, Date dateV2) throws IOException {
Date timeBetweenUpdates = DateUtils.addMilliseconds(dateV2, delayInMs);
assertTrue(timeBetweenUpdates.after(dateV1));
assertTrue(timeBetweenUpdates.after(dateV2));
List<String> resultIds = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + patientId + "/_history?_since=" + toStr(timeBetweenUpdates));
assertEquals(0, resultIds.size());
}
private void verifySinceBehaviourWhenQueriedDateBeforeTwoUpdatedDates(Long patientId, int delayInMs, Date dateV1, Date dateV2) throws IOException {
Date timeBetweenUpdates = DateUtils.addMilliseconds(dateV1, - delayInMs);
assertTrue(timeBetweenUpdates.before(dateV1));
assertTrue(timeBetweenUpdates.before(dateV2));
List<String> resultIds = searchAndReturnUnqualifiedIdValues(ourServerBase + "/Patient/" + patientId + "/_history?_since=" + toStr(timeBetweenUpdates));
assertEquals(2, resultIds.size());
assertTrue(resultIds.contains("Patient/"+ patientId +"/_history/1"));
assertTrue(resultIds.contains("Patient/"+ patientId +"/_history/2"));
}
@Test @Test
public void searchResource_bySourceWithPreserveRequestIdDisabled_isSuccess() { public void searchResource_bySourceWithPreserveRequestIdDisabled_isSuccess() {
String sourceUri = "http://acme.org"; String sourceUri = "http://acme.org";

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId> <artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</parent> </parent>
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId> <artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId> <artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</parent> </parent>
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId> <artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId> <artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</parent> </parent>
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId> <artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot</artifactId> <artifactId>hapi-fhir-spring-boot</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</parent> </parent>
<artifactId>hapi-fhir-spring-boot-samples</artifactId> <artifactId>hapi-fhir-spring-boot-samples</artifactId>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -40,6 +40,7 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails; 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.ResourcePersistentId;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.param.HistorySearchDateRangeParam;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.hl7.fhir.instance.model.api.IBaseMetaType; import org.hl7.fhir.instance.model.api.IBaseMetaType;
@ -123,8 +124,14 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
IBundleProvider history(Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails); IBundleProvider history(Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails);
/**
* @deprecated Just use history(IIdType theId, HistorySearchDateRangeParam theHistorySearchDateRangeParam, RequestDetails theRequestDetails) instead;
*/
@Deprecated(since = "6.2")
IBundleProvider history(IIdType theId, Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails); IBundleProvider history(IIdType theId, Date theSince, Date theUntil, Integer theOffset, RequestDetails theRequestDetails);
IBundleProvider history(IIdType theId, HistorySearchDateRangeParam theHistorySearchDateRangeParam, RequestDetails theRequestDetails);
/** /**
* Not supported in DSTU1! * Not supported in DSTU1!
* *

View File

@ -49,6 +49,7 @@ import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HistorySearchDateRangeParam;
import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.provider.ProviderConstants; import ca.uhn.fhir.rest.server.provider.ProviderConstants;
@ -118,7 +119,7 @@ public abstract class BaseJpaResourceProvider<T extends IBaseResource> extends B
startRequest(theRequest); startRequest(theRequest);
try { try {
DateRangeParam sinceOrAt = processSinceOrAt(theSince, theAt); DateRangeParam sinceOrAt = processSinceOrAt(theSince, theAt);
return myDao.history(theId, sinceOrAt.getLowerBoundAsInstant(), sinceOrAt.getUpperBoundAsInstant(), theOffset, theRequestDetails); return myDao.history(theId, new HistorySearchDateRangeParam(theRequestDetails.getParameters(), sinceOrAt, theOffset), theRequestDetails);
} finally { } finally {
endRequest(theRequest); endRequest(theRequest);
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -58,37 +58,37 @@
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu3</artifactId> <artifactId>hapi-fhir-structures-dstu3</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId> <artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-r4</artifactId> <artifactId>hapi-fhir-structures-r4</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-r5</artifactId> <artifactId>hapi-fhir-structures-r5</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId> <artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId> <artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources-r4</artifactId> <artifactId>hapi-fhir-validation-resources-r4</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.velocity</groupId> <groupId>org.apache.velocity</groupId>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<name>HAPI-FHIR</name> <name>HAPI-FHIR</name>
<description>An open-source implementation of the FHIR specification in Java.</description> <description>An open-source implementation of the FHIR specification in Java.</description>
<url>https://hapifhir.io</url> <url>https://hapifhir.io</url>
@ -2024,7 +2024,7 @@
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-checkstyle</artifactId> <artifactId>hapi-fhir-checkstyle</artifactId>
<!-- Remember to bump this when you upgrade the version --> <!-- Remember to bump this when you upgrade the version -->
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> </dependencies>
</plugin> </plugin>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.2.0-PRE10-SNAPSHOT</version> <version>6.2.0-PRE11-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>