HHH-18587 Implement Oracle array functions using set operations

https://hibernate.atlassian.net/browse/HHH-18587
This commit is contained in:
Philippe Marschall 2024-09-08 17:41:36 +02:00 committed by Christian Beikov
parent 58ee919feb
commit e7f5f886c7
4 changed files with 77 additions and 40 deletions

View File

@ -40,6 +40,7 @@ import org.hibernate.sql.ast.tree.from.ValuesTableReference;
import org.hibernate.sql.ast.tree.insert.ConflictClause;
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
import org.hibernate.sql.ast.tree.insert.Values;
import org.hibernate.sql.ast.tree.predicate.InArrayPredicate;
import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.QueryGroup;
@ -121,6 +122,15 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends SqlAstTrans
return false;
}
@Override
public void visitInArrayPredicate(InArrayPredicate inArrayPredicate) {
// column in (select column_value from(?) )
inArrayPredicate.getTestExpression().accept( this );
appendSql( " in (select column_value from table(" );
inArrayPredicate.getArrayParameter().accept( this );
appendSql( "))" );
}
@Override
protected boolean supportsWithClauseInSubquery() {
// Oracle has some limitations, see ORA-32034, so we just report false here for simplicity

View File

@ -32,27 +32,35 @@ public class OracleArrayContainsFunction extends AbstractArrayContainsFunction {
final Expression needleExpression = (Expression) sqlAstArguments.get( 1 );
final JdbcMappingContainer needleTypeContainer = needleExpression.getExpressionType();
final JdbcMapping needleType = needleTypeContainer == null ? null : needleTypeContainer.getSingleJdbcMapping();
final String arrayTypeName = DdlTypeHelper.getTypeName(
haystackExpression.getExpressionType(),
walker.getSessionFactory().getTypeConfiguration()
);
sqlAppender.appendSql( arrayTypeName );
if ( needleType == null || needleType instanceof BasicPluralType<?, ?> ) {
LOG.deprecatedArrayContainsWithArray();
sqlAppender.append( "_includes(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ',' );
sqlAppender.append( nullable ? "1" : "0" );
sqlAppender.append( ")>0" );
if ( nullable ) {
final String arrayTypeName = DdlTypeHelper.getTypeName(
haystackExpression.getExpressionType(),
walker.getSessionFactory().getTypeConfiguration()
);
sqlAppender.appendSql( arrayTypeName );
sqlAppender.append( "_includes(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ',' );
sqlAppender.append( "1" );
sqlAppender.append( ")>0" );
}
else {
sqlAppender.append( " exists (select 1 from (table (" );
needleExpression.accept( walker );
sqlAppender.append( ") join (table (" );
haystackExpression.accept( walker );
sqlAppender.append( ")) using (column_value)))" );
}
}
else {
sqlAppender.append( "_position(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
needleExpression.accept( walker );
sqlAppender.append( ")>0" );
sqlAppender.append( " in (select column_value from table(" );
haystackExpression.accept( walker );
sqlAppender.append( "))" );
}
}
}

View File

@ -26,17 +26,27 @@ public class OracleArrayIncludesFunction extends AbstractArrayIncludesFunction {
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final String arrayTypeName = DdlTypeHelper.getTypeName(
haystackExpression.getExpressionType(),
walker.getSessionFactory().getTypeConfiguration()
);
sqlAppender.appendSql( arrayTypeName );
sqlAppender.append( "_includes(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ',' );
sqlAppender.append( nullable ? "1" : "0" );
sqlAppender.append( ")>0" );
if ( nullable ) {
final String arrayTypeName = DdlTypeHelper.getTypeName(
haystackExpression.getExpressionType(),
walker.getSessionFactory().getTypeConfiguration()
);
sqlAppender.appendSql( arrayTypeName );
sqlAppender.append( "_includes(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ',' );
sqlAppender.append( "1" );
sqlAppender.append( ")>0" );
}
else {
sqlAppender.append( " not exists ((select column_value from table (" );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ")) minus (select column_value from table(" );
haystackExpression.accept( walker );
sqlAppender.append( ")))" );
}
}
}

View File

@ -26,18 +26,27 @@ public class OracleArrayIntersectsFunction extends AbstractArrayIntersectsFuncti
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final String arrayTypeName = DdlTypeHelper.getTypeName(
haystackExpression.getExpressionType(),
walker.getSessionFactory().getTypeConfiguration()
);
sqlAppender.appendSql( arrayTypeName );
sqlAppender.append( "_intersects(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ',' );
sqlAppender.append( nullable ? "1" : "0" );
sqlAppender.append( ")>0" );
if ( nullable ) {
final String arrayTypeName = DdlTypeHelper.getTypeName(
haystackExpression.getExpressionType(),
walker.getSessionFactory().getTypeConfiguration()
);
sqlAppender.appendSql( arrayTypeName );
sqlAppender.append( "_intersects(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ',' );
sqlAppender.append( "1" );
sqlAppender.append( ")>0" );
}
else {
sqlAppender.append( " exists (select 1 from (table (" );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ") join (table (" );
haystackExpression.accept( walker );
sqlAppender.append( ")) using (column_value)))" );
}
}
}