From 4bf817ef8e080e454682fa6e41986879e1a1cf62 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 3f1d6ed56553..ea3c475253e0 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 @@ -237,4 +237,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 f4f6a9fffb4a..8c18859cbe07 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java @@ -211,4 +211,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 2d3d3a645447..9a212fa732ca 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 @@ -7706,12 +7706,21 @@ public void visitInListPredicate(InListPredicate inListPredicate) { else if ( !dialect.supportsRowValueConstructorSyntaxInInList() ) { // Some DBs like Oracle support tuples only for the IN subquery predicate if ( dialect.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 ); @@ -7720,6 +7729,15 @@ else if ( !dialect.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 ( dialect.supportsRowValueConstructorSyntaxInInSubQuery() && dialect.supportsUnionAll() ) {