From 5fe2b75d2db18ab43d68a5285cf0565fa3b08fb8 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Tue, 20 Feb 2024 00:22:02 +0100 Subject: [PATCH] HHH-15519 make bitand(), bitor(), bitxor() portable - add bitwise functions on SQL Server and Sybase - add bitor(), bitxor() on Oracle - add missing bitwise functions to HANA and h2 - fix broken bitxor() on Postgres - add bitwise functions for EDB --- .../community/dialect/H2LegacyDialect.java | 1 + .../community/dialect/PostgreSQLLegacyDialect.java | 8 +++++++- .../org/hibernate/dialect/AbstractHANADialect.java | 3 +++ .../dialect/AbstractTransactSQLDialect.java | 2 ++ .../main/java/org/hibernate/dialect/H2Dialect.java | 1 + .../java/org/hibernate/dialect/OracleDialect.java | 13 +++++++++++++ .../org/hibernate/dialect/PostgreSQLDialect.java | 7 +++++++ .../org/hibernate/dialect/PostgresPlusDialect.java | 11 ++++++++--- 8 files changed, 42 insertions(+), 4 deletions(-) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java index ca4a526fcd..30c3decba6 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java @@ -328,6 +328,7 @@ public class H2LegacyDialect extends Dialect { functionFactory.bitand(); functionFactory.bitor(); functionFactory.bitxor(); + functionFactory.bitnot(); functionFactory.bitAndOr(); functionFactory.yearMonthDay(); functionFactory.hourMinuteSecond(); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java index 2b5dc2f83f..43814e2e25 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java @@ -66,6 +66,7 @@ import org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy; import org.hibernate.query.sqm.mutation.internal.cte.CteMutationStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; +import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslatorFactory; @@ -80,7 +81,6 @@ import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; import org.hibernate.type.descriptor.jdbc.BlobJdbcType; import org.hibernate.type.descriptor.jdbc.ClobJdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType; -import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor; import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcType; import org.hibernate.type.descriptor.jdbc.XmlJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; @@ -616,6 +616,12 @@ public class PostgreSQLLegacyDialect extends Dialect { functionContributions.getFunctionRegistry().register( "max", new PostgreSQLMinMaxFunction( "max" ) ); } + // Postgres uses # instead of ^ for XOR + functionContributions.getFunctionRegistry().patternDescriptorBuilder( "bitxor", "(?1#?2)" ) + .setExactArgumentCount( 2 ) + .setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE ) + .register(); + functionContributions.getFunctionRegistry().register( "round", new PostgreSQLTruncRoundFunction( "round", true ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java index 48ad7ba988..147a1ee5c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java @@ -427,6 +427,9 @@ public abstract class AbstractHANADialect extends Dialect { functionFactory.log10_log(); functionFactory.log(); functionFactory.bitand(); + functionFactory.bitor(); + functionFactory.bitxor(); + functionFactory.bitnot(); functionFactory.hourMinuteSecond(); functionFactory.yearMonthDay(); functionFactory.dayofweekmonthyear(); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java index d2af7fde99..60f2e89b1a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java @@ -150,6 +150,8 @@ public abstract class AbstractTransactSQLDialect extends Dialect { functionFactory.datepartDatename(); functionFactory.lastDay_eomonth(); + functionFactory.bitandorxornot_operator(); + functionContributions.getFunctionRegistry().register( "least", new CaseLeastGreatestEmulation( true ) ); functionContributions.getFunctionRegistry().register( "greatest", new CaseLeastGreatestEmulation( false ) ); functionContributions.getFunctionRegistry().register( "str", new TransactSQLStrFunction( functionContributions.getTypeConfiguration() ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java index 00c760f1ae..b0fd9e0423 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -274,6 +274,7 @@ public class H2Dialect extends Dialect { functionFactory.bitand(); functionFactory.bitor(); functionFactory.bitxor(); + functionFactory.bitnot(); functionFactory.bitAndOr(); functionFactory.yearMonthDay(); functionFactory.hourMinuteSecond(); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java index 9c57fef651..688d24f49d 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -65,6 +65,7 @@ import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableM import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; import org.hibernate.query.sqm.produce.function.FunctionParameterType; +import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslatorFactory; @@ -303,6 +304,17 @@ public class OracleDialect extends Dialect { //Oracle has had coalesce() since 9.0.1 functionFactory.coalesce(); + functionContributions.getFunctionRegistry() + .patternDescriptorBuilder( "bitor", "(?1+?2-bitand(?1,?2))") + .setExactArgumentCount( 2 ) + .setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE ) + .register(); + functionContributions.getFunctionRegistry() + .patternDescriptorBuilder( "bitxor", "(?1+?2-2*bitand(?1,?2))") + .setExactArgumentCount( 2 ) + .setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE ) + .register(); + functionContributions.getFunctionRegistry().registerBinaryTernaryPattern( "locate", typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.INTEGER ), @@ -311,6 +323,7 @@ public class OracleDialect extends Dialect { FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER, typeConfiguration ).setArgumentListSignature("(pattern, string[, start])"); + // The within group clause became optional in 18 functionFactory.listagg( null ); functionFactory.windowFunctions(); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index ac78bb5a24..7870b3d2bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -64,6 +64,7 @@ import org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy; import org.hibernate.query.sqm.mutation.internal.cte.CteMutationStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; +import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslatorFactory; @@ -662,6 +663,12 @@ public class PostgreSQLDialect extends Dialect { functionContributions.getFunctionRegistry().register( "max", new PostgreSQLMinMaxFunction( "max" ) ); } + // Postgres uses # instead of ^ for XOR + functionContributions.getFunctionRegistry().patternDescriptorBuilder( "bitxor", "(?1#?2)" ) + .setExactArgumentCount( 2 ) + .setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE ) + .register(); + functionContributions.getFunctionRegistry().register( "round", new PostgreSQLTruncRoundFunction( "round", true ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgresPlusDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgresPlusDialect.java index c49013f2e3..e5963b3535 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgresPlusDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgresPlusDialect.java @@ -17,6 +17,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.persister.entity.mutation.EntityMutationTarget; import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.TemporalUnit; +import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory; @@ -60,9 +61,13 @@ public class PostgresPlusDialect extends PostgreSQLDialect { functionFactory.rownumRowid(); functionFactory.sysdate(); functionFactory.systimestamp(); - -// queryEngine.getSqmFunctionRegistry().register( "coalesce", new NvlCoalesceEmulation() ); - + + functionFactory.bitand(); + functionFactory.bitor(); + functionContributions.getFunctionRegistry().patternDescriptorBuilder( "bitxor", "(bitor(?1,?2)-bitand(?1,?2))" ) + .setExactArgumentCount( 2 ) + .setArgumentTypeResolver( StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE ) + .register(); } @Override