diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 0516ef1832ea..25fc42e05fd2 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -1961,4 +1961,19 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings { */ String QUERY_STATISTICS_MAX_SIZE = "hibernate.statistics.query_max_size"; + /** + * This setting defines the {@link org.hibernate.id.SequenceMismatchStrategy} used when + * Hibernate detects a mismatch between a sequence configuration in an entity mapping + * and its database sequence object counterpart. + *

+ * Possible values are {@link org.hibernate.id.SequenceMismatchStrategy#EXCEPTION}, + * {@link org.hibernate.id.SequenceMismatchStrategy#LOG}, and + * {@link org.hibernate.id.SequenceMismatchStrategy#FIX}. + *

+ * The default value is given by the {@link org.hibernate.id.SequenceMismatchStrategy#EXCEPTION}, + * meaning that an Exception is thrown when detecting such a conflict. + * + * @since 5.4 + */ + String SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY = "hibernate.id.sequence.increment_size_mismatch_strategy"; } 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 85db531f0746..1a2d84904976 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java @@ -79,6 +79,8 @@ import org.hibernate.procedure.internal.StandardCallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; import org.hibernate.service.ServiceRegistry; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHANADatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.tool.schema.internal.StandardTableExporter; import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.type.StandardBasicTypes; @@ -1108,7 +1110,12 @@ public String getNotExpression(final String expression) { @Override public String getQuerySequencesString() { - return "select sequence_name from sys.sequences"; + return "select * from sys.sequences"; + } + + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceInformationExtractorHANADatabaseImpl.INSTANCE; } @Override @@ -1636,5 +1643,4 @@ public int registerResultSetOutParameter(CallableStatement statement, String nam public boolean supportsNoWait() { return true; } - } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/CUBRIDDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/CUBRIDDialect.java index 8c350393f858..f0560cf38540 100755 --- a/hibernate-core/src/main/java/org/hibernate/dialect/CUBRIDDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/CUBRIDDialect.java @@ -16,6 +16,8 @@ import org.hibernate.dialect.identity.IdentityColumnSupport; import org.hibernate.dialect.pagination.CUBRIDLimitHandler; import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorCUBRIDDatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; /** @@ -284,7 +286,12 @@ public boolean supportsExistsInSelect() { @Override public String getQuerySequencesString() { - return "select name from db_serial"; + return "select * from db_serial"; + } + + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceInformationExtractorCUBRIDDatabaseImpl.INSTANCE; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2390V8Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2390V8Dialect.java index e5e2b1464174..b4b0d97299e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2390V8Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2390V8Dialect.java @@ -32,6 +32,6 @@ public String getDropSequenceString(String sequenceName) { } public String getQuerySequencesString() { - return "select name from sysibm.syssequences"; + return "select * from sysibm.syssequences"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java index 13a84cee857a..ae4f849308f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -33,12 +33,14 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.hql.spi.id.IdTableSupportStandardImpl; import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy; -import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy; import org.hibernate.hql.spi.id.local.AfterUseAction; import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.JdbcExceptionHelper; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDB2DatabaseImpl; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.sql.DecimalTypeDescriptor; import org.hibernate.type.descriptor.sql.SmallIntTypeDescriptor; @@ -267,7 +269,17 @@ public boolean supportsPooledSequences() { @Override public String getQuerySequencesString() { - return "select seqname from sysibm.syssequences"; + return "select * from syscat.sequences"; + } + + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + if ( getQuerySequencesString() == null ) { + return SequenceInformationExtractorNoOpImpl.INSTANCE; + } + else { + return SequenceInformationExtractorDB2DatabaseImpl.INSTANCE; + } } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java index 63ef4e50a2c9..421a8085dd0e 100755 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java @@ -29,6 +29,9 @@ import org.hibernate.internal.util.ReflectHelper; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.DerbyCaseFragment; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDerbyDatabaseImpl; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.jboss.logging.Logger; @@ -130,13 +133,23 @@ public boolean supportsSequences() { @Override public String getQuerySequencesString() { if ( supportsSequences() ) { - return "select SEQUENCENAME from SYS.SYSSEQUENCES"; + return "select sys.sysschemas.schemaname as sequence_schema, sys.syssequences.* from sys.syssequences left join sys.sysschemas on sys.syssequences.schemaid = sys.sysschemas.schemaid"; } else { return null; } } + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + if ( getQuerySequencesString() == null ) { + return SequenceInformationExtractorNoOpImpl.INSTANCE; + } + else { + return SequenceInformationExtractorDerbyDatabaseImpl.INSTANCE; + } + } + @Override public String getSequenceNextValString(String sequenceName) { if ( supportsSequences() ) { 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 fea16552b57a..74a2e9b34b58 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -37,7 +37,7 @@ import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2DatabaseImpl; -import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; @@ -81,18 +81,15 @@ public boolean bindLimitParametersInReverseOrder() { public H2Dialect() { super(); - String querySequenceString = "select sequence_name from information_schema.sequences"; - SequenceInformationExtractor sequenceInformationExtractor = SequenceInformationExtractorH2DatabaseImpl.INSTANCE; + int buildId = Integer.MIN_VALUE; + try { // HHH-2300 final Class h2ConstantsClass = ReflectHelper.classForName( "org.h2.engine.Constants" ); final int majorVersion = (Integer) h2ConstantsClass.getDeclaredField( "VERSION_MAJOR" ).get( null ); final int minorVersion = (Integer) h2ConstantsClass.getDeclaredField( "VERSION_MINOR" ).get( null ); - final int buildId = (Integer) h2ConstantsClass.getDeclaredField( "BUILD_ID" ).get( null ); - if ( buildId < 32 ) { - querySequenceString = "select name from information_schema.sequences"; - sequenceInformationExtractor = SequenceInformationExtractorLegacyImpl.INSTANCE; - } + buildId = (Integer) h2ConstantsClass.getDeclaredField( "BUILD_ID" ).get( null ); + if ( ! ( majorVersion > 1 || minorVersion > 2 || buildId >= 139 ) ) { LOG.unsupportedMultiTableBulkHqlJpaql( majorVersion, minorVersion, buildId ); } @@ -103,8 +100,14 @@ public H2Dialect() { LOG.undeterminedH2Version(); } - this.querySequenceString = querySequenceString; - this.sequenceInformationExtractor = sequenceInformationExtractor; + if ( buildId >= 32 ) { + this.sequenceInformationExtractor = SequenceInformationExtractorH2DatabaseImpl.INSTANCE; + this.querySequenceString = "select * from information_schema.sequences"; + } + else { + this.sequenceInformationExtractor = SequenceInformationExtractorNoOpImpl.INSTANCE; + this.querySequenceString = null; + } registerColumnType( Types.BOOLEAN, "boolean" ); registerColumnType( Types.BIGINT, "bigint" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java index 5ac0bbe54dc2..626129727391 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java @@ -7,6 +7,7 @@ package org.hibernate.dialect; import java.io.Serializable; +import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.sql.Types; import java.util.Locale; @@ -48,10 +49,12 @@ import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.persister.entity.Lockable; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHANADatabaseImpl; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHSQLDBDatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; import org.jboss.logging.Logger; -import java.sql.DatabaseMetaData; /** * An SQL dialect compatible with HSQLDB (HyperSQL). @@ -369,7 +372,12 @@ public String getSequenceNextValString(String sequenceName) { @Override public String getQuerySequencesString() { // this assumes schema support, which is present in 1.8.0 and later... - return "select sequence_name from information_schema.system_sequences"; + return "select * from information_schema.sequences"; + } + + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceInformationExtractorHSQLDBDatabaseImpl.INSTANCE; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java index 8ed37b7abb08..96ea458be796 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/InformixDialect.java @@ -28,6 +28,8 @@ import org.hibernate.hql.spi.id.local.AfterUseAction; import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy; import org.hibernate.internal.util.JdbcExceptionHelper; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorInformixDatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; /** @@ -148,7 +150,7 @@ public String getCreateSequenceString(String sequenceName) { @Override public String getDropSequenceString(String sequenceName) { - return "drop sequence " + sequenceName + " restrict"; + return "drop sequence " + sequenceName; } @Override @@ -173,7 +175,12 @@ public boolean supportsPooledSequences() { @Override public String getQuerySequencesString() { - return "select tabname from informix.systables where tabtype='Q'"; + return "select systables.tabname as sequence_name, syssequences.* from syssequences join systables on syssequences.tabid = systables.tabid where tabtype = 'Q'"; + } + + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceInformationExtractorInformixDatabaseImpl.INSTANCE; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java index 382da0379e30..908fd7f7de69 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Ingres9Dialect.java @@ -16,6 +16,8 @@ import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.LimitHelper; import org.hibernate.engine.spi.RowSelection; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorIngresDatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; /** diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java index 17391152d873..33affffe4b4a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/IngresDialect.java @@ -20,6 +20,8 @@ import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy; import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy; import org.hibernate.hql.spi.id.local.AfterUseAction; +import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; /** @@ -215,6 +217,11 @@ public String getQuerySequencesString() { return "select seq_name from iisequence"; } + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceNameExtractorImpl.INSTANCE; + } + @Override public String getLowercaseFunction() { return "lowercase"; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/InterbaseDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/InterbaseDialect.java index cdbc7c54c09d..96eb77691c5e 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/InterbaseDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/InterbaseDialect.java @@ -5,6 +5,7 @@ * See the lgpl.txt file in the root directory or . */ package org.hibernate.dialect; + import java.sql.Types; import java.util.Locale; @@ -15,6 +16,8 @@ import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.LimitHelper; import org.hibernate.engine.spi.RowSelection; +import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; /** @@ -97,6 +100,11 @@ public String getQuerySequencesString() { return "select RDB$GENERATOR_NAME from RDB$GENERATORS"; } + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceNameExtractorImpl.INSTANCE; + } + @Override public String getForUpdateString() { return " with lock"; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDB103Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDB103Dialect.java index 9c0abaca3803..01321352c473 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDB103Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDB103Dialect.java @@ -9,6 +9,8 @@ import org.hibernate.LockOptions; import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.tool.schema.extract.internal.SequenceNameExtractorImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; /** @@ -59,6 +61,12 @@ public String getQuerySequencesString() { return "select table_name from information_schema.TABLES where table_type='SEQUENCE'"; } + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + //TODO: Future improvement - https://hibernate.atlassian.net/browse/HHH-13008 + return SequenceNameExtractorImpl.INSTANCE; + } + @Override public String getWriteLockString(int timeout) { if ( timeout == LockOptions.NO_WAIT ) { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MimerSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MimerSQLDialect.java index 706cc778c73b..d40430982526 100755 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MimerSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MimerSQLDialect.java @@ -12,6 +12,8 @@ import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.identity.IdentityColumnSupport; import org.hibernate.dialect.identity.MimerSQLIdentityColumnSupport; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorMimerSQLDatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; /** @@ -166,7 +168,12 @@ public String getCascadeConstraintsString() { @Override public String getQuerySequencesString() { - return "select sequence_schema || '.' || sequence_name from information_schema.ext_sequences"; + return "select * from information_schema.ext_sequences"; + } + + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceInformationExtractorMimerSQLDatabaseImpl.INSTANCE; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java index e3243fee7338..351eaf7ce6bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java @@ -10,7 +10,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; -import java.util.List; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -45,6 +44,8 @@ import org.hibernate.sql.DecodeCaseFragment; import org.hibernate.sql.JoinFragment; import org.hibernate.sql.OracleJoinFragment; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.sql.BitTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; @@ -489,12 +490,11 @@ public boolean forUpdateOfColumns() { @Override public String getQuerySequencesString() { - return " select sequence_name from all_sequences" - + " union" - + " select synonym_name" - + " from all_synonyms us, all_sequences asq" - + " where asq.sequence_name = us.table_name" - + " and asq.sequence_owner = us.table_owner"; + return "select * from all_sequences"; + } + + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceInformationExtractorOracleDatabaseImpl.INSTANCE; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java index 9a717e57ed92..1fe9a24a4162 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Oracle9Dialect.java @@ -20,6 +20,8 @@ import org.hibernate.hql.spi.id.local.AfterUseAction; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.JdbcExceptionHelper; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; import org.jboss.logging.Logger; @@ -284,7 +286,11 @@ public boolean forUpdateOfColumns() { @Override public String getQuerySequencesString() { - return "select sequence_name from user_sequences"; + return "select * from all_sequences"; + } + + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceInformationExtractorOracleDatabaseImpl.INSTANCE; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java index f8cdaf44ee86..d75135d7c1e7 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java @@ -242,7 +242,7 @@ public boolean supportsSequences() { @Override public String getQuerySequencesString() { - return "select relname from pg_class where relkind='S'"; + return "select * from information_schema.sequences"; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java index 8614b98a9bbf..0e5453c1e46c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SAPDBDialect.java @@ -19,6 +19,8 @@ import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.DecodeCaseFragment; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorSAPDBDatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; /** @@ -198,7 +200,12 @@ public String getDropSequenceString(String sequenceName) { @Override public String getQuerySequencesString() { - return "select sequence_name from domain.sequences"; + return "select * from domain.sequences"; + } + + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceInformationExtractorSAPDBDatabaseImpl.INSTANCE; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2012Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2012Dialect.java index 1fdb8f35978b..795c4c4499cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2012Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServer2012Dialect.java @@ -6,8 +6,6 @@ */ package org.hibernate.dialect; -import java.util.List; - import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.SQLServer2012LimitHandler; @@ -50,7 +48,7 @@ public String getSequenceNextValString(String sequenceName) { @Override public String getQuerySequencesString() { - return "select name from sys.sequences"; + return "select * from information_schema.sequences"; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java index 41e016f9428f..9a1fb668af06 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/TimesTenDialect.java @@ -30,6 +30,8 @@ import org.hibernate.persister.entity.Lockable; import org.hibernate.sql.JoinFragment; import org.hibernate.sql.OracleJoinFragment; +import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorTimesTenDatabaseImpl; +import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.StandardBasicTypes; /** @@ -129,7 +131,12 @@ public String getDropSequenceString(String sequenceName) { @Override public String getQuerySequencesString() { - return "select NAME from sys.sequences"; + return "select * from sys.sequences"; + } + + @Override + public SequenceInformationExtractor getSequenceInformationExtractor() { + return SequenceInformationExtractorTimesTenDatabaseImpl.INSTANCE; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java index 11f1ed780d82..406dfbedb31b 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java @@ -13,6 +13,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; import org.hibernate.engine.jdbc.cursor.internal.StandardRefCursorSupport; @@ -21,6 +22,7 @@ import org.hibernate.engine.jdbc.env.spi.SQLStateType; import org.hibernate.engine.jdbc.spi.TypeInfo; import org.hibernate.internal.util.StringHelper; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; /** * Standard implementation of ExtractedDatabaseMetaData @@ -45,6 +47,7 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData private final Set extraKeywords; private final LinkedHashSet typeInfoSet; + private final List sequenceInformationList; private ExtractedDatabaseMetaDataImpl( JdbcEnvironment jdbcEnvironment, @@ -60,7 +63,8 @@ private ExtractedDatabaseMetaDataImpl( boolean supportsDataDefinitionInTransaction, boolean doesDataDefinitionCauseTransactionCommit, SQLStateType sqlStateType, - boolean lobLocatorUpdateCopy) { + boolean lobLocatorUpdateCopy, + List sequenceInformationList) { this.jdbcEnvironment = jdbcEnvironment; this.connectionCatalogName = connectionCatalogName; @@ -82,6 +86,7 @@ private ExtractedDatabaseMetaDataImpl( this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit; this.sqlStateType = sqlStateType; this.lobLocatorUpdateCopy = lobLocatorUpdateCopy; + this.sequenceInformationList = sequenceInformationList; } @Override @@ -154,6 +159,11 @@ public LinkedHashSet getTypeInfoSet() { return typeInfoSet; } + @Override + public List getSequenceInformationList() { + return sequenceInformationList; + } + public static class Builder { private final JdbcEnvironment jdbcEnvironment; @@ -172,6 +182,7 @@ public static class Builder { private boolean doesDataDefinitionCauseTransactionCommit; private SQLStateType sqlStateType; private boolean lobLocatorUpdateCopy; + private List sequenceInformationList = Collections.emptyList(); public Builder(JdbcEnvironment jdbcEnvironment) { this.jdbcEnvironment = jdbcEnvironment; @@ -296,6 +307,11 @@ public Builder setLobLocatorUpdateCopy(boolean lobLocatorUpdateCopy) { return this; } + public Builder setSequenceInformationList(List sequenceInformationList) { + this.sequenceInformationList = sequenceInformationList; + return this; + } + public ExtractedDatabaseMetaDataImpl build() { return new ExtractedDatabaseMetaDataImpl( jdbcEnvironment, @@ -311,7 +327,8 @@ public ExtractedDatabaseMetaDataImpl build() { supportsDataDefinitionInTransaction, doesDataDefinitionCauseTransactionCommit, sqlStateType, - lobLocatorUpdateCopy + lobLocatorUpdateCopy, + sequenceInformationList ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java index e983cb850f37..2c3b5739e001 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java @@ -6,12 +6,17 @@ */ package org.hibernate.engine.jdbc.env.internal; +import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.registry.selector.spi.StrategySelector; @@ -34,6 +39,8 @@ import org.hibernate.exception.internal.StandardSQLExceptionConverter; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.tool.schema.extract.spi.ExtractionContext; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; import org.jboss.logging.Logger; @@ -62,7 +69,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment { * @param serviceRegistry The service registry * @param dialect The resolved dialect. */ - public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect) { + public JdbcEnvironmentImpl(final ServiceRegistryImplementor serviceRegistry, Dialect dialect) { this.dialect = dialect; final ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class ); @@ -78,7 +85,8 @@ public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect d final IdentifierHelperBuilder identifierHelperBuilder = IdentifierHelperBuilder.from( this ); identifierHelperBuilder.setGloballyQuoteIdentifiers( globalQuoting( cfgService ) ); - identifierHelperBuilder.setSkipGlobalQuotingForColumnDefinitions( globalQuotingSkippedForColumnDefinitions( cfgService ) ); + identifierHelperBuilder.setSkipGlobalQuotingForColumnDefinitions( globalQuotingSkippedForColumnDefinitions( + cfgService ) ); identifierHelperBuilder.setAutoQuoteKeywords( autoKeywordQuoting( cfgService ) ); identifierHelperBuilder.setNameQualifierSupport( nameQualifierSupport ); @@ -153,11 +161,6 @@ public JdbcEnvironmentImpl(DatabaseMetaData databaseMetaData, Dialect dialect) t this.sqlExceptionHelper = buildSqlExceptionHelper( dialect, false ); - this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this ) - .apply( databaseMetaData ) - .setSupportsNamedParameters( databaseMetaData.supportsNamedParameters() ) - .build(); - NameQualifierSupport nameQualifierSupport = dialect.getNameQualifierSupport(); if ( nameQualifierSupport == null ) { nameQualifierSupport = determineNameQualifierSupport( databaseMetaData ); @@ -179,6 +182,12 @@ public JdbcEnvironmentImpl(DatabaseMetaData databaseMetaData, Dialect dialect) t } this.identifierHelper = identifierHelper; + this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this ) + .apply( databaseMetaData ) + .setSupportsNamedParameters( databaseMetaData.supportsNamedParameters() ) + .setSequenceInformationList( sequenceInformationList( databaseMetaData.getConnection() ) ) + .build(); + this.currentCatalog = null; this.currentSchema = null; @@ -227,12 +236,6 @@ public JdbcEnvironmentImpl( this.sqlExceptionHelper = buildSqlExceptionHelper( dialect, logWarnings( cfgService, dialect ) ); - this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this ) - .apply( databaseMetaData ) - .setConnectionSchemaName( determineCurrentSchemaName( databaseMetaData, serviceRegistry, dialect ) ) - .setSupportsNamedParameters(dialect.supportsNamedParameters(databaseMetaData)) - .build(); - NameQualifierSupport nameQualifierSupport = dialect.getNameQualifierSupport(); if ( nameQualifierSupport == null ) { nameQualifierSupport = determineNameQualifierSupport( databaseMetaData ); @@ -241,7 +244,8 @@ public JdbcEnvironmentImpl( final IdentifierHelperBuilder identifierHelperBuilder = IdentifierHelperBuilder.from( this ); identifierHelperBuilder.setGloballyQuoteIdentifiers( globalQuoting( cfgService ) ); - identifierHelperBuilder.setSkipGlobalQuotingForColumnDefinitions( globalQuotingSkippedForColumnDefinitions( cfgService ) ); + identifierHelperBuilder.setSkipGlobalQuotingForColumnDefinitions( globalQuotingSkippedForColumnDefinitions( + cfgService ) ); identifierHelperBuilder.setAutoQuoteKeywords( autoKeywordQuoting( cfgService ) ); identifierHelperBuilder.setNameQualifierSupport( nameQualifierSupport ); IdentifierHelper identifierHelper = null; @@ -257,6 +261,13 @@ public JdbcEnvironmentImpl( } this.identifierHelper = identifierHelper; + this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this ) + .apply( databaseMetaData ) + .setConnectionSchemaName( determineCurrentSchemaName( databaseMetaData, serviceRegistry, dialect ) ) + .setSupportsNamedParameters( dialect.supportsNamedParameters( databaseMetaData ) ) + .setSequenceInformationList( sequenceInformationList( databaseMetaData.getConnection() ) ) + .build(); + // and that current-catalog and current-schema happen after it this.currentCatalog = identifierHelper.toIdentifier( extractedMetaDataSupport.getConnectionCatalogName() ); this.currentSchema = identifierHelper.toIdentifier( extractedMetaDataSupport.getConnectionSchemaName() ); @@ -282,7 +293,8 @@ private String determineCurrentSchemaName( Dialect dialect) throws SQLException { final SchemaNameResolver schemaNameResolver; - final Object setting = serviceRegistry.getService( ConfigurationService.class ).getSettings().get( SCHEMA_NAME_RESOLVER ); + final Object setting = serviceRegistry.getService( ConfigurationService.class ).getSettings().get( + SCHEMA_NAME_RESOLVER ); if ( setting == null ) { schemaNameResolver = dialect.getSchemaNameResolver(); } @@ -375,4 +387,38 @@ public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) { } return null; } + + /** + * Get the sequence information List from the database. + * + * @param connection database connection + * @return sequence information List + */ + private List sequenceInformationList(final Connection connection) { + try { + + Iterable sequenceInformationIterable = dialect + .getSequenceInformationExtractor() + .extractMetadata( new ExtractionContext.EmptyExtractionContext() { + @Override + public Connection getJdbcConnection() { + return connection; + } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return JdbcEnvironmentImpl.this; + } + } + ); + + return StreamSupport.stream( sequenceInformationIterable.spliterator(), false ) + .collect( Collectors.toList() ); + } + catch (SQLException e) { + log.error( "Could not fetch the SequenceInformation from the database", e ); + } + + return Collections.emptyList(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java index e2f418580e88..7410cdbf32fc 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java @@ -6,10 +6,14 @@ */ package org.hibernate.engine.jdbc.env.spi; +import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; import org.hibernate.engine.jdbc.spi.TypeInfo; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; /** * Information extracted from {@link java.sql.DatabaseMetaData} regarding what the JDBC driver reports as @@ -140,4 +144,13 @@ public interface ExtractedDatabaseMetaData { * @see java.sql.DatabaseMetaData#locatorsUpdateCopy() */ boolean doesLobLocatorUpdateCopy(); + + /** + * Retrieve the list of {@code SequenceInformation} objects which describe the underlying database sequences. + * + * @return {@code SequenceInformation} objects. + */ + default List getSequenceInformationList() { + return Collections.emptyList(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/id/SequenceMismatchStrategy.java b/hibernate-core/src/main/java/org/hibernate/id/SequenceMismatchStrategy.java new file mode 100644 index 000000000000..cd90cdf0b962 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/id/SequenceMismatchStrategy.java @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id; + +import org.hibernate.HibernateException; + +/** + * Describes the strategy for handling the mismatch between a database sequence configuration and + * the one defined by the entity mapping. + * + * @author Vlad Mihalcea + */ +public enum SequenceMismatchStrategy { + + /** + * When detecting a mismatch, Hibernate simply logs the sequence whose entity mapping configuration conflicts + * with the one found in the database. + */ + LOG, + + /** + * When detecting a mismatch, Hibernate throws a {@link org.hibernate.MappingException} indicating the sequence + * whose entity mapping configuration conflict with the one found in the database. + */ + EXCEPTION, + + /** + * When detecting a mismatch, Hibernate tries to fix it by overriding the entity sequence mapping using the one + * found in the database. + */ + FIX; + + /** + * Interpret the configured SequenceMismatchStrategy value. + *

+ * Valid values are either a {@link SequenceMismatchStrategy} object or its String representation. + *

+ * For string values, the matching is case insensitive, so you can use either {@code FIX} or {@code fix}. + * + * @param sequenceMismatchStrategy configured {@link SequenceMismatchStrategy} representation + * + * @return associated {@link SequenceMismatchStrategy} object + */ + public static SequenceMismatchStrategy interpret(Object sequenceMismatchStrategy) { + if ( sequenceMismatchStrategy == null ) { + return EXCEPTION; + } + else if ( sequenceMismatchStrategy instanceof SequenceMismatchStrategy ) { + return (SequenceMismatchStrategy) sequenceMismatchStrategy; + } + else if ( sequenceMismatchStrategy instanceof String ) { + String sequenceMismatchStrategyString = (String) sequenceMismatchStrategy; + for ( SequenceMismatchStrategy value : values() ) { + if ( value.name().equalsIgnoreCase( sequenceMismatchStrategyString ) ) { + return value; + } + } + } + throw new HibernateException( + "Unrecognized sequence.increment_size_mismatch_strategy value : [" + sequenceMismatchStrategy + + "]. Supported values include [log], [exception], and [fix]." + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java index e4b80e562696..eb475effb279 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java @@ -25,10 +25,12 @@ import org.hibernate.id.Configurable; import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.PersistentIdentifierGenerator; +import org.hibernate.id.SequenceMismatchStrategy; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.ServiceRegistry; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; import org.hibernate.type.Type; import org.jboss.logging.Logger; @@ -218,12 +220,13 @@ public Type getIdentifierType() { } - // Configurable implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException { final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class ); + final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class ); + final Dialect dialect = jdbcEnvironment.getDialect(); this.identifierType = type; @@ -234,6 +237,37 @@ public void configure(Type type, Properties params, ServiceRegistry serviceRegis final int initialValue = determineInitialValue( params ); int incrementSize = determineIncrementSize( params ); + if ( isPhysicalSequence( jdbcEnvironment, forceTableUse ) ) { + String databaseSequenceName = sequenceName.getObjectName().getText(); + Long databaseIncrementValue = getSequenceIncrementValue( jdbcEnvironment, databaseSequenceName ); + + if ( databaseIncrementValue != null && !databaseIncrementValue.equals( (long) incrementSize ) ) { + int dbIncrementValue = databaseIncrementValue.intValue(); + + SequenceMismatchStrategy sequenceMismatchStrategy = configurationService.getSetting( + AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY, + SequenceMismatchStrategy::interpret, + SequenceMismatchStrategy.EXCEPTION + ); + + switch ( sequenceMismatchStrategy ) { + case EXCEPTION: + throw new MappingException( + String.format( + "The increment size of the [%s] sequence is set to [%d] in the entity mapping " + + "while the associated database sequence increment size is [%d].", + databaseSequenceName, incrementSize, dbIncrementValue + ) + ); + case FIX: + incrementSize = dbIncrementValue; + case LOG: + LOG.sequenceIncrementSizeMismatch( databaseSequenceName, incrementSize, dbIncrementValue ); + break; + } + } + } + final String optimizationStrategy = determineOptimizationStrategy( params, incrementSize ); incrementSize = determineAdjustedIncrementSize( optimizationStrategy, incrementSize ); @@ -443,8 +477,7 @@ protected DatabaseStructure buildDatabaseStructure( QualifiedName sequenceName, int initialValue, int incrementSize) { - final boolean useSequence = jdbcEnvironment.getDialect().supportsSequences() && !forceTableUse; - if ( useSequence ) { + if ( isPhysicalSequence( jdbcEnvironment, forceTableUse ) ) { return buildSequenceStructure( type, params, jdbcEnvironment, sequenceName, initialValue, incrementSize ); } else { @@ -452,6 +485,10 @@ protected DatabaseStructure buildDatabaseStructure( } } + protected boolean isPhysicalSequence(JdbcEnvironment jdbcEnvironment, boolean forceTableUse) { + return jdbcEnvironment.getDialect().supportsSequences() && !forceTableUse; + } + protected DatabaseStructure buildSequenceStructure( Type type, Properties params, @@ -521,4 +558,24 @@ public String determineBulkInsertionIdentifierGenerationSelectFragment(Dialect d public void registerExportables(Database database) { databaseStructure.registerExportables( database ); } + + /** + * Get the database sequence increment value from the associated {@link SequenceInformation} object. + * + * @param jdbcEnvironment the current JdbcEnvironment + * @param sequenceName sequence name + * + * @return sequence increment value + */ + private Long getSequenceIncrementValue(JdbcEnvironment jdbcEnvironment, String sequenceName) { + return jdbcEnvironment.getExtractedDatabaseMetaData().getSequenceInformationList().stream().filter( + sequenceInformation -> { + Identifier catalog = sequenceInformation.getSequenceName().getCatalogName(); + Identifier schema = sequenceInformation.getSequenceName().getSchemaName(); + return sequenceName.equalsIgnoreCase( sequenceInformation.getSequenceName().getSequenceName().getText() ) && + ( catalog == null || catalog.equals( jdbcEnvironment.getCurrentCatalog() ) ) && + ( schema == null || schema.equals( jdbcEnvironment.getCurrentSchema() ) ); + } + ).map( SequenceInformation::getIncrementValue ).findFirst().orElse( null ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java index 99fa6dd97431..bde56cf1e4c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java @@ -1843,4 +1843,8 @@ void attemptToAssociateProxyWithTwoOpenSessions( @LogMessage(level = WARN) @Message(value = "Detaching an uninitialized collection with queued operations from a session: %s", id = 496) void queuedOperationWhenDetachFromSession(String collectionInfoString); + + @LogMessage(level = WARN) + @Message(value = "The increment size of the [%s] sequence is set to [%d] in the entity mapping while the associated database sequence increment size is [%d]. The database sequence increment size will take precedence to avoid identifier allocation conflicts.", id = 497) + void sequenceIncrementSizeMismatch(String sequenceName, int incrementSize, int databaseIncrementSize); } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorCUBRIDDatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorCUBRIDDatabaseImpl.java new file mode 100644 index 000000000000..ad3c37aa1710 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorCUBRIDDatabaseImpl.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorCUBRIDDatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorCUBRIDDatabaseImpl INSTANCE = new SequenceInformationExtractorCUBRIDDatabaseImpl(); + + @Override + protected String sequenceNameColumn() { + return "name"; + } + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceSchemaColumn() { + return null; + } + + @Override + protected String sequenceStartValueColumn() { + return "started"; + } + + @Override + protected String sequenceMinValueColumn() { + return "min_val"; + } + + @Override + protected String sequenceMaxValueColumn() { + return "max_val"; + } + + @Override + protected String sequenceIncrementColumn() { + return "increment_val"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorDB2DatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorDB2DatabaseImpl.java new file mode 100644 index 000000000000..40aa2907c249 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorDB2DatabaseImpl.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorDB2DatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorDB2DatabaseImpl INSTANCE = new SequenceInformationExtractorDB2DatabaseImpl(); + + @Override + protected String sequenceNameColumn() { + return "seqname"; + } + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceSchemaColumn() { + return "seqschema"; + } + + @Override + protected String sequenceStartValueColumn() { + return "start"; + } + + @Override + protected String sequenceMinValueColumn() { + return "minvalue"; + } + + @Override + protected String sequenceMaxValueColumn() { + return "maxvalue"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorDerbyDatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorDerbyDatabaseImpl.java new file mode 100644 index 000000000000..b139c32d47ed --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorDerbyDatabaseImpl.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorDerbyDatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorDerbyDatabaseImpl INSTANCE = new SequenceInformationExtractorDerbyDatabaseImpl(); + + @Override + protected String sequenceNameColumn() { + return "sequencename"; + } + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceStartValueColumn() { + return "startvalue"; + } + + @Override + protected String sequenceMinValueColumn() { + return "minimumvalue"; + } + + @Override + protected String sequenceMaxValueColumn() { + return "maximumvalue"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorH2DatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorH2DatabaseImpl.java index 9049807e4432..860b47b06da8 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorH2DatabaseImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorH2DatabaseImpl.java @@ -8,72 +8,28 @@ import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.boot.model.relational.QualifiedSequenceName; -import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; -import org.hibernate.tool.schema.extract.spi.ExtractionContext; -import org.hibernate.tool.schema.extract.spi.SequenceInformation; -import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; /** - * Temporary implementation that works for H2. - * * @author Steve Ebersole */ -public class SequenceInformationExtractorH2DatabaseImpl implements SequenceInformationExtractor { +public class SequenceInformationExtractorH2DatabaseImpl extends SequenceInformationExtractorLegacyImpl { /** * Singleton access */ public static final SequenceInformationExtractorH2DatabaseImpl INSTANCE = new SequenceInformationExtractorH2DatabaseImpl(); @Override - public Iterable extractMetadata(ExtractionContext extractionContext) throws SQLException { - final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper(); - final Statement statement = extractionContext.getJdbcConnection().createStatement(); - try { - ResultSet resultSet = statement.executeQuery( - "select SEQUENCE_CATALOG, SEQUENCE_SCHEMA, SEQUENCE_NAME, INCREMENT " + - "from information_schema.sequences" - ); - try { - final List sequenceInformationList = new ArrayList(); - while ( resultSet.next() ) { - sequenceInformationList.add( - new SequenceInformationImpl( - new QualifiedSequenceName( - identifierHelper.toIdentifier( - resultSet.getString( "SEQUENCE_CATALOG" ) - ), - identifierHelper.toIdentifier( - resultSet.getString( "SEQUENCE_SCHEMA" ) - ), - identifierHelper.toIdentifier( - resultSet.getString( "SEQUENCE_NAME" ) - ) - ), - resultSet.getInt( "INCREMENT" ) - ) - ); - } - return sequenceInformationList; - } - finally { - try { - resultSet.close(); - } - catch (SQLException ignore) { - } - } - } - finally { - try { - statement.close(); - } - catch (SQLException ignore) { - } - } + protected String sequenceStartValueColumn() { + return null; + } + + @Override + protected String sequenceMinValueColumn() { + return "min_value"; + } + + @Override + protected String sequenceMaxValueColumn() { + return "max_value"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorHANADatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorHANADatabaseImpl.java new file mode 100644 index 000000000000..943ddc4901d0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorHANADatabaseImpl.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorHANADatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorHANADatabaseImpl INSTANCE = new SequenceInformationExtractorHANADatabaseImpl(); + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceSchemaColumn() { + return "schema_name"; + } + + @Override + protected String sequenceStartValueColumn() { + return "start_number"; + } + + @Override + protected String sequenceMinValueColumn() { + return "min_value"; + } + + @Override + protected String sequenceMaxValueColumn() { + return "max_value"; + } + + @Override + protected String sequenceIncrementColumn() { + return "increment_by"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorHSQLDBDatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorHSQLDBDatabaseImpl.java new file mode 100644 index 000000000000..9da2d724301d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorHSQLDBDatabaseImpl.java @@ -0,0 +1,23 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorHSQLDBDatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorHSQLDBDatabaseImpl INSTANCE = new SequenceInformationExtractorHSQLDBDatabaseImpl(); + + @Override + protected String sequenceStartValueColumn() { + return "start_with"; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorInformixDatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorInformixDatabaseImpl.java new file mode 100644 index 000000000000..f4d8a1e73055 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorInformixDatabaseImpl.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorInformixDatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorInformixDatabaseImpl INSTANCE = new SequenceInformationExtractorInformixDatabaseImpl(); + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceSchemaColumn() { + return null; + } + + @Override + protected String sequenceStartValueColumn() { + return "start_val"; + } + + @Override + protected String sequenceMinValueColumn() { + return "min_val"; + } + + @Override + protected String sequenceMaxValueColumn() { + return "max_val"; + } + + @Override + protected String sequenceIncrementColumn() { + return "inc_val"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorIngresDatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorIngresDatabaseImpl.java new file mode 100644 index 000000000000..8178a406f2e4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorIngresDatabaseImpl.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorIngresDatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorIngresDatabaseImpl INSTANCE = new SequenceInformationExtractorIngresDatabaseImpl(); + + @Override + protected String sequenceNameColumn() { + return "seq_name"; + } + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceSchemaColumn() { + return null; + } + + @Override + protected String sequenceStartValueColumn() { + return null; + } + + @Override + protected String sequenceMinValueColumn() { + return null; + } + + @Override + protected String sequenceMaxValueColumn() { + return null; + } + + @Override + protected String sequenceIncrementColumn() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorLegacyImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorLegacyImpl.java index d661c584f1fe..c8e4ae09abe3 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorLegacyImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorLegacyImpl.java @@ -41,18 +41,25 @@ public Iterable extractMetadata(ExtractionContext extractio try { final ResultSet resultSet = statement.executeQuery( lookupSql ); try { - final List sequenceInformationList = new ArrayList(); + final List sequenceInformationList = new ArrayList<>(); while ( resultSet.next() ) { sequenceInformationList.add( new SequenceInformationImpl( new QualifiedSequenceName( - null, - null, identifierHelper.toIdentifier( - resultSet.getString( 1 ) + resultSetCatalogName( resultSet ) + ), + identifierHelper.toIdentifier( + resultSetSchemaName( resultSet ) + ), + identifierHelper.toIdentifier( + resultSetSequenceName( resultSet ) ) ), - -1 + resultSetStartValueSize( resultSet ), + resultSetMinValue( resultSet ), + resultSetMaxValue( resultSet ), + resultSetIncrementValue( resultSet ) ) ); } @@ -74,4 +81,66 @@ public Iterable extractMetadata(ExtractionContext extractio } } } + + protected String sequenceNameColumn() { + return "sequence_name"; + } + + protected String sequenceCatalogColumn() { + return "sequence_catalog"; + } + + protected String sequenceSchemaColumn() { + return "sequence_schema"; + } + + protected String sequenceStartValueColumn() { + return "start_value"; + } + + protected String sequenceMinValueColumn() { + return "minimum_value"; + } + + protected String sequenceMaxValueColumn() { + return "maximum_value"; + } + + protected String sequenceIncrementColumn() { + return "increment"; + } + + protected String resultSetSequenceName(ResultSet resultSet) throws SQLException { + return resultSet.getString( sequenceNameColumn() ); + } + + protected String resultSetCatalogName(ResultSet resultSet) throws SQLException { + String column = sequenceCatalogColumn(); + return column != null ? resultSet.getString( column ) : null; + } + + protected String resultSetSchemaName(ResultSet resultSet) throws SQLException { + String column = sequenceSchemaColumn(); + return column != null ? resultSet.getString( column ) : null; + } + + protected Long resultSetStartValueSize(ResultSet resultSet) throws SQLException { + String column = sequenceStartValueColumn(); + return column != null ? resultSet.getLong( column ) : null; + } + + protected Long resultSetMinValue(ResultSet resultSet) throws SQLException { + String column = sequenceMinValueColumn(); + return column != null ? resultSet.getLong( column ) : null; + } + + protected Long resultSetMaxValue(ResultSet resultSet) throws SQLException { + String column = sequenceMaxValueColumn(); + return column != null ? resultSet.getLong( column ) : null; + } + + protected Long resultSetIncrementValue(ResultSet resultSet) throws SQLException { + String column = sequenceIncrementColumn(); + return column != null ? resultSet.getLong( column ) : null; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorMimerSQLDatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorMimerSQLDatabaseImpl.java new file mode 100644 index 000000000000..0d8551d80d05 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorMimerSQLDatabaseImpl.java @@ -0,0 +1,27 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorMimerSQLDatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorMimerSQLDatabaseImpl INSTANCE = new SequenceInformationExtractorMimerSQLDatabaseImpl(); + + @Override + protected String sequenceStartValueColumn() { + return "initial_value"; + } + + @Override + protected String sequenceMinValueColumn() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorOracleDatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorOracleDatabaseImpl.java new file mode 100644 index 000000000000..b4706177b904 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorOracleDatabaseImpl.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorOracleDatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorOracleDatabaseImpl INSTANCE = new SequenceInformationExtractorOracleDatabaseImpl(); + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceSchemaColumn() { + return null; + } + + @Override + protected String sequenceStartValueColumn() { + return null; + } + + @Override + protected String sequenceMinValueColumn() { + return "min_value"; + } + + @Override + protected Long resultSetMaxValue(ResultSet resultSet) throws SQLException { + return resultSet.getBigDecimal( "max_value" ).longValue(); + } + + @Override + protected String sequenceIncrementColumn() { + return "increment_by"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorSAPDBDatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorSAPDBDatabaseImpl.java new file mode 100644 index 000000000000..de7ab98927d5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorSAPDBDatabaseImpl.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorSAPDBDatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorSAPDBDatabaseImpl INSTANCE = new SequenceInformationExtractorSAPDBDatabaseImpl(); + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceSchemaColumn() { + return "schemaname"; + } + + @Override + protected String sequenceStartValueColumn() { + return null; + } + + @Override + protected String sequenceMinValueColumn() { + return "min_value"; + } + + @Override + protected String sequenceMaxValueColumn() { + return "max_value"; + } + + @Override + protected String sequenceIncrementColumn() { + return "increment_by"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorTimesTenDatabaseImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorTimesTenDatabaseImpl.java new file mode 100644 index 000000000000..7c0eba504bf6 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationExtractorTimesTenDatabaseImpl.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +/** + * @author Vlad Mihalcea + */ +public class SequenceInformationExtractorTimesTenDatabaseImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceInformationExtractorTimesTenDatabaseImpl INSTANCE = new SequenceInformationExtractorTimesTenDatabaseImpl(); + + @Override + protected String sequenceNameColumn() { + return "name"; + } + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceSchemaColumn() { + return null; + } + + @Override + protected String sequenceStartValueColumn() { + return null; + } + + @Override + protected String sequenceMinValueColumn() { + return "minval"; + } + + @Override + protected String sequenceMaxValueColumn() { + return "maxval"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java index 6838a0fa49fb..f83dd7e710e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceInformationImpl.java @@ -16,11 +16,22 @@ */ public class SequenceInformationImpl implements SequenceInformation { private final QualifiedSequenceName sequenceName; - private final int incrementSize; - public SequenceInformationImpl(QualifiedSequenceName sequenceName, int incrementSize) { + private final Long startValue; + private final Long minValue; + private final Long maxValue; + private final Long incrementValue; + + public SequenceInformationImpl( + QualifiedSequenceName sequenceName, + Long startValue, + Long minValue, + Long maxValue, Long incrementValue) { this.sequenceName = sequenceName; - this.incrementSize = incrementSize; + this.startValue = startValue; + this.minValue = minValue; + this.maxValue = maxValue; + this.incrementValue = incrementValue; } @Override @@ -29,7 +40,21 @@ public QualifiedSequenceName getSequenceName() { } @Override - public int getIncrementSize() { - return incrementSize; + public Long getStartValue() { + return startValue; + } + + @Override + public Long getMinValue() { + return minValue; + } + + public Long getMaxValue() { + return maxValue; + } + + @Override + public Long getIncrementValue() { + return incrementValue; } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceNameExtractorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceNameExtractorImpl.java new file mode 100644 index 000000000000..28960447e600 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/SequenceNameExtractorImpl.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public class SequenceNameExtractorImpl extends SequenceInformationExtractorLegacyImpl { + /** + * Singleton access + */ + public static final SequenceNameExtractorImpl INSTANCE = new SequenceNameExtractorImpl(); + + protected String resultSetSequenceName(ResultSet resultSet) throws SQLException { + return resultSet.getString( 1 ); + } + + @Override + protected String sequenceCatalogColumn() { + return null; + } + + @Override + protected String sequenceSchemaColumn() { + return null; + } + + @Override + protected String sequenceStartValueColumn() { + return null; + } + + @Override + protected String sequenceMinValueColumn() { + return null; + } + + @Override + protected String sequenceMaxValueColumn() { + return null; + } + + @Override + protected String sequenceIncrementColumn() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java index 5f1b3f80542f..6709039b2d82 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/ExtractionContext.java @@ -45,4 +45,46 @@ interface DatabaseObjectAccess { DatabaseObjectAccess getDatabaseObjectAccess(); void cleanup(); + + abstract class EmptyExtractionContext implements ExtractionContext { + @Override + public ServiceRegistry getServiceRegistry() { + return null; + } + + @Override + public JdbcEnvironment getJdbcEnvironment() { + return null; + } + + @Override + public Connection getJdbcConnection() { + return null; + } + + @Override + public DatabaseMetaData getJdbcDatabaseMetaData() { + return null; + } + + @Override + public Identifier getDefaultCatalog() { + return null; + } + + @Override + public Identifier getDefaultSchema() { + return null; + } + + @Override + public DatabaseObjectAccess getDatabaseObjectAccess() { + return null; + } + + @Override + public void cleanup() { + + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java index 92c16ded9172..355a3ead6c66 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/spi/SequenceInformation.java @@ -14,17 +14,52 @@ * @author Steve Ebersole */ public interface SequenceInformation { + /** * The qualified sequence name. * * @return The sequence name */ - public QualifiedSequenceName getSequenceName(); + QualifiedSequenceName getSequenceName(); /** * Retrieve the extracted increment-size defined for the sequence. * * @return The extracted increment size; use a negative number to indicate the increment could not be extracted. + * + * @deprecated use {@link #getIncrementValue()} instead. + */ + @Deprecated + default int getIncrementSize() { + Long incrementSize = getIncrementValue(); + return incrementSize != null ? incrementSize.intValue() : -1; + } + + /** + * Retrieve the extracted start value defined for the sequence. + * + * @return The extracted start value or null id the value could not be extracted. + */ + Long getStartValue(); + + /** + * Retrieve the extracted minimum value defined for the sequence. + * + * @return The extracted minimum value or null id the value could not be extracted. + */ + Long getMinValue(); + + /** + * Retrieve the extracted maximum value defined for the sequence. + * + * @return The extracted maximum value or null id the value could not be extracted. + */ + Long getMaxValue(); + + /** + * Retrieve the extracted increment value defined for the sequence. + * + * @return The extracted increment value; use a negative number to indicate the increment could not be extracted. */ - public int getIncrementSize(); + Long getIncrementValue(); } diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/PostgreSQLSequenceGeneratorWithSerialTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/PostgreSQLSequenceGeneratorWithSerialTest.java new file mode 100644 index 000000000000..a30693bcf9c6 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/PostgreSQLSequenceGeneratorWithSerialTest.java @@ -0,0 +1,154 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import java.io.StringReader; +import java.sql.Statement; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; +import org.hibernate.dialect.PostgreSQL82Dialect; +import org.hibernate.id.SequenceMismatchStrategy; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.logger.LoggerInspectionRule; +import org.hibernate.testing.logger.Triggerable; +import org.junit.Rule; +import org.junit.Test; + +import org.jboss.logging.Logger; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +@RequiresDialect(PostgreSQL82Dialect.class) +public class PostgreSQLSequenceGeneratorWithSerialTest extends BaseEntityManagerFunctionalTestCase { + + @Rule + public LoggerInspectionRule logInspection = new LoggerInspectionRule( Logger.getMessageLogger( CoreMessageLogger.class, + SequenceStyleGenerator.class + .getName() + ) ); + + private Triggerable triggerable = logInspection.watchForLogMessages( "HHH000497:" ); + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + ApplicationConfiguration.class, + }; + } + + private static final String DROP_SEQUENCE = "DROP SEQUENCE IF EXISTS application_configurations_id_seq"; + private static final String DROP_TABLE = "DROP TABLE IF EXISTS application_configurations CASCADE"; + private static final String CREATE_TABLE = "CREATE TABLE application_configurations (id BIGSERIAL NOT NULL PRIMARY KEY)"; + + @Override + protected void addMappings(Map settings) { + triggerable.reset(); + assertFalse( triggerable.wasTriggered() ); + + //For this test, we need to make sure the DB is created prior to bootstrapping Hibernate + StandardServiceRegistry ssr = new StandardServiceRegistryBuilder() + .build(); + + SessionFactory sessionFactory = null; + + try { + Configuration config = new Configuration(); + sessionFactory = config.buildSessionFactory( ssr ); + + try(Session session = sessionFactory.openSession()) { + session.doWork( connection -> { + try(Statement statement = connection.createStatement()) { + statement.execute( DROP_TABLE ); + statement.execute( DROP_SEQUENCE ); + statement.execute( CREATE_TABLE ); + } + } ); + } + } + finally { + if ( sessionFactory != null ) { + sessionFactory.close(); + } + ssr.close(); + } + + settings.put( AvailableSettings.HBM2DDL_DROP_SCRIPT_SOURCE, new StringReader( + DROP_TABLE + ";" + DROP_SEQUENCE + ) ); + settings.put( AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY, SequenceMismatchStrategy.FIX); + } + + @Override + protected void afterEntityManagerFactoryBuilt() { + assertTrue( triggerable.wasTriggered() ); + } + + @Test + public void test() { + + final AtomicLong id = new AtomicLong(); + + final int ITERATIONS = 51; + + doInJPA( this::entityManagerFactory, entityManager -> { + for ( int i = 1; i <= ITERATIONS; i++ ) { + ApplicationConfiguration model = new ApplicationConfiguration(); + + entityManager.persist( model ); + + id.set( model.getId() ); + } + } ); + + assertEquals( ITERATIONS, id.get() ); + } + + @Entity + @Table(name = "application_configurations") + public static class ApplicationConfiguration { + + @Id + @javax.persistence.SequenceGenerator( + name = "application_configurations_id_seq", + sequenceName = "application_configurations_id_seq" + ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "application_configurations_id_seq") + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyDefaultExceptionTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyDefaultExceptionTest.java new file mode 100644 index 000000000000..f7c60efca7e3 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyDefaultExceptionTest.java @@ -0,0 +1,144 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import java.util.EnumSet; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.MappingException; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.tool.hbm2ddl.SchemaExport; +import org.hibernate.tool.schema.TargetType; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.logger.LoggerInspectionRule; +import org.hibernate.testing.logger.Triggerable; +import org.hibernate.testing.util.ExceptionUtil; +import org.junit.Rule; +import org.junit.Test; + +import org.jboss.logging.Logger; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assert.assertFalse; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +@RequiresDialectFeature(DialectChecks.SupportsSequences.class) +public class SequenceMismatchStrategyDefaultExceptionTest extends BaseEntityManagerFunctionalTestCase { + + protected ServiceRegistry serviceRegistry; + protected MetadataImplementor metadata; + + @Override + public void buildEntityManagerFactory() { + serviceRegistry = new StandardServiceRegistryBuilder().build(); + metadata = (MetadataImplementor) new MetadataSources( serviceRegistry ) + .addAnnotatedClass( ApplicationConfigurationHBM2DDL.class ) + .buildMetadata(); + + new SchemaExport().create( EnumSet.of( TargetType.DATABASE ), metadata ); + try { + super.buildEntityManagerFactory(); + + fail("Should throw MappingException!"); + } + catch (Exception e) { + Throwable rootCause = ExceptionUtil.rootCause( e ); + assertTrue( rootCause instanceof MappingException ); + assertTrue( rootCause.getMessage().contains( "in the entity mapping while the associated database sequence increment size is" ) ); + } + } + + @Override + public void releaseResources() { + super.releaseResources(); + + new SchemaExport().drop( EnumSet.of( TargetType.DATABASE ), metadata ); + StandardServiceRegistryBuilder.destroy( serviceRegistry ); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + ApplicationConfiguration.class, + }; + } + + @Override + protected void addMappings(Map settings) { + settings.put( AvailableSettings.HBM2DDL_AUTO, "none" ); + } + + @Test + public void test() { + + } + + @Entity + @Table(name = "application_configurations") + public static class ApplicationConfigurationHBM2DDL { + + @Id + @javax.persistence.SequenceGenerator( + name = "app_config_sequence", + sequenceName = "app_config_sequence", + allocationSize = 1 + ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "app_config_sequence") + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + } + + @Entity + @Table(name = "application_configurations") + public static class ApplicationConfiguration { + + @Id + @javax.persistence.SequenceGenerator( + name = "app_config_sequence", + sequenceName = "app_config_sequence" + ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "app_config_sequence") + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyExceptionEnumTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyExceptionEnumTest.java new file mode 100644 index 000000000000..cae595e45ab7 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyExceptionEnumTest.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import java.util.Map; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.id.SequenceMismatchStrategy; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.TestForIssue; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +@RequiresDialectFeature(DialectChecks.SupportsSequences.class) +public class SequenceMismatchStrategyExceptionEnumTest extends SequenceMismatchStrategyDefaultExceptionTest { + + @Override + protected void addMappings(Map settings) { + super.addMappings( settings ); + settings.put( AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY, SequenceMismatchStrategy.EXCEPTION ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyFixWithSequenceGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyFixWithSequenceGeneratorTest.java new file mode 100644 index 000000000000..6d2e86ae88f7 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyFixWithSequenceGeneratorTest.java @@ -0,0 +1,171 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import java.util.EnumSet; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Environment; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.dialect.Oracle8iDialect; +import org.hibernate.dialect.PostgreSQL82Dialect; +import org.hibernate.dialect.SQLServer2012Dialect; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.tool.hbm2ddl.SchemaExport; +import org.hibernate.tool.schema.TargetType; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.logger.LoggerInspectionRule; +import org.hibernate.testing.logger.Triggerable; +import org.hibernate.test.schemaupdate.SchemaExportWithGlobalQuotingEnabledTest; +import org.junit.Rule; +import org.junit.Test; + +import org.jboss.logging.Logger; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +@RequiresDialectFeature(DialectChecks.SupportsSequences.class) +public class SequenceMismatchStrategyFixWithSequenceGeneratorTest extends BaseEntityManagerFunctionalTestCase { + + @Rule + public LoggerInspectionRule logInspection = new LoggerInspectionRule( + Logger.getMessageLogger( + CoreMessageLogger.class, + SequenceStyleGenerator.class.getName() + ) + ); + + private Triggerable triggerable = logInspection.watchForLogMessages( "HHH000497:" ); + + protected ServiceRegistry serviceRegistry; + protected MetadataImplementor metadata; + + @Override + public void buildEntityManagerFactory() { + serviceRegistry = new StandardServiceRegistryBuilder().build(); + metadata = (MetadataImplementor) new MetadataSources( serviceRegistry ) + .addAnnotatedClass( ApplicationConfigurationHBM2DDL.class ) + .buildMetadata(); + + new SchemaExport().create( EnumSet.of( TargetType.DATABASE ), metadata ); + super.buildEntityManagerFactory(); + } + + @Override + public void releaseResources() { + super.releaseResources(); + + new SchemaExport().drop( EnumSet.of( TargetType.DATABASE ), metadata ); + StandardServiceRegistryBuilder.destroy( serviceRegistry ); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + ApplicationConfiguration.class, + }; + } + + @Override + protected void addMappings(Map settings) { + settings.put( AvailableSettings.HBM2DDL_AUTO, "none" ); + settings.put( AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY, "fix" ); + triggerable.reset(); + } + + @Override + protected void afterEntityManagerFactoryBuilt() { + assertTrue( triggerable.wasTriggered() ); + } + + @Test + public void test() { + + final AtomicLong id = new AtomicLong(); + + final int ITERATIONS = 51; + + doInJPA( this::entityManagerFactory, entityManager -> { + for ( int i = 1; i <= ITERATIONS; i++ ) { + ApplicationConfiguration model = new ApplicationConfiguration(); + + entityManager.persist( model ); + + id.set( model.getId() ); + } + } ); + + assertEquals( ITERATIONS, id.get() ); + } + + @Entity + @Table(name = "application_configurations") + public static class ApplicationConfigurationHBM2DDL { + + @Id + @javax.persistence.SequenceGenerator( + name = "app_config_sequence", + sequenceName = "app_config_sequence", + allocationSize = 1 + ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "app_config_sequence") + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + } + + @Entity + @Table(name = "application_configurations") + public static class ApplicationConfiguration { + + @Id + @javax.persistence.SequenceGenerator( + name = "app_config_sequence", + sequenceName = "app_config_sequence" + ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "app_config_sequence") + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyLogTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyLogTest.java new file mode 100644 index 000000000000..ac5824a0f968 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyLogTest.java @@ -0,0 +1,146 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import java.util.EnumSet; +import java.util.Map; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.tool.hbm2ddl.SchemaExport; +import org.hibernate.tool.schema.TargetType; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.logger.LoggerInspectionRule; +import org.hibernate.testing.logger.Triggerable; +import org.junit.Rule; +import org.junit.Test; + +import org.jboss.logging.Logger; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +@RequiresDialectFeature(DialectChecks.SupportsSequences.class) +public class SequenceMismatchStrategyLogTest extends BaseEntityManagerFunctionalTestCase { + + @Rule + public LoggerInspectionRule logInspection = new LoggerInspectionRule( + Logger.getMessageLogger( + CoreMessageLogger.class, + SequenceStyleGenerator.class.getName() + ) + ); + + private Triggerable triggerable = logInspection.watchForLogMessages( "HHH000497:" ); + + protected ServiceRegistry serviceRegistry; + protected MetadataImplementor metadata; + + @Override + public void buildEntityManagerFactory() { + serviceRegistry = new StandardServiceRegistryBuilder().build(); + metadata = (MetadataImplementor) new MetadataSources( serviceRegistry ) + .addAnnotatedClass( ApplicationConfigurationHBM2DDL.class ) + .buildMetadata(); + + new SchemaExport().create( EnumSet.of( TargetType.DATABASE ), metadata ); + super.buildEntityManagerFactory(); + } + + @Override + public void releaseResources() { + super.releaseResources(); + + new SchemaExport().drop( EnumSet.of( TargetType.DATABASE ), metadata ); + StandardServiceRegistryBuilder.destroy( serviceRegistry ); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + ApplicationConfiguration.class, + }; + } + + @Override + protected void addMappings(Map settings) { + settings.put( AvailableSettings.HBM2DDL_AUTO, "none" ); + settings.put( AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY, "log" ); + triggerable.reset(); + assertFalse( triggerable.wasTriggered() ); + } + + @Override + protected void afterEntityManagerFactoryBuilt() { + assertTrue( triggerable.wasTriggered() ); + } + + @Test + public void test() { + } + + @Entity + @Table(name = "application_configurations") + public static class ApplicationConfigurationHBM2DDL { + + @Id + @javax.persistence.SequenceGenerator( + name = "app_config_sequence", + sequenceName = "app_config_sequence", + allocationSize = 1 + ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "app_config_sequence") + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + } + + @Entity + @Table(name = "application_configurations") + public static class ApplicationConfiguration { + + @Id + @javax.persistence.SequenceGenerator( + name = "app_config_sequence", + sequenceName = "app_config_sequence" + ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "app_config_sequence") + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyLowerCaseStringValueTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyLowerCaseStringValueTest.java new file mode 100644 index 000000000000..7fd79352ebeb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyLowerCaseStringValueTest.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import org.hibernate.id.SequenceMismatchStrategy; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +public class SequenceMismatchStrategyLowerCaseStringValueTest extends BaseUnitTestCase { + + @Test + public void test() { + assertEquals( SequenceMismatchStrategy.EXCEPTION, SequenceMismatchStrategy.interpret( "exception" ) ); + assertEquals( SequenceMismatchStrategy.LOG, SequenceMismatchStrategy.interpret( "log" ) ); + assertEquals( SequenceMismatchStrategy.FIX, SequenceMismatchStrategy.interpret( "fix" ) ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyNullValueTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyNullValueTest.java new file mode 100644 index 000000000000..ced57af2ccb8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyNullValueTest.java @@ -0,0 +1,27 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import org.hibernate.id.SequenceMismatchStrategy; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +public class SequenceMismatchStrategyNullValueTest extends BaseUnitTestCase { + + @Test + public void test() { + assertEquals( SequenceMismatchStrategy.EXCEPTION, SequenceMismatchStrategy.interpret( null ) ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyUnknownEnumValueTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyUnknownEnumValueTest.java new file mode 100644 index 000000000000..bb6bf72eb342 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyUnknownEnumValueTest.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import org.hibernate.HibernateException; +import org.hibernate.id.SequenceMismatchStrategy; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.hibernate.testing.util.ExceptionUtil; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +public class SequenceMismatchStrategyUnknownEnumValueTest extends BaseUnitTestCase { + + @Test + public void test() { + try { + SequenceMismatchStrategy.interpret( "acme" ); + + fail("Should throw HibernateException!"); + } + catch (Exception e) { + Throwable rootCause = ExceptionUtil.rootCause( e ); + assertTrue( rootCause instanceof HibernateException ); + assertEquals( "Unrecognized sequence.increment_size_mismatch_strategy value : [acme]. Supported values include [log], [exception], and [fix].", rootCause.getMessage() ); + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyUpperCaseStringValueTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyUpperCaseStringValueTest.java new file mode 100644 index 000000000000..cbb9d57c2954 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyUpperCaseStringValueTest.java @@ -0,0 +1,29 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import org.hibernate.id.SequenceMismatchStrategy; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +public class SequenceMismatchStrategyUpperCaseStringValueTest extends BaseUnitTestCase { + + @Test + public void test() { + assertEquals( SequenceMismatchStrategy.EXCEPTION, SequenceMismatchStrategy.interpret( "EXCEPTION" ) ); + assertEquals( SequenceMismatchStrategy.LOG, SequenceMismatchStrategy.interpret( "LOG" ) ); + assertEquals( SequenceMismatchStrategy.FIX, SequenceMismatchStrategy.interpret( "FIX" ) ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyWithoutSequenceGeneratorTest.java b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyWithoutSequenceGeneratorTest.java new file mode 100644 index 000000000000..51ef22de42ca --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/id/hhh12973/SequenceMismatchStrategyWithoutSequenceGeneratorTest.java @@ -0,0 +1,159 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.id.hhh12973; + +import java.util.EnumSet; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.tool.hbm2ddl.SchemaExport; +import org.hibernate.tool.schema.TargetType; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.logger.LoggerInspectionRule; +import org.hibernate.testing.logger.Triggerable; +import org.junit.Rule; +import org.junit.Test; + +import org.jboss.logging.Logger; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +@RequiresDialectFeature(DialectChecks.SupportsSequences.class) +public class SequenceMismatchStrategyWithoutSequenceGeneratorTest extends BaseEntityManagerFunctionalTestCase { + + @Rule + public LoggerInspectionRule logInspection = new LoggerInspectionRule( + Logger.getMessageLogger( + CoreMessageLogger.class, + SequenceStyleGenerator.class.getName() + ) + ); + + private Triggerable triggerable = logInspection.watchForLogMessages( "HHH000497:" ); + + protected ServiceRegistry serviceRegistry; + protected MetadataImplementor metadata; + + @Override + public void buildEntityManagerFactory() { + serviceRegistry = new StandardServiceRegistryBuilder().build(); + metadata = (MetadataImplementor) new MetadataSources( serviceRegistry ) + .addAnnotatedClass( ApplicationConfigurationHBM2DDL.class ) + .buildMetadata(); + + new SchemaExport().create( EnumSet.of( TargetType.DATABASE ), metadata ); + super.buildEntityManagerFactory(); + } + + @Override + public void releaseResources() { + super.releaseResources(); + + new SchemaExport().drop( EnumSet.of( TargetType.DATABASE ), metadata ); + StandardServiceRegistryBuilder.destroy( serviceRegistry ); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + ApplicationConfiguration.class, + }; + } + + @Override + protected void addMappings(Map settings) { + settings.put( AvailableSettings.HBM2DDL_AUTO, "none" ); + triggerable.reset(); + } + + @Override + protected void afterEntityManagerFactoryBuilt() { + assertFalse( triggerable.wasTriggered() ); + } + + @Test + public void test() { + + final AtomicLong id = new AtomicLong(); + + final int ITERATIONS = 51; + + doInJPA( this::entityManagerFactory, entityManager -> { + for ( int i = 1; i <= ITERATIONS; i++ ) { + ApplicationConfiguration model = new ApplicationConfiguration(); + + entityManager.persist( model ); + + id.set( model.getId() ); + } + } ); + + assertEquals( ITERATIONS, id.get() ); + } + + @Entity + @Table(name = "application_configurations") + public static class ApplicationConfigurationHBM2DDL { + + @Id + @javax.persistence.SequenceGenerator( + name = "hibernate_sequence", + sequenceName = "hibernate_sequence", + allocationSize = 1 + ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hibernate_sequence") + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + } + + @Entity + @Table(name = "application_configurations") + public static class ApplicationConfiguration { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/connection/DataSourceInjectionTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/connection/DataSourceInjectionTest.java index 8a113e016f89..c34a643b632f 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/connection/DataSourceInjectionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/connection/DataSourceInjectionTest.java @@ -15,6 +15,7 @@ import org.hibernate.jpa.HibernatePersistenceProvider; +import org.hibernate.testing.util.ExceptionUtil; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -49,7 +50,7 @@ public void testDatasourceInjection() throws Exception { if(emf != null){ emf.close(); } - Assert.assertTrue( pe.getCause() instanceof FakeDataSourceException ); + Assert.assertTrue( ExceptionUtil.rootCause( pe ) instanceof FakeDataSourceException ); } catch (FakeDataSourceException fde) { //success diff --git a/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/OracleSequenceInfoTest.java b/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/OracleSequenceInfoTest.java new file mode 100644 index 000000000000..234ba4d4a6a5 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/OracleSequenceInfoTest.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.dialect.functional; + +import org.hibernate.dialect.Oracle8iDialect; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; + +import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.TestForIssue; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +@RequiresDialect(value = { + Oracle8iDialect.class +}) +public class OracleSequenceInfoTest extends + SequenceInformationTest { + + @Override + protected void assertProductSequence(SequenceInformation productSequenceInfo) { + assertNull( productSequenceInfo.getStartValue() ); + assertEquals( Long.valueOf( 1 ), productSequenceInfo.getMinValue() ); + assertEquals( Long.valueOf( 10 ), productSequenceInfo.getIncrementValue() ); + } + + @Override + protected void assertVehicleSequenceInfo(SequenceInformation vehicleSequenceInfo) { + assertNull( vehicleSequenceInfo.getStartValue() ); + assertEquals( Long.valueOf( 1 ), vehicleSequenceInfo.getMinValue() ); + assertEquals( Long.valueOf( 1 ), vehicleSequenceInfo.getIncrementValue() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/SequenceInformationTest.java b/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/SequenceInformationTest.java new file mode 100644 index 000000000000..0d2868c649ef --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/dialect/functional/SequenceInformationTest.java @@ -0,0 +1,144 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.dialect.functional; + +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; + +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.AbstractHANADialect; +import org.hibernate.dialect.DB2Dialect; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.dialect.HSQLDialect; +import org.hibernate.dialect.InformixDialect; +import org.hibernate.dialect.PostgreSQL81Dialect; +import org.hibernate.dialect.SQLServer2012Dialect; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.tool.hbm2ddl.SchemaExport; +import org.hibernate.tool.schema.TargetType; +import org.hibernate.tool.schema.extract.spi.SequenceInformation; + +import org.hibernate.testing.DialectChecks; +import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.RequiresDialectFeature; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertFalse; + +/** + * @author Vlad Mihalcea + */ +@TestForIssue(jiraKey = "HHH-12973") +@RequiresDialectFeature(DialectChecks.SupportsSequences.class) +public class SequenceInformationTest extends + BaseEntityManagerFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Product.class, + Vehicle.class + }; + } + + protected ServiceRegistry serviceRegistry; + protected MetadataImplementor metadata; + + @Override + public void buildEntityManagerFactory() { + serviceRegistry = new StandardServiceRegistryBuilder().build(); + metadata = (MetadataImplementor) new MetadataSources( serviceRegistry ) + .addAnnotatedClass( Product.class ) + .addAnnotatedClass( Vehicle.class ) + .buildMetadata(); + + new SchemaExport().drop( EnumSet.of( TargetType.DATABASE ), metadata ); + new SchemaExport().create( EnumSet.of( TargetType.DATABASE ), metadata ); + super.buildEntityManagerFactory(); + } + + @Override + public void releaseResources() { + super.releaseResources(); + + new SchemaExport().drop( EnumSet.of( TargetType.DATABASE ), metadata ); + StandardServiceRegistryBuilder.destroy( serviceRegistry ); + } + + @Override + protected void addMappings(Map settings) { + settings.put( AvailableSettings.HBM2DDL_AUTO, "none" ); + } + + @Test + public void test() { + + SequenceInformation productSequenceInfo = sequenceInformation("product_sequence"); + + assertNotNull( productSequenceInfo ); + assertEquals( "product_sequence", productSequenceInfo.getSequenceName().getSequenceName().getText().toLowerCase() ); + assertProductSequence( productSequenceInfo ); + + SequenceInformation vehicleSequenceInfo = sequenceInformation("vehicle_sequence"); + + assertNotNull( vehicleSequenceInfo ); + assertEquals( "vehicle_sequence", vehicleSequenceInfo.getSequenceName().getSequenceName().getText().toLowerCase() ); + assertVehicleSequenceInfo( vehicleSequenceInfo ); + } + + protected void assertProductSequence(SequenceInformation productSequenceInfo) { + assertEquals( Long.valueOf( 10 ), productSequenceInfo.getIncrementValue() ); + } + + protected void assertVehicleSequenceInfo(SequenceInformation vehicleSequenceInfo) { + assertEquals( Long.valueOf( 1 ), vehicleSequenceInfo.getIncrementValue() ); + } + + private SequenceInformation sequenceInformation(String sequenceName) { + List sequenceInformationList = entityManagerFactory().unwrap( SessionFactoryImplementor.class ).getJdbcServices().getExtractedMetaDataSupport().getSequenceInformationList(); + + return sequenceInformationList.stream().filter( + sequenceInformation -> sequenceName.equalsIgnoreCase( sequenceInformation.getSequenceName().getSequenceName().getText() ) + ).findFirst().orElse( null ); + } + + @Entity(name = "Product") + public static class Product { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "product_sequence") + @SequenceGenerator( name = "product_sequence", sequenceName = "product_sequence", initialValue = 1, allocationSize = 10) + private Long id; + + private String name; + } + + @Entity(name = "Vehicle") + public static class Vehicle { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "vehicle_sequence") + @SequenceGenerator( name = "vehicle_sequence", sequenceName = "vehicle_sequence", initialValue = 1, allocationSize = 1) + private Long id; + + private String name; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/dialect/unit/sequence/DerbyTenSevenDialectSequenceInformationExtractorTest.java b/hibernate-core/src/test/java/org/hibernate/test/dialect/unit/sequence/DerbyTenSevenDialectSequenceInformationExtractorTest.java index c7030f93a0fe..166544245eef 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dialect/unit/sequence/DerbyTenSevenDialectSequenceInformationExtractorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dialect/unit/sequence/DerbyTenSevenDialectSequenceInformationExtractorTest.java @@ -25,7 +25,7 @@ public Dialect getDialect() { @Override public String expectedQuerySequencesString() { - return "select SEQUENCENAME from SYS.SYSSEQUENCES"; + return "select sys.sysschemas.schemaname as sequence_schema, sys.syssequences.* from sys.syssequences left join sys.sysschemas on sys.syssequences.schemaid = sys.sysschemas.schemaid"; } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/test/dialect/unit/sequence/DerbyTenSixDialectSequenceInformationExtractorTest.java b/hibernate-core/src/test/java/org/hibernate/test/dialect/unit/sequence/DerbyTenSixDialectSequenceInformationExtractorTest.java index 9a8480422218..a3835bddf534 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/dialect/unit/sequence/DerbyTenSixDialectSequenceInformationExtractorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/dialect/unit/sequence/DerbyTenSixDialectSequenceInformationExtractorTest.java @@ -25,7 +25,7 @@ public Dialect getDialect() { @Override public String expectedQuerySequencesString() { - return "select SEQUENCENAME from SYS.SYSSEQUENCES"; + return "select sys.sysschemas.schemaname as sequence_schema, sys.syssequences.* from sys.syssequences left join sys.sysschemas on sys.syssequences.schemaid = sys.sysschemas.schemaid"; } @Override