From 1b2fd1f8a2c80f5cae76d890be506cd4743408fa Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Fri, 27 Jan 2023 22:19:39 -0600 Subject: [PATCH] HHH-16113 - Add version checks for MERGE support to dialects --- .../java/org/hibernate/dialect/H2Dialect.java | 29 +++++++++++++++ .../hibernate/dialect/PostgreSQLDialect.java | 37 ++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) 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 f8264c188f..82627e12c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -63,6 +63,7 @@ import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.sql.model.MutationOperation; import org.hibernate.sql.model.internal.OptionalTableUpdate; +import org.hibernate.sql.model.jdbc.OptionalTableUpdateOperation; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2DatabaseImpl; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; @@ -119,6 +120,8 @@ public class H2Dialect extends Dialect { private final String querySequenceString; private final UniqueDelegate uniqueDelegate = new CreateTableUniqueDelegate(this); + private final OptionalTableUpdateStrategy optionalTableUpdateStrategy; + public H2Dialect(DialectResolutionInfo info) { this( parseVersion( info ) ); registerKeywords( info ); @@ -146,6 +149,10 @@ public class H2Dialect extends Dialect { ? SequenceInformationExtractorLegacyImpl.INSTANCE : SequenceInformationExtractorH2DatabaseImpl.INSTANCE; this.querySequenceString = "select * from INFORMATION_SCHEMA.SEQUENCES"; + + this.optionalTableUpdateStrategy = version.isSameOrAfter( 1, 4, 200 ) + ? H2Dialect::usingMerge + : H2Dialect::withoutMerge; } private static DatabaseVersion parseVersion(DialectResolutionInfo info) { @@ -871,12 +878,34 @@ public class H2Dialect extends Dialect { return BIGINT; } + @FunctionalInterface + private interface OptionalTableUpdateStrategy { + MutationOperation buildMutationOperation( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory); + } + @Override public MutationOperation createOptionalTableUpdateOperation( EntityMutationTarget mutationTarget, OptionalTableUpdate optionalTableUpdate, SessionFactoryImplementor factory) { + return optionalTableUpdateStrategy.buildMutationOperation( mutationTarget, optionalTableUpdate, factory ); + } + + private static MutationOperation usingMerge( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory) { final H2SqlAstTranslator translator = new H2SqlAstTranslator<>( factory, optionalTableUpdate ); return translator.createMergeOperation( optionalTableUpdate ); } + + private static MutationOperation withoutMerge( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory) { + return new OptionalTableUpdateOperation( mutationTarget, optionalTableUpdate, factory ); + } } 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 fccf122fdd..e01012313d 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -71,6 +71,7 @@ import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.sql.model.MutationOperation; import org.hibernate.sql.model.internal.OptionalTableUpdate; +import org.hibernate.sql.model.jdbc.OptionalTableUpdateOperation; import org.hibernate.type.JavaObjectType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; @@ -136,10 +137,12 @@ import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithM */ public class PostgreSQLDialect extends Dialect { private final static DatabaseVersion MINIMUM_VERSION = DatabaseVersion.make( 10 ); + private static final PostgreSQLIdentityColumnSupport IDENTITY_COLUMN_SUPPORT = new PostgreSQLIdentityColumnSupport(); + private final UniqueDelegate uniqueDelegate = new CreateTableUniqueDelegate(this); private final PostgreSQLDriverKind driverKind; - private final UniqueDelegate uniqueDelegate = new CreateTableUniqueDelegate(this); + private final OptionalTableUpdateStrategy optionalTableUpdateStrategy; public PostgreSQLDialect() { this( MINIMUM_VERSION ); @@ -148,16 +151,25 @@ public class PostgreSQLDialect extends Dialect { public PostgreSQLDialect(DialectResolutionInfo info) { super(info); driverKind = PostgreSQLDriverKind.determineKind( info ); + optionalTableUpdateStrategy = determineOptionalTableUpdateStrategy( info ); + } + + private static OptionalTableUpdateStrategy determineOptionalTableUpdateStrategy(DatabaseVersion version) { + return version.isSameOrAfter( DatabaseVersion.make( 15, 0 ) ) + ? PostgreSQLDialect::usingMerge + : PostgreSQLDialect::withoutMerge; } public PostgreSQLDialect(DatabaseVersion version) { super(version); driverKind = PostgreSQLDriverKind.PG_JDBC; + optionalTableUpdateStrategy = determineOptionalTableUpdateStrategy( version ); } public PostgreSQLDialect(DatabaseVersion version, PostgreSQLDriverKind driverKind) { super(version); this.driverKind = driverKind; + optionalTableUpdateStrategy = determineOptionalTableUpdateStrategy( version ); } @Override @@ -1376,12 +1388,35 @@ public class PostgreSQLDialect extends Dialect { return OTHER; } + + @FunctionalInterface + private interface OptionalTableUpdateStrategy { + MutationOperation buildMutationOperation( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory); + } + @Override public MutationOperation createOptionalTableUpdateOperation( EntityMutationTarget mutationTarget, OptionalTableUpdate optionalTableUpdate, SessionFactoryImplementor factory) { + return optionalTableUpdateStrategy.buildMutationOperation( mutationTarget, optionalTableUpdate, factory ); + } + + private static MutationOperation usingMerge( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory) { final PostgreSQLSqlAstTranslator translator = new PostgreSQLSqlAstTranslator<>( factory, optionalTableUpdate ); return translator.createMergeOperation( optionalTableUpdate ); } + + private static MutationOperation withoutMerge( + EntityMutationTarget mutationTarget, + OptionalTableUpdate optionalTableUpdate, + SessionFactoryImplementor factory) { + return new OptionalTableUpdateOperation( mutationTarget, optionalTableUpdate, factory ); + } }