From 3c5faf5415a0823cbaab9de9fa0c2b649a6fcd23 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 12 Nov 2025 18:00:20 +0100 Subject: [PATCH] HHH-19895 Use alias for row value IN predicate values list emulation and correct DB2 z/OS misconfiguration --- .../community/dialect/DB2zLegacyDialect.java | 6 ++++++ .../org/hibernate/dialect/DB2zDialect.java | 6 ++++++ .../sql/ast/spi/AbstractSqlAstTranslator.java | 20 ++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2zLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2zLegacyDialect.java index 6e8315dc0899..ad7b07daacf8 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2zLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2zLegacyDialect.java @@ -251,4 +251,10 @@ public int rowIdSqlType() { public String getRowIdColumnString(String rowId) { return rowId( rowId ) + " rowid not null generated always"; } + + @Override + public boolean supportsValuesList() { + // DB2 z/OS has a VALUES statement, but that doesn't support multiple values + return false; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java index 3726cc5a9492..7477ee082db7 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java @@ -233,4 +233,10 @@ public int rowIdSqlType() { public String getRowIdColumnString(String rowId) { return rowId( rowId ) + " rowid not null generated always"; } + + @Override + public boolean supportsValuesList() { + // DB2 z/OS has a VALUES statement, but that doesn't support multiple values + return false; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index 26c9fc4665b2..bdcec09221fd 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -7705,12 +7705,21 @@ public void visitInListPredicate(InListPredicate inListPredicate) { else if ( !supportsRowValueConstructorSyntaxInInList() ) { // Some DBs like Oracle support tuples only for the IN subquery predicate if ( supportsRowValueConstructorSyntaxInInSubQuery() && dialect.supportsValuesList() ) { + final int tupleSize = lhsTuple.getExpressionType().getJdbcTypeCount(); inListPredicate.getTestExpression().accept( this ); if ( inListPredicate.isNegated() ) { appendSql( " not" ); } - appendSql( " in (select * from (values" ); + appendSql( " in (select" ); char separator = ' '; + for ( int i = 0; i < tupleSize; i++ ) { + appendSql( separator ); + appendSql( "v_.c" ); + appendSql( i ); + separator = ','; + } + appendSql( " from (values" ); + separator = ' '; for ( Expression expression : listExpressions ) { appendSql( separator ); appendSql( OPEN_PARENTHESIS ); @@ -7719,6 +7728,15 @@ else if ( !supportsRowValueConstructorSyntaxInInList() ) { separator = ','; } appendSql( CLOSE_PARENTHESIS ); + appendSql( " v_" ); + separator = '('; + for ( int i = 0; i < tupleSize; i++ ) { + appendSql( separator ); + appendSql( "c" ); + appendSql( i ); + separator = ','; + } + appendSql( CLOSE_PARENTHESIS ); appendSql( CLOSE_PARENTHESIS ); } else if ( supportsRowValueConstructorSyntaxInInSubQuery() && dialect.supportsUnionAll() ) {