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
parent 8a88ad7f59
commit 91627440a3
4 changed files with 77 additions and 43 deletions

View File

@ -42,6 +42,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;
@ -123,6 +124,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

@ -34,27 +34,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

@ -8,14 +8,11 @@ package org.hibernate.dialect.function.array;
import java.util.List;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.BasicPluralType;
import org.hibernate.type.spi.TypeConfiguration;
public class OracleArrayIncludesFunction extends AbstractArrayIncludesFunction {
@ -31,17 +28,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

@ -28,18 +28,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)))" );
}
}
}