HHH-16984 Disable use of arrays for batch and multi-loader on H2

This commit is contained in:
Christian Beikov 2023-07-24 13:03:24 +02:00
parent 90eb697020
commit eb562d5078
11 changed files with 55 additions and 22 deletions

View File

@ -200,6 +200,12 @@ public class H2LegacyDialect extends Dialect {
return getVersion().isSameOrAfter( 2 );
}
@Override
public boolean useArrayForMultiValuedParameters() {
// Performance is worse than the in-predicate version
return false;
}
@Override
protected String columnType(int sqlTypeCode) {
switch ( sqlTypeCode ) {

View File

@ -4204,6 +4204,17 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
return false;
}
/**
* Does this database prefer to use array types for multi-valued parameters.
*
* @return boolean
*
* @since 6.3
*/
public boolean useArrayForMultiValuedParameters() {
return supportsStandardArrays() && getPreferredSqlTypeCodeForArray() == SqlTypes.ARRAY;
}
/**
* The SQL type name for the array type with elements of the given type name.
* <p>

View File

@ -192,6 +192,12 @@ public class H2Dialect extends Dialect {
return getVersion().isSameOrAfter( 2 );
}
@Override
public boolean useArrayForMultiValuedParameters() {
// Performance is worse than the in-predicate version
return false;
}
@Override
protected String columnType(int sqlTypeCode) {
switch ( sqlTypeCode ) {

View File

@ -26,8 +26,7 @@ public class MultiKeyLoadHelper {
}
public static boolean supportsSqlArrayType(Dialect dialect) {
return dialect.supportsStandardArrays()
&& dialect.getPreferredSqlTypeCodeForArray() == SqlTypes.ARRAY;
return dialect.useArrayForMultiValuedParameters();
}
public static JdbcMapping resolveArrayJdbcMapping(

View File

@ -120,6 +120,7 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation
Class<?> expectedResultType,
HqlTranslator translator) {
log.tracef( "QueryPlan#resolveHqlInterpretation( `%s` )", queryString );
final StatisticsImplementor statistics = statisticsSupplier.get();
final Object cacheKey;
if ( expectedResultType != null ) {
@ -130,30 +131,35 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation
}
final HqlInterpretation existing = hqlInterpretationCache.get( cacheKey );
if ( existing != null ) {
final StatisticsImplementor statistics = statisticsSupplier.get();
if ( statistics.isStatisticsEnabled() ) {
statistics.queryPlanCacheHit( queryString );
}
return existing;
}
else {
final HqlInterpretation hqlInterpretation = createHqlInterpretation(
queryString,
expectedResultType,
translator,
statisticsSupplier
);
hqlInterpretationCache.put( cacheKey, hqlInterpretation );
return hqlInterpretation;
else if ( expectedResultType != null ) {
final HqlInterpretation existingQueryOnly = hqlInterpretationCache.get( queryString );
if ( existingQueryOnly != null ) {
if ( statistics.isStatisticsEnabled() ) {
statistics.queryPlanCacheHit( queryString );
}
return existingQueryOnly;
}
}
final HqlInterpretation hqlInterpretation = createHqlInterpretation(
queryString,
expectedResultType,
translator,
statistics
);
hqlInterpretationCache.put( cacheKey, hqlInterpretation );
return hqlInterpretation;
}
protected static HqlInterpretation createHqlInterpretation(
String queryString,
Class<?> expectedResultType,
HqlTranslator translator,
Supplier<StatisticsImplementor> statisticsSupplier) {
final StatisticsImplementor statistics = statisticsSupplier.get();
StatisticsImplementor statistics) {
final boolean stats = statistics.isStatisticsEnabled();
final long startTime = stats ? System.nanoTime() : 0L;

View File

@ -103,7 +103,7 @@ public class BatchAndClassIdAndLazyCollectionTest {
}
statementInspector.assertExecutedCount( 2 );
if ( scope.getSessionFactory().getJdbcServices().getDialect().supportsStandardArrays() ) {
if ( scope.getSessionFactory().getJdbcServices().getDialect().useArrayForMultiValuedParameters() ) {
Assertions.assertThat( statementInspector.getSqlQueries().get( 0 ) ).containsOnlyOnce( "?" );
Assertions.assertThat( statementInspector.getSqlQueries().get( 1 ) ).containsOnlyOnce( "?" );
}

View File

@ -95,7 +95,7 @@ public class BatchAndClassIdTest {
statementInspector.clear();
List<Child> children = session.createQuery( "select c from Child c", Child.class ).getResultList();
statementInspector.assertExecutedCount( 3 );
if ( scope.getSessionFactory().getJdbcServices().getDialect().supportsStandardArrays() ) {
if ( scope.getSessionFactory().getJdbcServices().getDialect().useArrayForMultiValuedParameters() ) {
Assertions.assertThat( statementInspector.getSqlQueries().get( 1 ) ).containsOnlyOnce( "?" );
Assertions.assertThat( statementInspector.getSqlQueries().get( 2 ) ).containsOnlyOnce( "?" );
}

View File

@ -95,7 +95,7 @@ public class BatchAndEmbeddedIdId2Test {
statementInspector.clear();
List<Child> children = session.createQuery( "select c from Child c", Child.class ).getResultList();
statementInspector.assertExecutedCount( 3 );
if ( scope.getSessionFactory().getJdbcServices().getDialect().supportsStandardArrays() ) {
if ( scope.getSessionFactory().getJdbcServices().getDialect().useArrayForMultiValuedParameters() ) {
Assertions.assertThat( statementInspector.getSqlQueries().get( 1 ) ).containsOnlyOnce( "?" );
Assertions.assertThat( statementInspector.getSqlQueries().get( 2 ) ).containsOnlyOnce( "?" );
}

View File

@ -103,7 +103,7 @@ public class BatchAndEmbeddedIdIdAndLazyCollectionTest {
}
statementInspector.assertExecutedCount( 2 );
if ( scope.getSessionFactory().getJdbcServices().getDialect().supportsStandardArrays() ) {
if ( scope.getSessionFactory().getJdbcServices().getDialect().useArrayForMultiValuedParameters() ) {
Assertions.assertThat( statementInspector.getSqlQueries().get( 0 ) ).containsOnlyOnce( "?" );
Assertions.assertThat( statementInspector.getSqlQueries().get( 1 ) ).containsOnlyOnce( "?" );
}

View File

@ -93,7 +93,7 @@ public class BatchAndEmbeddedIdIdTest {
statementInspector.clear();
List<Child> children = session.createQuery( "select c from Child c", Child.class ).getResultList();
statementInspector.assertExecutedCount( 3 );
if ( scope.getSessionFactory().getJdbcServices().getDialect().supportsStandardArrays() ) {
if ( scope.getSessionFactory().getJdbcServices().getDialect().useArrayForMultiValuedParameters() ) {
assertThat( statementInspector.getSqlQueries().get( 1 ) ).containsOnlyOnce( "?" );
assertThat( statementInspector.getSqlQueries().get( 2 ) ).containsOnlyOnce( "?" );
}

View File

@ -109,6 +109,7 @@ public class MultiLoadSubSelectCollectionDialectWithLimitTest {
@TestForIssue(jiraKey = "HHH-12740")
public void testSubselect(SessionFactoryScope scope) {
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
final Dialect dialect = scope.getSessionFactory().getFastSessionServices().jdbcServices.getDialect();
statementInspector.clear();
scope.inTransaction(
@ -117,7 +118,12 @@ public class MultiLoadSubSelectCollectionDialectWithLimitTest {
assertEquals( 56, list.size() );
// None of the collections should be loaded yet
assertThat( statementInspector.getSqlQueries() ).hasSize( 1 );
if ( dialect.useArrayForMultiValuedParameters() ) {
assertThat( statementInspector.getSqlQueries() ).hasSize( 1 );
}
else {
assertThat( statementInspector.getSqlQueries() ).hasSize( 2 );
}
for ( Parent p : list ) {
assertFalse( Hibernate.isInitialized( p.children ) );
}
@ -128,8 +134,7 @@ public class MultiLoadSubSelectCollectionDialectWithLimitTest {
Hibernate.initialize( list.get( 0 ).children );
// exactly how depends on whether the Dialect supports use of SQL ARRAY
final Dialect dialect = scope.getSessionFactory().getFastSessionServices().jdbcServices.getDialect();
if ( MultiKeyLoadHelper.supportsSqlArrayType( dialect ) ) {
if ( dialect.useArrayForMultiValuedParameters() ) {
assertThat( Hibernate.isInitialized( list.get( 0 ).children ) ).isTrue();
assertThat( Hibernate.isInitialized( list.get( 50 ).children ) ).isTrue();
assertThat( Hibernate.isInitialized( list.get( 52 ).children ) ).isTrue();