Bump HIbernate to 5.6.x (#3305)
* Bump HIbernate to 5.6.x * Test fixes * Test fix * Dependency bump * Rollback change * Fix tests * One more fix * Avoid bump
This commit is contained in:
parent
0f0bf85f18
commit
80e4c3dd92
|
@ -5,16 +5,17 @@
|
|||
(dependent HAPI modules listed in brackets):
|
||||
<ul>
|
||||
<li>log4j-api (JPA): 2.11.1 -> 2.17.1 (Addresses CVE-2021-44228 - HAPI FHIR was not vulnerable to this issue but this upgrade avoids unnecessary OWASP scan notices)</li>
|
||||
<li>SLF4j (All): 1.7.30 -> 1.7.32</li>
|
||||
<li>SLF4j (All): 1.7.30 -> 1.7.33</li>
|
||||
<li>Logback (All): 1.2.8 -> 1.2.10</li>
|
||||
<li>Commons-IO (All): 2.8.0 -> 2.11.0</li>
|
||||
<li>Jackson (All): 2.13.0 -> 2.13.1</li>
|
||||
<li>Guava (All): 30.1.1-jre -> 31.0.1-jre</li>
|
||||
<li>JDOM (XML Patch Support): 2.0.6 -> 2.0.6.1 (Addresses CVE-2021-33813)</li>
|
||||
<li>Spring (JPA): 5.3.7 -> 5.3.14</li>
|
||||
<li>Spring-Data (JPA): 2.5.0 -> 2.6.0</li>
|
||||
<li>Hibernate ORM (JPA): 5.4.30.Final -> 5.4.33</li>
|
||||
<li>Flyway (JPA): 6.5.4 -> 8.3.0</li>
|
||||
<li>Spring (JPA): 5.3.7 -> 5.3.15</li>
|
||||
<li>Spring-Data (JPA): 2.5.0 -> 2.6.1</li>
|
||||
<li>Hibernate ORM (JPA): 5.4.30.Final -> 5.6.2.Final</li>
|
||||
<li>Flyway (JPA): 6.5.4 -> 8.4.1</li>
|
||||
<li>Sqlbuilder (JPA): 3.0.1 -> 3.0.2</li>
|
||||
<li>H2 (JPA): 1.4.200 -> 2.0.206 (Note that this change requires the use of the HapiFhirH2Dialect instead of the built-in Hibernate H2Dialect due to Hibernate issue <a href='https://hibernate.atlassian.net/browse/HHH-15002'>HHH-15002</a></li>
|
||||
<li>Commons-DBCP2 (JPA): .8.0 -> .8.0 -> 2.9.0</li>
|
||||
<li>Swagger-Models (OpenAPI Support): 2.1.7 -> 2.1.12</li>
|
||||
|
|
|
@ -350,6 +350,25 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
case ANY:
|
||||
ForcedId forcedId = createForcedIdIfNeeded(updatedEntity, theResource.getIdElement(), true);
|
||||
if (forcedId != null) {
|
||||
|
||||
/*
|
||||
* As of Hibernate 5.6.2, assigning the forced ID to the
|
||||
* resource table causes an extra update to happen, even
|
||||
* though the ResourceTable entity isn't actually changed
|
||||
* (there is a @OneToOne reference on ResourceTable to the
|
||||
* ForcedId table, but the actual column is on the ForcedId
|
||||
* table so it doesn't actually make sense to update the table
|
||||
* when this is set). But to work around that we clear this
|
||||
* here.
|
||||
*
|
||||
* If you get rid of the following line (maybe possible
|
||||
* in a future version of Hibernate) try running the tests
|
||||
* in FhirResourceDaoR4QueryCountTest
|
||||
* JA 20220126
|
||||
*/
|
||||
updatedEntity.setForcedId(null);
|
||||
updatedEntity.setTransientForcedId(forcedId.getForcedId());
|
||||
|
||||
myForcedIdDao.save(forcedId);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -74,6 +74,7 @@ import javax.annotation.Nullable;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -408,7 +409,7 @@ public class SearchQueryBuilder {
|
|||
// The SQLServerDialect has a bunch of one-off processing to deal with rules on when
|
||||
// a limit can be used, so we can't rely on the flags that the limithandler exposes since
|
||||
// the exact structure of the query depends on the parameters
|
||||
if (sql.contains("TOP(?)")) {
|
||||
if (sql.contains("top(?)")) {
|
||||
bindVariables.add(0, maxResultsToFetch);
|
||||
}
|
||||
if (sql.contains("offset 0 rows fetch next ? rows only")) {
|
||||
|
@ -418,7 +419,7 @@ public class SearchQueryBuilder {
|
|||
bindVariables.add(theOffset);
|
||||
bindVariables.add(maxResultsToFetch);
|
||||
}
|
||||
if (offset != null && sql.contains("__hibernate_row_nr__")) {
|
||||
if (offset != null && sql.contains("__row__")) {
|
||||
bindVariables.add(theOffset + 1);
|
||||
bindVariables.add(theOffset + maxResultsToFetch + 1);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.dao.r4;
|
|||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
|
@ -32,6 +33,7 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
|
@ -155,10 +157,19 @@ public class FhirResourceDaoCreatePlaceholdersR4Test extends BaseJpaR4Test {
|
|||
myDaoConfig.setAutoCreatePlaceholderReferenceTargets(true);
|
||||
myDaoConfig.setResourceClientIdStrategy(DaoConfig.ClientIdStrategyEnum.ANY);
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
|
||||
Observation o = new Observation();
|
||||
o.setStatus(ObservationStatus.FINAL);
|
||||
IIdType id = myObservationDao.create(o, mySrd).getId();
|
||||
|
||||
myCaptureQueriesListener.logAllQueries();
|
||||
|
||||
runInTransaction(()->{
|
||||
ResourceTable entity = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(()->new IllegalArgumentException());
|
||||
assertEquals(1, entity.getVersion());
|
||||
});
|
||||
|
||||
try {
|
||||
myPatientDao.read(new IdType("Patient/999999999999999"));
|
||||
fail();
|
||||
|
@ -167,11 +178,15 @@ public class FhirResourceDaoCreatePlaceholdersR4Test extends BaseJpaR4Test {
|
|||
}
|
||||
|
||||
o = new Observation();
|
||||
o.setId(id);
|
||||
o.setId(id.getValue());
|
||||
o.setStatus(ObservationStatus.FINAL);
|
||||
o.getSubject().setReference("Patient/999999999999999");
|
||||
myObservationDao.update(o, mySrd);
|
||||
|
||||
runInTransaction(()->{
|
||||
ResourceTable entity = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(()->new IllegalArgumentException());
|
||||
assertEquals(2, entity.getVersion());
|
||||
});
|
||||
|
||||
myPatientDao.read(new IdType("Patient/999999999999999"));
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@ package ca.uhn.fhir.jpa.dao.r4;
|
|||
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.model.HistoryCountModeEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.ForcedId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.provider.r4.BaseResourceProviderR4Test;
|
||||
|
@ -56,6 +58,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
|
|||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -77,6 +80,7 @@ public class FhirResourceDaoR4QueryCountTest extends BaseResourceProviderR4Test
|
|||
myDaoConfig.setTagStorageMode(new DaoConfig().getTagStorageMode());
|
||||
myDaoConfig.setAutoCreatePlaceholderReferenceTargets(new DaoConfig().isAutoCreatePlaceholderReferenceTargets());
|
||||
myDaoConfig.setPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets(new DaoConfig().isPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets());
|
||||
myDaoConfig.setResourceClientIdStrategy(new DaoConfig().getResourceClientIdStrategy());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,6 +140,7 @@ public class FhirResourceDaoR4QueryCountTest extends BaseResourceProviderR4Test
|
|||
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRead() {
|
||||
IIdType id = runInTransaction(() -> {
|
||||
|
@ -255,6 +260,129 @@ public class FhirResourceDaoR4QueryCountTest extends BaseResourceProviderR4Test
|
|||
assertEquals(4, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||
myCaptureQueriesListener.logDeleteQueriesForCurrentThread();
|
||||
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ResourceTable> resources = myResourceTableDao.findAll();
|
||||
assertEquals(2, resources.size());
|
||||
assertEquals(1, resources.get(0).getVersion());
|
||||
assertEquals(1, resources.get(1).getVersion());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWithServerAssignedId_AnyClientAssignedIdStrategy() {
|
||||
myDaoConfig.setResourceClientIdStrategy(DaoConfig.ClientIdStrategyEnum.ANY);
|
||||
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
|
||||
IIdType resourceId = runInTransaction(() -> {
|
||||
Patient p = new Patient();
|
||||
p.setUserData("ABAB", "ABAB");
|
||||
p.getMaritalStatus().setText("123");
|
||||
return myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
});
|
||||
|
||||
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||
assertEquals(0, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||
myCaptureQueriesListener.logUpdateQueriesForCurrentThread();
|
||||
assertEquals(4, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||
myCaptureQueriesListener.logDeleteQueriesForCurrentThread();
|
||||
assertEquals(0, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
|
||||
myCaptureQueriesListener.logInsertQueriesForCurrentThread();
|
||||
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ForcedId> allForcedIds = myForcedIdDao.findAll();
|
||||
for (ForcedId next : allForcedIds) {
|
||||
assertNotNull(next.getResourceId());
|
||||
assertNotNull(next.getForcedId());
|
||||
}
|
||||
|
||||
List<ResourceTable> resources = myResourceTableDao.findAll();
|
||||
String versions = "Resource Versions:\n * " + resources
|
||||
.stream()
|
||||
.map(t->"Resource " + t.getIdDt() + " has version: " + t.getVersion())
|
||||
.collect(Collectors.joining("\n * "));
|
||||
|
||||
for (ResourceTable next : resources) {
|
||||
assertEquals(1, next.getVersion(), versions);
|
||||
}
|
||||
});
|
||||
|
||||
runInTransaction(() -> {
|
||||
Patient patient = myPatientDao.read(resourceId, mySrd);
|
||||
assertEquals(resourceId.getIdPart(), patient.getIdElement().getIdPart());
|
||||
assertEquals("123", patient.getMaritalStatus().getText());
|
||||
assertEquals("1", patient.getIdElement().getVersionIdPart());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateWithClientAssignedId_AnyClientAssignedIdStrategy() {
|
||||
myDaoConfig.setResourceClientIdStrategy(DaoConfig.ClientIdStrategyEnum.ANY);
|
||||
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
|
||||
|
||||
runInTransaction(() -> {
|
||||
Patient p = new Patient();
|
||||
p.setUserData("ABAB", "ABAB");
|
||||
p.getMaritalStatus().setText("123");
|
||||
return myPatientDao.create(p).getId().toUnqualified();
|
||||
});
|
||||
|
||||
runInTransaction(() -> {
|
||||
Patient p = new Patient();
|
||||
p.setId("BBB");
|
||||
p.getMaritalStatus().setText("123");
|
||||
myPatientDao.update(p);
|
||||
});
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
|
||||
runInTransaction(() -> {
|
||||
Patient p = new Patient();
|
||||
p.setId("AAA");
|
||||
p.getMaritalStatus().setText("123");
|
||||
myPatientDao.update(p);
|
||||
});
|
||||
|
||||
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||
assertEquals(1, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||
myCaptureQueriesListener.logUpdateQueriesForCurrentThread();
|
||||
assertEquals(0, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
|
||||
myCaptureQueriesListener.logInsertQueriesForCurrentThread();
|
||||
assertEquals(4, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||
myCaptureQueriesListener.logDeleteQueriesForCurrentThread();
|
||||
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ForcedId> allForcedIds = myForcedIdDao.findAll();
|
||||
for (ForcedId next : allForcedIds) {
|
||||
assertNotNull(next.getResourceId());
|
||||
assertNotNull(next.getForcedId());
|
||||
}
|
||||
|
||||
List<ResourceTable> resources = myResourceTableDao.findAll();
|
||||
String versions = "Resource Versions:\n * " + resources
|
||||
.stream()
|
||||
.map(t->"Resource " + t.getIdDt() + " has version: " + t.getVersion())
|
||||
.collect(Collectors.joining("\n * "));
|
||||
|
||||
for (ResourceTable next : resources) {
|
||||
assertEquals(1, next.getVersion(), versions);
|
||||
}
|
||||
});
|
||||
|
||||
runInTransaction(() -> {
|
||||
Patient patient = myPatientDao.read(new IdType("Patient/AAA"), mySrd);
|
||||
assertEquals("AAA", patient.getIdElement().getIdPart());
|
||||
assertEquals("123", patient.getMaritalStatus().getText());
|
||||
assertEquals("1", patient.getIdElement().getVersionIdPart());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package ca.uhn.fhir.jpa.search.builder.sql;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.config.HibernatePropertiesProvider;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.BaseJoiningPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceTablePredicateBuilder;
|
||||
import com.healthmarketscience.sqlbuilder.Condition;
|
||||
import com.healthmarketscience.sqlbuilder.OrderObject;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.internal.BasicFormatterImpl;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.mockito.Mock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public abstract class BaseSearchQueryBuilderDialectTest {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(BaseSearchQueryBuilderDialectTest.class);
|
||||
protected final FhirContext myFhirContext = FhirContext.forR4Cached();
|
||||
@Mock
|
||||
protected SqlObjectFactory mySqlObjectFactory;
|
||||
@Mock
|
||||
protected HibernatePropertiesProvider myHibernatePropertiesProvider;
|
||||
|
||||
@BeforeEach
|
||||
public void beforeInitMocks() {
|
||||
when(myHibernatePropertiesProvider.getDialect())
|
||||
.thenReturn(createDialect());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected abstract Dialect createDialect();
|
||||
|
||||
protected SearchQueryBuilder createSearchQueryBuilder() {
|
||||
return new SearchQueryBuilder(myFhirContext, new ModelConfig(), new PartitionSettings(), RequestPartitionId.allPartitions(), "Patient", mySqlObjectFactory, myHibernatePropertiesProvider, false);
|
||||
}
|
||||
|
||||
protected GeneratedSql buildSqlWithNumericSort(Boolean theAscending, OrderObject.NullOrder theNullOrder) {
|
||||
SearchQueryBuilder searchQueryBuilder = createSearchQueryBuilder();
|
||||
when(mySqlObjectFactory.resourceTable(any())).thenReturn(new ResourceTablePredicateBuilder(searchQueryBuilder));
|
||||
when(mySqlObjectFactory.dateIndexTable(any())).thenReturn(new DatePredicateBuilder(searchQueryBuilder));
|
||||
|
||||
BaseJoiningPredicateBuilder firstPredicateBuilder = searchQueryBuilder.getOrCreateFirstPredicateBuilder();
|
||||
DatePredicateBuilder sortPredicateBuilder = searchQueryBuilder.addDatePredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
||||
|
||||
Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate("MolecularSequence", "variant-start");
|
||||
searchQueryBuilder.addPredicate(hashIdentityPredicate);
|
||||
if (theNullOrder == null) {
|
||||
searchQueryBuilder.addSortNumeric(sortPredicateBuilder.getColumnValueLow(), theAscending);
|
||||
} else {
|
||||
searchQueryBuilder.addSortNumeric(sortPredicateBuilder.getColumnValueLow(), theAscending, theNullOrder);
|
||||
}
|
||||
|
||||
return searchQueryBuilder.generate(0, 500);
|
||||
|
||||
}
|
||||
|
||||
public void logSql(GeneratedSql theGeneratedSql) {
|
||||
String output = new BasicFormatterImpl().format(theGeneratedSql.getSql());
|
||||
ourLog.info("SQL: {}", output);
|
||||
}
|
||||
}
|
|
@ -1,43 +1,24 @@
|
|||
package ca.uhn.fhir.jpa.search.builder.sql;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.config.HibernatePropertiesProvider;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.BaseJoiningPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceTablePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.StringPredicateBuilder;
|
||||
import com.healthmarketscience.sqlbuilder.Condition;
|
||||
import com.healthmarketscience.sqlbuilder.OrderObject;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SearchQueryBuilderMySqlTest {
|
||||
|
||||
@Mock
|
||||
private SqlObjectFactory mySqlObjectFactory;
|
||||
@Mock
|
||||
private HibernatePropertiesProvider myHibernatePropertiesProvider;
|
||||
|
||||
private final FhirContext myFhirContext = FhirContext.forR4();
|
||||
|
||||
@BeforeEach
|
||||
public void beforeInitMocks() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(myHibernatePropertiesProvider.getDialect()).thenReturn(new org.hibernate.dialect.MySQL57Dialect());
|
||||
}
|
||||
|
||||
private SearchQueryBuilder createSearchQueryBuilder() {
|
||||
return new SearchQueryBuilder(myFhirContext, new ModelConfig(), new PartitionSettings(), RequestPartitionId.allPartitions(), "Patient", mySqlObjectFactory, myHibernatePropertiesProvider, false);
|
||||
}
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class SearchQueryBuilderDialectMySqlTest extends BaseSearchQueryBuilderDialectTest {
|
||||
|
||||
@Test
|
||||
public void testAddSortNumericNoNullOrder() {
|
||||
|
@ -49,26 +30,6 @@ public class SearchQueryBuilderMySqlTest {
|
|||
|
||||
}
|
||||
|
||||
private GeneratedSql buildSqlWithNumericSort(Boolean theAscending, OrderObject.NullOrder theNullOrder) {
|
||||
SearchQueryBuilder searchQueryBuilder = createSearchQueryBuilder();
|
||||
when(mySqlObjectFactory.resourceTable(any())).thenReturn(new ResourceTablePredicateBuilder(searchQueryBuilder));
|
||||
when(mySqlObjectFactory.dateIndexTable(any())).thenReturn(new DatePredicateBuilder(searchQueryBuilder));
|
||||
|
||||
BaseJoiningPredicateBuilder firstPredicateBuilder = searchQueryBuilder.getOrCreateFirstPredicateBuilder();
|
||||
DatePredicateBuilder sortPredicateBuilder = searchQueryBuilder.addDatePredicateBuilder(firstPredicateBuilder.getResourceIdColumn());
|
||||
|
||||
Condition hashIdentityPredicate = sortPredicateBuilder.createHashIdentityPredicate("MolecularSequence", "variant-start");
|
||||
searchQueryBuilder.addPredicate(hashIdentityPredicate);
|
||||
if (theNullOrder == null) {
|
||||
searchQueryBuilder.addSortNumeric(sortPredicateBuilder.getColumnValueLow(), theAscending);
|
||||
} else {
|
||||
searchQueryBuilder.addSortNumeric(sortPredicateBuilder.getColumnValueLow(), theAscending, theNullOrder);
|
||||
}
|
||||
|
||||
return searchQueryBuilder.generate(0,500);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddSortNumericWithNullOrder() {
|
||||
GeneratedSql generatedSql = buildSqlWithNumericSort(true, OrderObject.NullOrder.FIRST);
|
||||
|
@ -182,4 +143,10 @@ public class SearchQueryBuilderMySqlTest {
|
|||
assertTrue(generatedSql.getSql().endsWith("ORDER BY t1.SP_VALUE_LOW DESC limit ?"));
|
||||
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Dialect createDialect() {
|
||||
return new org.hibernate.dialect.MySQL57Dialect();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package ca.uhn.fhir.jpa.search.builder.sql;
|
||||
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ResourceTablePredicateBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.SQLServer2012Dialect;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class SearchQueryBuilderDialectSqlServerTest extends BaseSearchQueryBuilderDialectTest {
|
||||
|
||||
@Test
|
||||
public void testAddSort() {
|
||||
GeneratedSql generatedSql = buildSqlWithNumericSort(true, null);
|
||||
logSql(generatedSql);
|
||||
|
||||
String sql = generatedSql.getSql();
|
||||
assertTrue(sql.endsWith("ORDER BY -t1.SP_VALUE_LOW DESC offset 0 rows fetch next ? rows only"), sql);
|
||||
|
||||
assertEquals(3, StringUtils.countMatches(sql, "?"));
|
||||
assertEquals(3, generatedSql.getBindVariables().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRangeWithOffset() {
|
||||
SearchQueryBuilder searchQueryBuilder = createSearchQueryBuilder();
|
||||
when(mySqlObjectFactory.resourceTable(any())).thenReturn(new ResourceTablePredicateBuilder(searchQueryBuilder));
|
||||
|
||||
GeneratedSql generatedSql = searchQueryBuilder.generate(10, 500);
|
||||
logSql(generatedSql);
|
||||
|
||||
String sql = generatedSql.getSql();
|
||||
assertTrue(sql.endsWith("select page0_ from query where __row__ >= ? and __row__ < ?"), sql);
|
||||
|
||||
assertEquals(3, StringUtils.countMatches(sql, "?"));
|
||||
assertEquals(3, generatedSql.getBindVariables().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRangeWithoutOffset() {
|
||||
SearchQueryBuilder searchQueryBuilder = createSearchQueryBuilder();
|
||||
when(mySqlObjectFactory.resourceTable(any())).thenReturn(new ResourceTablePredicateBuilder(searchQueryBuilder));
|
||||
|
||||
GeneratedSql generatedSql = searchQueryBuilder.generate(0, 500);
|
||||
logSql(generatedSql);
|
||||
|
||||
String sql = generatedSql.getSql();
|
||||
assertTrue(sql.toUpperCase(Locale.ROOT).contains("SELECT TOP(?) T0.RES_ID FROM"), sql);
|
||||
|
||||
assertEquals(2, StringUtils.countMatches(sql, "?"));
|
||||
assertEquals(2, generatedSql.getBindVariables().size());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Dialect createDialect() {
|
||||
return new SQLServer2012Dialect();
|
||||
}
|
||||
}
|
|
@ -24,6 +24,8 @@ import org.springframework.context.annotation.Scope;
|
|||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -64,12 +66,12 @@ public class SearchQueryBuilderTest {
|
|||
|
||||
// Max only
|
||||
generated = builder.generate(null, 10);
|
||||
assertEquals("SELECT TOP(?) t0.RES_ID FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) ))", generated.getSql());
|
||||
assertEquals("SELECT TOP(?) T0.RES_ID FROM HFJ_RESOURCE T0 WHERE (((T0.RES_TYPE = ?) AND (T0.RES_DELETED_AT IS NULL)) AND (T0.RES_ID IN (?,?) ))", generated.getSql().toUpperCase(Locale.ROOT));
|
||||
assertThat(generated.getBindVariables().toString(), generated.getBindVariables(), contains(10, "Patient", 500L, 501L));
|
||||
|
||||
// Range
|
||||
generated = builder.generate(10, 5);
|
||||
assertEquals("WITH query AS (SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__ FROM ( SELECT t0.RES_ID as page0_ FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) )) ) inner_query ) SELECT page0_ FROM query WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?", generated.getSql());
|
||||
assertEquals("with query as (select inner_query.*, row_number() over (order by current_timestamp) as __row__ from ( SELECT t0.RES_ID as page0_ FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) )) ) inner_query ) select page0_ from query where __row__ >= ? and __row__ < ?", generated.getSql());
|
||||
assertThat(generated.getBindVariables().toString(), generated.getBindVariables(), contains("Patient", 500L, 501L, 11, 16));
|
||||
|
||||
}
|
||||
|
@ -93,13 +95,13 @@ public class SearchQueryBuilderTest {
|
|||
// Max only
|
||||
generated = builder.generate(null, 10);
|
||||
// assertEquals("SELECT TOP(?) t0.RES_ID FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) )) ORDER BY CASE WHEN t0.RES_UPDATED IS NULL THEN 1 ELSE 0 END ASC, t0.RES_UPDATED ASC", generated.getSql());
|
||||
assertEquals("SELECT TOP(?) t0.RES_ID FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) )) ORDER BY t0.RES_UPDATED ASC", generated.getSql());
|
||||
assertEquals("SELECT TOP(?) T0.RES_ID FROM HFJ_RESOURCE T0 WHERE (((T0.RES_TYPE = ?) AND (T0.RES_DELETED_AT IS NULL)) AND (T0.RES_ID IN (?,?) )) ORDER BY T0.RES_UPDATED ASC", generated.getSql().toUpperCase(Locale.ROOT));
|
||||
assertThat(generated.getBindVariables().toString(), generated.getBindVariables(), contains(10, "Patient", 500L, 501L));
|
||||
|
||||
// Range
|
||||
generated = builder.generate(10, 5);
|
||||
// assertEquals("WITH query AS (SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__ FROM ( SELECT TOP(?) t0.RES_ID as page0_ FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) )) ORDER BY CASE WHEN t0.RES_UPDATED IS NULL THEN 1 ELSE 0 END ASC, t0.RES_UPDATED ASC ) inner_query ) SELECT page0_ FROM query WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?", generated.getSql());
|
||||
assertEquals("WITH query AS (SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__ FROM ( SELECT TOP(?) t0.RES_ID as page0_ FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) )) ORDER BY t0.RES_UPDATED ASC ) inner_query ) SELECT page0_ FROM query WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?", generated.getSql());
|
||||
assertEquals("with query as (select inner_query.*, row_number() over (order by current_timestamp) as __row__ from ( SELECT top(?) t0.RES_ID as page0_ FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) )) ORDER BY t0.RES_UPDATED ASC ) inner_query ) select page0_ from query where __row__ >= ? and __row__ < ?", generated.getSql());
|
||||
assertThat(generated.getBindVariables().toString(), generated.getBindVariables(), contains(5, "Patient", 500L, 501L, 11, 16));
|
||||
|
||||
}
|
||||
|
@ -121,12 +123,12 @@ public class SearchQueryBuilderTest {
|
|||
|
||||
// Max only
|
||||
generated = builder.generate(null, 10);
|
||||
assertEquals("SELECT TOP(?) t0.RES_ID FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) ))", generated.getSql());
|
||||
assertEquals("SELECT TOP(?) T0.RES_ID FROM HFJ_RESOURCE T0 WHERE (((T0.RES_TYPE = ?) AND (T0.RES_DELETED_AT IS NULL)) AND (T0.RES_ID IN (?,?) ))", generated.getSql().toUpperCase(Locale.ROOT));
|
||||
assertThat(generated.getBindVariables().toString(), generated.getBindVariables(), contains(10, "Patient", 500L, 501L));
|
||||
|
||||
// Range
|
||||
generated = builder.generate(10, 5);
|
||||
assertEquals("WITH query AS (SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__ FROM ( SELECT t0.RES_ID as page0_ FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) )) ) inner_query ) SELECT page0_ FROM query WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?", generated.getSql());
|
||||
assertEquals("with query as (select inner_query.*, row_number() over (order by current_timestamp) as __row__ from ( SELECT t0.RES_ID as page0_ FROM HFJ_RESOURCE t0 WHERE (((t0.RES_TYPE = ?) AND (t0.RES_DELETED_AT IS NULL)) AND (t0.RES_ID IN (?,?) )) ) inner_query ) select page0_ from query where __row__ >= ? and __row__ < ?", generated.getSql());
|
||||
assertThat(generated.getBindVariables().toString(), generated.getBindVariables(), contains("Patient", 500L, 501L, 11, 16));
|
||||
|
||||
}
|
||||
|
|
|
@ -270,6 +270,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
private transient ResourceHistoryTable myCurrentVersionEntity;
|
||||
|
||||
@OneToOne(optional = true, fetch = FetchType.EAGER, cascade = {}, orphanRemoval = false, mappedBy = "myResource")
|
||||
@OptimisticLock(excluded = true)
|
||||
private ForcedId myForcedId;
|
||||
|
||||
@Transient
|
||||
|
|
12
pom.xml
12
pom.xml
|
@ -809,8 +809,8 @@
|
|||
<jsr305_version>3.0.2</jsr305_version>
|
||||
<junit_version>5.8.2</junit_version>
|
||||
<flexmark_version>0.50.40</flexmark_version>
|
||||
<flyway_version>8.3.0</flyway_version>
|
||||
<hibernate_version>5.4.33</hibernate_version>
|
||||
<flyway_version>8.4.1</flyway_version>
|
||||
<hibernate_version>5.6.2.Final</hibernate_version>
|
||||
<hibernate_search_version>6.0.3.Final</hibernate_search_version>
|
||||
<!-- Update lucene version when you update hibernate-search version -->
|
||||
<lucene_version>8.7.0</lucene_version>
|
||||
|
@ -832,10 +832,10 @@
|
|||
<servicemix_saxon_version>9.8.0-15</servicemix_saxon_version>
|
||||
<servicemix_xmlresolver_version>1.2_5</servicemix_xmlresolver_version>
|
||||
<swagger_version>2.1.12</swagger_version>
|
||||
<slf4j_version>1.7.32</slf4j_version>
|
||||
<slf4j_version>1.7.33</slf4j_version>
|
||||
<log4j_to_slf4j_version>2.17.1</log4j_to_slf4j_version>
|
||||
<spring_version>5.3.14</spring_version>
|
||||
<spring_data_version>2.6.0</spring_data_version>
|
||||
<spring_version>5.3.15</spring_version>
|
||||
<spring_data_version>2.6.1</spring_data_version>
|
||||
<spring_batch_version>4.3.3</spring_batch_version>
|
||||
<spring_boot_version>2.6.2</spring_boot_version>
|
||||
<spring_retry_version>1.2.2.RELEASE</spring_retry_version>
|
||||
|
@ -1134,7 +1134,7 @@
|
|||
<dependency>
|
||||
<groupId>com.healthmarketscience.sqlbuilder</groupId>
|
||||
<artifactId>sqlbuilder</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
|
|
Loading…
Reference in New Issue