Fix row value comparison emulation rendering issue that occurred on SAP HANA

This commit is contained in:
Christian Beikov 2021-07-29 16:15:53 +02:00
parent 4ee71faecf
commit b8afa46d8f
4 changed files with 62 additions and 55 deletions

3
Jenkinsfile vendored
View File

@ -34,7 +34,8 @@ stage('Configure') {
buildEnv('8', 'mssql'), buildEnv('8', 'mssql'),
buildEnv('8', 'sybase'), buildEnv('8', 'sybase'),
buildEnv('8', 'hana', 'HANA'), buildEnv('8', 'hana', 'HANA'),
buildEnv('8', 'edb') // Disable EDB for now as the image is not available anymore
// buildEnv('8', 'edb')
]; ];
helper.configure { helper.configure {

View File

@ -15,6 +15,7 @@ import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.SqlTuple;
import org.hibernate.sql.ast.tree.expression.SqlTupleContainer; import org.hibernate.sql.ast.tree.expression.SqlTupleContainer;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
@ -36,9 +37,9 @@ public class FieldFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
sqlAppender.appendSql( ", " ); sqlAppender.appendSql( ", " );
final SqlAstNode argument = sqlAstArguments.get( i ); final SqlAstNode argument = sqlAstArguments.get( i );
if ( argument instanceof SqlTupleContainer ) { final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( argument );
final List<? extends Expression> expressions = ( (SqlTupleContainer) argument ).getSqlTuple() if ( sqlTuple != null ) {
.getExpressions(); final List<? extends Expression> expressions = sqlTuple.getExpressions();
for ( int j = 0; j < expressions.size(); j++ ) { for ( int j = 0; j < expressions.size(); j++ ) {
if ( j != 0 ) { if ( j != 0 ) {
sqlAppender.appendSql( ", " ); sqlAppender.appendSql( ", " );

View File

@ -842,20 +842,15 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
columnReferences.get( 0 ).accept( this ); columnReferences.get( 0 ).accept( this );
appendSql( " = " ); appendSql( " = " );
final Expression assignedValue = assignment.getAssignedValue(); final Expression assignedValue = assignment.getAssignedValue();
if ( assignedValue instanceof SqlTupleContainer ) { final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( assignedValue );
final SqlTuple sqlTuple = ( (SqlTupleContainer) assignedValue ).getSqlTuple(); if ( sqlTuple != null ) {
if ( sqlTuple != null ) { final Expression expression = sqlTuple
final Expression expression = sqlTuple .getExpressions()
.getExpressions() .get( 0 );
.get( 0 ); expression.accept( this );
expression.accept( this );
}
else {
assignedValue.accept( this );
}
} }
else { else {
assignment.getAssignedValue().accept( this ); assignedValue.accept( this );
} }
} }
else { else {
@ -1604,8 +1599,9 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
Function<Expression, Expression> resolveAliasExpression) { Function<Expression, Expression> resolveAliasExpression) {
String separator = ""; String separator = "";
for ( Expression partitionExpression : partitionExpressions ) { for ( Expression partitionExpression : partitionExpressions ) {
if ( partitionExpression instanceof SqlTupleContainer ) { final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( partitionExpression );
for ( Expression e : ( (SqlTupleContainer) partitionExpression ).getSqlTuple().getExpressions() ) { if ( sqlTuple != null ) {
for ( Expression e : sqlTuple.getExpressions() ) {
appendSql( separator ); appendSql( separator );
renderPartitionItem( resolveAliasExpression.apply( e ) ); renderPartitionItem( resolveAliasExpression.apply( e ) );
separator = COMA_SEPARATOR; separator = COMA_SEPARATOR;
@ -1971,10 +1967,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
case NOT_DISTINCT_FROM: { case NOT_DISTINCT_FROM: {
appendSql( "exists (select " ); appendSql( "exists (select " );
clauseStack.push( Clause.SELECT ); clauseStack.push( Clause.SELECT );
renderSelectExpression( lhs ); visitSqlSelectExpression( lhs );
appendSql( getFromDualForSelectOnly() ); appendSql( getFromDualForSelectOnly() );
appendSql( " intersect select " ); appendSql( " intersect select " );
renderSelectExpression( rhs ); visitSqlSelectExpression( rhs );
appendSql( getFromDualForSelectOnly() ); appendSql( getFromDualForSelectOnly() );
clauseStack.pop(); clauseStack.pop();
appendSql( ")" ); appendSql( ")" );
@ -1996,18 +1992,13 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
final Expression sortExpression = sortSpecification.getSortExpression(); final Expression sortExpression = sortSpecification.getSortExpression();
final NullPrecedence nullPrecedence = sortSpecification.getNullPrecedence(); final NullPrecedence nullPrecedence = sortSpecification.getNullPrecedence();
final SortOrder sortOrder = sortSpecification.getSortOrder(); final SortOrder sortOrder = sortSpecification.getSortOrder();
if ( sortExpression instanceof SqlTupleContainer ) { final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( sortExpression );
final SqlTuple sqlTuple = ( (SqlTupleContainer) sortExpression ).getSqlTuple(); if ( sqlTuple != null ) {
if ( sqlTuple != null ){ String separator = NO_SEPARATOR;
String separator = NO_SEPARATOR; for ( Expression expression : sqlTuple.getExpressions() ) {
for ( Expression expression : sqlTuple.getExpressions() ) { appendSql( separator );
appendSql( separator ); visitSortSpecification( expression, sortOrder, nullPrecedence );
visitSortSpecification( expression, sortOrder, nullPrecedence ); separator = COMA_SEPARATOR;
separator = COMA_SEPARATOR;
}
}
else {
visitSortSpecification( sortExpression, sortOrder, nullPrecedence );
} }
} }
else { else {
@ -3051,10 +3042,14 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
@Override @Override
public void visitSqlSelection(SqlSelection sqlSelection) { public void visitSqlSelection(SqlSelection sqlSelection) {
final Expression expression = sqlSelection.getExpression(); visitSqlSelectExpression( sqlSelection.getExpression() );
if ( expression instanceof SqlTupleContainer ) { }
protected void visitSqlSelectExpression(Expression expression) {
final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( expression );
if ( sqlTuple != null ) {
boolean isFirst = true; boolean isFirst = true;
for ( Expression e : ( (SqlTupleContainer) expression ).getSqlTuple().getExpressions() ) { for ( Expression e : sqlTuple.getExpressions() ) {
if ( isFirst ) { if ( isFirst ) {
isFirst = false; isFirst = false;
} }
@ -3556,11 +3551,20 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
protected final void renderCommaSeparatedSelectExpression(Iterable<? extends SqlAstNode> expressions) { protected final void renderCommaSeparatedSelectExpression(Iterable<? extends SqlAstNode> expressions) {
String separator = NO_SEPARATOR; String separator = NO_SEPARATOR;
for ( SqlAstNode expression : expressions ) { for ( SqlAstNode expression : expressions ) {
appendSql( separator ); final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple( expression );
if ( expression instanceof Expression ) { if ( sqlTuple != null ) {
for ( Expression e : sqlTuple.getExpressions() ) {
appendSql( separator );
renderSelectExpression( e );
separator = COMA_SEPARATOR;
}
}
else if ( expression instanceof Expression ) {
appendSql( separator );
renderSelectExpression( (Expression) expression ); renderSelectExpression( (Expression) expression );
} }
else { else {
appendSql( separator );
expression.accept( this ); expression.accept( this );
} }
separator = COMA_SEPARATOR; separator = COMA_SEPARATOR;
@ -4181,7 +4185,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
return; return;
} }
final SqlTuple lhsTuple; final SqlTuple lhsTuple;
if ( ( lhsTuple = getTuple( inListPredicate.getTestExpression() ) ) != null ) { if ( ( lhsTuple = SqlTupleContainer.getSqlTuple( inListPredicate.getTestExpression() ) ) != null ) {
if ( lhsTuple.getExpressions().size() == 1 ) { if ( lhsTuple.getExpressions().size() == 1 ) {
// Special case for tuples with arity 1 as any DBMS supports scalar IN predicates // Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
lhsTuple.getExpressions().get( 0 ).accept( this ); lhsTuple.getExpressions().get( 0 ).accept( this );
@ -4192,7 +4196,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
String separator = NO_SEPARATOR; String separator = NO_SEPARATOR;
for ( Expression expression : listExpressions ) { for ( Expression expression : listExpressions ) {
appendSql( separator ); appendSql( separator );
getTuple( expression ).getExpressions().get( 0 ).accept( this ); SqlTupleContainer.getSqlTuple( expression ).getExpressions().get( 0 ).accept( this );
separator = COMA_SEPARATOR; separator = COMA_SEPARATOR;
} }
appendSql( CLOSE_PARENTHESIS ); appendSql( CLOSE_PARENTHESIS );
@ -4212,7 +4216,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
for ( Expression expression : listExpressions ) { for ( Expression expression : listExpressions ) {
appendSql( separator ); appendSql( separator );
renderExpressionsAsSubquery( renderExpressionsAsSubquery(
getTuple( expression ).getExpressions() SqlTupleContainer.getSqlTuple( expression ).getExpressions()
); );
separator = " union all "; separator = " union all ";
} }
@ -4224,7 +4228,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
appendSql( separator ); appendSql( separator );
emulateTupleComparison( emulateTupleComparison(
lhsTuple.getExpressions(), lhsTuple.getExpressions(),
getTuple( expression ).getExpressions(), SqlTupleContainer.getSqlTuple( expression ).getExpressions(),
comparisonOperator, comparisonOperator,
true true
); );
@ -4253,18 +4257,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
} }
} }
protected final SqlTuple getTuple(Expression expression) {
if ( expression instanceof SqlTupleContainer ) {
return ( (SqlTupleContainer) expression ).getSqlTuple();
}
return null;
}
@Override @Override
public void visitInSubQueryPredicate(InSubQueryPredicate inSubQueryPredicate) { public void visitInSubQueryPredicate(InSubQueryPredicate inSubQueryPredicate) {
final SqlTuple lhsTuple; final SqlTuple lhsTuple;
if ( ( lhsTuple = getTuple( inSubQueryPredicate.getTestExpression() ) ) != null ) { if ( ( lhsTuple = SqlTupleContainer.getSqlTuple( inSubQueryPredicate.getTestExpression() ) ) != null ) {
if ( lhsTuple.getExpressions().size() == 1 ) { if ( lhsTuple.getExpressions().size() == 1 ) {
// Special case for tuples with arity 1 as any DBMS supports scalar IN predicates // Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
lhsTuple.getExpressions().get( 0 ).accept( this ); lhsTuple.getExpressions().get( 0 ).accept( this );
@ -4532,7 +4528,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
predicateValue = " is null"; predicateValue = " is null";
} }
final SqlTuple tuple; final SqlTuple tuple;
if ( ( tuple = getTuple( expression ) ) != null ) { if ( ( tuple = SqlTupleContainer.getSqlTuple( expression ) ) != null ) {
String separator = NO_SEPARATOR; String separator = NO_SEPARATOR;
for ( Expression exp : tuple.getExpressions() ) { for ( Expression exp : tuple.getExpressions() ) {
appendSql( separator ); appendSql( separator );
@ -4561,7 +4557,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
final SqlTuple lhsTuple; final SqlTuple lhsTuple;
final SqlTuple rhsTuple; final SqlTuple rhsTuple;
if ( ( lhsTuple = getTuple( comparisonPredicate.getLeftHandExpression() ) ) != null ) { if ( ( lhsTuple = SqlTupleContainer.getSqlTuple( comparisonPredicate.getLeftHandExpression() ) ) != null ) {
final Expression rhsExpression = comparisonPredicate.getRightHandExpression(); final Expression rhsExpression = comparisonPredicate.getRightHandExpression();
final boolean all; final boolean all;
final QueryPart subquery; final QueryPart subquery;
@ -4591,7 +4587,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
renderComparison( renderComparison(
lhsTuple.getExpressions().get( 0 ), lhsTuple.getExpressions().get( 0 ),
operator, operator,
getTuple( comparisonPredicate.getRightHandExpression() ).getExpressions().get( 0 ) SqlTupleContainer.getSqlTuple( comparisonPredicate.getRightHandExpression() ).getExpressions().get( 0 )
); );
} }
else { else {
@ -4626,7 +4622,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
); );
} }
else if ( !supportsRowValueConstructorSyntax() ) { else if ( !supportsRowValueConstructorSyntax() ) {
rhsTuple = getTuple( rhsExpression ); rhsTuple = SqlTupleContainer.getSqlTuple( rhsExpression );
assert rhsTuple != null; assert rhsTuple != null;
// Some DBs like Oracle support tuples only for the IN subquery predicate // Some DBs like Oracle support tuples only for the IN subquery predicate
if ( ( operator == ComparisonOperator.EQUAL || operator == ComparisonOperator.NOT_EQUAL ) && supportsRowValueConstructorSyntaxInInSubQuery() ) { if ( ( operator == ComparisonOperator.EQUAL || operator == ComparisonOperator.NOT_EQUAL ) && supportsRowValueConstructorSyntaxInInSubQuery() ) {
@ -4651,7 +4647,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
renderComparison( comparisonPredicate.getLeftHandExpression(), operator, rhsExpression ); renderComparison( comparisonPredicate.getLeftHandExpression(), operator, rhsExpression );
} }
} }
else if ( ( rhsTuple = getTuple( comparisonPredicate.getRightHandExpression() ) ) != null ) { else if ( ( rhsTuple = SqlTupleContainer.getSqlTuple( comparisonPredicate.getRightHandExpression() ) ) != null ) {
final Expression lhsExpression = comparisonPredicate.getLeftHandExpression(); final Expression lhsExpression = comparisonPredicate.getLeftHandExpression();
if ( lhsExpression instanceof QueryGroup ) { if ( lhsExpression instanceof QueryGroup ) {

View File

@ -6,9 +6,18 @@
*/ */
package org.hibernate.sql.ast.tree.expression; package org.hibernate.sql.ast.tree.expression;
import org.hibernate.sql.ast.tree.SqlAstNode;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface SqlTupleContainer { public interface SqlTupleContainer {
SqlTuple getSqlTuple(); SqlTuple getSqlTuple();
static SqlTuple getSqlTuple(SqlAstNode expression) {
if ( expression instanceof SqlTupleContainer ) {
return ( (SqlTupleContainer) expression ).getSqlTuple();
}
return null;
}
} }