From 47eb2f6057c29d06c252b38364f5664f49086291 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 20 Nov 2024 19:26:13 +0100 Subject: [PATCH 1/4] Fix Sybase ASE nightly failure of NationalizedTest --- .../orm/test/mapping/basic/NationalizedTest.java | 3 +++ .../testing/orm/junit/DialectFeatureChecks.java | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/NationalizedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/NationalizedTest.java index 92677fca47cd..4dd0a0119f41 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/NationalizedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/NationalizedTest.java @@ -10,6 +10,8 @@ import org.hibernate.annotations.Nationalized; import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; import org.junit.Test; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; @@ -18,6 +20,7 @@ /** * @author Vlad Mihalcea */ +@RequiresDialectFeature(feature = DialectFeatureChecks.SupportsUnicodeNClob.class) public class NationalizedTest extends BaseEntityManagerFunctionalTestCase { @Override diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java index 32ba62a309c0..174ae834d0cd 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java @@ -66,6 +66,7 @@ import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.SpannerDialect; +import org.hibernate.dialect.SybaseASEDialect; import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.SybaseDriverKind; import org.hibernate.dialect.TiDBDialect; @@ -1023,6 +1024,15 @@ public boolean apply(Dialect dialect) { } } + public static class SupportsUnicodeNClob implements DialectFeatureCheck { + @Override + public boolean apply(Dialect dialect) { + return !(dialect instanceof SybaseASEDialect aseDialect) + // The jconn driver apparently doesn't support unicode characters + || aseDialect.getDriverKind() == SybaseDriverKind.JTDS; + } + } + private static final HashMap FUNCTION_REGISTRIES = new HashMap<>(); public static boolean definesFunction(Dialect dialect, String functionName) { From f1510f8509ed9cd6e7a3df2c5b785b9db7de337a Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 20 Nov 2024 19:30:44 +0100 Subject: [PATCH 2/4] Fix issue with unnest rendering for old PostgreSQL and EDB versions --- .../dialect/function/array/PostgreSQLUnnestFunction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLUnnestFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLUnnestFunction.java index 0b11cda338a0..bc926434ad3e 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLUnnestFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLUnnestFunction.java @@ -57,7 +57,7 @@ protected void renderJsonTable( selectableMapping ) ); } - sqlAppender.append( ' ' ); + sqlAppender.append( " as " ); sqlAppender.append( selectableMapping.getSelectionExpression() ); } ); sqlAppender.appendSql( " from jsonb_array_elements(" ); From 8f19a23ada6c5182e15b9b9b019b60f6d84b2e59 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 20 Nov 2024 19:47:24 +0100 Subject: [PATCH 3/4] Fix rendering of xmltable and boolean handling for older versions of DB2 --- .../dialect/function/xml/DB2XmlTableFunction.java | 11 ++++++++--- .../dialect/function/xml/HANAXmlTableFunction.java | 5 ++++- .../function/xml/SybaseASEXmlTableFunction.java | 5 ++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/DB2XmlTableFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/DB2XmlTableFunction.java index f42998681363..ca0341e899d6 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/DB2XmlTableFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/DB2XmlTableFunction.java @@ -37,7 +37,8 @@ public DB2XmlTableFunction(TypeConfiguration typeConfiguration) { protected void renderXmlTable(SqlAppender sqlAppender, XmlTableArguments arguments, AnonymousTupleTableGroupProducer tupleType, String tableIdentifierVariable, SqlAstTranslator walker) { sqlAppender.appendSql( "xmltable(" ); // DB2 doesn't like parameters for the xpath expression - walker.render( arguments.xpath(), SqlAstNodeRenderingMode.INLINE_PARAMETERS ); + final String xpath = walker.getLiteralValue( arguments.xpath() ); + sqlAppender.appendSingleQuoteEscapedString( "$d" + xpath ); sqlAppender.appendSql( " passing " ); if ( !arguments.isXmlType() ) { sqlAppender.appendSql( "xmlparse(document " ); @@ -45,8 +46,9 @@ protected void renderXmlTable(SqlAppender sqlAppender, XmlTableArguments argumen // DB2 needs parameters to be casted here walker.render( arguments.xmlDocument(), SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER ); if ( !arguments.isXmlType() ) { - sqlAppender.appendSql( ")" ); + sqlAppender.appendSql( ')' ); } + sqlAppender.appendSql( " as \"d\"" ); renderColumns( sqlAppender, arguments.columnsClause(), walker ); sqlAppender.appendSql( ')' ); } @@ -69,7 +71,10 @@ protected void renderXmlValueColumnDefinition(SqlAppender sqlAppender, XmlTableV } static boolean isBoolean(JdbcMapping type) { - return type.getJdbcType().isBoolean(); + return switch ( type.getCastType() ) { + case BOOLEAN, TF_BOOLEAN, YN_BOOLEAN, INTEGER_BOOLEAN -> true; + default -> false; + }; } private static class DB2XmlTableSetReturningFunctionTypeResolver extends XmlTableSetReturningFunctionTypeResolver { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/HANAXmlTableFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/HANAXmlTableFunction.java index b8ffd8555863..78ce92e5a92d 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/HANAXmlTableFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/HANAXmlTableFunction.java @@ -417,7 +417,10 @@ protected void renderDefaultExpression(@Nullable Expression expression, SqlAppen } static boolean isBoolean(JdbcMapping type) { - return type.getJdbcType().isBoolean(); + return switch ( type.getCastType() ) { + case BOOLEAN, TF_BOOLEAN, YN_BOOLEAN, INTEGER_BOOLEAN -> true; + default -> false; + }; } private static class DB2XmlTableSetReturningFunctionTypeResolver extends XmlTableSetReturningFunctionTypeResolver { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/SybaseASEXmlTableFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/SybaseASEXmlTableFunction.java index b72458e34dfc..7629d5d4420f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/SybaseASEXmlTableFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/SybaseASEXmlTableFunction.java @@ -203,6 +203,9 @@ protected void addSelectableMapping(List selectableMappings, } public static boolean isBoolean(JdbcMapping type) { - return type.getJavaTypeDescriptor().getJavaTypeClass() == Boolean.class; + return switch ( type.getCastType() ) { + case BOOLEAN, TF_BOOLEAN, YN_BOOLEAN, INTEGER_BOOLEAN -> true; + default -> false; + }; } } From c5a4cd1b11e126c0f017ce85089da07eab5ea018 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 20 Nov 2024 19:59:56 +0100 Subject: [PATCH 4/4] Don't render distinct from predicate on SQL Server versions that don't support it --- .../SQLServerLegacySqlAstTranslator.java | 34 +++++++++++++++++-- .../dialect/SQLServerSqlAstTranslator.java | 34 +++++++++++++++++-- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacySqlAstTranslator.java index fe4b65b02918..b3011650f534 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacySqlAstTranslator.java @@ -492,10 +492,28 @@ protected void renderComparison(Expression lhs, ComparisonOperator operator, Exp && lhsExpressionType.getSingleJdbcMapping().getJdbcType().getDdlTypeCode() == SqlTypes.SQLXML ) { // In SQL Server, XMLTYPE is not "comparable", so we have to cast the two parts to varchar for this purpose switch ( operator ) { + case DISTINCT_FROM: + if ( !supportsDistinctFromPredicate() ) { + appendSql( "not " ); + } + case NOT_DISTINCT_FROM: { + if ( !supportsDistinctFromPredicate() ) { + appendSql( "exists (select cast(" ); + getClauseStack().push( Clause.SELECT ); + visitSqlSelectExpression( lhs ); + appendSql( " as nvarchar(max))" ); + appendSql( getFromDualForSelectOnly() ); + appendSql( " intersect select cast(" ); + visitSqlSelectExpression( rhs ); + appendSql( " as nvarchar(max))" ); + appendSql( getFromDualForSelectOnly() ); + getClauseStack().pop(); + appendSql( CLOSE_PARENTHESIS ); + return; + } + } case EQUAL: - case NOT_DISTINCT_FROM: case NOT_EQUAL: - case DISTINCT_FROM: appendSql( "cast(" ); lhs.accept( this ); appendSql( " as nvarchar(max))" ); @@ -509,7 +527,17 @@ protected void renderComparison(Expression lhs, ComparisonOperator operator, Exp break; } } - renderComparisonEmulateIntersect( lhs, operator, rhs ); + if ( supportsDistinctFromPredicate() ) { + renderComparisonStandard( lhs, operator, rhs ); + } + else { + renderComparisonEmulateIntersect( lhs, operator, rhs ); + } + } + + @Override + protected boolean supportsDistinctFromPredicate() { + return getDialect().getVersion().isSameOrAfter( 16 ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerSqlAstTranslator.java index 6262ab70a808..4df00fa2903b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerSqlAstTranslator.java @@ -463,10 +463,28 @@ protected void renderComparison(Expression lhs, ComparisonOperator operator, Exp && lhsExpressionType.getSingleJdbcMapping().getJdbcType().getDdlTypeCode() == SqlTypes.SQLXML ) { // In SQL Server, XMLTYPE is not "comparable", so we have to cast the two parts to varchar for this purpose switch ( operator ) { + case DISTINCT_FROM: + if ( !supportsDistinctFromPredicate() ) { + appendSql( "not " ); + } + case NOT_DISTINCT_FROM: { + if ( !supportsDistinctFromPredicate() ) { + appendSql( "exists (select cast(" ); + getClauseStack().push( Clause.SELECT ); + visitSqlSelectExpression( lhs ); + appendSql( " as nvarchar(max))" ); + appendSql( getFromDualForSelectOnly() ); + appendSql( " intersect select cast(" ); + visitSqlSelectExpression( rhs ); + appendSql( " as nvarchar(max))" ); + appendSql( getFromDualForSelectOnly() ); + getClauseStack().pop(); + appendSql( CLOSE_PARENTHESIS ); + return; + } + } case EQUAL: - case NOT_DISTINCT_FROM: case NOT_EQUAL: - case DISTINCT_FROM: appendSql( "cast(" ); lhs.accept( this ); appendSql( " as nvarchar(max))" ); @@ -480,7 +498,17 @@ protected void renderComparison(Expression lhs, ComparisonOperator operator, Exp break; } } - renderComparisonEmulateIntersect( lhs, operator, rhs ); + if ( supportsDistinctFromPredicate() ) { + renderComparisonStandard( lhs, operator, rhs ); + } + else { + renderComparisonEmulateIntersect( lhs, operator, rhs ); + } + } + + @Override + protected boolean supportsDistinctFromPredicate() { + return getDialect().getVersion().isSameOrAfter( 16 ); } @Override