Skip to content

Commit

Permalink
HHH-16589 In clause padding can no longer cause in clauses to exceed …
Browse files Browse the repository at this point in the history
…Dialect.getInExpressionCountLimit
  • Loading branch information
Adrodoc authored and beikov committed Jun 20, 2023
1 parent 4e7c5df commit 5695536
Showing 1 changed file with 122 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package org.hibernate.orm.test.query;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

Expand All @@ -25,6 +26,8 @@
import jakarta.persistence.Entity;
import jakarta.persistence.Id;

import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
Expand All @@ -39,7 +42,7 @@
@Setting(name = AvailableSettings.IN_CLAUSE_PARAMETER_PADDING, value = "true"),
@Setting(name = AvailableSettings.DIALECT_NATIVE_PARAM_MARKERS, value = "false"),
},
settingProviders ={
settingProviders = {
@SettingProvider(
settingName = AvailableSettings.DIALECT,
provider = MaxInExpressionParameterPaddingTest.DialectProvider.class
Expand Down Expand Up @@ -76,20 +79,33 @@ public void testInClauseParameterPadding(EntityManagerFactoryScope scope) {
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
statementInspector.clear();

scope.inTransaction( entityManager ->
entityManager.createQuery( "select p from Person p where p.id in :ids" )
.setParameter( "ids", IntStream.range( 0, MAX_COUNT ).boxed().collect( Collectors.toList() ) )
.getResultList()
);
scope.inTransaction( entityManager -> entityManager
.createQuery( "select p from Person p where p.id in :ids" )
.setParameter( "ids", integerRangeList( 0, 5 ) )
.getResultList() );

StringBuilder expectedInClause = new StringBuilder();
expectedInClause.append( "in (?" );
for ( int i = 1; i < MAX_COUNT; i++ ) {
expectedInClause.append( ",?" );
}
expectedInClause.append( ")" );
expectedInClause.append( "where p1_0.id in " );
appendInClause( expectedInClause, 8 );

assertThat( statementInspector.getSqlQueries().get( 0 ) ).endsWith( expectedInClause.toString() );
}

@Test
public void testInClauseParameterNoPaddingAtLimit(EntityManagerFactoryScope scope) {
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
statementInspector.clear();

scope.inTransaction( entityManager -> entityManager
.createQuery( "select p from Person p where p.id in :ids" )
.setParameter( "ids", integerRangeList( 0, MAX_COUNT ) )
.getResultList() );

StringBuilder expectedInClause = new StringBuilder();
expectedInClause.append( "where p1_0.id in " );
appendInClause( expectedInClause, MAX_COUNT );

assertTrue( statementInspector.getSqlQueries().get( 0 ).endsWith( expectedInClause.toString() ) );
assertThat( statementInspector.getSqlQueries().get( 0 ) ).endsWith( expectedInClause.toString() );
}

@TestForIssue(jiraKey = "HHH-14109")
Expand All @@ -98,108 +114,134 @@ public void testInClauseParameterPaddingToLimit(EntityManagerFactoryScope scope)
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
statementInspector.clear();

scope.inTransaction(
entityManager ->
entityManager.createQuery(
"select p from Person p where p.id in :ids" )
.setParameter( "ids", IntStream.range( 0, 10 )
.boxed()
.collect( Collectors.toList() ) )
.getResultList()
);
scope.inTransaction( entityManager -> entityManager
.createQuery( "select p from Person p where p.id in :ids" )
.setParameter( "ids", integerRangeList( 0, 10 ) )
.getResultList() );

StringBuilder expectedInClause = new StringBuilder();
expectedInClause.append( "in (?" );
for ( int i = 1; i < MAX_COUNT; i++ ) {
expectedInClause.append( ",?" );
}
expectedInClause.append( ")" );
expectedInClause.append( "where p1_0.id in " );
appendInClause( expectedInClause, MAX_COUNT );

assertTrue( statementInspector.getSqlQueries().get( 0 ).endsWith( expectedInClause.toString() ) );
assertThat( statementInspector.getSqlQueries().get( 0 ) ).endsWith( expectedInClause.toString() );
}

@Test
public void testInClauseParameterSplittingAfterLimit(EntityManagerFactoryScope scope) {
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
statementInspector.clear();

scope.inTransaction(
entityManager ->
entityManager.createQuery(
"select p from Person p where p.id in :ids" )
.setParameter( "ids", IntStream.range( 0, 16 )
.boxed()
.collect( Collectors.toList() ) )
.getResultList()
);
scope.inTransaction( entityManager -> entityManager
.createQuery( "select p from Person p where p.id in :ids" )
.setParameter( "ids", integerRangeList( 0, 16 ) )
.getResultList() );

StringBuilder expectedInClause = new StringBuilder();
expectedInClause.append( "in (?" );
for ( int i = 1; i < MAX_COUNT; i++ ) {
expectedInClause.append( ",?" );
}
expectedInClause.append( ")" );
expectedInClause.append( " or p1_0.id in (?)" );
expectedInClause.append( "where (p1_0.id in " );
appendInClause( expectedInClause, MAX_COUNT );
expectedInClause.append( " or p1_0.id in " );
appendInClause( expectedInClause, 1 );
expectedInClause.append( ')' );

assertTrue( statementInspector.getSqlQueries().get( 0 ).endsWith( expectedInClause.toString() ) );
assertThat( statementInspector.getSqlQueries().get( 0 ) ).endsWith( expectedInClause.toString() );
}

@Test
public void testInClauseParameterSplittingAfterLimitNotIn(EntityManagerFactoryScope scope) {
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
statementInspector.clear();

scope.inTransaction( entityManager -> entityManager
.createQuery( "select p from Person p where p.id not in :ids" )
.setParameter( "ids", integerRangeList( 0, 16 ) )
.getResultList() );

StringBuilder expectedInClause = new StringBuilder();
expectedInClause.append( "where p1_0.id not in " );
appendInClause( expectedInClause, MAX_COUNT );
expectedInClause.append( " and p1_0.id not in " );
appendInClause( expectedInClause, 1 );

assertThat( statementInspector.getSqlQueries().get( 0 ) ).endsWith( expectedInClause.toString() );
}

@Test
public void testInClauseParameterSplittingAfterLimit2(EntityManagerFactoryScope scope) {
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
statementInspector.clear();

scope.inTransaction(
entityManager ->
entityManager.createQuery(
"select p from Person p where p.id in :ids" )
.setParameter( "ids", IntStream.range( 0, 18 )
.boxed()
.collect( Collectors.toList() ) )
.getResultList()
);
scope.inTransaction( entityManager -> entityManager
.createQuery( "select p from Person p where p.id in :ids" )
.setParameter( "ids", integerRangeList( 0, 18 ) )
.getResultList() );

StringBuilder expectedInClause = new StringBuilder();
expectedInClause.append( "in (?" );
for ( int i = 1; i < MAX_COUNT; i++ ) {
expectedInClause.append( ",?" );
}
expectedInClause.append( ")" );
expectedInClause.append( " or p1_0.id in (?,?,?,?)" );
expectedInClause.append( "where (p1_0.id in " );
appendInClause( expectedInClause, MAX_COUNT );
expectedInClause.append( " or p1_0.id in " );
appendInClause( expectedInClause, 4 );
expectedInClause.append( ')' );

assertTrue( statementInspector.getSqlQueries().get( 0 ).endsWith( expectedInClause.toString() ) );
assertThat( statementInspector.getSqlQueries().get( 0 ) ).endsWith( expectedInClause.toString() );
}

@Test
public void testInClauseParameterSplittingAfterLimit3(EntityManagerFactoryScope scope) {
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
statementInspector.clear();

scope.inTransaction(
entityManager ->
entityManager.createQuery(
"select p from Person p where p.id in :ids" )
.setParameter( "ids", IntStream.range( 0, 33 )
.boxed()
.collect( Collectors.toList() ) )
.getResultList()
);
scope.inTransaction( entityManager -> entityManager
.createQuery( "select p from Person p where p.id in :ids" )
.setParameter( "ids", integerRangeList( 0, 33 ) )
.getResultList() );

StringBuilder expectedInClause = new StringBuilder();
expectedInClause.append( "in (?" );
for ( int i = 1; i < MAX_COUNT; i++ ) {
expectedInClause.append( ",?" );
}
expectedInClause.append( ")" );
expectedInClause.append( " or p1_0.id in (?");
for ( int i = 1; i < MAX_COUNT; i++ ) {
expectedInClause.append( ",?" );
}
expectedInClause.append( ")" );
expectedInClause.append( " or p1_0.id in (?,?,?,?)" );
expectedInClause.append( "where (p1_0.id in " );
appendInClause( expectedInClause, MAX_COUNT );
expectedInClause.append( " or p1_0.id in " );
appendInClause( expectedInClause, MAX_COUNT );
expectedInClause.append( " or p1_0.id in " );
appendInClause( expectedInClause, 4 );
expectedInClause.append( ')' );

assertThat( statementInspector.getSqlQueries().get( 0 ) ).endsWith( expectedInClause.toString() );
}

@TestForIssue(jiraKey = "HHH-16589")
@Test
public void testInClauseParameterSplittingAfterLimit4(EntityManagerFactoryScope scope) {
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
statementInspector.clear();

scope.inTransaction( entityManager -> entityManager
.createQuery( "select p from Person p where p.id in :ids" )
.setParameter( "ids", integerRangeList( 0, 39 ) )
.getResultList() );

StringBuilder expectedInClause = new StringBuilder();
expectedInClause.append( "where (p1_0.id in " );
appendInClause( expectedInClause, MAX_COUNT );
expectedInClause.append( " or p1_0.id in " );
appendInClause( expectedInClause, MAX_COUNT );
expectedInClause.append( " or p1_0.id in " );
appendInClause( expectedInClause, MAX_COUNT );
expectedInClause.append( ')' );

assertThat( statementInspector.getSqlQueries().get( 0 ) ).endsWith( expectedInClause.toString() );
}

private static List<Integer> integerRangeList(int start, int end) {
return IntStream.range( start, end )
.boxed()
.collect( Collectors.toList() );
}

assertTrue( statementInspector.getSqlQueries().get( 0 ).endsWith( expectedInClause.toString() ) );
private void appendInClause(StringBuilder sql, int inClauseSize) {
sql.append( "(?" );
for ( int i = 1; i < inClauseSize; i++ ) {
sql.append( ",?" );
}
sql.append( ')' );
}

@Entity(name = "Person")
Expand Down

0 comments on commit 5695536

Please sign in to comment.