From 2c80250b0e0c13fea874458bd0e59f14d1493e25 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 4 Mar 2022 20:48:32 +0100 Subject: [PATCH] Replace typeNames in Dialect with SqlType and SqlTypeRegistry that dialects contribute into --- .../userguide/sql/CollectionLoaderTest.java | 14 +- .../community/dialect/CUBRIDDialect.java | 80 ++- .../community/dialect/CacheDialect.java | 48 +- .../community/dialect/FirebirdDialect.java | 103 ++-- .../community/dialect/InformixDialect.java | 109 +++- .../community/dialect/IngresDialect.java | 116 ++-- .../community/dialect/MaxDBDialect.java | 60 +- .../community/dialect/MimerSQLDialect.java | 88 ++- .../community/dialect/RDMSOS2200Dialect.java | 85 ++- .../community/dialect/SQLiteDialect.java | 67 +-- .../dialect/SybaseAnywhereDialect.java | 15 +- .../community/dialect/TeradataDialect.java | 54 +- .../community/dialect/TimesTenDialect.java | 70 +-- .../sequence/IngresLegacySequenceSupport.java | 23 + .../boot/internal/MetadataBuilderImpl.java | 18 - .../boot/model/TypeContributions.java | 31 +- .../process/spi/MetadataBuildingProcess.java | 55 +- .../dialect/AbstractHANADialect.java | 152 ++--- .../dialect/AbstractTransactSQLDialect.java | 15 +- .../hibernate/dialect/CockroachDialect.java | 80 +-- .../org/hibernate/dialect/DB2Dialect.java | 73 +-- .../org/hibernate/dialect/DB2iDialect.java | 16 +- .../org/hibernate/dialect/DB2zDialect.java | 8 +- .../org/hibernate/dialect/DerbyDialect.java | 120 ++-- .../java/org/hibernate/dialect/Dialect.java | 551 ++++-------------- .../java/org/hibernate/dialect/H2Dialect.java | 68 ++- .../dialect/HANAColumnStoreDialect.java | 28 +- .../org/hibernate/dialect/HSQLDialect.java | 27 +- .../org/hibernate/dialect/MySQLDialect.java | 281 ++++----- .../org/hibernate/dialect/OracleDialect.java | 59 +- .../hibernate/dialect/PostgreSQLDialect.java | 113 ++-- .../hibernate/dialect/SQLServerDialect.java | 130 ++--- .../org/hibernate/dialect/SpannerDialect.java | 55 +- .../hibernate/dialect/SybaseASEDialect.java | 73 +-- .../org/hibernate/dialect/SybaseDialect.java | 8 - .../org/hibernate/dialect/TiDBDialect.java | 6 +- .../function/CastingConcatFunction.java | 14 +- .../dialect/temptable/TemporaryTable.java | 48 +- .../org/hibernate/id/ExportableColumn.java | 4 +- .../hibernate/id/enhanced/TableGenerator.java | 4 +- .../org/hibernate/internal/FilterHelper.java | 1 + .../java/org/hibernate/mapping/Column.java | 10 +- .../java/org/hibernate/mapping/Formula.java | 8 +- .../org/hibernate/mapping/Selectable.java | 10 +- .../java/org/hibernate/mapping/Table.java | 6 +- .../internal/AbstractEmbeddableMapping.java | 6 +- .../internal/EmbeddableMappingTypeImpl.java | 6 +- .../internal/EntityCollectionPart.java | 1 + .../internal/MappingModelCreationHelper.java | 9 + .../internal/SelectableMappingImpl.java | 4 +- .../internal/SelectableMappingsImpl.java | 3 + .../AbstractCollectionPersister.java | 20 +- .../entity/AbstractEntityPersister.java | 31 +- .../entity/JoinedSubclassEntityPersister.java | 12 +- .../entity/SingleTableEntityPersister.java | 13 +- .../entity/UnionSubclassEntityPersister.java | 4 +- ...SelfRenderingFunctionSqlAstExpression.java | 5 +- .../main/java/org/hibernate/sql/Template.java | 30 +- .../sql/ast/spi/AbstractSqlAstTranslator.java | 15 +- .../internal/AbstractSchemaValidator.java | 2 +- .../internal/StandardTableExporter.java | 10 +- .../type/descriptor/jdbc/JdbcType.java | 58 +- .../type/descriptor/sql/DdlType.java | 63 ++ .../sql/internal/BinaryFloatDdlType.java | 34 ++ .../internal/CapacityDependentDdlType.java | 109 ++++ .../descriptor/sql/internal/DdlTypeImpl.java | 130 +++++ .../internal/Scale6IntervalSecondDdlType.java | 29 + .../descriptor/sql/spi/DdlTypeRegistry.java | 134 +++++ .../hibernate/type/spi/TypeConfiguration.java | 9 +- .../orm/test/dialect/DB2DialectTestCase.java | 17 +- .../test/dialect/DB2zDialectInitTestCase.java | 9 +- .../enhanced/SequenceStyleConfigUnitTest.java | 33 ++ .../env/DefaultSchemaNameResolverTest.java | 14 +- ...stractCriteriaLiteralHandlingModeTest.java | 9 +- .../test/type/AbstractJavaTimeTypeTest.java | 7 +- .../manytomany/sametable/BasicSametable.java | 22 +- ...tyAuditStrategyRevEndTestCustomRevEnt.java | 24 +- .../ValidityAuditStrategyRevEndTsTest.java | 24 +- .../testing/junit4/CustomRunner.java | 7 +- 79 files changed, 2179 insertions(+), 1728 deletions(-) create mode 100644 hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/sequence/IngresLegacySequenceSupport.java create mode 100644 hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/DdlType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/BinaryFloatDdlType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/CapacityDependentDdlType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/DdlTypeImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/Scale6IntervalSecondDdlType.java create mode 100644 hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/spi/DdlTypeRegistry.java diff --git a/documentation/src/test/java/org/hibernate/userguide/sql/CollectionLoaderTest.java b/documentation/src/test/java/org/hibernate/userguide/sql/CollectionLoaderTest.java index fada5fccc5..88688db168 100644 --- a/documentation/src/test/java/org/hibernate/userguide/sql/CollectionLoaderTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/sql/CollectionLoaderTest.java @@ -19,7 +19,6 @@ import jakarta.persistence.Id; import jakarta.persistence.NamedNativeQueries; import jakarta.persistence.NamedNativeQuery; -import org.hibernate.Session; import org.hibernate.annotations.Loader; import org.hibernate.annotations.ResultCheckStyle; import org.hibernate.annotations.SQLDelete; @@ -28,8 +27,10 @@ import org.hibernate.annotations.SQLInsert; import org.hibernate.annotations.SQLUpdate; import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.PostgreSQLDialect; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.metamodel.CollectionClassification; import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; @@ -65,13 +66,14 @@ public class CollectionLoaderTest extends BaseEntityManagerFunctionalTestCase { @Before public void init() { doInJPA(this::entityManagerFactory, entityManager -> { - Session session = entityManager.unwrap(Session.class); + SessionImplementor session = entityManager.unwrap( SessionImplementor.class); + DdlTypeRegistry ddlTypeRegistry = session.getTypeConfiguration().getDdlTypeRegistry(); session.doWork(connection -> { try(Statement statement = connection.createStatement();) { - statement.executeUpdate(String.format("ALTER TABLE person %s valid %s", - getDialect().getAddColumnString(), getDialect().getTypeName(Types.BOOLEAN))); - statement.executeUpdate(String.format("ALTER TABLE Person_phones %s valid %s", - getDialect().getAddColumnString(), getDialect().getTypeName(Types.BOOLEAN))); + statement.executeUpdate(String.format( "ALTER TABLE person %s valid %s", + getDialect().getAddColumnString(), ddlTypeRegistry.getTypeName( Types.BOOLEAN, getDialect()))); + statement.executeUpdate(String.format( "ALTER TABLE Person_phones %s valid %s", + getDialect().getAddColumnString(), ddlTypeRegistry.getTypeName( Types.BOOLEAN, getDialect()))); } }); }); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java index 0ee6f3dd79..223836806a 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java @@ -8,26 +8,26 @@ package org.hibernate.community.dialect; import java.sql.Types; -import org.hibernate.HibernateException; +import org.hibernate.boot.model.TypeContributions; import org.hibernate.community.dialect.identity.CUBRIDIdentityColumnSupport; import org.hibernate.community.dialect.sequence.CUBRIDSequenceSupport; import org.hibernate.community.dialect.sequence.SequenceInformationExtractorCUBRIDDatabaseImpl; -import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.OracleDialect; +import org.hibernate.dialect.SimpleDatabaseVersion; import org.hibernate.dialect.TimeZoneSupport; import org.hibernate.dialect.function.CommonFunctionFactory; import org.hibernate.dialect.identity.IdentityColumnSupport; import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.LimitLimitHandler; import org.hibernate.dialect.sequence.SequenceSupport; -import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.SemanticException; import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.spi.QueryEngine; +import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.spi.SqlAppender; @@ -37,6 +37,10 @@ import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.BinaryFloatDdlType; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import jakarta.persistence.TemporalType; @@ -45,6 +49,13 @@ import static org.hibernate.query.sqm.TemporalUnit.MINUTE; import static org.hibernate.query.sqm.TemporalUnit.NANOSECOND; import static org.hibernate.query.sqm.TemporalUnit.NATIVE; import static org.hibernate.query.sqm.TemporalUnit.SECOND; +import static org.hibernate.type.SqlTypes.BINARY; +import static org.hibernate.type.SqlTypes.BLOB; +import static org.hibernate.type.SqlTypes.BOOLEAN; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.VARBINARY; /** * An SQL dialect for CUBRID (8.3.x and later). @@ -52,33 +63,55 @@ import static org.hibernate.query.sqm.TemporalUnit.SECOND; * @author Seok Jeong Il */ public class CUBRIDDialect extends Dialect { - private static final DatabaseVersion VERSION = DatabaseVersion.make( 0, 0 ); /** * Constructs a CUBRIDDialect */ public CUBRIDDialect() { - super(); + super( SimpleDatabaseVersion.ZERO_VERSION ); + } - registerColumnType( Types.BOOLEAN, "bit" ); - registerColumnType( Types.TINYINT, "smallint" ); //no 'tinyint' + @Override + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case BOOLEAN: + return "bit"; + case TINYINT: + return "smallint"; + //'timestamp' has a very limited range + //'datetime' does not support explicit precision + //(always 3, millisecond precision) + case TIMESTAMP: + return "datetime"; + case TIMESTAMP_WITH_TIMEZONE: + return "datetimetz"; + } + return super.columnType( sqlTypeCode ); + } - //'timestamp' has a very limited range - //'datetime' does not support explicit precision - //(always 3, millisecond precision) - registerColumnType(Types.TIMESTAMP, "datetime" ); - registerColumnType(Types.TIMESTAMP, "datetimetz" ); + @Override + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + + //precision of a Mimer 'float(p)' represents + //decimal digits instead of binary digits + ddlTypeRegistry.addDescriptor( new BinaryFloatDdlType( this ) ); //CUBRID has no 'binary' nor 'varbinary', but 'bit' is //intended to be used for binary data (unfortunately the //length parameter is measured in bits, not bytes) - registerColumnType( Types.BINARY, "bit($l)" ); - registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "bit varying($l)" ); - - registerCubridKeywords(); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( BINARY, "bit($l)", this ) ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( VARBINARY, columnType( BLOB ), this ) + .withTypeCapacity( getMaxVarbinaryLength(), "bit varying($l)" ) + .build() + ); } - private void registerCubridKeywords() { + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); registerKeyword( "TYPE" ); registerKeyword( "YEAR" ); registerKeyword( "MONTH" ); @@ -132,11 +165,6 @@ public class CUBRIDDialect extends Dialect { return 1_073_741_823; } - @Override - public DatabaseVersion getVersion() { - return VERSION; - } - @Override public JdbcType resolveSqlTypeDescriptor( String columnTypeName, @@ -168,13 +196,6 @@ public class CUBRIDDialect extends Dialect { return 3; } - @Override - public String getTypeName(int code, Size size) throws HibernateException { - //precision of a CUBRID 'float(p)' represents - //decimal digits instead of binary digits - return super.getTypeName( code, binaryToDecimalPrecision( code, size ) ); - } - @Override public int getFloatPrecision() { return 21; // -> 7 decimal digits @@ -482,4 +503,5 @@ public class CUBRIDDialect extends Dialect { sqlAppender.append(",timediff(?3,?2))"); sqlAppender.append( diffUnit.conversionFactor( toUnit, this ) ); } + } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java index 976b60eb8a..2746be1b6f 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java @@ -8,9 +8,9 @@ package org.hibernate.community.dialect; import org.hibernate.LockMode; import org.hibernate.cfg.Environment; -import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.OracleDialect; +import org.hibernate.dialect.SimpleDatabaseVersion; import org.hibernate.dialect.function.CommonFunctionFactory; import org.hibernate.community.dialect.identity.CacheIdentityColumnSupport; import org.hibernate.dialect.identity.IdentityColumnSupport; @@ -51,6 +51,11 @@ import jakarta.persistence.TemporalType; import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; +import static org.hibernate.type.SqlTypes.BLOB; +import static org.hibernate.type.SqlTypes.BOOLEAN; +import static org.hibernate.type.SqlTypes.CLOB; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; /** * Dialect for Intersystems Caché SQL 2007.1 and above. @@ -58,26 +63,32 @@ import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STR * @author Jonathan Levinson */ public class CacheDialect extends Dialect { - private final DatabaseVersion version = DatabaseVersion.make( 0, 0 ); public CacheDialect() { - super(); - // Note: For object <-> SQL datatype mappings see: - // Configuration Manager > Advanced > SQL > System DDL Datatype Mappings - - registerColumnType( Types.BOOLEAN, "bit" ); - - //no explicit precision - registerColumnType( Types.TIMESTAMP, "timestamp" ); - registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" ); - - registerColumnType( Types.BLOB, "image" ); - registerColumnType( Types.CLOB, "text" ); + super( SimpleDatabaseVersion.ZERO_VERSION ); } public CacheDialect(DialectResolutionInfo info) { - this(); - registerKeywords( info ); + super( info ); + } + + @Override + protected String columnType(int sqlTypeCode) { + // Note: For object <-> SQL datatype mappings see: + // Configuration Manager > Advanced > SQL > System DDL Datatype Mappings + switch ( sqlTypeCode ) { + case BOOLEAN: + return "bit"; + //no explicit precision + case TIMESTAMP: + case TIMESTAMP_WITH_TIMEZONE: + return "timestamp"; + case BLOB: + return "image"; + case CLOB: + return "text"; + } + return super.columnType( sqlTypeCode ); } @Override @@ -99,11 +110,6 @@ public class CacheDialect extends Dialect { ); } - @Override - public DatabaseVersion getVersion() { - return version; - } - @Override public JdbcType resolveSqlTypeDescriptor( String columnTypeName, diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java index 1d85da191f..49e8c71e6c 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java @@ -17,8 +17,8 @@ import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.hibernate.HibernateException; import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.boot.model.TypeContributions; import org.hibernate.community.dialect.identity.FirebirdIdentityColumnSupport; import org.hibernate.community.dialect.pagination.SkipFirstLimitHandler; import org.hibernate.community.dialect.sequence.FirebirdSequenceSupport; @@ -33,7 +33,6 @@ import org.hibernate.dialect.identity.IdentityColumnSupport; import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.OffsetFetchLimitHandler; import org.hibernate.dialect.sequence.SequenceSupport; -import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder; @@ -58,6 +57,7 @@ import org.hibernate.dialect.temptable.TemporaryTable; import org.hibernate.dialect.temptable.TemporaryTableKind; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; +import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.spi.SqlAppender; @@ -71,11 +71,23 @@ import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.BinaryFloatDdlType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import jakarta.persistence.TemporalType; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; +import static org.hibernate.type.SqlTypes.BINARY; +import static org.hibernate.type.SqlTypes.BLOB; +import static org.hibernate.type.SqlTypes.BOOLEAN; +import static org.hibernate.type.SqlTypes.CLOB; +import static org.hibernate.type.SqlTypes.NCLOB; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TIME_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.VARBINARY; import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_END; import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_DATE; import static org.hibernate.type.descriptor.DateTimeUtils.JDBC_ESCAPE_START_TIME; @@ -93,8 +105,6 @@ import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithM */ public class FirebirdDialect extends Dialect { - private final DatabaseVersion version; - @SuppressWarnings("unused") public FirebirdDialect() { this( DatabaseVersion.make( 2, 5 ) ); @@ -114,15 +124,47 @@ public class FirebirdDialect extends Dialect { // cast (not even when wrapped in a function call) public FirebirdDialect(DatabaseVersion version) { - super(); - this.version = version; + super( version ); + } - if ( version.isBefore( 3, 0 ) ) { + @Override + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { //'boolean' type introduced in 3.0 - registerColumnType( Types.BOOLEAN, "smallint" ); + case BOOLEAN: + return getVersion().isBefore( 3, 0 ) ? "smallint" : super.columnType( sqlTypeCode ); + case TINYINT: + return "smallint"; + //no precision for 'timestamp' type + case TIMESTAMP: + return "timestamp"; + case TIME_WITH_TIMEZONE: + return getVersion().isBefore( 4, 0 ) ? "time" : super.columnType( sqlTypeCode ); + case TIMESTAMP_WITH_TIMEZONE: + return getVersion().isBefore( 4, 0 ) ? "timestamp" : "timestamp with time zone"; + case BINARY: + return getVersion().isBefore( 4, 0 ) ? "char($l) character set octets" : super.columnType( sqlTypeCode ); + case VARBINARY: + return getVersion().isBefore( 4, 0 ) ? "varchar($l) character set octets" : super.columnType( sqlTypeCode ); + case BLOB: + return "blob sub_type binary"; + case CLOB: + case NCLOB: + return "blob sub_type text"; } + return super.columnType( sqlTypeCode ); + } - registerColumnType( Types.TINYINT, "smallint" ); + @Override + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + + if ( getVersion().isBefore( 4, 0 ) ) { + //precision of a Firebird 3 and earlier 'float(p)' represents + //decimal digits instead of binary digits + ddlTypeRegistry.addDescriptor( new BinaryFloatDdlType( this ) ); + } // Note: according to the documentation, Firebird has // just two floating point types: @@ -131,29 +173,6 @@ public class FirebirdDialect extends Dialect { // However, it turns out that Firebird actually supports // the ANSI types 'real', 'float(p)', 'double precision'. // So we don't override anything here. - - //no precision for 'timestamp' type - registerColumnType( Types.TIMESTAMP, "timestamp" ); - if ( getVersion().isBefore( 4, 0 ) ) { - // No time zone support, map to without time zone types - registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" ); - registerColumnType( Types.TIME_WITH_TIMEZONE, "time" ); - } - else { - registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp with time zone" ); - } - - registerColumnType( Types.VARCHAR, "blob sub_type text" ); - - if ( getVersion().isBefore( 4, 0 ) ) { - registerColumnType( Types.BINARY, "char($l) character set octets" ); - registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "varchar($l) character set octets" ); - } - registerColumnType( Types.VARBINARY, "blob sub_type binary" ); - - registerColumnType( Types.BLOB, "blob sub_type binary" ); - registerColumnType( Types.CLOB, "blob sub_type text" ); - registerColumnType( Types.NCLOB, "blob sub_type text" ); // Firebird doesn't have NCLOB, but Jaybird emulates NCLOB support } @Override @@ -168,11 +187,6 @@ public class FirebirdDialect extends Dialect { return 32_756; } - @Override - public DatabaseVersion getVersion() { - return version; - } - @Override public int getDefaultStatementBatchSize() { return 0; @@ -209,19 +223,6 @@ public class FirebirdDialect extends Dialect { : super.getPreferredSqlTypeCodeForBoolean(); } - @Override - public String getTypeName(int code, Size size) throws HibernateException { - if ( getVersion().isBefore( 4, 0 ) ) { - //precision of a Firebird 3 and earlier 'float(p)' represents - //decimal digits instead of binary digits - return super.getTypeName( code, binaryToDecimalPrecision( code, size ) ); - } - else { - // Firebird 4 and higher supports standard 'float(p)' (with precision in binary digits) - return super.getTypeName( code, size ); - } - } - @Override public int getFloatPrecision() { return getVersion().isBefore( 4, 0 ) @@ -514,7 +515,7 @@ public class FirebirdDialect extends Dialect { // Additional reserved words // The Hibernate list of SQL:2003 reserved words doesn't contain all SQL:2003 reserved words, // and Firebird is finicky when it comes to reserved words - if ( version.isSameOrAfter( 3, 0 ) ) { + if ( getVersion().isSameOrAfter( 3, 0 ) ) { builder.applyReservedWords( "AVG", "BOOLEAN", "CHARACTER_LENGTH", "CHAR_LENGTH", "CORR", "COUNT", "COVAR_POP", "COVAR_SAMP", "EXTRACT", "LOWER", "MAX", "MIN", "OCTET_LENGTH", "POSITION", diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java index 2a322cbf04..52a7775147 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java @@ -6,6 +6,7 @@ */ package org.hibernate.community.dialect; +import org.hibernate.boot.model.TypeContributions; import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Replacer; @@ -45,6 +46,7 @@ import org.hibernate.query.sqm.sql.SqmTranslator; import org.hibernate.query.sqm.sql.SqmTranslatorFactory; import org.hibernate.query.sqm.sql.StandardSqmTranslatorFactory; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; +import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.spi.SqlAppender; @@ -55,10 +57,26 @@ import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.community.dialect.sequence.SequenceInformationExtractorInformixDatabaseImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; - -import java.sql.Types; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate; +import static org.hibernate.type.SqlTypes.BIGINT; +import static org.hibernate.type.SqlTypes.BINARY; +import static org.hibernate.type.SqlTypes.FLOAT; +import static org.hibernate.type.SqlTypes.LONG32NVARCHAR; +import static org.hibernate.type.SqlTypes.LONG32VARBINARY; +import static org.hibernate.type.SqlTypes.LONG32VARCHAR; +import static org.hibernate.type.SqlTypes.LONGNVARCHAR; +import static org.hibernate.type.SqlTypes.LONGVARBINARY; +import static org.hibernate.type.SqlTypes.LONGVARCHAR; +import static org.hibernate.type.SqlTypes.NVARCHAR; +import static org.hibernate.type.SqlTypes.TIME; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.VARBINARY; +import static org.hibernate.type.SqlTypes.VARCHAR; /** * Dialect for Informix 7.31.UD3 with Informix @@ -68,7 +86,6 @@ import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtract */ public class InformixDialect extends Dialect { - private final DatabaseVersion version; private final UniqueDelegate uniqueDelegate; private final LimitHandler limitHandler; @@ -86,28 +103,7 @@ public class InformixDialect extends Dialect { * Informix type mappings. */ public InformixDialect(DatabaseVersion version) { - super(); - this.version = version; - - registerColumnType( Types.TINYINT, "smallint" ); - registerColumnType( Types.BIGINT, "int8" ); - - //Ingres ignores the precision argument in - //float(n) and just always defaults to - //double precision. - //TODO: return 'smallfloat' when n <= 24 - - registerColumnType( Types.TIME, "datetime hour to second" ); - registerColumnType( Types.TIMESTAMP, "datetime year to fraction($p)" ); - registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "datetime year to fraction($p)" ); - - //these types have no defined length - registerColumnType( Types.BINARY, "byte" ); - registerColumnType( Types.VARBINARY, "byte" ); - - registerColumnType( Types.VARCHAR, 255, "varchar($l)" ); - registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "lvarchar($l)" ); - registerColumnType( Types.VARCHAR, "text" ); + super(version); uniqueDelegate = new InformixUniqueDelegate( this ); @@ -119,6 +115,64 @@ public class InformixDialect extends Dialect { : new SkipFirstLimitHandler( getVersion().isSameOrAfter( 11 ) ); } + @Override + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case TINYINT: + return "smallint"; + case BIGINT: + return "int8"; + case TIME: + return "datetime hour to second"; + case TIMESTAMP: + case TIMESTAMP_WITH_TIMEZONE: + return "datetime year to fraction($p)"; + //these types have no defined length + case BINARY: + case VARBINARY: + case LONGVARBINARY: + case LONG32VARBINARY: + return "byte"; + case LONGVARCHAR: + case LONGNVARCHAR: + case LONG32VARCHAR: + case LONG32NVARCHAR: + return "text"; + case VARCHAR: + case NVARCHAR: + return "lvarchar($l)"; + } + return super.columnType( sqlTypeCode ); + } + + @Override + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + + //Ingres ignores the precision argument in + //float(n) and just always defaults to + //double precision. + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( FLOAT, "float($p)", this ) + .withTypeCapacity( 24, "smallfloat" ) + .build() + ); + + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( VARCHAR, columnType( LONGVARCHAR ), this ) + .withTypeCapacity( 255, "varchar($l)" ) + .withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( NVARCHAR, columnType( LONGNVARCHAR ), this ) + .withTypeCapacity( 255, "varchar($l)" ) + .withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) ) + .build() + ); + } + @Override public int getMaxVarbinaryLength() { //there's no varbinary type, only byte @@ -131,11 +185,6 @@ public class InformixDialect extends Dialect { return 32_739; } - @Override - public DatabaseVersion getVersion() { - return version; - } - @Override public int getDefaultDecimalPrecision() { //the maximum diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java index 231fbc426a..9c937ec979 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java @@ -12,6 +12,7 @@ import org.hibernate.community.dialect.identity.Ingres10IdentityColumnSupport; import org.hibernate.community.dialect.identity.Ingres9IdentityColumnSupport; import org.hibernate.community.dialect.pagination.FirstLimitHandler; import org.hibernate.community.dialect.pagination.IngresLimitHandler; +import org.hibernate.community.dialect.sequence.IngresLegacySequenceSupport; import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.MySQLDialect; @@ -63,6 +64,21 @@ import jakarta.persistence.TemporalType; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; +import static org.hibernate.type.SqlTypes.BINARY; +import static org.hibernate.type.SqlTypes.BLOB; +import static org.hibernate.type.SqlTypes.BOOLEAN; +import static org.hibernate.type.SqlTypes.CLOB; +import static org.hibernate.type.SqlTypes.DATE; +import static org.hibernate.type.SqlTypes.DECIMAL; +import static org.hibernate.type.SqlTypes.LONG32NVARCHAR; +import static org.hibernate.type.SqlTypes.LONG32VARBINARY; +import static org.hibernate.type.SqlTypes.LONG32VARCHAR; +import static org.hibernate.type.SqlTypes.LONGNVARCHAR; +import static org.hibernate.type.SqlTypes.LONGVARBINARY; +import static org.hibernate.type.SqlTypes.LONGVARCHAR; +import static org.hibernate.type.SqlTypes.NCLOB; +import static org.hibernate.type.SqlTypes.NUMERIC; +import static org.hibernate.type.SqlTypes.VARBINARY; /** * An SQL dialect for Ingres 9.2. @@ -91,83 +107,74 @@ import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STR public class IngresDialect extends Dialect { private final LimitHandler limitHandler; - - private final DatabaseVersion version; - private final SequenceSupport sequenceSupport; + public IngresDialect() { + this( DatabaseVersion.make( 9, 2 ) ); + } + public IngresDialect(DialectResolutionInfo info) { this( info.makeCopy() ); registerKeywords( info ); } - public IngresDialect() { - this( DatabaseVersion.make( 9, 2 ) ); - } - /** * Constructs a IngresDialect */ public IngresDialect(DatabaseVersion version) { - super(); - this.version = version; - - if ( version.isBefore( 10 ) ) { - registerColumnType( Types.BOOLEAN, "tinyint" ); + super( version ); + if ( getVersion().isSameOrAfter( 9, 3 ) ) { + limitHandler = IngresLimitHandler.INSTANCE; + sequenceSupport = ANSISequenceSupport.INSTANCE; } else { - registerColumnType( Types.BOOLEAN, "boolean" ); + limitHandler = FirstLimitHandler.INSTANCE; + sequenceSupport = IngresLegacySequenceSupport.INSTANCE; } + } - registerColumnType( Types.NUMERIC, "decimal($p, $s)" ); //Ingres has no 'numeric' type - - registerColumnType( Types.BINARY, "byte($l)" ); - registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "varbyte($l)" ); - //note: 'long byte' is a synonym for 'blob' - registerColumnType( Types.VARBINARY, "long byte($l)" ); - + @Override + protected String columnType(int sqlTypeCode) { //TODO: should we be using nchar/nvarchar/long nvarchar // here? I think Ingres char/varchar types don't // support Unicode. Copy what AbstractHANADialect // does with a Hibernate property to config this. - registerColumnType( Types.CHAR, "char($l)" ); - registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "varchar($l)" ); - //note: 'long varchar' is a synonym for 'clob' - registerColumnType( Types.VARCHAR, "long varchar($l)" ); - registerColumnType( Types.NCHAR, "nchar($l)" ); - registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "nvarchar($l)" ); - //note: 'long nvarchar' is a synonym for 'nclob' - registerColumnType( Types.NVARCHAR, "long nvarchar($l)" ); - - if ( getVersion().isSameOrAfter( 9, 3 ) ) { + switch ( sqlTypeCode ) { + case BOOLEAN: + return getVersion().isBefore( 10 ) ? "tinyint" : super.columnType( sqlTypeCode ); // Not completely necessary, given that Ingres // can be configured to set DATE = ANSIDATE - registerColumnType( Types.DATE, "ansidate" ); + case DATE: + return getVersion().isBefore( 10 ) && getVersion().isSameOrAfter( 9, 3 ) + ? "ansidate" + : super.columnType( sqlTypeCode ); + //Ingres has no 'numeric' type + case NUMERIC: + return castType( DECIMAL ); + case BINARY: + return "byte($l)"; + case VARBINARY: + return "varbyte($l)"; + //note: 'long byte' is a synonym for 'blob' + case LONGVARBINARY: + case LONG32VARBINARY: + case BLOB: + return "long byte($l)"; + //note: 'long varchar' is a synonym for 'clob' + case LONGVARCHAR: + case LONG32VARCHAR: + case CLOB: + return "long varchar($l)"; + //note: 'long varchar' is a synonym for 'nclob' + case LONGNVARCHAR: + case LONG32NVARCHAR: + case NCLOB: + return "long nvarchar($l)"; } - - limitHandler = getVersion().isBefore( 9, 3 ) ? FirstLimitHandler.INSTANCE : IngresLimitHandler.INSTANCE; - - sequenceSupport = new ANSISequenceSupport() { - @Override - public boolean supportsPooledSequences() { - return getVersion().isSameOrAfter( 9, 3 ); - } - }; + return super.columnType( sqlTypeCode ); } -// @Override -// protected void initDefaultProperties() { -// super.initDefaultProperties(); -// -// if ( getVersion().isBefore( 10 ) ) { -// // There is no support for a native boolean type that accepts values -// // of true, false or unknown. Using the tinyint type requires -// // substitutions of true and false. -// getDefaultProperties().setProperty( Environment.QUERY_SUBSTITUTIONS, "true=1,false=0" ); -// } -// } - @Override public boolean getDefaultUseGetGeneratedKeys() { // Ingres driver supports getGeneratedKeys but only in the following @@ -183,11 +190,6 @@ public class IngresDialect extends Dialect { return false; } - @Override - public DatabaseVersion getVersion() { - return version; - } - @Override public int getMaxVarcharLength() { // the maximum possible (configurable) value for diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java index 3f6de2fddc..1dc2784b60 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java @@ -13,7 +13,6 @@ import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.community.dialect.sequence.MaxDBSequenceSupport; import org.hibernate.community.dialect.sequence.SequenceInformationExtractorSAPDBDatabaseImpl; import org.hibernate.dialect.AbstractTransactSQLDialect; -import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.function.CommonFunctionFactory; import org.hibernate.dialect.pagination.LimitHandler; @@ -40,6 +39,15 @@ import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import static org.hibernate.dialect.SimpleDatabaseVersion.ZERO_VERSION; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; +import static org.hibernate.type.SqlTypes.BIGINT; +import static org.hibernate.type.SqlTypes.BLOB; +import static org.hibernate.type.SqlTypes.CLOB; +import static org.hibernate.type.SqlTypes.DECIMAL; +import static org.hibernate.type.SqlTypes.NUMERIC; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.VARBINARY; /** * A SQL dialect compatible with SAP MaxDB. @@ -49,22 +57,34 @@ import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STR public class MaxDBDialect extends Dialect { public MaxDBDialect() { - super(); - registerColumnType( Types.TINYINT, "smallint" ); + super( ZERO_VERSION ); + } - registerColumnType( Types.BIGINT, "fixed(19,0)" ); + public MaxDBDialect(DialectResolutionInfo info) { + super( info ); + } - registerColumnType( Types.NUMERIC, "fixed($p,$s)" ); - registerColumnType( Types.DECIMAL, "fixed($p,$s)" ); - - //no explicit precision - registerColumnType(Types.TIMESTAMP, "timestamp"); - registerColumnType(Types.TIMESTAMP_WITH_TIMEZONE, "timestamp"); - - registerColumnType( Types.VARBINARY, "long byte" ); - - registerColumnType( Types.CLOB, "long varchar" ); - registerColumnType( Types.BLOB, "long byte" ); + @Override + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case TINYINT: + return "smallint"; + case BIGINT: + return "fixed(19,0)"; + case NUMERIC: + case DECIMAL: + return "fixed($p,$s)"; + //no explicit precision + case TIMESTAMP: + case TIMESTAMP_WITH_TIMEZONE: + return "timestamp"; + case VARBINARY: + case BLOB: + return "long byte"; + case CLOB: + return "long varchar"; + } + return super.columnType( sqlTypeCode ); } @Override @@ -96,16 +116,6 @@ public class MaxDBDialect extends Dialect { ); } - public MaxDBDialect(DialectResolutionInfo info) { - this(); - registerKeywords( info ); - } - - @Override - public DatabaseVersion getVersion() { - return ZERO_VERSION; - } - @Override public int getDefaultStatementBatchSize() { return 15; diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLDialect.java index d8fec874ed..762a74748b 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLDialect.java @@ -6,10 +6,8 @@ */ package org.hibernate.community.dialect; -import java.sql.Types; - -import org.hibernate.HibernateException; import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.boot.model.TypeContributions; import org.hibernate.community.dialect.identity.MimerSQLIdentityColumnSupport; import org.hibernate.community.dialect.sequence.MimerSequenceSupport; import org.hibernate.community.dialect.sequence.SequenceInformationExtractorMimerSQLDatabaseImpl; @@ -20,13 +18,13 @@ import org.hibernate.dialect.identity.IdentityColumnSupport; import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.OffsetFetchLimitHandler; import org.hibernate.dialect.sequence.SequenceSupport; -import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.SemanticException; import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.spi.QueryEngine; +import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.spi.SqlAppender; @@ -34,10 +32,26 @@ import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory; import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; +import org.hibernate.type.descriptor.sql.internal.BinaryFloatDdlType; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import jakarta.persistence.TemporalType; import static org.hibernate.dialect.SimpleDatabaseVersion.ZERO_VERSION; +import static org.hibernate.type.SqlTypes.CHAR; +import static org.hibernate.type.SqlTypes.CLOB; +import static org.hibernate.type.SqlTypes.LONG32NVARCHAR; +import static org.hibernate.type.SqlTypes.LONG32VARCHAR; +import static org.hibernate.type.SqlTypes.LONGNVARCHAR; +import static org.hibernate.type.SqlTypes.LONGVARCHAR; +import static org.hibernate.type.SqlTypes.NCHAR; +import static org.hibernate.type.SqlTypes.NCLOB; +import static org.hibernate.type.SqlTypes.NVARCHAR; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.VARCHAR; /** * A dialect for Mimer SQL 11. @@ -57,38 +71,56 @@ public class MimerSQLDialect extends Dialect { // in a cast or function call public MimerSQLDialect() { - super(); - //no 'tinyint', so use integer with 3 decimal digits - registerColumnType( Types.TINYINT, "integer(3)" ); - - //Mimer CHARs are ASCII!! - registerColumnType( Types.CHAR, "nchar($l)" ); - registerColumnType( Types.VARCHAR, 5_000, "nvarchar($l)" ); - registerColumnType( Types.VARCHAR, "nclob($l)" ); - registerColumnType( Types.NVARCHAR, 5_000, "nvarchar($l)" ); - registerColumnType( Types.NVARCHAR, "nclob($l)" ); - - registerColumnType( Types.VARBINARY, 15_000, "varbinary($l)" ); - registerColumnType( Types.VARBINARY, "blob($l)" ); - - //default length is 1M, which is quite low - registerColumnType( Types.BLOB, "blob($l)" ); - registerColumnType( Types.CLOB, "nclob($l)" ); - registerColumnType( Types.NCLOB, "nclob($l)" ); - - registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp($p)" ); + super( DatabaseVersion.make( 11 ) ); } public MimerSQLDialect(DialectResolutionInfo info) { - this(); - registerKeywords( info ); + super( info ); } @Override - public String getTypeName(int code, Size size) throws HibernateException { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + //no 'tinyint', so use integer with 3 decimal digits + case TINYINT: + return "integer(3)"; + case TIMESTAMP_WITH_TIMEZONE: + return columnType( TIMESTAMP ); + //Mimer CHARs are ASCII!! + case CHAR: + return columnType( NCHAR ); + case VARCHAR: + return columnType( NVARCHAR ); + case LONGVARCHAR: + return columnType( LONGNVARCHAR ); + case LONG32VARCHAR: + return columnType( LONG32NVARCHAR ); + case CLOB: + return columnType( NCLOB ); + } + return super.columnType( sqlTypeCode ); + } + + @Override + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + //precision of a Mimer 'float(p)' represents //decimal digits instead of binary digits - return super.getTypeName( code, binaryToDecimalPrecision( code, size ) ); + ddlTypeRegistry.addDescriptor( new BinaryFloatDdlType( this ) ); + + //Mimer CHARs are ASCII!! + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( VARCHAR, columnType( LONGVARCHAR ), "nvarchar(" + getMaxNVarcharLength() + ")", this ) + .withTypeCapacity( getMaxNVarcharLength(), columnType( VARCHAR ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( LONGVARCHAR, columnType( LONGVARCHAR ), "nvarchar(" + getMaxNVarcharLength() + ")", this ) + .withTypeCapacity( getMaxNVarcharLength(), columnType( VARCHAR ) ) + .build() + ); } // @Override diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200Dialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200Dialect.java index 653eed7530..d873b01c16 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200Dialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200Dialect.java @@ -14,6 +14,7 @@ import org.hibernate.dialect.AbstractTransactSQLDialect; import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.OracleDialect; +import org.hibernate.dialect.SimpleDatabaseVersion; import org.hibernate.dialect.function.CommonFunctionFactory; import org.hibernate.dialect.lock.LockingStrategy; import org.hibernate.dialect.lock.OptimisticForceIncrementLockingStrategy; @@ -48,6 +49,26 @@ import org.jboss.logging.Logger; import jakarta.persistence.TemporalType; import static org.hibernate.dialect.SimpleDatabaseVersion.ZERO_VERSION; +import static org.hibernate.type.SqlTypes.BIGINT; +import static org.hibernate.type.SqlTypes.BINARY; +import static org.hibernate.type.SqlTypes.BLOB; +import static org.hibernate.type.SqlTypes.BOOLEAN; +import static org.hibernate.type.SqlTypes.CHAR; +import static org.hibernate.type.SqlTypes.CLOB; +import static org.hibernate.type.SqlTypes.LONG32NVARCHAR; +import static org.hibernate.type.SqlTypes.LONG32VARBINARY; +import static org.hibernate.type.SqlTypes.LONG32VARCHAR; +import static org.hibernate.type.SqlTypes.LONGNVARCHAR; +import static org.hibernate.type.SqlTypes.LONGVARBINARY; +import static org.hibernate.type.SqlTypes.LONGVARCHAR; +import static org.hibernate.type.SqlTypes.NCHAR; +import static org.hibernate.type.SqlTypes.NCLOB; +import static org.hibernate.type.SqlTypes.NVARCHAR; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.VARBINARY; +import static org.hibernate.type.SqlTypes.VARCHAR; /** * This is the Hibernate dialect for the Unisys 2200 Relational Database (RDMS). @@ -71,10 +92,17 @@ public class RDMSOS2200Dialect extends Dialect { * Constructs a RDMSOS2200Dialect */ public RDMSOS2200Dialect() { - super(); + super( SimpleDatabaseVersion.ZERO_VERSION ); // Display the dialect version. LOG.rdmsOs2200Dialect(); + } + public RDMSOS2200Dialect(DialectResolutionInfo info) { + super( info ); + } + + @Override + protected String columnType(int sqlTypeCode) { /* * For a list of column types to register, see section A-1 * in 7862 7395, the Unisys JDBC manual. @@ -100,28 +128,39 @@ public class RDMSOS2200Dialect extends Dialect { * Note that $l (dollar-L) will use the length value if provided. * Also new for Hibernate3 is the $p percision and $s (scale) parameters */ - registerColumnType( Types.BOOLEAN, "smallint" ); - registerColumnType( Types.TINYINT, "smallint" ); - registerColumnType( Types.BIGINT, "numeric(19,0)" ); - registerColumnType( Types.BLOB, "blob($l)" ); - - //no 'binary' nor 'varbinary' so use 'blob' - registerColumnType( Types.BINARY, "blob($l)" ); - registerColumnType( Types.VARBINARY, "blob($l)" ); - - //'varchar' is not supported in RDMS for OS 2200 - //(but it is for other flavors of RDMS) - //'character' means ASCII by default, 'unicode(n)' - //means 'character(n) character set "UCS-2"' - registerColumnType( Types.CHAR, "unicode($l)" ); - registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "unicode($l)" ); - - registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp($p)" ); - } - - public RDMSOS2200Dialect(DialectResolutionInfo info) { - this(); - registerKeywords( info ); + switch ( sqlTypeCode ) { + case BOOLEAN: + case TINYINT: + return "smallint"; + case BIGINT: + return "numeric(19,0)"; + //'varchar' is not supported in RDMS for OS 2200 + //(but it is for other flavors of RDMS) + //'character' means ASCII by default, 'unicode(n)' + //means 'character(n) character set "UCS-2"' + case CHAR: + case NCHAR: + case VARCHAR: + case NVARCHAR: + case LONGVARCHAR: + case LONG32VARCHAR: + case LONGNVARCHAR: + case LONG32NVARCHAR: + return "unicode($l)"; + case CLOB: + case NCLOB: + return "clob($l)"; + //no 'binary' nor 'varbinary' so use 'blob' + case BINARY: + case VARBINARY: + case LONGVARBINARY: + case LONG32VARBINARY: + case BLOB: + return "blob($l)"; + case TIMESTAMP_WITH_TIMEZONE: + return columnType( TIMESTAMP ); + } + return super.columnType( sqlTypeCode ); } @Override diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java index 5aa43bb6e0..de57588a3d 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java @@ -53,11 +53,10 @@ import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.type.BasicType; import org.hibernate.type.BasicTypeRegistry; +import org.hibernate.type.SqlTypes; import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.BlobJdbcType; import org.hibernate.type.descriptor.jdbc.ClobJdbcType; -import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import jakarta.persistence.TemporalType; @@ -72,14 +71,15 @@ import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INT import static org.hibernate.query.sqm.produce.function.FunctionParameterType.NUMERIC; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING; import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEMPORAL; +import static org.hibernate.type.SqlTypes.BINARY; import static org.hibernate.type.SqlTypes.CHAR; -import static org.hibernate.type.SqlTypes.LONG32NVARCHAR; -import static org.hibernate.type.SqlTypes.LONG32VARCHAR; -import static org.hibernate.type.SqlTypes.LONGNVARCHAR; -import static org.hibernate.type.SqlTypes.LONGVARCHAR; +import static org.hibernate.type.SqlTypes.DECIMAL; +import static org.hibernate.type.SqlTypes.FLOAT; import static org.hibernate.type.SqlTypes.NCHAR; -import static org.hibernate.type.SqlTypes.NVARCHAR; -import static org.hibernate.type.SqlTypes.VARCHAR; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TIME_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.VARBINARY; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithMicros; @@ -95,7 +95,6 @@ public class SQLiteDialect extends Dialect { private static final SQLiteIdentityColumnSupport IDENTITY_COLUMN_SUPPORT = new SQLiteIdentityColumnSupport(); private final UniqueDelegate uniqueDelegate; - private final DatabaseVersion version; public SQLiteDialect(DialectResolutionInfo info) { this( info.makeCopy() ); @@ -107,39 +106,32 @@ public class SQLiteDialect extends Dialect { } public SQLiteDialect(DatabaseVersion version) { - super(); - this.version = version; - - if ( version.isBefore( 3 ) ) { - registerColumnType( Types.DECIMAL, "numeric($p,$s)" ); - registerColumnType( Types.CHAR, "char" ); - registerColumnType( Types.NCHAR, "nchar" ); - } - // No precision support - registerColumnType( Types.FLOAT, "float" ); - registerColumnType( Types.TIMESTAMP, "timestamp" ); - registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" ); - registerColumnType( Types.TIME_WITH_TIMEZONE, "time" ); - - registerColumnType( Types.BINARY, "blob" ); - registerColumnType( Types.VARBINARY, "blob" ); + super( version ); uniqueDelegate = new SQLiteUniqueDelegate( this ); } @Override - public String getUnboundedTypeName(JdbcType jdbcType, JavaType javaType) { - switch ( jdbcType.getDefaultSqlTypeCode() ) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case DECIMAL: + return getVersion().isBefore( 3 ) ? columnType( SqlTypes.NUMERIC ) : super.columnType( sqlTypeCode ); case CHAR: + return getVersion().isBefore( 3 ) ? "char" : super.columnType( sqlTypeCode ); case NCHAR: - case VARCHAR: - case NVARCHAR: - case LONGVARCHAR: - case LONGNVARCHAR: - case LONG32VARCHAR: - case LONG32NVARCHAR: - return "text"; + return getVersion().isBefore( 3 ) ? "nchar" : super.columnType( sqlTypeCode ); + // No precision support + case FLOAT: + return "float"; + case TIMESTAMP: + case TIMESTAMP_WITH_TIMEZONE: + return "timestamp"; + case TIME_WITH_TIMEZONE: + return "time"; + case BINARY: + case VARBINARY: + return "blob"; } - return super.getUnboundedTypeName( jdbcType, javaType ); + return super.columnType( sqlTypeCode ); } @Override @@ -163,11 +155,6 @@ public class SQLiteDialect extends Dialect { return uniqueDelegate; } - @Override - public DatabaseVersion getVersion() { - return version; - } - /** * The {@code extract()} function returns {@link TemporalUnit#DAY_OF_WEEK} * numbered from 0 to 6. This isn't consistent with what most other diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java index 05c17745c1..07f843a787 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java @@ -50,31 +50,22 @@ public class SybaseAnywhereDialect extends SybaseDialect { } @Override - protected String columnType(int jdbcTypeCode) { - switch (jdbcTypeCode) { - case DATE: - return "date"; - case TIME: - return "time"; + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case TIMESTAMP: return "timestamp"; case TIMESTAMP_WITH_TIMEZONE: return "timestamp with time zone"; - - //these types hold up to 2 GB case LONG32VARCHAR: return "long varchar"; case LONG32NVARCHAR: return "long nvarchar"; case LONG32VARBINARY: return "long binary"; - case NCLOB: return "ntext"; - - default: - return super.columnType(jdbcTypeCode); } + return super.columnType( sqlTypeCode ); } @Override diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java index fd267c599c..246fa11156 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java @@ -50,6 +50,7 @@ import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.spi.TypeConfiguration; import java.sql.CallableStatement; import java.sql.ResultSet; @@ -61,6 +62,11 @@ import java.util.Map; import jakarta.persistence.TemporalType; import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate; +import static org.hibernate.type.SqlTypes.BIGINT; +import static org.hibernate.type.SqlTypes.BINARY; +import static org.hibernate.type.SqlTypes.BOOLEAN; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.VARBINARY; /** * A dialect for the Teradata database created by MCR as part of the @@ -70,8 +76,6 @@ import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtract */ public class TeradataDialect extends Dialect { - private final DatabaseVersion version; - private static final int PARAM_LIST_SIZE_LIMIT = 1024; public TeradataDialect(DialectResolutionInfo info) { @@ -84,24 +88,12 @@ public class TeradataDialect extends Dialect { } public TeradataDialect(DatabaseVersion version) { - super(); - this.version = version; - - registerColumnType( Types.BOOLEAN, "byteint" ); - - registerColumnType( Types.TINYINT, "byteint" ); - - registerColumnType( Types.BINARY, "byte($l)" ); - registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "varbyte($l)" ); - - if ( getVersion().isBefore( 13 ) ) { - registerColumnType( Types.BIGINT, "numeric(19,0)" ); - } - else { - //'bigint' has been there since at least version 13 - registerColumnType( Types.BIGINT, "bigint" ); - } + super( version ); + } + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); registerKeyword( "password" ); registerKeyword( "type" ); registerKeyword( "title" ); @@ -116,6 +108,23 @@ public class TeradataDialect extends Dialect { registerKeyword( "class" ); } + @Override + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case BOOLEAN: + case TINYINT: + return "byteint"; + //'bigint' has been there since at least version 13 + case BIGINT: + return getVersion().isBefore( 13 ) ? "numeric(19,0)" : "bigint"; + case BINARY: + return "byte($l)"; + case VARBINARY: + return "varbyte($l)"; + } + return super.columnType( sqlTypeCode ); + } + @Override public int getDefaultStatementBatchSize() { return getVersion().isBefore( 14 ) @@ -173,11 +182,6 @@ public class TeradataDialect extends Dialect { }; } - @Override - public DatabaseVersion getVersion() { - return version; - } - @Override public int getPreferredSqlTypeCodeForBoolean() { return Types.BIT; @@ -389,7 +393,7 @@ public class TeradataDialect extends Dialect { } @Override - public String getSelectClauseNullString(int sqlType) { + public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { String v = "null"; switch ( sqlType ) { diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java index 54380a791d..46e3d6a437 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TimesTenDialect.java @@ -8,7 +8,6 @@ package org.hibernate.community.dialect; import org.hibernate.LockMode; import org.hibernate.LockOptions; -import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.RowLockStrategy; import org.hibernate.dialect.function.CommonFunctionFactory; @@ -38,9 +37,11 @@ import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.community.dialect.sequence.SequenceInformationExtractorTimesTenDatabaseImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; +import org.hibernate.type.SqlTypes; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.spi.TypeConfiguration; import java.sql.Types; import jakarta.persistence.TemporalType; @@ -67,45 +68,44 @@ import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STR public class TimesTenDialect extends Dialect { public TimesTenDialect() { - super(); - - //Note: these are the correct type mappings - // for the default Oracle type mode - // TypeMode=0 - registerColumnType( Types.BOOLEAN, "tt_tinyint" ); - - registerColumnType( Types.TINYINT, "tt_tinyint" ); - registerColumnType( Types.SMALLINT, "tt_smallint" ); - registerColumnType( Types.INTEGER, "tt_integer" ); - registerColumnType( Types.BIGINT, "tt_bigint" ); - - //note that 'binary_float'/'binary_double' might - //be better mappings for Java Float/Double - - //'numeric'/'decimal' are synonyms for 'number' - registerColumnType( Types.NUMERIC, "number($p,$s)" ); - registerColumnType( Types.DECIMAL, "number($p,$s)" ); - - registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "varchar2($l)" ); - registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "nvarchar2($l)" ); - - //do not use 'date' because it's a datetime - registerColumnType( Types.DATE, "tt_date" ); - //'time' and 'tt_time' are synonyms - registerColumnType( Types.TIME, "tt_time" ); - //`timestamp` has more precision than `tt_timestamp` -// registerColumnType(Types.TIMESTAMP, "tt_timestamp"); - registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp($p)" ); + super( ZERO_VERSION ); } public TimesTenDialect(DialectResolutionInfo info) { - this(); - registerKeywords( info ); + super( info ); } @Override - public DatabaseVersion getVersion() { - return ZERO_VERSION; + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + //Note: these are the correct type mappings + // for the default Oracle type mode + // TypeMode=0 + case SqlTypes.BOOLEAN: + case SqlTypes.TINYINT: + return "tt_tinyint"; + case SqlTypes.SMALLINT: + return "tt_smallint"; + case SqlTypes.INTEGER: + return "tt_integer"; + case SqlTypes.BIGINT: + return "tt_bigint"; + //note that 'binary_float'/'binary_double' might + //be better mappings for Java Float/Double + + //'numeric'/'decimal' are synonyms for 'number' + case SqlTypes.NUMERIC: + case SqlTypes.DECIMAL: + return "number($p,$s)"; + case SqlTypes.DATE: + return "tt_date"; + case SqlTypes.TIME: + return "tt_time"; + //`timestamp` has more precision than `tt_timestamp` + case SqlTypes.TIMESTAMP_WITH_TIMEZONE: + return "timestamp($p)"; + } + return super.columnType( sqlTypeCode ); } @Override @@ -399,7 +399,7 @@ public class TimesTenDialect extends Dialect { } @Override - public String getSelectClauseNullString(int sqlType) { + public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { switch (sqlType) { case Types.VARCHAR: case Types.CHAR: diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/sequence/IngresLegacySequenceSupport.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/sequence/IngresLegacySequenceSupport.java new file mode 100644 index 0000000000..b5335d031c --- /dev/null +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/sequence/IngresLegacySequenceSupport.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.community.dialect.sequence; + +import org.hibernate.dialect.sequence.ANSISequenceSupport; +import org.hibernate.dialect.sequence.SequenceSupport; + +/** + * Sequence support for {@link org.hibernate.community.dialect.IngresDialect}. + */ +public final class IngresLegacySequenceSupport extends ANSISequenceSupport { + + public static final SequenceSupport INSTANCE = new IngresLegacySequenceSupport(); + + @Override + public boolean supportsPooledSequences() { + return false; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java index 55467d893a..c256f85e25 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java @@ -296,24 +296,6 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont options.basicTypeRegistrations.add( new BasicTypeRegistration( type, keys, getTypeConfiguration() ) ); } - @Override - public void contributeJavaType(JavaType descriptor) { - this.bootstrapContext.getTypeConfiguration().getJavaTypeRegistry().addDescriptor( descriptor ); - } - - @Override - public void contributeJdbcType(JdbcType descriptor) { - this.bootstrapContext.getTypeConfiguration().getJdbcTypeRegistry().addDescriptor( descriptor ); - } - - @Override - public void contributeType(UserType descriptor) { - bootstrapContext.getTypeConfiguration().getBasicTypeRegistry().register( - descriptor, - descriptor.returnedClass().getName() - ); - } - @Override public TypeConfiguration getTypeConfiguration() { return bootstrapContext.getTypeConfiguration(); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributions.java b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributions.java index a4dc8f70c9..06e18c7256 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributions.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributions.java @@ -7,6 +7,7 @@ package org.hibernate.boot.model; import org.hibernate.type.BasicType; +import org.hibernate.type.CustomType; import org.hibernate.type.StandardBasicTypeTemplate; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; @@ -27,25 +28,35 @@ public interface TypeContributions { * Add the JavaType to the {@link TypeConfiguration}'s * {@link JavaTypeRegistry} */ - void contributeJavaType(JavaType descriptor); + default void contributeJavaType(JavaType descriptor) { + getTypeConfiguration().getJavaTypeRegistry().addDescriptor( descriptor ); + } /** * Add the JdbcType to the {@link TypeConfiguration}'s * {@link JdbcTypeRegistry} */ - void contributeJdbcType(JdbcType descriptor); + default void contributeJdbcType(JdbcType descriptor) { + getTypeConfiguration().getJdbcTypeRegistry().addDescriptor( descriptor ); + } /** * Registers a UserType as the implicit (auto-applied) type * for values of type {@link UserType#returnedClass()} */ - void contributeType(UserType type); + default void contributeType(UserType type) { + contributeType( type, type.returnedClass().getName() ); + } /** * @deprecated See user-guide section `2.2.46. TypeContributor` for details - `basic_types.adoc` */ @Deprecated(since = "6.0") - void contributeType(BasicType type); + default void contributeType(BasicType type) { + getTypeConfiguration().getBasicTypeRegistry().register( type ); + final JavaType javaType = type.getJavaTypeDescriptor(); + getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType.getJavaType(), () -> javaType ); + } /** * @deprecated Use {@link #contributeType(BasicType)} instead. Basic @@ -58,7 +69,11 @@ public interface TypeContributions { * registration keys and call {@link #contributeType(BasicType)} instead */ @Deprecated(since = "5.3") - void contributeType(BasicType type, String... keys); + default void contributeType(BasicType type, String... keys) { + getTypeConfiguration().getBasicTypeRegistry().register( type, keys ); + final JavaType javaType = type.getJavaTypeDescriptor(); + getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType.getJavaType(), () -> javaType ); + } /** * @deprecated Use {@link #contributeType(BasicType)} instead. @@ -71,5 +86,9 @@ public interface TypeContributions { * and call {@link #contributeType(BasicType)} instead */ @Deprecated(since = "5.3") - void contributeType(UserType type, String... keys); + default void contributeType(UserType type, String... keys) { + final CustomType customType = getTypeConfiguration().getBasicTypeRegistry().register( type, keys ); + final JavaType javaType = customType.getJavaTypeDescriptor(); + getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( javaType.getJavaType(), () -> javaType ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java index 5cfa83c602..4d65818025 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java @@ -44,15 +44,12 @@ import org.hibernate.engine.config.spi.StandardConverters; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.type.BasicType; import org.hibernate.type.BasicTypeRegistry; -import org.hibernate.type.CustomType; import org.hibernate.type.SqlTypes; -import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import org.hibernate.type.internal.NamedBasicTypeImpl; import org.hibernate.type.spi.TypeConfiguration; -import org.hibernate.usertype.UserType; import org.jboss.jandex.IndexView; import org.jboss.logging.Logger; @@ -363,57 +360,7 @@ public class MetadataBuildingProcess { final ClassLoaderService classLoaderService = options.getServiceRegistry().getService( ClassLoaderService.class ); final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration(); - final TypeContributions typeContributions = new TypeContributions() { - @Override - public void contributeType(BasicType type) { - getBasicTypeRegistry().register( type ); - conditionallyRegisterJtd( type.getJavaTypeDescriptor() ); - } - - private void conditionallyRegisterJtd(JavaType jtd) { - final JavaTypeRegistry jtdRegistry = getTypeConfiguration().getJavaTypeRegistry(); - jtdRegistry.resolveDescriptor( jtd.getJavaTypeClass(), () -> jtd ); - } - - @Override - public void contributeType(BasicType type, String... keys) { - getBasicTypeRegistry().register( type, keys ); - conditionallyRegisterJtd( type.getJavaTypeDescriptor() ); - } - - @Override - public void contributeType(UserType type, String[] keys) { - contributeType( new CustomType( type, keys, getTypeConfiguration() ) ); - } - - @Override - public void contributeJavaType(JavaType descriptor) { - typeConfiguration.getJavaTypeRegistry().addDescriptor( descriptor ); - } - - @Override - public void contributeJdbcType(JdbcType descriptor) { - typeConfiguration.getJdbcTypeRegistry().addDescriptor( descriptor ); - } - - @Override - public void contributeType(UserType descriptor) { - typeConfiguration.getBasicTypeRegistry().register( - descriptor, - descriptor.returnedClass().getName() - ); - } - - @Override - public TypeConfiguration getTypeConfiguration() { - return typeConfiguration; - } - - final BasicTypeRegistry getBasicTypeRegistry() { - return getTypeConfiguration().getBasicTypeRegistry(); - } - - }; + final TypeContributions typeContributions = () -> typeConfiguration; // add Dialect contributed types final Dialect dialect = options.getServiceRegistry().getService( JdbcServices.class ).getDialect(); 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 67afa42f89..f419a4f870 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java @@ -55,7 +55,6 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHA 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.SqlTypes; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.ValueExtractor; @@ -65,6 +64,9 @@ import org.hibernate.type.descriptor.java.DoubleJavaType; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.*; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.internal.BasicTypeImpl; import java.io.*; @@ -81,6 +83,27 @@ import jakarta.persistence.TemporalType; import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.type.spi.TypeConfiguration; +import static org.hibernate.type.SqlTypes.BINARY; +import static org.hibernate.type.SqlTypes.BOOLEAN; +import static org.hibernate.type.SqlTypes.CHAR; +import static org.hibernate.type.SqlTypes.CLOB; +import static org.hibernate.type.SqlTypes.DECIMAL; +import static org.hibernate.type.SqlTypes.DOUBLE; +import static org.hibernate.type.SqlTypes.GEOMETRY; +import static org.hibernate.type.SqlTypes.LONG32NVARCHAR; +import static org.hibernate.type.SqlTypes.LONG32VARCHAR; +import static org.hibernate.type.SqlTypes.LONGNVARCHAR; +import static org.hibernate.type.SqlTypes.LONGVARCHAR; +import static org.hibernate.type.SqlTypes.NCHAR; +import static org.hibernate.type.SqlTypes.NCLOB; +import static org.hibernate.type.SqlTypes.NUMERIC; +import static org.hibernate.type.SqlTypes.NVARCHAR; +import static org.hibernate.type.SqlTypes.POINT; +import static org.hibernate.type.SqlTypes.TIMESTAMP; +import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; +import static org.hibernate.type.SqlTypes.TINYINT; +import static org.hibernate.type.SqlTypes.VARCHAR; + /** * An abstract base class for SAP HANA dialects. *

@@ -165,57 +188,77 @@ public abstract class AbstractHANADialect extends Dialect { }; public AbstractHANADialect(DatabaseVersion version) { - super(version); + super( version ); this.useUnicodeStringTypes = useUnicodeStringTypesDefault(); this.clobTypeDescriptor = new HANAClobJdbcType( MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE, useUnicodeStringTypesDefault() ); + } - // Note that 38 is the maximum precision HANA supports - registerColumnType( Types.DECIMAL, "decimal($p, $s)" ); - //there is no 'numeric' type in HANA - registerColumnType( Types.NUMERIC, "decimal($p, $s)" ); + @Override + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case BOOLEAN: + return useLegacyBooleanType ? "tinyint" : super.columnType( sqlTypeCode ); + case NUMERIC: + //there is no 'numeric' type in HANA + return columnType( DECIMAL ); + //'double precision' syntax not supported + case DOUBLE: + return "double"; + //no explicit precision + case TIMESTAMP: + case TIMESTAMP_WITH_TIMEZONE: + return "timestamp"; + //there is no 'char' or 'nchar' type in HANA + case CHAR: + case VARCHAR: + return isUseUnicodeStringTypes() ? columnType( NVARCHAR ) : super.columnType( VARCHAR ); + case NCHAR: + return columnType( NVARCHAR ); + case LONG32VARCHAR: + return isUseUnicodeStringTypes() ? columnType( LONG32NVARCHAR ) : super.columnType( LONG32VARCHAR ); + case LONGVARCHAR: + return isUseUnicodeStringTypes() ? columnType( LONGNVARCHAR ) : super.columnType( LONGVARCHAR ); + case CLOB: + return isUseUnicodeStringTypes() ? columnType( NCLOB ) : super.columnType( CLOB ); + // map tinyint to smallint since tinyint is unsigned on HANA + case TINYINT: + return "smallint"; + } + return super.columnType( sqlTypeCode ); + } - //'double precision' syntax not supported - registerColumnType( Types.DOUBLE, "double" ); + @Override + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class ); + if ( supportsAsciiStringTypes() ) { + this.useUnicodeStringTypes = configurationService.getSetting( + USE_UNICODE_STRING_TYPES_PARAMETER_NAME, + StandardConverters.BOOLEAN, + useUnicodeStringTypesDefault() + ); + } + this.useLegacyBooleanType = configurationService.getSetting( + USE_LEGACY_BOOLEAN_TYPE_PARAMETER_NAME, + StandardConverters.BOOLEAN, + USE_LEGACY_BOOLEAN_TYPE_DEFAULT_VALUE + ); - //no explicit precision - registerColumnType(Types.TIMESTAMP, "timestamp"); - registerColumnType(Types.TIMESTAMP_WITH_TIMEZONE, "timestamp"); + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); // varbinary max length 5000 - registerColumnType( Types.BINARY, 5000, "varbinary($l)" ); - registerColumnType( Types.VARBINARY, 5000, "varbinary($l)" ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( BINARY, "blob", this ) + .withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" ) + .build() + ); - // for longer values, map to blob - registerColumnType( Types.BINARY, "blob" ); - registerColumnType( Types.VARBINARY, "blob" ); - - //there is no 'char' or 'nchar' type in HANA - registerColumnType( Types.CHAR, "varchar($l)" ); - registerColumnType( Types.NCHAR, "nvarchar($l)" ); - - registerColumnType( Types.VARCHAR, 5000, "varchar($l)" ); - registerColumnType( Types.NVARCHAR, 5000, "nvarchar($l)" ); - - // for longer values map to clob/nclob - registerColumnType( Types.VARCHAR, "clob" ); - registerColumnType( Types.NVARCHAR, "nclob" ); - - // map tinyint to smallint since tinyint is unsigned on HANA - registerColumnType( Types.TINYINT, "smallint" ); - - registerHibernateType( Types.NCLOB, StandardBasicTypes.MATERIALIZED_NCLOB.getName() ); - registerHibernateType( Types.CLOB, StandardBasicTypes.MATERIALIZED_CLOB.getName() ); - registerHibernateType( Types.BLOB, StandardBasicTypes.MATERIALIZED_BLOB.getName() ); - registerHibernateType( Types.NVARCHAR, StandardBasicTypes.NSTRING.getName() ); - - registerColumnType( SqlTypes.GEOMETRY, "st_geometry" ); - registerColumnType( SqlTypes.POINT, "st_point" ); - - registerHanaKeywords(); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "st_geometry", this ) ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( POINT, "st_point", this ) ); } @Override @@ -516,7 +559,9 @@ public abstract class AbstractHANADialect extends Dialect { return false; } - protected void registerHanaKeywords() { + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); registerKeyword( "all" ); registerKeyword( "alter" ); registerKeyword( "as" ); @@ -888,43 +933,18 @@ public abstract class AbstractHANADialect extends Dialect { } if ( supportsAsciiStringTypes() ) { - this.useUnicodeStringTypes = configurationService.getSetting( - USE_UNICODE_STRING_TYPES_PARAMETER_NAME, - StandardConverters.BOOLEAN, - useUnicodeStringTypesDefault() - ); - - if ( this.isUseUnicodeStringTypes() ) { - registerColumnType( Types.CHAR, "nvarchar($l)" ); - registerColumnType( Types.VARCHAR, 5000, "nvarchar($l)" ); - - // for longer values map to clob/nclob - registerColumnType( Types.VARCHAR, "nclob" ); - registerColumnType( Types.CLOB, "nclob" ); - } - if ( this.clobTypeDescriptor.getMaxLobPrefetchSize() != maxLobPrefetchSize || this.clobTypeDescriptor.isUseUnicodeStringTypes() != this.useUnicodeStringTypes ) { this.clobTypeDescriptor = new HANAClobJdbcType( maxLobPrefetchSize, this.useUnicodeStringTypes ); } } - this.useLegacyBooleanType = configurationService.getSetting(USE_LEGACY_BOOLEAN_TYPE_PARAMETER_NAME, StandardConverters.BOOLEAN, - USE_LEGACY_BOOLEAN_TYPE_DEFAULT_VALUE); - - if ( this.useLegacyBooleanType ) { - registerColumnType( Types.BOOLEAN, "tinyint" ); - } - boolean treatDoubleTypedFieldsAsDecimal = configurationService.getSetting(TREAT_DOUBLE_TYPED_FIELDS_AS_DECIMAL_PARAMETER_NAME, StandardConverters.BOOLEAN, TREAT_DOUBLE_TYPED_FIELDS_AS_DECIMAL_DEFAULT_VALUE); final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration() .getJdbcTypeRegistry(); if (treatDoubleTypedFieldsAsDecimal) { - registerHibernateType( Types.FLOAT, StandardBasicTypes.BIG_DECIMAL.getName() ); - registerHibernateType( Types.REAL, StandardBasicTypes.BIG_DECIMAL.getName() ); - registerHibernateType( Types.DOUBLE, StandardBasicTypes.BIG_DECIMAL.getName() ); typeContributions.getTypeConfiguration().getBasicTypeRegistry() .register( new BasicTypeImpl<>( diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java index 5946ad2628..739962fe8b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractTransactSQLDialect.java @@ -59,13 +59,12 @@ public abstract class AbstractTransactSQLDialect extends Dialect { } @Override - protected String columnType(int jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { // note that 'real' is double precision on SQL Server, single precision on Sybase // but 'float' is single precision on Sybase, double precision on SQL Server - switch(jdbcTypeCode) { + switch ( sqlTypeCode ) { case BOOLEAN: return "bit"; - case TINYINT: //'tinyint' is an unsigned type in Sybase and //SQL Server, holding values in the range 0-255 @@ -74,21 +73,19 @@ public abstract class AbstractTransactSQLDialect extends Dialect { case INTEGER: //it's called 'int' not 'integer' return "int"; - case DATE: case TIME: - case TIMESTAMP: case TIME_WITH_TIMEZONE: + case TIMESTAMP: + case TIMESTAMP_WITH_TIMEZONE: return "datetime"; - case BLOB: return "image"; case CLOB: + case NCLOB: return "text"; - - default: - return super.columnType(jdbcTypeCode); } + return super.columnType( sqlTypeCode ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java index ea604aac45..9e4479059f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java @@ -9,15 +9,12 @@ package org.hibernate.dialect; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.time.temporal.TemporalAccessor; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.TimeZone; -import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.boot.model.TypeContributions; @@ -26,7 +23,6 @@ import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.OffsetFetchLimitHandler; import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport; -import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy; import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; @@ -46,12 +42,13 @@ import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.type.BasicType; import org.hibernate.type.BasicTypeRegistry; -import org.hibernate.type.SqlTypes; import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.UUIDJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.Scale6IntervalSecondDdlType; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import jakarta.persistence.TemporalType; @@ -95,56 +92,36 @@ public class CockroachDialect extends Dialect { } @Override - protected List getSupportedJdbcTypeCodes() { - List typeCodes = new ArrayList<>( super.getSupportedJdbcTypeCodes() ); - typeCodes.addAll( List.of(UUID, INTERVAL_SECOND, GEOMETRY, JSON) ); - if ( getVersion().isSameOrAfter( 20 ) ) { - typeCodes.add(INET); - } - return typeCodes; - } - - @Override - protected String columnType(int jdbcTypeCode) { - switch (jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case TINYINT: return "smallint"; //no tinyint - case CHAR: case NCHAR: case VARCHAR: case NVARCHAR: + case LONGVARCHAR: + case LONGNVARCHAR: return "string($l)"; - - case NCLOB: case CLOB: + case NCLOB: + case LONG32VARCHAR: + case LONG32NVARCHAR: return "string"; - case BINARY: case VARBINARY: + case LONGVARBINARY: + return "bytes($l)"; case BLOB: + case LONG32VARBINARY: return "bytes"; - - case INET: - return "inet"; - case UUID: - return "uuid"; - case GEOMETRY: - return "geometry"; - case INTERVAL_SECOND: - return "interval second($s)"; - - case JSON: - // Prefer jsonb if possible - return getVersion().isSameOrAfter( 20 ) ? "jsonb" : "json"; - default: - return super.columnType(jdbcTypeCode); } + return super.columnType( sqlTypeCode ); } @Override - public String getUnboundedTypeName(JdbcType jdbcType, JavaType javaType) { - switch ( jdbcType.getDefaultSqlTypeCode() ) { + protected String castType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case CHAR: case NCHAR: case VARCHAR: @@ -160,19 +137,26 @@ public class CockroachDialect extends Dialect { case LONG32VARBINARY: return "bytes"; } - return super.getUnboundedTypeName( jdbcType, javaType ); + return super.castType( sqlTypeCode ); } @Override - public String getTypeName(int code, Size size) throws HibernateException { - // The maximum scale for `interval second` is 6 unfortunately so we have to use numeric by default - if ( code == SqlTypes.INTERVAL_SECOND ) { - final Integer scale = size.getScale(); - if ( scale == null || scale > 6 ) { - return getTypeName( SqlTypes.NUMERIC, size ); - } + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( UUID, "uuid", this ) ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "geometry", this ) ); + ddlTypeRegistry.addDescriptor( new Scale6IntervalSecondDdlType( this ) ); + + // Prefer jsonb if possible + if ( getVersion().isSameOrAfter( 20 ) ) { + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( INET, "inet", this ) ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "jsonb", this ) ); + } + else { + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "json", this ) ); } - return super.getTypeName( code, size ); } @Override 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 f83c73279e..a8d1788937 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -55,6 +55,9 @@ import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; import org.hibernate.type.descriptor.jdbc.*; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; +import org.hibernate.type.spi.TypeConfiguration; import java.sql.CallableStatement; import java.sql.DatabaseMetaData; @@ -92,16 +95,16 @@ public class DB2Dialect extends Dialect { } public DB2Dialect(DialectResolutionInfo info) { - super(info); - registerDB2Keywords(); + super( info ); } public DB2Dialect(DatabaseVersion version) { - super(version); - registerDB2Keywords(); + super( version ); } - private void registerDB2Keywords() { + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); //not keywords, at least not in DB2 11, //but perhaps they were in older versions? registerKeyword( "current" ); @@ -127,27 +130,19 @@ public class DB2Dialect extends Dialect { } @Override - protected String columnType(int jdbcTypeCode) { - if ( getDB2Version().isBefore( 11 ) ) { - switch (jdbcTypeCode) { - case BOOLEAN: - // prior to DB2 11, the 'boolean' type existed, - // but was not allowed as a column type - return "smallint"; - case BINARY: // should use 'binary' since version 11 - case VARBINARY: // should use 'varbinary' since version 11 - return "varchar($l) for bit data"; - } - } - - switch (jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case BOOLEAN: + // prior to DB2 11, the 'boolean' type existed, + // but was not allowed as a column type + return getDB2Version().isBefore( 11 ) ? "smallint" : super.columnType( sqlTypeCode ); case TINYINT: // no tinyint return "smallint"; case NUMERIC: // HHH-12827: map them both to the same type to avoid problems with schema update // Note that 31 is the maximum precision DB2 supports - return super.columnType(DECIMAL); + return columnType( DECIMAL ); case BLOB: return "blob($l)"; case CLOB: @@ -156,18 +151,25 @@ public class DB2Dialect extends Dialect { return "timestamp($p)"; case TIME_WITH_TIMEZONE: return "time"; - default: - return super.columnType(jdbcTypeCode); + case VARBINARY: + // should use 'varbinary' since version 11 + return getDB2Version().isBefore( 11 ) ? "varchar($l) for bit data" : super.columnType( sqlTypeCode ); } + return super.columnType( sqlTypeCode ); } @Override - protected void registerDefaultColumnTypes() { - // Note: the 'long varchar' data type was deprecated in DB2 and shouldn't be used anymore - super.registerDefaultColumnTypes(); + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + if ( getDB2Version().isBefore( 11 ) ) { // should use 'binary' since version 11 - registerColumnType( BINARY, 254, "char($l) for bit data" ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( BINARY, "varchar($l) for bit data", this ) + .withTypeCapacity( 254, "char($l) for bit data" ) + .build() + ); } } @@ -272,14 +274,15 @@ public class DB2Dialect extends Dialect { queryEngine.getTypeConfiguration(), SqlAstNodeRenderingMode.DEFAULT, "||", - getCastTypeName( - queryEngine.getTypeConfiguration() - .getBasicTypeRegistry() - .resolve( StandardBasicTypes.STRING ), - null, - null, - null - ), + queryEngine.getTypeConfiguration().getDdlTypeRegistry().getDescriptor( VARCHAR ) + .getCastTypeName( + queryEngine.getTypeConfiguration() + .getBasicTypeRegistry() + .resolve( StandardBasicTypes.STRING ), + null, + null, + null + ), true ) ); @@ -499,7 +502,7 @@ public class DB2Dialect extends Dialect { } @Override - public String getSelectClauseNullString(int sqlType) { + public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { return selectNullString(sqlType); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2iDialect.java index 4c7568c157..5174664194 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2iDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2iDialect.java @@ -42,6 +42,14 @@ public class DB2iDialect extends DB2Dialect { registerKeywords( info ); } + public DB2iDialect() { + this( DatabaseVersion.make(7) ); + } + + public DB2iDialect(DatabaseVersion version) { + super(version); + } + @Override public void initializeFunctionRegistry(QueryEngine queryEngine) { super.initializeFunctionRegistry( queryEngine ); @@ -53,14 +61,6 @@ public class DB2iDialect extends DB2Dialect { } } - public DB2iDialect() { - this( DatabaseVersion.make(7) ); - } - - public DB2iDialect(DatabaseVersion version) { - super(version); - } - @Override public DatabaseVersion getDB2Version() { return DB2_LUW_VERSION9; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java index 1f3c650770..4134453fdb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java @@ -65,12 +65,12 @@ public class DB2zDialect extends DB2Dialect { } @Override - protected String columnType(int jdbcTypeCode) { - // See https://www.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/wnew/src/tpc/db2z_10_timestamptimezone.html - if ( jdbcTypeCode==TIMESTAMP_WITH_TIMEZONE && getVersion().isAfter(10) ) { + protected String columnType(int sqlTypeCode) { + if ( sqlTypeCode == TIMESTAMP_WITH_TIMEZONE && getVersion().isAfter( 10 ) ) { + // See https://www.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/wnew/src/tpc/db2z_10_timestamptimezone.html return "timestamp with time zone"; } - return super.columnType(jdbcTypeCode); + return super.columnType( sqlTypeCode ); } @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 10a61b9110..5a35288cbe 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java @@ -6,7 +6,6 @@ */ package org.hibernate.dialect; -import org.hibernate.HibernateException; import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.boot.model.TypeContributions; import org.hibernate.dialect.function.CastingConcatFunction; @@ -23,7 +22,6 @@ import org.hibernate.dialect.pagination.DerbyLimitHandler; import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.sequence.DerbySequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport; -import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder; @@ -66,6 +64,9 @@ import org.hibernate.type.descriptor.jdbc.ObjectNullResolvingJdbcType; import org.hibernate.type.descriptor.jdbc.SmallIntJdbcType; import org.hibernate.type.descriptor.jdbc.TimestampJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; +import org.hibernate.type.spi.TypeConfiguration; import java.sql.DatabaseMetaData; import java.sql.SQLException; @@ -105,60 +106,100 @@ public class DerbyDialect extends Dialect { public DerbyDialect(DatabaseVersion version) { super(version); - registerDerbyKeywords(); } public DerbyDialect(DialectResolutionInfo info) { super(info); - registerDerbyKeywords(); } @Override - protected String columnType(int jdbcTypeCode) { - if ( jdbcTypeCode == BOOLEAN && getVersion().isBefore( 10, 7 ) ) { - return "smallint"; - } - - switch (jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case BOOLEAN: + return getVersion().isBefore( 10, 7 ) ? "smallint" : super.columnType( sqlTypeCode ); case TINYINT: //no tinyint return "smallint"; - case NUMERIC: // HHH-12827: map them both to the same type to avoid problems with schema update // Note that 31 is the maximum precision Derby supports - return super.columnType(DECIMAL); - + return columnType( DECIMAL ); case VARBINARY: return "varchar($l) for bit data"; - + case LONGVARBINARY: + case LONG32VARBINARY: + return "long varchar for bit data"; + case NCHAR: + return columnType( CHAR ); + case NVARCHAR: + return columnType( VARCHAR ); + case LONGNVARCHAR: + return columnType( LONGVARCHAR ); + case LONGVARCHAR: + case LONG32VARCHAR: + return "long varchar"; case BLOB: return "blob($l)"; case CLOB: + case NCLOB: return "clob($l)"; - case TIMESTAMP: case TIMESTAMP_WITH_TIMEZONE: return "timestamp"; - - default: - return super.columnType(jdbcTypeCode); } + return super.columnType( sqlTypeCode ); } @Override - protected void registerDefaultColumnTypes() { - super.registerDefaultColumnTypes(); + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); //long varchar is the right type to use for lengths between 32_672 and 32_700 int maxLongVarcharLength = 32_700; - registerColumnType( VARBINARY, maxLongVarcharLength,"long varchar for bit data" ); - registerColumnType( VARCHAR, maxLongVarcharLength, "long varchar" ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( VARBINARY, columnType( BLOB ), columnType( VARBINARY ), this ) + .withTypeCapacity( getMaxVarbinaryLength(), columnType( VARBINARY ) ) + .withTypeCapacity( maxLongVarcharLength, columnType( LONGVARBINARY ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( VARCHAR, columnType( CLOB ), columnType( VARCHAR ), this ) + .withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) ) + .withTypeCapacity( maxLongVarcharLength, columnType( LONGVARCHAR ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( NVARCHAR, columnType( CLOB ), columnType( NVARCHAR ), this ) + .withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) ) + .withTypeCapacity( maxLongVarcharLength, columnType( LONGVARCHAR ) ) + .build() + ); - registerColumnType( BINARY, 254, "char($l) for bit data" ); - registerColumnType( BINARY, getMaxVarcharLength(), "varchar($l) for bit data" ); - registerColumnType( BINARY, maxLongVarcharLength, "long varchar for bit data" ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( BINARY, columnType( BLOB ), columnType( VARBINARY ), this ) + .withTypeCapacity( 254, "char($l) for bit data" ) + .withTypeCapacity( getMaxVarbinaryLength(), columnType( VARBINARY ) ) + .withTypeCapacity( maxLongVarcharLength, columnType( LONGVARBINARY ) ) + .build() + ); + + // This is the maximum size for the CHAR datatype on Derby + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( CHAR, columnType( CLOB ), columnType( CHAR ), this ) + .withTypeCapacity( 254, columnType( CHAR ) ) + .withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) ) + .withTypeCapacity( maxLongVarcharLength, columnType( LONGVARCHAR ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( NCHAR, columnType( CLOB ), columnType( NCHAR ), this ) + .withTypeCapacity( 254, columnType( NCHAR ) ) + .withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) ) + .withTypeCapacity( maxLongVarcharLength, columnType( LONGNVARCHAR ) ) + .build() + ); } @Override @@ -166,17 +207,6 @@ public class DerbyDialect extends Dialect { return 32_672; } - @Override - public String getTypeName(int code, Size size) throws HibernateException { - if ( code == Types.CHAR ) { - // This is the maximum size for the CHAR datatype on Derby - if ( size.getLength() > 254 ) { - return "char(254)"; - } - } - return super.getTypeName( code, size ); - } - @Override public int getDefaultDecimalPrecision() { //this is the maximum allowed in Derby @@ -228,7 +258,8 @@ public class DerbyDialect extends Dialect { queryEngine.getTypeConfiguration(), SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER, "||", - getCastTypeName( stringType, null, null, null ), + queryEngine.getTypeConfiguration().getDdlTypeRegistry().getDescriptor( VARCHAR ) + .getCastTypeName( stringType, null, null, null ), true ) ); @@ -370,6 +401,15 @@ public class DerbyDialect extends Dialect { case LONG: case FIXED: return "cast(trim(cast(?1 as char(254))) as ?2)"; + case DATE: + // The maximum length of a date + return "cast(?1 as varchar(10))"; + case TIME: + // The maximum length of a time + return "cast(?1 as varchar(8))"; + case TIMESTAMP: + // The maximum length of a timestamp + return "cast(?1 as varchar(30))"; } break; } @@ -435,7 +475,7 @@ public class DerbyDialect extends Dialect { } @Override - public String getSelectClauseNullString(int sqlType) { + public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { return DB2Dialect.selectNullString( sqlType ); } @@ -597,7 +637,9 @@ public class DerbyDialect extends Dialect { throw new NotYetImplementedFor6Exception("format() function not supported on Derby"); } - private void registerDerbyKeywords() { + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); registerKeyword( "ADD" ); registerKeyword( "ALL" ); registerKeyword( "ALLOCATE" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index 272f7f829e..decfbf8432 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -36,10 +36,8 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TimeZone; -import java.util.UUID; import java.util.regex.Pattern; -import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.NotYetImplementedFor6Exception; @@ -108,8 +106,6 @@ import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.Index; import org.hibernate.mapping.Table; import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.metamodel.mapping.JdbcMapping; -import org.hibernate.metamodel.mapping.SqlExpressible; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.persister.entity.Lockable; import org.hibernate.procedure.internal.StandardCallableStatementSupport; @@ -150,7 +146,6 @@ import org.hibernate.type.BasicType; import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.SqlTypes; import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.Type; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; import org.hibernate.type.descriptor.jdbc.ClobJdbcType; @@ -160,6 +155,9 @@ import org.hibernate.type.descriptor.jdbc.NCharJdbcType; import org.hibernate.type.descriptor.jdbc.NClobJdbcType; import org.hibernate.type.descriptor.jdbc.NVarcharJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; import jakarta.persistence.TemporalType; @@ -189,8 +187,8 @@ import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithM *

* Almost every subclass must, as a bare minimum, override at least: *

    - *
  • {@link #columnType(int)} to define a mapping from JDBC - * {@linkplain Types type codes} to database column types, and + *
  • {@link #registerColumnTypes(TypeContributions, ServiceRegistry)} to define a mapping from SQL + * {@linkplain SqlTypes type codes} to database column types, and *
  • {@link #initializeFunctionRegistry(QueryEngine)} to register * mappings for standard HQL functions with the * {@link org.hibernate.query.sqm.function.SqmFunctionRegistry}. @@ -233,10 +231,7 @@ public abstract class Dialect implements ConversionContext { private static final Pattern ESCAPE_OPENING_COMMENT_PATTERN = Pattern.compile( "/\\*" ); //needed for converting precision from decimal to binary digits - private static final double LOG_BASE2OF10 = log(10)/log(2); - - private final TypeNames typeNames = new TypeNames(); - private final TypeNames hibernateTypeNames = new TypeNames(); + protected static final double LOG_BASE2OF10 = log(10)/log(2); private final Properties properties = new Properties(); private final Set sqlKeywords = new HashSet<>(); @@ -259,18 +254,12 @@ public abstract class Dialect implements ConversionContext { protected Dialect(DatabaseVersion version) { this.version = version; - beforeRegisteringColumnTypes(version); - registerDefaultColumnTypes(); - registerHibernateTypes(); registerDefaultKeywords(); initDefaultProperties(); } protected Dialect(DialectResolutionInfo info) { this.version = info.makeCopy(); - beforeRegisteringColumnTypes(info); - registerDefaultColumnTypes(); - registerHibernateTypes(); registerDefaultKeywords(); registerKeywords(info); initDefaultProperties(); @@ -288,23 +277,6 @@ public abstract class Dialect implements ConversionContext { Boolean.toString( getDefaultUseGetGeneratedKeys() ) ); } - /** - * Called right before {@link #registerDefaultColumnTypes()}, allowing - * the subclass to do something with the {@link DialectResolutionInfo}. - *

    - * Take care when overriding this method: it's only called when the - * {@code Dialect} is constructed using {@code Dialect(DialectResolutionInfo)}. - */ - protected void beforeRegisteringColumnTypes(DialectResolutionInfo info) {} - - /** - * Called right before {@link #registerDefaultColumnTypes()}. - *

    - * Take care when overriding this method: it's only called when the - * {@code Dialect} is constructed using {@code Dialect(DatabaseVersion)}. - */ - protected void beforeRegisteringColumnTypes(DatabaseVersion version) {} - /** * Register ANSI-standard column types using the length limits defined * by {@link #getMaxVarcharLength()}, {@link #getMaxNVarcharLength()}, @@ -312,102 +284,85 @@ public abstract class Dialect implements ConversionContext { *

    * This method is always called when a {@code Dialect} is instantiated. */ - protected void registerDefaultColumnTypes() { - registerDefaultColumnTypes( getMaxVarcharLength(), getMaxNVarcharLength(), getMaxVarbinaryLength() ); + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + + ddlTypeRegistry.addDescriptor( simpleSqlType( BOOLEAN ) ); + + ddlTypeRegistry.addDescriptor( simpleSqlType( TINYINT ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( SMALLINT ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( INTEGER ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( BIGINT ) ); + + ddlTypeRegistry.addDescriptor( simpleSqlType( FLOAT ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( REAL ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( DOUBLE ) ); + + ddlTypeRegistry.addDescriptor( simpleSqlType( NUMERIC ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( DECIMAL ) ); + + ddlTypeRegistry.addDescriptor( simpleSqlType( DATE ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( TIME ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( TIME_WITH_TIMEZONE ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( TIMESTAMP ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( TIMESTAMP_WITH_TIMEZONE ) ); + + ddlTypeRegistry.addDescriptor( simpleSqlType( CHAR ) ); + ddlTypeRegistry.addDescriptor( + sqlTypeBuilder( VARCHAR, LONGVARCHAR, VARCHAR ) + .withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( + sqlTypeBuilder( LONGVARCHAR, LONGVARCHAR, VARCHAR ) + .withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( simpleSqlType( CLOB ) ); + + ddlTypeRegistry.addDescriptor( simpleSqlType( NCHAR ) ); + ddlTypeRegistry.addDescriptor( + sqlTypeBuilder( NVARCHAR, LONGNVARCHAR, NVARCHAR ) + .withTypeCapacity( getMaxNVarcharLength(), columnType( NVARCHAR ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( + sqlTypeBuilder( LONGNVARCHAR, LONGNVARCHAR, NVARCHAR ) + .withTypeCapacity( getMaxNVarcharLength(), columnType( NVARCHAR ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( simpleSqlType( NCLOB ) ); + + ddlTypeRegistry.addDescriptor( simpleSqlType( BINARY ) ); + ddlTypeRegistry.addDescriptor( + sqlTypeBuilder( VARBINARY, LONGVARBINARY, VARBINARY ) + .withTypeCapacity( getMaxVarbinaryLength(), columnType( VARBINARY ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( + sqlTypeBuilder( LONGVARBINARY, LONGVARBINARY, VARBINARY ) + .withTypeCapacity( getMaxVarbinaryLength(), columnType( VARBINARY ) ) + .build() + ); + ddlTypeRegistry.addDescriptor( simpleSqlType( BLOB ) ); + + // by default use the LOB mappings for the "long" types + ddlTypeRegistry.addDescriptor( simpleSqlType( LONG32VARCHAR ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( LONG32NVARCHAR ) ); + ddlTypeRegistry.addDescriptor( simpleSqlType( LONG32VARBINARY ) ); } - /** - * Register an ANSI-standard column type for each JDBC type defined - * by {@link Types}. These mappings may be overridden by a concrete - * {@code Dialect} by calling {@link #registerColumnType(int,String)} - * from the constructor. - *

    - * The "long" types {@link Types#LONGVARCHAR}, {@link Types#LONGNVARCHAR} - * and {@link Types#LONGVARBINARY} are considered synonyms for their - * non-{@code LONG} counterparts, with the only difference being that - * a different default length is used: {@link org.hibernate.Length#LONG} - * instead of {@link org.hibernate.Length#DEFAULT}. - *

    - * This method is aware of the notion of a maximum length for each of - * the types {@link Types#VARCHAR}, {@link Types#NVARCHAR}, and - * {@link Types#VARBINARY}, usually the limits defined by - * {@link #getMaxVarcharLength()}, {@link #getMaxNVarcharLength()}, - * and {@link #getMaxVarbinaryLength()}, and registers "long32" types, - * that is, {@link org.hibernate.Length#LONG32} types, for lengths - * exceeding the limits. - *

    - * Any registrations made by this method may be overridden by calling - * {@link #registerColumnType(int, String)} explicitly. Alternatively, - * the registrations may be customized by overriding - * {@link #getSupportedJdbcTypeCodes()} and {@link #columnType(int)}. - * - * @param maxVarcharLength the maximum length of the {@link Types#VARCHAR} type - * @param maxNVarcharLength the maximum length of the {@link Types#NVARCHAR} type - * @param maxVarBinaryLength the maximum length of the {@link Types#VARBINARY} type - */ - protected void registerDefaultColumnTypes(int maxVarcharLength, int maxNVarcharLength, int maxVarBinaryLength) { - for ( int typeCode : getSupportedJdbcTypeCodes() ) { - switch (typeCode) { - case VARCHAR: - registerColumnType( typeCode, maxVarcharLength, columnType(typeCode) ); - // we look up the "long" type under the code LONG32VARCHAR - // which by default returns the CLOB type - registerColumnType( typeCode, columnType(LONG32VARCHAR) ); - break; - case NVARCHAR: - registerColumnType( typeCode, maxNVarcharLength, columnType(typeCode) ); - // we look up the "long" type under the code LONG32NVARCHAR - // which by default returns the NCLOB type - registerColumnType( typeCode, columnType(LONG32NVARCHAR) ); - break; - case VARBINARY: - registerColumnType( typeCode, maxVarBinaryLength, columnType(typeCode) ); - // we look up the "long" type under the code LONG32VARBINARY - // which by default returns the BLOB type - registerColumnType( typeCode, columnType(LONG32VARBINARY) ); - break; - default: - registerColumnType( typeCode, columnType(typeCode) ); - } - } + private DdlTypeImpl simpleSqlType(int sqlTypeCode) { + return new DdlTypeImpl( sqlTypeCode, columnType( sqlTypeCode ), castType( sqlTypeCode ), this ); } - /** - * A list of JDBC types that we expect to be supported on all databases. - */ - private static final List ANSI_SQL_TYPES = List.of( - BOOLEAN, - TINYINT, SMALLINT, INTEGER, BIGINT, - REAL, FLOAT, DOUBLE, - NUMERIC, DECIMAL, - DATE, - TIME, TIME_WITH_TIMEZONE, - TIMESTAMP, TIMESTAMP_WITH_TIMEZONE, - CHAR, VARCHAR, CLOB, - NCHAR, NVARCHAR, NCLOB, - BINARY, VARBINARY, BLOB - ); - - /** - * The JDBC type codes of types supported by this SQL dialect, from the lists - * defined by {@link Types} and {@link SqlTypes}. - *

    - * This method may be overridden by concrete {@code Dialect}s as an alternative - * to calling {@link #registerColumnType(int, String)}. In this case, - * {@link #columnType(int)} should also be overridden. - *

    - * Note that {@link Types#LONGVARCHAR}, {@link Types#LONGNVARCHAR} and - * {@link Types#LONGVARBINARY} are considered synonyms for their - * non-{@code LONG} counterparts, and should not be included in the returned - * array. - * - * @return an array of types from {@link SqlTypes} - * - * @see SqlTypes - * @see #columnType(int) - */ - protected List getSupportedJdbcTypeCodes() { - return ANSI_SQL_TYPES; + private CapacityDependentDdlType.Builder sqlTypeBuilder(int sqlTypeCode, int biggestSqlTypeCode, int castTypeCode) { + return CapacityDependentDdlType.builder( + sqlTypeCode, + columnType( biggestSqlTypeCode ), + castType( castTypeCode ), + this + ); } /** @@ -416,16 +371,15 @@ public abstract class Dialect implements ConversionContext { * name. *

    * This method may be overridden by concrete {@code Dialect}s as an alternative - * to calling {@link #registerColumnType(int,String)}. + * to {@link #registerColumnTypes(TypeContributions, ServiceRegistry)} for simple registrations. * - * @param jdbcTypeCode a JDBC type code + * @param sqlTypeCode a SQL type code * @return a column type name, with $l, $p, $s placeholders for length, precision, scale * * @see SqlTypes - * @see #getSupportedJdbcTypeCodes() */ - protected String columnType(int jdbcTypeCode) { - switch (jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case BOOLEAN: return "boolean"; @@ -494,57 +448,23 @@ public abstract class Dialect implements ConversionContext { return "blob"; // by default use the LOB mappings for the "long" types + case LONGVARCHAR: case LONG32VARCHAR: - return columnType(CLOB); + return columnType( CLOB ); + case LONGNVARCHAR: case LONG32NVARCHAR: - return columnType(NCLOB); + return columnType( NCLOB ); + case LONGVARBINARY: case LONG32VARBINARY: - return columnType(BLOB); + return columnType( BLOB ); default: - throw new IllegalArgumentException("unknown type: " + jdbcTypeCode); + throw new IllegalArgumentException( "unknown type: " + sqlTypeCode ); } } - protected void registerHibernateTypes() { - // register hibernate types for default use in scalar sqlquery type auto detection - registerHibernateType( Types.BOOLEAN, StandardBasicTypes.BOOLEAN.getName() ); - - registerHibernateType( Types.BIT, 64, StandardBasicTypes.LONG.getName() ); - registerHibernateType( Types.BIT, 32, StandardBasicTypes.INTEGER.getName() ); - registerHibernateType( Types.BIT, 16, StandardBasicTypes.SHORT.getName() ); - registerHibernateType( Types.BIT, 8, StandardBasicTypes.BYTE.getName() ); - registerHibernateType( Types.BIT, 1, StandardBasicTypes.BOOLEAN.getName() ); - - registerHibernateType( Types.REAL, StandardBasicTypes.FLOAT.getName() ); - registerHibernateType( Types.DOUBLE, StandardBasicTypes.DOUBLE.getName() ); - registerHibernateType( Types.FLOAT, StandardBasicTypes.DOUBLE.getName() ); - registerHibernateType( Types.NUMERIC, StandardBasicTypes.BIG_DECIMAL.getName() ); - registerHibernateType( Types.DECIMAL, StandardBasicTypes.BIG_DECIMAL.getName() ); - - registerHibernateType( Types.BIGINT, StandardBasicTypes.LONG.getName() ); - registerHibernateType( Types.INTEGER, StandardBasicTypes.INTEGER.getName() ); - registerHibernateType( Types.SMALLINT, StandardBasicTypes.SHORT.getName() ); - registerHibernateType( Types.TINYINT, StandardBasicTypes.BYTE.getName() ); - - registerHibernateType( Types.CHAR, 1, StandardBasicTypes.CHARACTER.getName() ); - registerHibernateType( Types.CHAR, StandardBasicTypes.STRING.getName() ); - registerHibernateType( Types.VARCHAR, 1, StandardBasicTypes.CHARACTER.getName() ); - registerHibernateType( Types.VARCHAR, StandardBasicTypes.STRING.getName() ); - registerHibernateType( Types.NVARCHAR, StandardBasicTypes.NSTRING.getName() ); - registerHibernateType( Types.LONGVARCHAR, StandardBasicTypes.TEXT.getName() ); - registerHibernateType( Types.LONGNVARCHAR, StandardBasicTypes.NTEXT.getName() ); - - registerHibernateType( Types.BINARY, StandardBasicTypes.BINARY.getName() ); - registerHibernateType( Types.VARBINARY, StandardBasicTypes.BINARY.getName() ); - registerHibernateType( Types.LONGVARBINARY, StandardBasicTypes.IMAGE.getName() ); - - registerHibernateType( Types.BLOB, StandardBasicTypes.BLOB.getName() ); - registerHibernateType( Types.CLOB, StandardBasicTypes.CLOB.getName() ); - - registerHibernateType( Types.DATE, StandardBasicTypes.DATE.getName() ); - registerHibernateType( Types.TIME, StandardBasicTypes.TIME.getName() ); - registerHibernateType( Types.TIMESTAMP, StandardBasicTypes.TIMESTAMP.getName() ); + protected String castType(int sqlTypeCode) { + return columnType( sqlTypeCode ); } protected void registerDefaultKeywords() { @@ -588,19 +508,6 @@ public abstract class Dialect implements ConversionContext { } } - /** - * Useful conversion for databases which represent the - * precision of a float(p) using p expressed in decimal - * digits instead of the usual (standard) binary digits. - */ - protected static Size binaryToDecimalPrecision(int code, Size size) { - return code == Types.FLOAT - && size != null - && size.getPrecision() != null - ? Size.precision( (int) Math.ceil( size.getPrecision() / LOG_BASE2OF10 ) ) - : size; - } - /** * Render a SQL check condition for a column that represents a boolean value. */ @@ -1337,7 +1244,7 @@ public abstract class Dialect implements ConversionContext { */ public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { // by default, not much to do... - + registerColumnTypes( typeContributions, serviceRegistry ); final NationalizationSupport nationalizationSupport = getNationalizationSupport(); if ( nationalizationSupport == NationalizationSupport.EXPLICIT ) { typeContributions.contributeJdbcType( NCharJdbcType.INSTANCE ); @@ -1354,183 +1261,6 @@ public abstract class Dialect implements ConversionContext { } } - /** - * Get the name of the database type associated with the given - * {@link SqlTypes} typecode, with no length, precision, - * or scale. - * - * @param code The {@link SqlTypes} typecode - * @return the database type name - * @throws HibernateException If no mapping was specified for that type. - */ - public String getRawTypeName(int code) throws HibernateException { - final String result = typeNames.get( code ); - if ( result == null ) { - throw new HibernateException( "No default type mapping for (org.hibernate.type.SqlTypes) " + code ); - } - //trim off the length/precision/scale - final int paren = result.indexOf('('); - return paren>0 ? result.substring(0, paren) : result; - } - - public String getRawTypeName(JdbcType jdbcType) throws HibernateException { - return getRawTypeName( jdbcType.getDefaultSqlTypeCode() ); - } - - public String getTypeName(JdbcType jdbcType) throws HibernateException { - return getTypeName( jdbcType.getDefaultSqlTypeCode() ); - } - - public String getTypeName(int code) throws HibernateException { - // explicitly enforce dialect's default precisions - switch ( code ) { - case Types.DECIMAL: - case Types.NUMERIC: - return getTypeName( code, Size.precision( getDefaultDecimalPrecision() ) ); - case Types.FLOAT: - case Types.REAL: - return getTypeName( code, Size.precision( getFloatPrecision() ) ); - case Types.DOUBLE: - return getTypeName( code, Size.precision( getDoublePrecision() ) ); - case Types.TIMESTAMP: - case Types.TIMESTAMP_WITH_TIMEZONE: - return getTypeName( code, Size.precision( getDefaultTimestampPrecision() ) ); - default: - return getTypeName( code, Size.nil() ); - } - } - - /** - * Get the name of the database type associated with the given - * {@code org.hibernate.type.SqlTypes} typecode. - * - * @param code {@code org.hibernate.type.SqlTypes} typecode - * @param size the length, precision, scale of the column - * - * @return the database type name - * - */ - public String getTypeName(int code, Size size) throws HibernateException { - String result = typeNames.get( code, size.getLength(), size.getPrecision(), size.getScale() ); - if ( result == null ) { - switch ( code ) { - // these are no longer considered separate column types as such - // they're just used to indicate that JavaType.getLongSqlLength() - // should be used by default (and that's already handled by the - // time we get to here) - case Types.LONGVARCHAR: - return getTypeName( Types.VARCHAR, size ); - case Types.LONGNVARCHAR: - return getTypeName( Types.NVARCHAR, size ); - case Types.LONGVARBINARY: - return getTypeName( Types.VARBINARY, size ); - } - throw new HibernateException( - String.format( - "No type mapping for java.sql.Types code: %s, length: %s", - code, - size.getLength() - ) - ); - } - return result; - } - - /** - * Get the name of the database type associated with the given - * {@code SqlTypeDescriptor}. - * - * @param jdbcType the SQL type - * @param size the length, precision, scale of the column - * - * @return the database type name - * - */ - public String getTypeName(JdbcType jdbcType, Size size) { - return getTypeName( jdbcType.getDefaultSqlTypeCode(), size ); - } - - /** - * Get the name of the database type appropriate for casting operations - * (via the CAST() SQL function) for the given {@link SqlExpressible} - * SQL type. - * - * @return The database type name - */ - public String getCastTypeName(SqlExpressible type, Long length, Integer precision, Integer scale) { - final JdbcMapping jdbcMapping = type.getJdbcMapping(); - final JdbcType jdbcType = jdbcMapping.getJdbcType(); - final JavaType javaType = jdbcMapping.getJavaTypeDescriptor(); - Size size; - if ( length == null && precision == null ) { - return getUnboundedTypeName( jdbcType, javaType ); - } - else { - //use the given length/precision/scale - if ( precision != null && scale == null ) { - //needed for cast(x as BigInteger(p)) - scale = javaType.getDefaultSqlScale( Dialect.this, jdbcType ); - } - size = new Size() - .setLength( length ) - .setPrecision( precision ) - .setScale( scale ); - } - - return getTypeName( jdbcType, size ); - } - - public String getUnboundedTypeName(JdbcType jdbcType, JavaType javaType) { - Long length = null; - Integer precision = null; - Integer scale = null; - switch ( jdbcType.getDefaultSqlTypeCode() ) { - case VARCHAR: - length = (long) getMaxVarcharLength(); - break; - case NVARCHAR: - length = (long) getMaxNVarcharLength(); - break; - case VARBINARY: - length = (long) getMaxVarbinaryLength(); - break; - } - return getTypeName( - jdbcType, - getSizeStrategy().resolveSize( - jdbcType, - javaType, - precision, - scale, - length - ) - ); - } - - /** - * Subclasses register a type name for the given type code and maximum - * column length. {@code $l} in the type name with be replaced by the - * column length (if appropriate). - * - * @param code The {@link Types} typecode - * @param capacity The maximum length of database type - * @param name The database type name - */ - protected void registerColumnType(int code, long capacity, String name) { - typeNames.put( code, capacity, name ); - } - - /** - * Subclasses register a type name for the given type code. {@code $l} in - * the type name with be replaced by the column length (if appropriate). - * - * @param code The {@link Types} typecode - * @param name The database type name - */ - protected void registerColumnType(int code, String name) { - typeNames.put( code, name ); - } - /** * The legacy behavior of Hibernate. LOBs are not processed by merge */ @@ -1679,87 +1409,6 @@ public abstract class Dialect implements ConversionContext { } - // hibernate type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - /** - * Get the name of the Hibernate {@link Type} associated with the given - * {@link Types} type code. - * - * @param code The {@link Types} type code - * @return The Hibernate {@link Type} name. - * @throws HibernateException If no mapping was specified for that type. - */ - @SuppressWarnings("UnusedDeclaration") - public String getHibernateTypeName(int code) throws HibernateException { - final String result = hibernateTypeNames.get( code ); - if ( result == null ) { - throw new HibernateException( "No Hibernate type mapping for java.sql.Types code: " + code ); - } - return result; - } - - /** - * Whether or not the given type name has been registered for this dialect (including both hibernate type names and - * custom-registered type names). - * - * @param typeName the type name. - * - * @return true if the given string has been registered either as a hibernate type or as a custom-registered one - */ - public boolean isTypeNameRegistered(final String typeName) { - return this.typeNames.containsTypeName( typeName ); - } - - /** - * Get the name of the Hibernate {@link Type} associated - * with the given {@link Types} typecode with the given storage - * specification parameters. - * - * @param code The {@link Types} typecode - * @param length The datatype length - * @param precision The datatype precision - * @param scale The datatype scale - * @return The Hibernate {@link Type} name. - * @throws HibernateException If no mapping was specified for that type. - */ - public String getHibernateTypeName(int code, Integer length, Integer precision, Integer scale) throws HibernateException { - final String result = hibernateTypeNames.get( code, length.longValue(), precision, scale ); - if ( result == null ) { - throw new HibernateException( - String.format( - "No Hibernate type mapping for type [code=%s, length=%s]", - code, - length - ) - ); - } - return result; - } - - /** - * Registers a Hibernate {@link Type} name for the given - * {@link Types} type code and maximum column length. - * - * @param code The {@link Types} typecode - * @param capacity The maximum length of database type - * @param name The Hibernate {@link Type} name - */ - protected void registerHibernateType(int code, long capacity, String name) { - hibernateTypeNames.put( code, capacity, name ); - } - - /** - * Registers a Hibernate {@link Type} name for the given - * {@link Types} type code. - * - * @param code The {@link Types} typecode - * @param name The Hibernate {@link Type} name - */ - protected void registerHibernateType(int code, String name) { - hibernateTypeNames.put( code, name ); - } - - // native identifier generation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** @@ -2383,9 +2032,10 @@ public abstract class Dialect implements ConversionContext { * will be part of a UNION/UNION ALL. * * @param sqlType The {@link Types} type code. + * @param typeConfiguration The type configuration * @return The appropriate select clause value fragment. */ - public String getSelectClauseNullString(int sqlType) { + public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { return "null"; } @@ -3998,7 +3648,7 @@ public abstract class Dialect implements ConversionContext { case Types.REAL: // this is almost always the thing we use: size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) ); - if (scale != null && scale!=0) { + if ( scale != null && scale != 0 ) { throw new IllegalArgumentException("scale has no meaning for floating point numbers"); } // but if the user explicitly specifies a precision, we need to convert it: @@ -4011,7 +3661,7 @@ public abstract class Dialect implements ConversionContext { case Types.TIMESTAMP: case Types.TIMESTAMP_WITH_TIMEZONE: size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) ); - if (scale != null && scale!=0) { + if ( scale != null && scale != 0 ) { throw new IllegalArgumentException("scale has no meaning for timestamps"); } break; @@ -4019,10 +3669,11 @@ public abstract class Dialect implements ConversionContext { case Types.DECIMAL: case SqlTypes.INTERVAL_SECOND: size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) ); - size.setScale( javaType.getDefaultSqlScale( Dialect.this, jdbcType ) ); break; } + size.setScale( javaType.getDefaultSqlScale( Dialect.this, jdbcType ) ); + if ( precision != null ) { size.setPrecision( precision ); } 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 31ecb34632..b3c8bf5d86 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -8,8 +8,6 @@ package org.hibernate.dialect; import java.sql.CallableStatement; import java.sql.SQLException; -import java.sql.Types; -import java.util.ArrayList; import java.util.List; import org.hibernate.PessimisticLockException; @@ -60,11 +58,11 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2 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.SqlTypes; -import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.UUIDJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import jakarta.persistence.TemporalType; @@ -75,6 +73,8 @@ import static org.hibernate.type.SqlTypes.CHAR; import static org.hibernate.type.SqlTypes.DECIMAL; import static org.hibernate.type.SqlTypes.DOUBLE; import static org.hibernate.type.SqlTypes.FLOAT; +import static org.hibernate.type.SqlTypes.GEOMETRY; +import static org.hibernate.type.SqlTypes.INTERVAL_SECOND; import static org.hibernate.type.SqlTypes.LONG32NVARCHAR; import static org.hibernate.type.SqlTypes.LONG32VARBINARY; import static org.hibernate.type.SqlTypes.LONG32VARCHAR; @@ -84,6 +84,7 @@ import static org.hibernate.type.SqlTypes.LONGVARCHAR; import static org.hibernate.type.SqlTypes.NCHAR; import static org.hibernate.type.SqlTypes.NUMERIC; import static org.hibernate.type.SqlTypes.NVARCHAR; +import static org.hibernate.type.SqlTypes.UUID; import static org.hibernate.type.SqlTypes.VARBINARY; import static org.hibernate.type.SqlTypes.VARCHAR; @@ -141,14 +142,6 @@ public class H2Dialect extends Dialect { ? SequenceInformationExtractorLegacyImpl.INSTANCE : SequenceInformationExtractorH2DatabaseImpl.INSTANCE; this.querySequenceString = "select * from INFORMATION_SCHEMA.SEQUENCES"; - registerColumnType( Types.DECIMAL, "numeric($p,$s)" ); - if ( version.isSameOrAfter( 1, 4, 197 ) ) { - registerColumnType( SqlTypes.UUID, "uuid" ); - registerColumnType( SqlTypes.GEOMETRY, "geometry" ); - if ( version.isSameOrAfter( 1, 4, 198 ) ) { - registerColumnType( SqlTypes.INTERVAL_SECOND, "interval second($p,$s)" ); - } - } } else { this.sequenceInformationExtractor = SequenceInformationExtractorNoOpImpl.INSTANCE; @@ -177,29 +170,30 @@ public class H2Dialect extends Dialect { } @Override - protected String columnType(int jdbcTypeCode) { - if ( jdbcTypeCode == NUMERIC && getVersion().isBefore(2) ) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { // prior to version 2.0, H2 reported NUMERIC columns as DECIMAL, // which caused problems for schema update tool - return super.columnType(DECIMAL); - } - - switch (jdbcTypeCode) { - case LONG32VARCHAR: + case NUMERIC: + return getVersion().isBefore( 2 ) ? columnType( DECIMAL ) : super.columnType( sqlTypeCode ); + case NCHAR: + return columnType( CHAR ); + case NVARCHAR: + case LONGNVARCHAR: case LONG32NVARCHAR: - return "varchar"; + case LONGVARCHAR: + case LONG32VARCHAR: + return columnType( VARCHAR ); + case LONGVARBINARY: case LONG32VARBINARY: - return "varbinary"; - case ARRAY: - return "array"; - default: - return super.columnType(jdbcTypeCode); + return columnType( VARBINARY ); } + return super.columnType( sqlTypeCode ); } @Override - public String getUnboundedTypeName(JdbcType jdbcType, JavaType javaType) { - switch ( jdbcType.getDefaultSqlTypeCode() ) { + protected String castType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case CHAR: case NCHAR: return "char"; @@ -216,14 +210,24 @@ public class H2Dialect extends Dialect { case LONG32VARBINARY: return "varbinary"; } - return super.getUnboundedTypeName( jdbcType, javaType ); + return super.castType( sqlTypeCode ); } @Override - protected List getSupportedJdbcTypeCodes() { - List typeCodes = new ArrayList<>( super.getSupportedJdbcTypeCodes() ); - typeCodes.add(ARRAY); - return typeCodes; + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + + if ( getVersion().isBefore( 2 ) ) { + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( ARRAY, "array", this ) ); + } + if ( getVersion().isSameOrAfter( 1, 4, 197 ) ) { + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( UUID, "uuid", this ) ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "geometry", this ) ); + if ( getVersion().isSameOrAfter( 1, 4, 198 ) ) { + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( INTERVAL_SECOND, "interval second($p,$s)", this ) ); + } + } } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java index b02cc6dde6..a8d2fb2284 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java @@ -6,8 +6,6 @@ */ package org.hibernate.dialect; -import java.sql.Types; - import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; @@ -51,25 +49,11 @@ public class HANAColumnStoreDialect extends AbstractHANADialect { public HANAColumnStoreDialect(DatabaseVersion version) { super( version ); - if ( version.isSameOrAfter( 4 ) ) { - registerColumnType( Types.CHAR, "nvarchar($l)" ); - registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "nvarchar($l)" ); + } - // for longer values map to clob/nclob - registerColumnType( Types.VARCHAR, "nclob" ); - registerColumnType( Types.CLOB, "nclob" ); - - registerHibernateType( Types.CLOB, StandardBasicTypes.MATERIALIZED_NCLOB.getName() ); - registerHibernateType( Types.NCHAR, StandardBasicTypes.NSTRING.getName() ); - registerHibernateType( Types.CHAR, StandardBasicTypes.CHARACTER.getName() ); - registerHibernateType( Types.CHAR, 1, StandardBasicTypes.CHARACTER.getName() ); - registerHibernateType( Types.CHAR, 5000, StandardBasicTypes.NSTRING.getName() ); - registerHibernateType( Types.VARCHAR, StandardBasicTypes.NSTRING.getName() ); - registerHibernateType( Types.LONGVARCHAR, StandardBasicTypes.NTEXT.getName() ); - - // register additional keywords - registerHanaCloudKeywords(); - } + @Override + public boolean isUseUnicodeStringTypes() { + return getVersion().isSameOrAfter( 4 ) || super.isUseUnicodeStringTypes(); } @Override @@ -77,7 +61,9 @@ public class HANAColumnStoreDialect extends AbstractHANADialect { return 5000; } - private void registerHanaCloudKeywords() { + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); registerKeyword( "array" ); registerKeyword( "at" ); registerKeyword( "authorization" ); 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 3e0b3ba211..fbfe4790cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java @@ -67,6 +67,7 @@ import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHSQLDBDatabaseImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; +import org.hibernate.type.spi.TypeConfiguration; import org.jboss.logging.Logger; @@ -92,8 +93,7 @@ public class HSQLDialect extends Dialect { ); public HSQLDialect(DialectResolutionInfo info) { - this( info.makeCopy() ); - registerKeywords( info ); + super( info ); } public HSQLDialect() { @@ -102,14 +102,18 @@ public class HSQLDialect extends Dialect { public HSQLDialect(DatabaseVersion version) { super( version.isSame( 1, 8 ) ? reflectedVersion( version ) : version ); + } + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); if ( getVersion().isSameOrAfter( 2, 5 ) ) { registerKeyword( "period" ); } } @Override - protected String columnType(int jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { // Note that all floating point types are synonyms for 'double' // Note that the HSQL type 'longvarchar' and 'longvarbinary' are @@ -117,28 +121,25 @@ public class HSQLDialect extends Dialect { // But using these types results in schema validation issue as // described in HHH-9693. - //HSQL has no 'nclob' type, but 'clob' is Unicode (See HHH-10364) - if ( jdbcTypeCode==NCLOB ) { - jdbcTypeCode = CLOB; + switch ( sqlTypeCode ) { + //HSQL has no 'nclob' type, but 'clob' is Unicode (See HHH-10364) + case NCLOB: + return "clob"; } - if ( getVersion().isBefore( 2 ) ) { - switch (jdbcTypeCode) { + switch ( sqlTypeCode ) { case NUMERIC: // Older versions of HSQL did not accept // precision for the 'numeric' type return "numeric"; - // Older versions of HSQL had no lob support case BLOB: return "longvarbinary"; case CLOB: return "longvarchar"; - } } - - return super.columnType(jdbcTypeCode); + return super.columnType( sqlTypeCode ); } @Override @@ -468,7 +469,7 @@ public class HSQLDialect extends Dialect { } ); @Override - public String getSelectClauseNullString(int sqlType) { + public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { String literal; switch ( sqlType ) { case Types.LONGVARCHAR: diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java index e35b4d5b33..b1d19b8c4a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -11,8 +11,6 @@ import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; -import java.util.ArrayList; -import java.util.List; import org.hibernate.LockOptions; import org.hibernate.PessimisticLockException; @@ -42,8 +40,6 @@ import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor; import org.hibernate.exception.spi.ViolatedConstraintNameExtractor; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.metamodel.mapping.JdbcMapping; -import org.hibernate.metamodel.mapping.SqlExpressible; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.IntervalType; @@ -73,6 +69,9 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JsonJdbcType; import org.hibernate.type.descriptor.jdbc.NullJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import jakarta.persistence.TemporalType; @@ -107,20 +106,25 @@ public class MySQLDialect extends Dialect { } }; - private int maxVarcharLength; - private int maxVarbinaryLength; + private final int maxVarcharLength; + private final int maxVarbinaryLength; public MySQLDialect() { this( DatabaseVersion.make( 5, 0 ) ); } public MySQLDialect(DatabaseVersion version) { - super(version); + super( version ); registerKeyword( "key" ); + maxVarcharLength = maxVarcharLength( getMySQLVersion(), 4 ); //conservative assumption + maxVarbinaryLength = maxVarbinaryLength( getMySQLVersion() ); } public MySQLDialect(DialectResolutionInfo info) { - super(info); + super( info ); + int bytesPerCharacter = getCharacterSetBytesPerCharacter( info.getDatabaseMetadata() ); + maxVarcharLength = maxVarcharLength( getMySQLVersion(), bytesPerCharacter ); + maxVarbinaryLength = maxVarbinaryLength( getMySQLVersion() ); } @Override @@ -149,40 +153,18 @@ public class MySQLDialect extends Dialect { } @Override - protected List getSupportedJdbcTypeCodes() { - List typeCodes = new ArrayList<>( super.getSupportedJdbcTypeCodes() ); - typeCodes.add(GEOMETRY); - if ( getMySQLVersion().isBefore( 5, 7 ) ) { - // MySQL 5.7 brings JSON native support with a dedicated datatype - // https://dev.mysql.com/doc/refman/5.7/en/json.html - typeCodes.add(JSON); - } - return typeCodes; - } - - @Override - protected String columnType(int jdbcTypeCode) { - switch (jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case BOOLEAN: // HHH-6935: Don't use "boolean" i.e. tinyint(1) due to JDBC ResultSetMetaData return "bit"; - case TIMESTAMP: - return getMySQLVersion().isBefore( 5, 7 ) - ? "datetime" : "datetime($p)"; + return getMySQLVersion().isBefore( 5, 7 ) ? "datetime" : "datetime($p)"; case TIMESTAMP_WITH_TIMEZONE: - return getMySQLVersion().isBefore( 5, 7 ) - ? "timestamp" : "timestamp($p)"; - + return getMySQLVersion().isBefore( 5, 7 ) ? "timestamp" : "timestamp($p)"; case NUMERIC: // it's just a synonym - return super.columnType(DECIMAL); - - case JSON: - return "json"; - case GEOMETRY: - return "geometry"; - + return columnType( DECIMAL ); // the maximum long LOB length is 4_294_967_295, bigger than any Java string case BLOB: return "longblob"; @@ -190,28 +172,61 @@ public class MySQLDialect extends Dialect { case CLOB: return "longtext"; } - return super.columnType(jdbcTypeCode); + return super.columnType( sqlTypeCode ); } @Override - protected void beforeRegisteringColumnTypes(DialectResolutionInfo info) { - // we need to remember the character set before calling getMaxVarcharLength() - // we could not do this earlier because we get called from the constructor - // of the superclass, before our own constructor has run - int bytesPerCharacter = getCharacterSetBytesPerCharacter( info.getDatabaseMetadata() ); - maxVarcharLength = maxVarcharLength( getMySQLVersion(), bytesPerCharacter ); - maxVarbinaryLength = maxVarbinaryLength( getMySQLVersion() ); + protected String castType(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case BOOLEAN: + case BIT: + //special case for casting to Boolean + return "unsigned"; + case TINYINT: + case SMALLINT: + case INTEGER: + case BIGINT: + //MySQL doesn't let you cast to INTEGER/BIGINT/TINYINT + return "signed"; + case FLOAT: + case REAL: + case DOUBLE: + //MySQL doesn't let you cast to DOUBLE/FLOAT + //but don't just return 'decimal' because + //the default scale is 0 (no decimal places) + return "decimal($p,$s)"; + case CHAR: + case NCHAR: + case VARCHAR: + case NVARCHAR: + case LONGVARCHAR: + case LONGNVARCHAR: + case LONG32VARCHAR: + case LONG32NVARCHAR: + //MySQL doesn't let you cast to TEXT/LONGTEXT + return "char"; + case BINARY: + case VARBINARY: + case LONGVARBINARY: + case LONG32VARBINARY: + //MySQL doesn't let you cast to BLOB/TINYBLOB/LONGBLOB + return "binary"; + } + return super.castType( sqlTypeCode ); } @Override - protected void beforeRegisteringColumnTypes(DatabaseVersion version) { - maxVarcharLength = maxVarcharLength( getMySQLVersion(), 4 ); //conservative assumption - maxVarbinaryLength = maxVarbinaryLength( getMySQLVersion() ); - } + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); - @Override - protected void registerDefaultColumnTypes() { - super.registerDefaultColumnTypes(); + if ( getMySQLVersion().isSameOrAfter( 5, 7 ) ) { + // MySQL 5.7 brings JSON native support with a dedicated datatype + // https://dev.mysql.com/doc/refman/5.7/en/json.html + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "json", this ) ); + } + + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "geometry", this ) ); // MySQL has approximately one million text and blob types. We have // already registered longtext + longblob via the regular method, @@ -221,32 +236,98 @@ public class MySQLDialect extends Dialect { final int maxLobLen = 65_535; final int maxMediumLobLen = 16_777_215; - registerColumnType( VARCHAR, maxMediumLobLen, "mediumtext" ); + final CapacityDependentDdlType.Builder varcharBuilder = CapacityDependentDdlType.builder( + VARCHAR, + columnType( CLOB ), + "char", + this + ) + .withTypeCapacity( getMaxVarcharLength(), "varchar($l)" ) + .withTypeCapacity( maxMediumLobLen, "mediumtext" ); if ( getMaxVarcharLength() < maxLobLen ) { - registerColumnType( VARCHAR, maxLobLen, "text" ); + varcharBuilder.withTypeCapacity( maxLobLen, "text" ); } + ddlTypeRegistry.addDescriptor( varcharBuilder.build() ); - registerColumnType( NVARCHAR, maxMediumLobLen, "mediumtext" ); - if ( getMaxNVarcharLength() < maxLobLen ) { - registerColumnType( NVARCHAR, maxLobLen, "text" ); + final CapacityDependentDdlType.Builder nvarcharBuilder = CapacityDependentDdlType.builder( + NVARCHAR, + columnType( NCLOB ), + "char", + this + ) + .withTypeCapacity( getMaxVarcharLength(), "varchar($l)" ) + .withTypeCapacity( maxMediumLobLen, "mediumtext" ); + if ( getMaxVarcharLength() < maxLobLen ) { + nvarcharBuilder.withTypeCapacity( maxLobLen, "text" ); } + ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() ); - registerColumnType( VARBINARY, maxMediumLobLen, "mediumblob" ); - if ( getMaxVarbinaryLength() < maxLobLen ) { - registerColumnType( VARBINARY, maxLobLen, "blob" ); + final CapacityDependentDdlType.Builder varbinaryBuilder = CapacityDependentDdlType.builder( + VARBINARY, + columnType( BLOB ), + "binary", + this + ) + .withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" ) + .withTypeCapacity( maxMediumLobLen, "mediumblob" ); + if ( getMaxVarcharLength() < maxLobLen ) { + varbinaryBuilder.withTypeCapacity( maxLobLen, "blob" ); } + ddlTypeRegistry.addDescriptor( varbinaryBuilder.build() ); - registerColumnType( BLOB, maxMediumLobLen, "mediumblob" ); - registerColumnType( BLOB, maxLobLen, "blob" ); - registerColumnType( BLOB, maxTinyLobLen, "tinyblob" ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( LONGVARBINARY, columnType( BLOB ), "binary", this ) + .withTypeCapacity( maxTinyLobLen, "tinyblob" ) + .withTypeCapacity( maxMediumLobLen, "mediumblob" ) + .withTypeCapacity( maxLobLen, "blob" ) + .build() + ); - registerColumnType( CLOB, maxMediumLobLen, "mediumtext" ); - registerColumnType( CLOB, maxLobLen, "text" ); - registerColumnType( CLOB, maxTinyLobLen, "tinytext" ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARBINARY, columnType( BLOB ), "binary", this ) ); - registerColumnType( NCLOB, maxMediumLobLen, "mediumtext" ); - registerColumnType( NCLOB, maxLobLen, "text" ); - registerColumnType( NCLOB, maxTinyLobLen, "tinytext" ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( LONGVARCHAR, columnType( CLOB ), "char", this ) + .withTypeCapacity( maxTinyLobLen, "tinytext" ) + .withTypeCapacity( maxMediumLobLen, "mediumtext" ) + .withTypeCapacity( maxLobLen, "text" ) + .build() + ); + + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32VARCHAR, columnType( CLOB ), "char", this ) ); + + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( LONGNVARCHAR, columnType( NCLOB ), "char", this ) + .withTypeCapacity( maxTinyLobLen, "tinytext" ) + .withTypeCapacity( maxMediumLobLen, "mediumtext" ) + .withTypeCapacity( maxLobLen, "text" ) + .build() + ); + + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( LONG32NVARCHAR, columnType( CLOB ), "char", this ) ); + + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( BLOB, columnType( BLOB ), "binary", this ) + .withTypeCapacity( maxTinyLobLen, "tinyblob" ) + .withTypeCapacity( maxMediumLobLen, "mediumblob" ) + .withTypeCapacity( maxLobLen, "blob" ) + .build() + ); + + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( CLOB, columnType( CLOB ), "char", this ) + .withTypeCapacity( maxTinyLobLen, "tinytext" ) + .withTypeCapacity( maxMediumLobLen, "mediumtext" ) + .withTypeCapacity( maxLobLen, "text" ) + .build() + ); + + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( NCLOB, columnType( NCLOB ), "char", this ) + .withTypeCapacity( maxTinyLobLen, "tinytext" ) + .withTypeCapacity( maxMediumLobLen, "mediumtext" ) + .withTypeCapacity( maxLobLen, "text" ) + .build() + ); } protected static int getCharacterSetBytesPerCharacter(DatabaseMetaData databaseMetaData) { @@ -820,72 +901,6 @@ public class MySQLDialect extends Dialect { return 64; } - @Override - public String getCastTypeName(SqlExpressible type, Long length, Integer precision, Integer scale) { - final JdbcMapping jdbcMapping = type.getJdbcMapping(); - final JdbcType jdbcType = jdbcMapping.getJdbcType(); - final JavaType javaType = jdbcMapping.getJavaTypeDescriptor(); - switch ( jdbcType.getDefaultSqlTypeCode() ) { - case Types.INTEGER: - case Types.BIGINT: - case Types.SMALLINT: - case Types.TINYINT: - //MySQL doesn't let you cast to INTEGER/BIGINT/TINYINT - return "signed"; - case Types.BIT: - //special case for casting to Boolean - return "unsigned"; - case Types.FLOAT: - case Types.DOUBLE: - case Types.REAL: - //MySQL doesn't let you cast to DOUBLE/FLOAT - //but don't just return 'decimal' because - //the default scale is 0 (no decimal places) - return String.format( - "decimal(%d, %d)", - precision == null ? javaType.getDefaultSqlPrecision( this, jdbcType ) : precision, - scale == null ? javaType.getDefaultSqlScale( this, jdbcType ) : scale - ); - case Types.VARBINARY: - case Types.LONGVARBINARY: - //MySQL doesn't let you cast to BLOB/TINYBLOB/LONGBLOB - if ( length == null ) { - return "binary"; - } - return String.format( "binary(%d)", length ); - case Types.VARCHAR: - case Types.LONGVARCHAR: - //MySQL doesn't let you cast to TEXT/LONGTEXT - if ( length == null ) { - return "char"; - } - return String.format( "char(%d)", length ); - default: - return super.getCastTypeName( type, length, precision, scale ); - } - } - - @Override - public String getUnboundedTypeName(JdbcType jdbcType, JavaType javaType) { - switch ( jdbcType.getDefaultSqlTypeCode() ) { - case CHAR: - case NCHAR: - case VARCHAR: - case NVARCHAR: - case LONGVARCHAR: - case LONGNVARCHAR: - case LONG32VARCHAR: - case LONG32NVARCHAR: - return "char"; - case BINARY: - case VARBINARY: - case LONGVARBINARY: - case LONG32VARBINARY: - return "binary"; - } - return super.getUnboundedTypeName( jdbcType, javaType ); - } - @Override public boolean supportsCurrentTimestampSelection() { return true; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java index 665e1a2321..f48796e41c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -11,8 +11,6 @@ import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -93,6 +91,8 @@ import static org.hibernate.query.sqm.TemporalUnit.SECOND; import static org.hibernate.query.sqm.TemporalUnit.YEAR; import org.hibernate.query.sqm.produce.function.FunctionParameterType; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; import static org.hibernate.type.SqlTypes.*; @@ -549,68 +549,53 @@ public class OracleDialect extends Dialect { } @Override - protected String columnType(int jdbcTypeCode) { - //note: the 'long' type is deprecated - switch (jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case BOOLEAN: // still, after all these years... return "number(1,0)"; - - case VARCHAR: - return getVersion().isBefore( 9 ) - ? "varchar2($l)": "varchar2($l char)"; - case NVARCHAR: - return "nvarchar2($l)"; - - case BIGINT: - return "number(19,0)"; - case SMALLINT: - return "number(5,0)"; case TINYINT: return "number(3,0)"; + case SMALLINT: + return "number(5,0)"; case INTEGER: return "number(10,0)"; - + case BIGINT: + return "number(19,0)"; case REAL: // Oracle's 'real' type is actually double precision return "float(24)"; - case NUMERIC: case DECIMAL: // Note that 38 is the maximum precision Oracle supports return "number($p,$s)"; - case DATE: case TIME: return "date"; case TIMESTAMP: // the only difference between date and timestamp // on Oracle is that date has no fractional seconds - return getVersion().isBefore( 9 ) - ? "date" : "timestamp($p)"; - case TIME_WITH_TIMEZONE: - return getVersion().isBefore( 9 ) - ? "date" : "timestamp($p) with time zone"; - + case TIMESTAMP_WITH_TIMEZONE: + return getVersion().isBefore( 9 ) ? "date" : super.columnType( sqlTypeCode ); + case VARCHAR: + return getVersion().isBefore( 9 ) ? "varchar2($l)" : "varchar2($l char)"; + case NVARCHAR: + return "nvarchar2($l)"; case BINARY: case VARBINARY: return "raw($l)"; - - case GEOMETRY: - return "MDSYS.SDO_GEOMETRY"; - - default: - return super.columnType(jdbcTypeCode); } + return super.columnType( sqlTypeCode ); } @Override - protected List getSupportedJdbcTypeCodes() { - List list = new ArrayList<>( super.getSupportedJdbcTypeCodes() ); + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + if ( getVersion().isSameOrAfter( 10 ) ) { - list.add(GEOMETRY); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "MDSYS.SDO_GEOMETRY", this ) ); } - return list; } @Override @@ -754,9 +739,9 @@ public class OracleDialect extends Dialect { } @Override - public String getSelectClauseNullString(int sqlType) { + public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { if ( getVersion().isSameOrAfter( 9 ) ) { - return super.getSelectClauseNullString(sqlType); + return super.getSelectClauseNullString( sqlType, typeConfiguration ); } else { switch(sqlType) { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index 13d37095ea..2d95459e0b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -12,7 +12,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.time.temporal.TemporalAccessor; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Iterator; @@ -20,7 +19,6 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; -import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.PessimisticLockException; @@ -34,7 +32,6 @@ import org.hibernate.dialect.pagination.LimitOffsetLimitHandler; import org.hibernate.dialect.pagination.OffsetFetchLimitHandler; import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport; -import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy; import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; @@ -67,7 +64,6 @@ import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory; import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.type.JavaObjectType; -import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; import org.hibernate.type.descriptor.jdbc.BlobJdbcType; import org.hibernate.type.descriptor.jdbc.ClobJdbcType; @@ -75,6 +71,10 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcType; import org.hibernate.type.descriptor.jdbc.UUIDJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.Scale6IntervalSecondDdlType; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; +import org.hibernate.type.spi.TypeConfiguration; import jakarta.persistence.TemporalType; @@ -126,66 +126,43 @@ public class PostgreSQLDialect extends Dialect { } @Override - protected String columnType(int jdbcTypeCode) { - switch (jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case TINYINT: // no tinyint, not even in Postgres 11 return "smallint"; - - case BINARY: - return "bytea"; - - case BLOB: - case CLOB: - // use oid as the blob type on Postgres because - // the JDBC driver is rubbish - return "oid"; - - // there are no nchar/nvarchar types in Postgres case NCHAR: - return super.columnType(CHAR); + return columnType( CHAR ); case NVARCHAR: - return super.columnType(VARCHAR); - - // since there's no real difference between TEXT and VARCHAR, - // except for the length limit, we can just use 'text' for the - // "long" string types + return columnType( VARCHAR ); + case LONGVARCHAR: case LONG32VARCHAR: + case LONGNVARCHAR: case LONG32NVARCHAR: return "text"; - // use bytea as the "long" binary type (that there is no - // real VARBINARY type in Postgres, so we always use this) + case BLOB: + case CLOB: + case NCLOB: + return "oid"; + case BINARY: + case VARBINARY: + case LONGVARBINARY: case LONG32VARBINARY: return "bytea"; - - case INET: - return "inet"; - case UUID: - return "uuid"; - case GEOMETRY: - return "geometry"; - case JSON: - // Prefer jsonb if possible - return getVersion().isSameOrAfter( 9, 4 ) - ? "jsonb" : "json"; - case INTERVAL_SECOND: - return "interval second($s)"; - - default: - return super.columnType(jdbcTypeCode); } + return super.columnType( sqlTypeCode ); } @Override - public String getUnboundedTypeName(JdbcType jdbcType, JavaType javaType) { - switch ( jdbcType.getDefaultSqlTypeCode() ) { + protected String castType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case CHAR: case NCHAR: case VARCHAR: case NVARCHAR: case LONGVARCHAR: - case LONGNVARCHAR: case LONG32VARCHAR: + case LONGNVARCHAR: case LONG32NVARCHAR: return "text"; case BINARY: @@ -194,20 +171,31 @@ public class PostgreSQLDialect extends Dialect { case LONG32VARBINARY: return "bytea"; } - return super.getUnboundedTypeName( jdbcType, javaType ); + return super.castType( sqlTypeCode ); } @Override - protected List getSupportedJdbcTypeCodes() { - List typeCodes = new ArrayList<>( super.getSupportedJdbcTypeCodes() ); - typeCodes.addAll( List.of(INET, INTERVAL_SECOND, GEOMETRY) ); + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( INET, "inet", this ) ); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "geometry", this ) ); + ddlTypeRegistry.addDescriptor( new Scale6IntervalSecondDdlType( this ) ); + if ( getVersion().isSameOrAfter( 8, 2 ) ) { - typeCodes.add(UUID); + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( UUID, "uuid", this ) ); + + if ( getVersion().isSameOrAfter( 9, 2 ) ) { + // Prefer jsonb if possible + if ( getVersion().isSameOrAfter( 9, 4 ) ) { + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "jsonb", this ) ); + } + else { + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "json", this ) ); + } + } } - if ( getVersion().isSameOrAfter( 9, 2 ) ) { - typeCodes.add(JSON); - } - return typeCodes; } @Override @@ -218,20 +206,7 @@ public class PostgreSQLDialect extends Dialect { @Override public int getMaxVarbinaryLength() { //postgres has no varbinary-like type - return -1; - } - - @Override - public String getTypeName(int code, Size size) throws HibernateException { - // The maximum scale for `interval second` is 6 unfortunately so we have to use numeric by default - switch ( code ) { - case INTERVAL_SECOND: - final Integer scale = size.getScale(); - if ( scale == null || scale > 6 ) { - return getTypeName( NUMERIC, size ); - } - } - return super.getTypeName( code, size ); + return Integer.MAX_VALUE; } @Override @@ -627,9 +602,9 @@ public class PostgreSQLDialect extends Dialect { } @Override - public String getSelectClauseNullString(int sqlType) { + public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { // Workaround for postgres bug #1453 - return "null::" + getRawTypeName( sqlType ); + return "null::" + typeConfiguration.getDdlTypeRegistry().getDescriptor( sqlType ).getRawTypeName(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java index a49397b943..9fe615c6f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java @@ -52,20 +52,18 @@ import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.type.BasicType; import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; -import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.SmallIntJdbcType; +import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.sql.Types; import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.List; import java.util.TimeZone; import jakarta.persistence.TemporalType; @@ -94,95 +92,95 @@ public class SQLServerDialect extends AbstractTransactSQLDialect { public SQLServerDialect(DatabaseVersion version) { super(version); exporter = createSequenceExporter(version); - registerSqlServerKeywords(); } public SQLServerDialect(DialectResolutionInfo info) { super(info); exporter = createSequenceExporter(info); - registerSqlServerKeywords(); } private StandardSequenceExporter createSequenceExporter(DatabaseVersion version) { return version.isSameOrAfter(11) ? new SqlServerSequenceExporter(this) : null; } - private void registerSqlServerKeywords() { + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); registerKeyword( "top" ); registerKeyword( "key" ); } @Override - protected List getSupportedJdbcTypeCodes() { - List list = new ArrayList<>( super.getSupportedJdbcTypeCodes() ); - if ( getVersion().isSameOrAfter( 10 ) ) { - list.add(GEOMETRY); + protected String columnType(int sqlTypeCode) { + // there is no 'double' type in SQL server + // but 'float' is double precision by default + if ( sqlTypeCode == DOUBLE ) { + return "float"; } - return list; - } - - @Override - protected String columnType(int jdbcTypeCode) { - if ( getVersion().isSameOrAfter( 10 ) ) { - switch (jdbcTypeCode) { - case DATE: - return "date"; - case TIME: - return "time"; - case TIMESTAMP: - return"datetime2($p)"; - case TIMESTAMP_WITH_TIMEZONE: - return "datetimeoffset($p)"; - } - } - - if ( getVersion().isSameOrAfter(9) ) { - // Prefer 'varchar(max)' and 'varbinary(max)' to - // the deprecated TEXT and IMAGE types. Note that - // the length of a VARCHAR or VARBINARY column must - // be either between 1 and 8000 or exactly MAX, and - // the length of an NVARCHAR column must be either - // between 1 and 4000 or exactly MAX. (HHH-3965) - switch (jdbcTypeCode) { - case BLOB: - return "varbinary(max)"; + if ( getVersion().isSameOrAfter( 9 ) ) { + switch ( sqlTypeCode ) { + // Prefer 'varchar(max)' and 'varbinary(max)' to + // the deprecated TEXT and IMAGE types. Note that + // the length of a VARCHAR or VARBINARY column must + // be either between 1 and 8000 or exactly MAX, and + // the length of an NVARCHAR column must be either + // between 1 and 4000 or exactly MAX. (HHH-3965) + case LONGVARCHAR: + case LONG32VARCHAR: case CLOB: return "varchar(max)"; + case LONGNVARCHAR: + case LONG32NVARCHAR: case NCLOB: return "nvarchar(max)"; + case LONGVARBINARY: + case LONG32VARBINARY: + case BLOB: + return "varbinary(max)"; + case DATE: + return getVersion().isSameOrAfter( 10 ) ? "date" : super.columnType( sqlTypeCode ); + case TIME: + return getVersion().isSameOrAfter( 10 ) ? "time" : super.columnType( sqlTypeCode ); + case TIMESTAMP: + return getVersion().isSameOrAfter( 10 ) ? "datetime2($p)" : super.columnType( sqlTypeCode ); + case TIMESTAMP_WITH_TIMEZONE: + return getVersion().isSameOrAfter( 10 ) ? "datetimeoffset($p)" : super.columnType( sqlTypeCode ); } } - - switch (jdbcTypeCode) { - case DOUBLE: - // there is no 'double' type in SQL server - // but 'float' is double precision by default - return "float"; - case GEOMETRY: - return "geometry"; - default: - return super.columnType(jdbcTypeCode); - } + return super.columnType( sqlTypeCode ); } @Override - public String getUnboundedTypeName(JdbcType jdbcType, JavaType javaType) { - switch ( jdbcType.getDefaultSqlTypeCode() ) { - case VARCHAR: - case LONGVARCHAR: - case LONG32VARCHAR: - return "varchar(max)"; - case NVARCHAR: - case LONGNVARCHAR: - case LONG32NVARCHAR: - return "nvarchar(max)"; - case BINARY: - case VARBINARY: - case LONGVARBINARY: - case LONG32VARBINARY: - return "varbinary(max)"; + protected String castType(int sqlTypeCode) { + if ( getVersion().isSameOrAfter( 9 ) ) { + switch ( sqlTypeCode ) { + case VARCHAR: + case LONGVARCHAR: + case LONG32VARCHAR: + case CLOB: + return "varchar(max)"; + case NVARCHAR: + case LONGNVARCHAR: + case LONG32NVARCHAR: + case NCLOB: + return "nvarchar(max)"; + case VARBINARY: + case LONGVARBINARY: + case LONG32VARBINARY: + case BLOB: + return "varbinary(max)"; + } + } + return super.castType( sqlTypeCode ); + } + + @Override + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); + if ( getVersion().isSameOrAfter( 10 ) ) { + ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "geometry", this ) ); } - return super.getUnboundedTypeName( jdbcType, javaType ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java index 0f237315b0..33bfb033d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java @@ -32,7 +32,6 @@ import org.hibernate.mapping.Constraint; import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.Table; import org.hibernate.mapping.UniqueKey; -import org.hibernate.metamodel.mapping.SqlExpressible; import org.hibernate.persister.entity.Lockable; import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.SemanticException; @@ -48,8 +47,6 @@ import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.type.BasicType; import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.descriptor.java.JavaType; -import org.hibernate.type.descriptor.jdbc.JdbcType; import jakarta.persistence.TemporalType; @@ -75,7 +72,7 @@ public class SpannerDialect extends Dialect { private static final UniqueDelegate NOOP_UNIQUE_DELEGATE = new DoNothingUniqueDelegate(); public SpannerDialect() { - super(); + super( ZERO_VERSION ); } public SpannerDialect(DialectResolutionInfo info) { @@ -83,55 +80,53 @@ public class SpannerDialect extends Dialect { } @Override - protected String columnType(int jdbcTypeCode) { - switch (jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case BOOLEAN: return "bool"; - case TINYINT: case SMALLINT: case INTEGER: case BIGINT: return "int64"; - case REAL: case FLOAT: case DOUBLE: case DECIMAL: case NUMERIC: return "float64"; - //there is no time type of any kind case TIME: //timestamp does not accept precision case TIMESTAMP: case TIMESTAMP_WITH_TIMEZONE: return "timestamp"; - case CHAR: case NCHAR: case VARCHAR: case NVARCHAR: + case LONGVARCHAR: + case LONGNVARCHAR: return "string($l)"; - - case BINARY: - case VARBINARY: - return "bytes($l)"; - case CLOB: case NCLOB: + case LONG32VARCHAR: + case LONG32NVARCHAR: return "string(max)"; + case BINARY: + case VARBINARY: + case LONGVARBINARY: + return "bytes($l)"; case BLOB: + case LONG32VARBINARY: return "bytes(max)"; - - default: - return super.columnType(jdbcTypeCode); } + return super.columnType( sqlTypeCode ); } @Override - public String getUnboundedTypeName(JdbcType jdbcType, JavaType javaType) { - switch ( jdbcType.getDefaultSqlTypeCode() ) { + protected String castType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case CHAR: case NCHAR: case VARCHAR: @@ -147,7 +142,7 @@ public class SpannerDialect extends Dialect { case LONG32VARBINARY: return "bytes"; } - return super.getUnboundedTypeName( jdbcType, javaType ); + return super.castType( sqlTypeCode ); } @Override @@ -162,11 +157,6 @@ public class SpannerDialect extends Dialect { return 10_485_760; } - @Override - public DatabaseVersion getVersion() { - return ZERO_VERSION; - } - @Override public void initializeFunctionRegistry(QueryEngine queryEngine) { super.initializeFunctionRegistry( queryEngine ); @@ -826,19 +816,6 @@ public class SpannerDialect extends Dialect { /* Type conversion and casting */ - @Override - public String getCastTypeName(SqlExpressible type, Long length, Integer precision, Integer scale) { - switch ( type.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode() ) { - case VARCHAR: - case NVARCHAR: - return "string"; - case VARBINARY: - return "bytes"; - } - //Spanner doesn't let you specify a length in cast() types - return super.getRawTypeName( type.getJdbcMapping().getJdbcType() ); - } - /** * A no-op {@link Exporter} which is responsible for returning empty Create and Drop SQL strings. * diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java index a836a386e6..696275760c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java @@ -39,6 +39,8 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.TimestampJdbcType; import org.hibernate.type.descriptor.jdbc.TinyIntJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import jakarta.persistence.TemporalType; @@ -78,62 +80,61 @@ public class SybaseASEDialect extends SybaseDialect { public SybaseASEDialect(DatabaseVersion version) { super(version); ansiNull = false; - registerSybaseKeywords(); } public SybaseASEDialect(DialectResolutionInfo info) { super(info); ansiNull = isAnsiNull( info.getDatabaseMetadata() ); - registerSybaseKeywords(); } @Override - protected String columnType(int jdbcTypeCode) { - - if ( jdbcTypeCode == BIGINT && getVersion().isBefore( 15 ) ) { - // Sybase ASE didn't introduce 'bigint' until version 15.0 - return "numeric(19,0)"; - } - - if ( getVersion().isSameOrAfter( 12 ) ) { - // 'date' and 'time' were introduced in version 12 - // note: 'timestamp' is something weird on ASE, - // not what we're looking for here! - switch (jdbcTypeCode) { - case DATE: - return "date"; - case TIME: - return "time"; - } - } - - switch (jdbcTypeCode) { + protected String columnType(int sqlTypeCode) { + switch ( sqlTypeCode ) { case BOOLEAN: // On Sybase ASE, the 'bit' type cannot be null, // and cannot have indexes (while we don't use // tinyint to store signed bytes, we can use it // to store boolean values) return "tinyint"; - default: - return super.columnType(jdbcTypeCode); + case BIGINT: + // Sybase ASE didn't introduce 'bigint' until version 15.0 + return getVersion().isBefore( 15 ) ? "numeric(19,0)" : super.columnType( sqlTypeCode ); + case DATE: + return getVersion().isSameOrAfter( 12 ) ? "date" : super.columnType( sqlTypeCode ); + case TIME: + return getVersion().isSameOrAfter( 12 ) ? "time" : super.columnType( sqlTypeCode ); } + return super.columnType( sqlTypeCode ); } @Override - protected void registerDefaultColumnTypes() { - super.registerDefaultColumnTypes(); + protected void registerColumnTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { + super.registerColumnTypes( typeContributions, serviceRegistry ); + final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry(); // According to Wikipedia bigdatetime and bigtime were added in 15.5 // But with jTDS we can't use them as the driver can't handle the types if ( getVersion().isSameOrAfter( 15, 5 ) && !jtdsDriver ) { - registerColumnType( DATE, "bigdatetime" ); - registerColumnType( DATE, 3, "datetime" ); - registerColumnType( TIME, "bigtime" ); - registerColumnType( TIME, 3, "datetime" ); - registerColumnType( TIMESTAMP, "bigdatetime" ); - registerColumnType( TIMESTAMP, 3, "datetime" ); - registerColumnType( TIMESTAMP_WITH_TIMEZONE, "bigdatetime" ); - registerColumnType( TIMESTAMP_WITH_TIMEZONE, 3, "datetime" ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( DATE, "bigdatetime", "bigdatetime", this ) + .withTypeCapacity( 3, "datetime" ) + .build() + ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( TIME, "bigdatetime", "bigdatetime", this ) + .withTypeCapacity( 3, "datetime" ) + .build() + ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( TIMESTAMP, "bigdatetime", "bigdatetime", this ) + .withTypeCapacity( 3, "datetime" ) + .build() + ); + ddlTypeRegistry.addDescriptor( + CapacityDependentDdlType.builder( TIMESTAMP_WITH_TIMEZONE, "bigdatetime", "bigdatetime", this ) + .withTypeCapacity( 3, "datetime" ) + .build() + ); } } @@ -282,7 +283,9 @@ public class SybaseASEDialect extends SybaseDialect { } } - private void registerSybaseKeywords() { + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); registerKeyword( "add" ); registerKeyword( "all" ); registerKeyword( "alter" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java index 226ecb5a84..8a5c31749c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java @@ -76,14 +76,6 @@ public class SybaseDialect extends AbstractTransactSQLDialect { public SybaseDialect(DialectResolutionInfo info) { super(info); - } - - @Override - protected void beforeRegisteringColumnTypes(DialectResolutionInfo info) { - // we need to check init the jtdsDriver field here, - // because we need it in the registerDefaultColumnTypes() - // of the subclass, which is called from the superclass - // constructor, before our constructor has been called jtdsDriver = info.getDriverName() != null && info.getDriverName().contains( "jTDS" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TiDBDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/TiDBDialect.java index 10e4d4472c..f442663fc1 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/TiDBDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/TiDBDialect.java @@ -36,12 +36,10 @@ public class TiDBDialect extends MySQLDialect { public TiDBDialect(DatabaseVersion version) { super(version); - registerKeywords(); } public TiDBDialect(DialectResolutionInfo info) { super(info); - registerKeywords(); } @Override @@ -50,7 +48,9 @@ public class TiDBDialect extends MySQLDialect { return VERSION57; } - private void registerKeywords() { + @Override + protected void registerDefaultKeywords() { + super.registerDefaultKeywords(); // TiDB implemented 'Window Functions' of MySQL 8, so the following keywords are reserved. registerKeyword("CUME_DIST"); registerKeyword("DENSE_RANK"); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CastingConcatFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CastingConcatFunction.java index f453bf95ee..96da74362a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CastingConcatFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CastingConcatFunction.java @@ -13,7 +13,6 @@ import org.hibernate.dialect.Dialect; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; -import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; @@ -55,12 +54,13 @@ public class CastingConcatFunction extends AbstractSqmSelfRenderingFunctionDescr this.concatOperator = concatOperator; this.needsCastWrapper = needsCastWrapper; this.argumentRenderingMode = argumentRenderingMode; - this.concatArgumentCastType = dialect.getCastTypeName( - typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ), - null, - null, - null - ); + this.concatArgumentCastType = typeConfiguration.getDdlTypeRegistry().getDescriptor( SqlTypes.VARCHAR ) + .getCastTypeName( + typeConfiguration.getBasicTypeRegistry().resolve( StandardBasicTypes.STRING ), + null, + null, + null + ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java index 08966aaae7..4e21cf1216 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTable.java @@ -37,6 +37,7 @@ import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.type.BasicType; +import org.hibernate.type.spi.TypeConfiguration; /** * @author Steve Ebersole @@ -83,15 +84,16 @@ public class TemporaryTable implements Exportable, Contributable { } this.dialect = dialect; if ( dialect.getSupportedTemporaryTableKind() == TemporaryTableKind.PERSISTENT ) { - final BasicType uuidType = entityDescriptor.getEntityPersister() + final TypeConfiguration typeConfiguration = entityDescriptor.getEntityPersister() .getFactory() - .getTypeConfiguration() + .getTypeConfiguration(); + final BasicType uuidType = typeConfiguration .getBasicTypeForJavaType( UUID.class ); this.sessionUidColumn = new TemporaryTableSessionUidColumn( this, uuidType, - dialect.getTypeName( - uuidType.getJdbcType(), + typeConfiguration.getDdlTypeRegistry().getTypeName( + uuidType.getJdbcType().getDefaultSqlTypeCode(), dialect.getSizeStrategy().resolveSize( uuidType.getJdbcType(), uuidType.getJavaTypeDescriptor(), @@ -136,7 +138,11 @@ public class TemporaryTable implements Exportable, Contributable { temporaryTable, column.getText( dialect ), jdbcMapping, - column.getSqlType( dialect, runtimeModelCreationContext.getMetadata() ), + column.getSqlType( + runtimeModelCreationContext.getTypeConfiguration(), + dialect, + runtimeModelCreationContext.getMetadata() + ), column.isNullable(), true ) @@ -176,6 +182,7 @@ public class TemporaryTable implements Exportable, Contributable { selectable.getText( dialect ), selection.getJdbcMapping(), column.getSqlType( + runtimeModelCreationContext.getTypeConfiguration(), dialect, runtimeModelCreationContext.getMetadata() ), @@ -225,7 +232,11 @@ public class TemporaryTable implements Exportable, Contributable { temporaryTable, ENTITY_TABLE_IDENTITY_COLUMN, jdbcMapping, - column.getSqlType( dialect, runtimeModelCreationContext.getMetadata() ) + " " + + column.getSqlType( + runtimeModelCreationContext.getTypeConfiguration(), + dialect, + runtimeModelCreationContext.getMetadata() + ) + " " + dialect.getIdentityColumnSupport().getIdentityColumnString( column.getSqlTypeCode( runtimeModelCreationContext.getMetadata() ) ), // Always report as nullable as the identity column string usually includes the not null constraint true, //column.isNullable() @@ -253,7 +264,11 @@ public class TemporaryTable implements Exportable, Contributable { temporaryTable, column.getText( dialect ), jdbcMapping, - column.getSqlType( dialect, runtimeModelCreationContext.getMetadata() ), + column.getSqlType( + runtimeModelCreationContext.getTypeConfiguration(), + dialect, + runtimeModelCreationContext.getMetadata() + ), // We have to set the identity column after the root table insert column.isNullable() || identityColumn || hasOptimizer, !identityColumn && !hasOptimizer @@ -269,7 +284,11 @@ public class TemporaryTable implements Exportable, Contributable { temporaryTable, discriminator.getText( dialect ), discriminatorMapping.getJdbcMapping(), - discriminator.getSqlType( dialect, runtimeModelCreationContext.getMetadata() ), + discriminator.getSqlType( + runtimeModelCreationContext.getTypeConfiguration(), + dialect, + runtimeModelCreationContext.getMetadata() + ), // We have to set the identity column after the root table insert discriminator.isNullable() ) @@ -294,6 +313,7 @@ public class TemporaryTable implements Exportable, Contributable { selectable.getText( dialect ), selection.getJdbcMapping(), column.getSqlType( + runtimeModelCreationContext.getTypeConfiguration(), dialect, runtimeModelCreationContext.getMetadata() ), @@ -308,14 +328,12 @@ public class TemporaryTable implements Exportable, Contributable { } ); if ( hasOptimizer ) { + final TypeConfiguration typeConfiguration = runtimeModelCreationContext.getTypeConfiguration(); // We add a special row number column that we can use to identify and join rows - final BasicType integerBasicType = entityDescriptor.getEntityPersister() - .getFactory() - .getTypeConfiguration() - .getBasicTypeForJavaType( Integer.class ); + final BasicType integerBasicType = typeConfiguration.getBasicTypeForJavaType( Integer.class ); final String rowNumberType; if ( dialect.supportsWindowFunctions() ) { - rowNumberType = dialect.getTypeName( + rowNumberType = typeConfiguration.getDdlTypeRegistry().getTypeName( integerBasicType.getJdbcType().getJdbcTypeCode(), dialect.getSizeStrategy().resolveSize( integerBasicType.getJdbcType(), @@ -327,7 +345,7 @@ public class TemporaryTable implements Exportable, Contributable { ); } else if ( dialect.getIdentityColumnSupport().supportsIdentityColumns() ) { - rowNumberType = dialect.getTypeName( + rowNumberType = typeConfiguration.getDdlTypeRegistry().getTypeName( integerBasicType.getJdbcType().getJdbcTypeCode(), dialect.getSizeStrategy().resolveSize( integerBasicType.getJdbcType(), @@ -341,7 +359,7 @@ public class TemporaryTable implements Exportable, Contributable { } else { LOG.multiTableInsertNotAvailable( entityBinding.getEntityName() ); - rowNumberType = dialect.getTypeName( + rowNumberType = typeConfiguration.getDdlTypeRegistry().getTypeName( integerBasicType.getJdbcType().getJdbcTypeCode(), dialect.getSizeStrategy().resolveSize( integerBasicType.getJdbcType(), diff --git a/hibernate-core/src/main/java/org/hibernate/id/ExportableColumn.java b/hibernate-core/src/main/java/org/hibernate/id/ExportableColumn.java index 6531d61ed1..50298664f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/ExportableColumn.java +++ b/hibernate-core/src/main/java/org/hibernate/id/ExportableColumn.java @@ -35,7 +35,9 @@ public class ExportableColumn extends Column { table, name, type, - database.getDialect().getTypeName( type.getJdbcType().getDefaultSqlTypeCode() ) + database.getTypeConfiguration() + .getDdlTypeRegistry() + .getTypeName( type.getJdbcType().getDefaultSqlTypeCode(), database.getDialect() ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java index 12a9dcbfc6..3d6c13c3ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java @@ -688,7 +688,9 @@ public class TableGenerator implements PersistentIdentifierGenerator { table, segmentColumnName, basicTypeRegistry.resolve( StandardBasicTypes.STRING ), - dialect.getTypeName( Types.VARCHAR, Size.length(segmentValueLength) ) + database.getTypeConfiguration() + .getDdlTypeRegistry() + .getTypeName( Types.VARCHAR, Size.length( segmentValueLength ) ) ); segmentColumn.setNullable( false ); table.addColumn( segmentColumn ); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/FilterHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/FilterHelper.java index d8616b7b81..fb0d00be68 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/FilterHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/FilterHelper.java @@ -79,6 +79,7 @@ public class FilterHelper { filter.getCondition(), FilterImpl.MARKER, factory.getJdbcServices().getDialect(), + factory.getTypeConfiguration(), factory.getQueryEngine().getSqmFunctionRegistry() ); filterConditions[filterCount] = safeInterning( autoAliasedCondition ); diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java index c3edb72003..65d91da659 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java @@ -22,6 +22,7 @@ import org.hibernate.sql.Template; import org.hibernate.type.ComponentType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; import static org.hibernate.internal.util.StringHelper.safeInterning; @@ -240,10 +241,10 @@ public class Column implements Selectable, Serializable, Cloneable { sqlTypeCode = typeCode; } - public String getSqlType(Dialect dialect, Mapping mapping) throws HibernateException { + public String getSqlType(TypeConfiguration typeConfiguration, Dialect dialect, Mapping mapping) throws HibernateException { if ( sqlType == null ) { try { - sqlType = dialect.getTypeName( getSqlTypeCode( mapping ), getColumnSize( dialect, mapping ) ); + sqlType = typeConfiguration.getDdlTypeRegistry().getTypeName( getSqlTypeCode( mapping ), getColumnSize( dialect, mapping ) ); } catch (HibernateException cause) { throw new HibernateException( @@ -365,7 +366,10 @@ public class Column implements Selectable, Serializable, Cloneable { } @Override - public String getTemplate(Dialect dialect, SqmFunctionRegistry functionRegistry) { + public String getTemplate( + Dialect dialect, + TypeConfiguration typeConfiguration, + SqmFunctionRegistry functionRegistry) { return safeInterning( hasCustomRead() // see note in renderTransformerReadFragment wrt access to SessionFactory diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Formula.java b/hibernate-core/src/main/java/org/hibernate/mapping/Formula.java index 42548d5920..7c7f13bdbd 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Formula.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Formula.java @@ -14,6 +14,7 @@ import org.hibernate.internal.util.StringHelper; import org.hibernate.loader.internal.AliasConstantsHelper; import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.sql.Template; +import org.hibernate.type.spi.TypeConfiguration; import static org.hibernate.internal.util.StringHelper.safeInterning; @@ -38,8 +39,11 @@ public class Formula implements Selectable, Serializable { } @Override - public String getTemplate(Dialect dialect, SqmFunctionRegistry functionRegistry) { - String template = Template.renderWhereStringTemplate(formula, dialect, functionRegistry); + public String getTemplate( + Dialect dialect, + TypeConfiguration typeConfiguration, + SqmFunctionRegistry functionRegistry) { + String template = Template.renderWhereStringTemplate( formula, dialect, typeConfiguration, functionRegistry ); return safeInterning( StringHelper.replace( template, "{alias}", Template.TEMPLATE ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Selectable.java b/hibernate-core/src/main/java/org/hibernate/mapping/Selectable.java index fa4bc26027..86b281db4a 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Selectable.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Selectable.java @@ -8,6 +8,7 @@ package org.hibernate.mapping; import org.hibernate.dialect.Dialect; import org.hibernate.query.sqm.function.SqmFunctionRegistry; +import org.hibernate.type.spi.TypeConfiguration; /** * Models the commonality between a column and a formula (computed value). @@ -60,9 +61,8 @@ public interface Selectable { @Deprecated(since = "6.0") String getAlias(Dialect dialect, Table table); - /** - * @deprecated use {@link #getCustomWriteExpression()} instead - */ - @Deprecated(since = "6.0") - String getTemplate(Dialect dialect, SqmFunctionRegistry functionRegistry); + String getTemplate( + Dialect dialect, + TypeConfiguration typeConfiguration, + SqmFunctionRegistry functionRegistry); } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java index 161218b859..e86e203db4 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java @@ -441,7 +441,11 @@ public class Table implements RelationalModel, Serializable, ContributableDataba .append( ' ' ) .append( column.getQuotedName( dialect ) ); - String columnType = column.getSqlType(dialect, metadata); + String columnType = column.getSqlType( + metadata.getDatabase().getTypeConfiguration(), + dialect, + metadata + ); if ( column.getGeneratedAs()==null || dialect.hasDataTypeBeforeGeneratedAs() ) { alter.append( ' ' ).append(columnType); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java index 53a2e4cf39..0269de4f18 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEmbeddableMapping.java @@ -166,7 +166,11 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType final String columnExpression; if ( rootTableKeyColumnNames == null ) { if ( selectable.isFormula() ) { - columnExpression = selectable.getTemplate( dialect, creationProcess.getSqmFunctionRegistry() ); + columnExpression = selectable.getTemplate( + dialect, + creationProcess.getCreationContext().getTypeConfiguration(), + creationProcess.getSqmFunctionRegistry() + ); } else { columnExpression = selectable.getText( dialect ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java index 90a5deae53..7f28fe9027 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EmbeddableMappingTypeImpl.java @@ -312,7 +312,11 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme final String columnExpression; if ( rootTableKeyColumnNames == null ) { if ( selectable.isFormula() ) { - columnExpression = selectable.getTemplate( dialect, creationProcess.getSqmFunctionRegistry() ); + columnExpression = selectable.getTemplate( + dialect, + creationProcess.getCreationContext().getTypeConfiguration(), + creationProcess.getSqmFunctionRegistry() + ); } else { columnExpression = selectable.getText( dialect ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java index 62cdfb0ec3..141e93a446 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java @@ -305,6 +305,7 @@ public class EntityCollectionPart fkKeyTableName, fkBootDescriptorSource.getSelectables().get(0), basicFkTargetPart.getJdbcMapping(), + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java index d97419eb72..36c3a27a59 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java @@ -593,6 +593,7 @@ public class MappingModelCreationHelper { tableExpression, index.getSelectables().get(0), creationContext.getTypeConfiguration().getBasicTypeForJavaType( Integer.class ), + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); @@ -644,6 +645,7 @@ public class MappingModelCreationHelper { tableExpression, index.getSelectables().get(0), creationContext.getTypeConfiguration().getBasicTypeForJavaType( Integer.class ), + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); @@ -873,6 +875,7 @@ public class MappingModelCreationHelper { tableExpression, bootValueMappingKey.getSelectables().get(0), (JdbcMapping) keyType, + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); @@ -1044,6 +1047,7 @@ public class MappingModelCreationHelper { tableExpression, columnIterator.next(), simpleFkTarget.getJdbcMapping(), + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); @@ -1054,6 +1058,7 @@ public class MappingModelCreationHelper { tableExpression, table.getColumn( 0 ), simpleFkTarget.getJdbcMapping(), + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); @@ -1168,6 +1173,7 @@ public class MappingModelCreationHelper { collectionBootValueMapping.getKey(), getPropertyOrder( bootValueMapping, creationProcess ), creationProcess.getCreationContext().getSessionFactory(), + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); @@ -1189,6 +1195,7 @@ public class MappingModelCreationHelper { bootValueMapping, getPropertyOrder( bootValueMapping, creationProcess ), creationProcess.getCreationContext().getSessionFactory(), + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); @@ -1335,6 +1342,7 @@ public class MappingModelCreationHelper { tableExpression, basicValue.getSelectables().get(0), basicValue.resolve().getJdbcMapping(), + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); @@ -1419,6 +1427,7 @@ public class MappingModelCreationHelper { tableExpression, basicElement.getSelectables().get(0), basicElement.resolve().getJdbcMapping(), + creationProcess.getCreationContext().getTypeConfiguration(), dialect, creationProcess.getSqmFunctionRegistry() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingImpl.java index f90fc9081c..48f2b6da05 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingImpl.java @@ -12,6 +12,7 @@ import org.hibernate.mapping.Selectable; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.query.sqm.function.SqmFunctionRegistry; +import org.hibernate.type.spi.TypeConfiguration; /** * @author Christian Beikov @@ -48,6 +49,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select final String containingTableExpression, final Selectable selectable, final JdbcMapping jdbcMapping, + final TypeConfiguration typeConfiguration, final Dialect dialect, final SqmFunctionRegistry sqmFunctionRegistry) { final String columnExpression; @@ -56,7 +58,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select final Integer precision; final Integer scale; if ( selectable.isFormula() ) { - columnExpression = selectable.getTemplate( dialect, sqmFunctionRegistry ); + columnExpression = selectable.getTemplate( dialect, typeConfiguration, sqmFunctionRegistry ); columnDefinition = null; length = null; precision = null; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingsImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingsImpl.java index 989a00b340..05eebfe9cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SelectableMappingsImpl.java @@ -23,6 +23,7 @@ import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.type.CompositeType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; +import org.hibernate.type.spi.TypeConfiguration; /** * @author Christian Beikov @@ -59,6 +60,7 @@ public class SelectableMappingsImpl implements SelectableMappings { Value value, int[] propertyOrder, Mapping mapping, + TypeConfiguration typeConfiguration, Dialect dialect, SqmFunctionRegistry sqmFunctionRegistry) { final List jdbcMappings = new ArrayList<>(); @@ -72,6 +74,7 @@ public class SelectableMappingsImpl implements SelectableMappings { containingTableExpression, selectables.get( i ), jdbcMappings.get( propertyOrder[i] ), + typeConfiguration, dialect, sqmFunctionRegistry ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index ab3aa5e39f..face57d229 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -329,6 +329,7 @@ public abstract class AbstractCollectionPersister sqlWhereStringTemplate = Template.renderWhereStringTemplate( sqlWhereString, dialect, + factory.getTypeConfiguration(), factory.getQueryEngine().getSqmFunctionRegistry() ); } @@ -399,7 +400,11 @@ public abstract class AbstractCollectionPersister elementColumnAliases[j] = selectable.getAlias( dialect, table ); if ( selectable.isFormula() ) { Formula form = (Formula) selectable; - elementFormulaTemplates[j] = form.getTemplate( dialect, factory.getQueryEngine().getSqmFunctionRegistry() ); + elementFormulaTemplates[j] = form.getTemplate( + dialect, + factory.getTypeConfiguration(), + factory.getQueryEngine().getSqmFunctionRegistry() + ); elementFormulas[j] = form.getFormula(); } else { @@ -407,7 +412,11 @@ public abstract class AbstractCollectionPersister elementColumnNames[j] = col.getQuotedName( dialect ); elementColumnWriters[j] = col.getWriteExpr(); elementColumnReaders[j] = col.getReadExpr( dialect ); - elementColumnReaderTemplates[j] = col.getTemplate( dialect, factory.getQueryEngine().getSqmFunctionRegistry() ); + elementColumnReaderTemplates[j] = col.getTemplate( + dialect, + factory.getTypeConfiguration(), + factory.getQueryEngine().getSqmFunctionRegistry() + ); elementColumnIsGettable[j] = true; if ( elementType.isComponentType() ) { // Implements desired behavior specifically for @ElementCollection mappings. @@ -456,7 +465,11 @@ public abstract class AbstractCollectionPersister indexColumnAliases[i] = s.getAlias( dialect ); if ( s.isFormula() ) { Formula indexForm = (Formula) s; - indexFormulaTemplates[i] = indexForm.getTemplate( dialect, factory.getQueryEngine().getSqmFunctionRegistry() ); + indexFormulaTemplates[i] = indexForm.getTemplate( + dialect, + factory.getTypeConfiguration(), + factory.getQueryEngine().getSqmFunctionRegistry() + ); indexFormulas[i] = indexForm.getFormula(); hasFormula = true; } @@ -647,6 +660,7 @@ public abstract class AbstractCollectionPersister manyToManyWhereTemplate = Template.renderWhereStringTemplate( manyToManyWhereString, factory.getJdbcServices().getDialect(), + factory.getTypeConfiguration(), factory.getQueryEngine().getSqmFunctionRegistry() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 81a09a6948..eebd252938 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -777,7 +777,11 @@ public abstract class AbstractEntityPersister Column column = columns.get(i); rootTableKeyColumnNames[i] = column.getQuotedName( dialect ); rootTableKeyColumnReaders[i] = column.getReadExpr( dialect ); - rootTableKeyColumnReaderTemplates[i] = column.getTemplate( dialect, functionRegistry ); + rootTableKeyColumnReaderTemplates[i] = column.getTemplate( + dialect, + factory.getTypeConfiguration(), + functionRegistry + ); identifierAliases[i] = column.getAlias( dialect, bootDescriptor.getRootTable() ); } @@ -806,6 +810,7 @@ public abstract class AbstractEntityPersister sqlWhereStringTemplate = Template.renderWhereStringTemplate( "(" + bootDescriptor.getWhere() + ")", dialect, + factory.getTypeConfiguration(), functionRegistry ); } @@ -853,7 +858,11 @@ public abstract class AbstractEntityPersister foundFormula = true; Formula formula = (Formula) selectable; formula.setFormula( substituteBrackets( formula.getFormula() ) ); - formulaTemplates[k] = selectable.getTemplate( dialect, functionRegistry ); + formulaTemplates[k] = selectable.getTemplate( + dialect, + factory.getTypeConfiguration(), + functionRegistry + ); } else { Column column = (Column) selectable; @@ -961,7 +970,11 @@ public abstract class AbstractEntityPersister for ( int i = 0; i < selectables.size(); i++ ) { Selectable selectable = selectables.get(i); if ( selectable.isFormula() ) { - String template = selectable.getTemplate( dialect, functionRegistry ); + String template = selectable.getTemplate( + dialect, + factory.getTypeConfiguration(), + functionRegistry + ); // formnos[l] = formulaTemplates.size(); // colnos[l] = -1; // formulaTemplates.add( template ); @@ -982,7 +995,11 @@ public abstract class AbstractEntityPersister columnSelectables.add( prop.isSelectable() ); readers[i] = column.getReadExpr( dialect ); - readerTemplates[i] = column.getTemplate( dialect, functionRegistry ); + readerTemplates[i] = column.getTemplate( + dialect, + factory.getTypeConfiguration(), + functionRegistry + ); // columnReaderTemplates.add( readerTemplate ); } } @@ -6196,7 +6213,11 @@ public abstract class AbstractEntityPersister assert attrColumnExpression.equals( selectable.getText(sessionFactory.getJdbcServices().getDialect()) ); - customReadExpr = selectable.getTemplate( dialect, sessionFactory.getQueryEngine().getSqmFunctionRegistry() ); + customReadExpr = selectable.getTemplate( + dialect, + sessionFactory.getTypeConfiguration(), + sessionFactory.getQueryEngine().getSqmFunctionRegistry() + ); customWriteExpr = selectable.getCustomWriteExpression(); Column column = bootValue.getColumns().get( 0 ); columnDefinition = column.getSqlType(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index 74aa45fd2e..d6c6bbe085 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -250,7 +250,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { Column column = columns.get(k); keyCols[k] = column.getQuotedName( dialect ); keyColReaders[k] = column.getReadExpr( dialect ); - keyColReaderTemplates[k] = column.getTemplate( dialect, sqmFunctionRegistry ); + keyColReaderTemplates[k] = column.getTemplate( + dialect, + factory.getTypeConfiguration(), + sqmFunctionRegistry + ); } keyColumns.add( keyCols ); keyColumnReaders.add( keyColReaders ); @@ -285,7 +289,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { Column column = columns.get(k); keyCols[k] = column.getQuotedName( dialect ); keyColReaders[k] = column.getReadExpr( dialect ); - keyColReaderTemplates[k] = column.getTemplate( dialect, sqmFunctionRegistry ); + keyColReaderTemplates[k] = column.getTemplate( + dialect, + factory.getTypeConfiguration(), + sqmFunctionRegistry + ); } keyColumns.add( keyCols ); keyColumnReaders.add( keyColReaders ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index 06b38b7442..a73a2380ec 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -25,7 +25,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.DynamicFilterAliasGenerator; import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.mapping.Column; @@ -304,7 +303,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { if ( discriminator.hasFormula() ) { Formula formula = (Formula) selectable; // discriminatorFormula = formula.getFormula(); - discriminatorFormulaTemplate = formula.getTemplate( dialect, functionRegistry ); + discriminatorFormulaTemplate = formula.getTemplate( + dialect, + factory.getTypeConfiguration(), + functionRegistry + ); discriminatorColumnName = null; discriminatorColumnReaders = null; discriminatorColumnReaderTemplate = null; @@ -314,7 +317,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { Column column = (Column) selectable; discriminatorColumnName = column.getQuotedName( dialect ); discriminatorColumnReaders = column.getReadExpr( dialect ); - discriminatorColumnReaderTemplate = column.getTemplate( dialect, functionRegistry ); + discriminatorColumnReaderTemplate = column.getTemplate( + dialect, + factory.getTypeConfiguration(), + functionRegistry + ); discriminatorAlias = column.getAlias( dialect, persistentClass.getRootTable() ); // discriminatorFormula = null; discriminatorFormulaTemplate = null; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java index 5cbc417844..8618539251 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java @@ -450,7 +450,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { for ( Column col : columns ) { if ( !table.containsColumn(col) ) { int sqlType = col.getSqlTypeCode( mapping ); - buf.append( dialect.getSelectClauseNullString(sqlType) ) + buf.append( dialect.getSelectClauseNullString( sqlType, getFactory().getTypeConfiguration() ) ) .append(" as "); } buf.append(col.getQuotedName(dialect)); @@ -528,7 +528,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { selectableMapping = selectableMappings.values().iterator().next(); final int sqlType = selectableMapping.getJdbcMapping().getJdbcType() .getDefaultSqlTypeCode(); - buf.append( dialect.getSelectClauseNullString( sqlType ) ) + buf.append( dialect.getSelectClauseNullString( sqlType, getFactory().getTypeConfiguration() ) ) .append( " as " ); } buf.append( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingFunctionSqlAstExpression.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingFunctionSqlAstExpression.java index c4a6669c96..c8084e6396 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingFunctionSqlAstExpression.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingFunctionSqlAstExpression.java @@ -138,7 +138,10 @@ public class SelfRenderingFunctionSqlAstExpression } @Override - public String getTemplate(Dialect dialect, SqmFunctionRegistry functionRegistry) { + public String getTemplate( + Dialect dialect, + TypeConfiguration typeConfiguration, + SqmFunctionRegistry functionRegistry) { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/Template.java b/hibernate-core/src/main/java/org/hibernate/sql/Template.java index a8fb810eb8..23a8e212c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/Template.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/Template.java @@ -18,6 +18,7 @@ import org.hibernate.dialect.Dialect; import org.hibernate.internal.util.StringHelper; import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionRegistry; +import org.hibernate.type.spi.TypeConfiguration; /** * Parses SQL fragments specified in mapping documents @@ -94,8 +95,12 @@ public final class Template { return fragment; } - public static String renderWhereStringTemplate(String sqlWhereString, Dialect dialect, SqmFunctionRegistry functionRegistry) { - return renderWhereStringTemplate(sqlWhereString, TEMPLATE, dialect, functionRegistry); + public static String renderWhereStringTemplate( + String sqlWhereString, + Dialect dialect, + TypeConfiguration typeConfiguration, + SqmFunctionRegistry functionRegistry) { + return renderWhereStringTemplate(sqlWhereString, TEMPLATE, dialect, typeConfiguration, functionRegistry); } /** @@ -109,7 +114,12 @@ public final class Template { * @param functionRegistry The registry of all sql functions * @return The rendered sql fragment */ - public static String renderWhereStringTemplate(String sqlWhereString, String placeholder, Dialect dialect, SqmFunctionRegistry functionRegistry ) { + public static String renderWhereStringTemplate( + String sqlWhereString, + String placeholder, + Dialect dialect, + TypeConfiguration typeConfiguration, + SqmFunctionRegistry functionRegistry) { // IMPL NOTE : The basic process here is to tokenize the incoming string and to iterate over each token // in turn. As we process each token, we set a series of flags used to indicate the type of context in @@ -182,6 +192,7 @@ public final class Template { extractUntil( tokens, ")" ), placeholder, dialect, + typeConfiguration, functionRegistry ); result.append( "extract(" ).append( field ).append( " from " ).append( source ).append( ')' ); @@ -273,7 +284,7 @@ public final class Template { } else { result.append( - renderWhereStringTemplate( trimOperands.trimSpec, placeholder, dialect, functionRegistry ) + renderWhereStringTemplate( trimOperands.trimSpec, placeholder, dialect, typeConfiguration, functionRegistry ) ); } result.append( ' ' ); @@ -286,7 +297,7 @@ public final class Template { result.append( "from " ); } - result.append( renderWhereStringTemplate( trimOperands.trimSource, placeholder, dialect, functionRegistry ) ) + result.append( renderWhereStringTemplate( trimOperands.trimSource, placeholder, dialect, typeConfiguration, functionRegistry ) ) .append( ')' ); hasMore = tokens.hasMoreTokens(); @@ -316,7 +327,7 @@ public final class Template { result.append(token); } else if ( isIdentifier(token) - && !isFunctionOrKeyword(lcToken, nextToken, dialect , functionRegistry) ) { + && !isFunctionOrKeyword(lcToken, nextToken, dialect, typeConfiguration, functionRegistry) ) { result.append(placeholder) .append('.') .append( dialect.quote(token) ); @@ -650,17 +661,18 @@ public final class Template { String lcToken, String nextToken, Dialect dialect, + TypeConfiguration typeConfiguration, SqmFunctionRegistry functionRegistry) { return "(".equals( nextToken ) || KEYWORDS.contains( lcToken ) || - isType( lcToken, dialect ) || + isType( lcToken, typeConfiguration ) || isFunction( lcToken, nextToken, functionRegistry ) || dialect.getKeywords().contains( lcToken ) || FUNCTION_KEYWORDS.contains( lcToken ); } - private static boolean isType(String lcToken, Dialect dialect) { - return dialect.isTypeNameRegistered( lcToken ); + private static boolean isType(String lcToken, TypeConfiguration typeConfiguration) { + return typeConfiguration.getDdlTypeRegistry().isTypeNameRegistered( lcToken ); } private static boolean isFunction(String lcToken, String nextToken, SqmFunctionRegistry functionRegistry) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index c5da000e38..79a8cc15df 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -4256,13 +4256,16 @@ public abstract class AbstractSqlAstTranslator implemen appendSql( castTarget.getSqlType() ); } else { + final SqlExpressible expressionType = (SqlExpressible) castTarget.getExpressionType(); appendSql( - getDialect().getCastTypeName( - (SqlExpressible) castTarget.getExpressionType(), - castTarget.getLength(), - castTarget.getPrecision(), - castTarget.getScale() - ) + sessionFactory.getTypeConfiguration().getDdlTypeRegistry() + .getDescriptor( expressionType.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode() ) + .getCastTypeName( + expressionType, + castTarget.getLength(), + castTarget.getPrecision(), + castTarget.getScale() + ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java index a2e5b33084..6915a85d97 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java @@ -159,7 +159,7 @@ public abstract class AbstractSchemaValidator implements SchemaValidator { ExecutionOptions options, Dialect dialect) { boolean typesMatch = dialect.equivalentTypes( column.getSqlTypeCode( metadata ), columnInformation.getTypeCode() ) - || column.getSqlType( dialect, metadata ).toLowerCase(Locale.ROOT) + || column.getSqlType( metadata.getDatabase().getTypeConfiguration(), dialect, metadata ).toLowerCase(Locale.ROOT) .startsWith( columnInformation.getTypeName().toLowerCase(Locale.ROOT) ); if ( !typesMatch ) { throw new SchemaManagementException( diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java index 799b3fe4ef..c8ddf9ee35 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardTableExporter.java @@ -85,14 +85,20 @@ public class StandardTableExporter implements Exporter { if ( isPrimaryKeyIdentity && colName.equals( pkColName ) ) { // to support dialects that have their own identity data type if ( dialect.getIdentityColumnSupport().hasDataTypeInIdentityColumn() ) { - buf.append( ' ' ).append( col.getSqlType( dialect, metadata ) ); + buf.append( ' ' ).append( + col.getSqlType( metadata.getDatabase().getTypeConfiguration(), dialect, metadata ) + ); } String identityColumnString = dialect.getIdentityColumnSupport() .getIdentityColumnString( col.getSqlTypeCode(metadata) ); buf.append( ' ' ).append( identityColumnString ); } else { - final String columnType = col.getSqlType( dialect, metadata ); + final String columnType = col.getSqlType( + metadata.getDatabase().getTypeConfiguration(), + dialect, + metadata + ); if ( col.getGeneratedAs()==null || dialect.hasDataTypeBeforeGeneratedAs() ) { buf.append( ' ' ).append( columnType ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JdbcType.java index 035a485f57..6cdd4fa7cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JdbcType.java @@ -9,12 +9,14 @@ package org.hibernate.type.descriptor.jdbc; import java.io.Serializable; import java.sql.Types; +import org.hibernate.engine.jdbc.Size; import org.hibernate.query.sqm.CastType; import org.hibernate.type.SqlTypes; import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.java.BasicJavaType; import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; /** @@ -56,7 +58,7 @@ public interface JdbcType extends Serializable { * A {@linkplain SqlTypes JDBC type code} that identifies the SQL column type to * be used for schema generation. *

    - * This value is passed to {@link org.hibernate.dialect.Dialect#getTypeName(int)} + * This value is passed to {@link DdlTypeRegistry#getTypeName(int, Size)} * to obtain the SQL column type. * * @return a JDBC type code @@ -108,7 +110,11 @@ public interface JdbcType extends Serializable { ValueExtractor getExtractor(JavaType javaType); default boolean isInteger() { - switch ( getJdbcTypeCode() ) { + return isInteger( getJdbcTypeCode() ); + } + + static boolean isInteger(int typeCode) { + switch ( typeCode ) { case Types.BIT: case Types.TINYINT: case Types.SMALLINT: @@ -120,7 +126,11 @@ public interface JdbcType extends Serializable { } default boolean isFloat() { - switch ( getJdbcTypeCode() ) { + return isFloat( getJdbcTypeCode() ); + } + + static boolean isFloat(int typeCode) { + switch ( typeCode ) { case Types.FLOAT: case Types.REAL: case Types.DOUBLE: @@ -130,7 +140,11 @@ public interface JdbcType extends Serializable { } default boolean isDecimal() { - switch ( getJdbcTypeCode() ) { + return isDecimal( getJdbcTypeCode() ); + } + + static boolean isDecimal(int typeCode) { + switch ( typeCode ) { case Types.DECIMAL: case Types.NUMERIC: return true; @@ -139,7 +153,11 @@ public interface JdbcType extends Serializable { } default boolean isNumber() { - switch ( getJdbcTypeCode() ) { + return isNumber( getJdbcTypeCode() ); + } + + static boolean isNumber(int typeCode) { + switch ( typeCode ) { case Types.BIT: case Types.TINYINT: case Types.SMALLINT: @@ -156,7 +174,11 @@ public interface JdbcType extends Serializable { } default boolean isBinary() { - switch ( getJdbcTypeCode() ) { + return isBinary( getJdbcTypeCode() ); + } + + static boolean isBinary(int typeCode) { + switch ( typeCode ) { case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: @@ -167,7 +189,11 @@ public interface JdbcType extends Serializable { } default boolean isString() { - switch ( getJdbcTypeCode() ) { + return isString( getJdbcTypeCode() ); + } + + static boolean isString(int typeCode) { + switch ( typeCode ) { case Types.CHAR: case Types.NCHAR: case Types.VARCHAR: @@ -182,7 +208,11 @@ public interface JdbcType extends Serializable { } default boolean isTemporal() { - switch ( getJdbcTypeCode() ) { + return isTemporal( getDefaultSqlTypeCode() ); + } + + static boolean isTemporal(int typeCode) { + switch ( typeCode ) { case Types.DATE: case Types.TIME: case Types.TIMESTAMP: @@ -193,7 +223,11 @@ public interface JdbcType extends Serializable { } default boolean isInterval() { - switch ( getDefaultSqlTypeCode() ) { + return isInterval( getDefaultSqlTypeCode() ); + } + + static boolean isInterval(int typeCode) { + switch ( typeCode ) { case SqlTypes.INTERVAL_SECOND: return true; } @@ -201,7 +235,11 @@ public interface JdbcType extends Serializable { } default CastType getCastType() { - switch ( getJdbcTypeCode() ) { + return getCastType( getJdbcTypeCode() ); + } + + static CastType getCastType(int typeCode) { + switch ( typeCode ) { case Types.INTEGER: case Types.TINYINT: case Types.SMALLINT: diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/DdlType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/DdlType.java new file mode 100644 index 0000000000..3765b9dcc9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/DdlType.java @@ -0,0 +1,63 @@ +/* + * 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.type.descriptor.sql; + +import java.io.Serializable; +import java.sql.Types; + +import org.hibernate.engine.jdbc.Size; +import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.metamodel.mapping.SqlExpressible; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.jdbc.JdbcType; + +/** + * Descriptor for a DDL type. + * + * @author Christian Beikov + */ +public interface DdlType extends Serializable { + + /** + * The {@linkplain SqlTypes SQL type code} of the descriptor. + * + * @return a SQL type code + */ + int getSqlTypeCode(); + + String getRawTypeName(); + + String getTypeNamePattern(); + + default String getTypeName(Size size) { + return getTypeName( size.getLength(), size.getPrecision(), size.getScale() ); + } + + String getTypeName(Long size, Integer precision, Integer scale); + + String getCastTypeName(JdbcType jdbcType, JavaType javaType); + + /** + * Get the name of the database type appropriate for casting operations + * (via the CAST() SQL function) for the given {@link SqlExpressible} + * SQL type. + * + * @return The database type name + */ + default String getCastTypeName(SqlExpressible type, Long length, Integer precision, Integer scale) { + return getCastTypeName( + type.getJdbcMapping().getJdbcType(), + type.getJdbcMapping().getJavaTypeDescriptor(), + length, + precision, + scale + ); + } + + String getCastTypeName(JdbcType jdbcType, JavaType javaType, Long length, Integer precision, Integer scale); +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/BinaryFloatDdlType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/BinaryFloatDdlType.java new file mode 100644 index 0000000000..6f9aa1fb38 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/BinaryFloatDdlType.java @@ -0,0 +1,34 @@ +/* + * 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.type.descriptor.sql.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.type.SqlTypes; + +import static java.lang.Math.log; + +public class BinaryFloatDdlType extends DdlTypeImpl { + + //needed for converting precision from decimal to binary digits + private static final double LOG_BASE2OF10 = log(10)/log(2); + + public BinaryFloatDdlType(Dialect dialect) { + this( "float($p)", dialect ); + } + + public BinaryFloatDdlType(String typeNamePattern, Dialect dialect) { + super( SqlTypes.FLOAT, typeNamePattern, dialect ); + } + + @Override + public String getTypeName(Long size, Integer precision, Integer scale) { + if ( precision != null ) { + return super.getTypeName( size, (int) ( precision / LOG_BASE2OF10 ), scale ); + } + return super.getTypeName( size, precision, scale ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/CapacityDependentDdlType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/CapacityDependentDdlType.java new file mode 100644 index 0000000000..54e657607b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/CapacityDependentDdlType.java @@ -0,0 +1,109 @@ +/* + * 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.type.descriptor.sql.internal; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import org.hibernate.dialect.Dialect; + +/** + * Descriptor for a SQL type. + * + * @author Christian Beikov + */ +public class CapacityDependentDdlType extends DdlTypeImpl { + + private final TypeEntry[] typeEntries; + + private CapacityDependentDdlType(Builder builder) { + super( + builder.sqlTypeCode, + builder.typeNamePattern, + builder.castTypeNamePattern, + builder.dialect + ); + builder.typeEntries.sort( Comparator.naturalOrder() ); + this.typeEntries = builder.typeEntries.toArray(new TypeEntry[0]); + } + + @Override + public String getTypeName(Long size, Integer precision, Integer scale) { + if ( size != null && size > 0 ) { + for ( TypeEntry typeEntry : typeEntries ) { + if ( size <= typeEntry.capacity ) { + return replace( typeEntry.typeNamePattern, size, precision, scale ); + } + } + } + else if ( precision != null && precision > 0 ) { + for ( TypeEntry typeEntry : typeEntries ) { + if ( precision <= typeEntry.capacity ) { + return replace( typeEntry.typeNamePattern, size, precision, scale ); + } + } + } + return super.getTypeName( size, precision, scale ); + } + + public static Builder builder(int sqlTypeCode, String typeNamePattern, Dialect dialect) { + return builder( sqlTypeCode, typeNamePattern, typeNamePattern, dialect ); + } + + public static Builder builder( + int sqlTypeCode, + String typeNamePattern, + String castTypeNamePattern, + Dialect dialect) { + return new Builder( sqlTypeCode, typeNamePattern, castTypeNamePattern, dialect ); + } + + public static class Builder { + private final int sqlTypeCode; + private final String typeNamePattern; + private final String castTypeNamePattern; + private final Dialect dialect; + private final List typeEntries; + + private Builder( + int sqlTypeCode, + String typeNamePattern, + String castTypeNamePattern, + Dialect dialect) { + this.sqlTypeCode = sqlTypeCode; + this.typeNamePattern = typeNamePattern; + this.castTypeNamePattern = castTypeNamePattern; + this.dialect = dialect; + this.typeEntries = new ArrayList<>(); + } + + public Builder withTypeCapacity(long capacity, String typeNamePattern) { + typeEntries.add( new TypeEntry( capacity, typeNamePattern ) ); + return this; + } + + public CapacityDependentDdlType build() { + return new CapacityDependentDdlType( this ); + } + } + + private static class TypeEntry implements Comparable { + private final long capacity; + private final String typeNamePattern; + + public TypeEntry(long capacity, String typeNamePattern) { + this.capacity = capacity; + this.typeNamePattern = typeNamePattern; + } + + @Override + public int compareTo(TypeEntry o) { + return Long.compare( capacity, o.capacity ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/DdlTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/DdlTypeImpl.java new file mode 100644 index 0000000000..5aed56c20b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/DdlTypeImpl.java @@ -0,0 +1,130 @@ +/* + * 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.type.descriptor.sql.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.Size; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.sql.DdlType; + +/** + * Descriptor for a SQL type. + * + * @author Christian Beikov + */ +public class DdlTypeImpl implements DdlType { + + private final int sqlTypeCode; + private final String typeNamePattern; + private final String castTypeNamePattern; + private final boolean castTypeNameIsStatic; + private final Dialect dialect; + + public DdlTypeImpl(int sqlTypeCode, String typeNamePattern, Dialect dialect) { + this( sqlTypeCode, typeNamePattern, typeNamePattern, dialect ); + } + + public DdlTypeImpl( + int sqlTypeCode, + String typeNamePattern, + String castTypeNamePattern, + Dialect dialect) { + this.sqlTypeCode = sqlTypeCode; + this.typeNamePattern = typeNamePattern; + this.castTypeNamePattern = castTypeNamePattern; + this.castTypeNameIsStatic = !castTypeNamePattern.contains( "$s" ) + && !castTypeNamePattern.contains( "$l" ) + && !castTypeNamePattern.contains( "$p" ); + this.dialect = dialect; + } + + @Override + public int getSqlTypeCode() { + return sqlTypeCode; + } + + @Override + public String getRawTypeName() { + //trim off the length/precision/scale + final int paren = typeNamePattern.indexOf( '(' ); + return paren > 0 ? typeNamePattern.substring( 0, paren ) : typeNamePattern; + } + + @Override + public String getTypeNamePattern() { + return typeNamePattern; + } + + @Override + public String getTypeName(Long size, Integer precision, Integer scale) { + return replace( typeNamePattern, size, precision, scale ); + } + + @Override + public String getCastTypeName(JdbcType jdbcType, JavaType javaType, Long length, Integer precision, Integer scale) { + if ( length == null && precision == null ) { + return getCastTypeName( jdbcType, javaType ); + } + else { + //use the given length/precision/scale + if ( precision != null && scale == null ) { + //needed for cast(x as BigInteger(p)) + scale = javaType.getDefaultSqlScale( dialect, jdbcType ); + } + } + + return getTypeName( length, precision, scale ); + } + + @Override + public String getCastTypeName(JdbcType jdbcType, JavaType javaType) { + if ( castTypeNameIsStatic ) { + return castTypeNamePattern; + } + Long length = null; + Integer precision = null; + Integer scale = null; + switch ( jdbcType.getDefaultSqlTypeCode() ) { + case SqlTypes.VARCHAR: + length = (long) dialect.getMaxVarcharLength(); + break; + case SqlTypes.NVARCHAR: + length = (long) dialect.getMaxNVarcharLength(); + break; + case SqlTypes.VARBINARY: + length = (long) dialect.getMaxVarbinaryLength(); + break; + } + final Size size = dialect.getSizeStrategy().resolveSize( + jdbcType, + javaType, + precision, + scale, + length + ); + return replace( castTypeNamePattern, size.getLength(), size.getPrecision(), size.getScale() ); + } + + /** + * Fill in the placemarkers with the given length, precision, and scale. + */ + public static String replace(String type, Long size, Integer precision, Integer scale) { + if ( scale != null ) { + type = StringHelper.replaceOnce( type, "$s", scale.toString() ); + } + if ( size != null ) { + type = StringHelper.replaceOnce( type, "$l", size.toString() ); + } + if ( precision != null ) { + type = StringHelper.replaceOnce( type, "$p", precision.toString() ); + } + return type; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/Scale6IntervalSecondDdlType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/Scale6IntervalSecondDdlType.java new file mode 100644 index 0000000000..f0219abfcb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/Scale6IntervalSecondDdlType.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.type.descriptor.sql.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.type.SqlTypes; + +public class Scale6IntervalSecondDdlType extends DdlTypeImpl { + + public Scale6IntervalSecondDdlType(Dialect dialect) { + this( "interval second($s)", dialect ); + } + + public Scale6IntervalSecondDdlType(String typeNamePattern, Dialect dialect) { + super( SqlTypes.INTERVAL_SECOND, typeNamePattern, dialect ); + } + @Override + public String getTypeName(Long size, Integer precision, Integer scale) { + // The maximum scale for `interval second` is 6 unfortunately so we have to use numeric by default + if ( scale == null || scale > 6 ) { + return DdlTypeImpl.replace( "numeric($p,$s)", size, precision, scale ); + } + return super.getTypeName( size, precision, scale ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/spi/DdlTypeRegistry.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/spi/DdlTypeRegistry.java new file mode 100644 index 0000000000..12878d916b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/spi/DdlTypeRegistry.java @@ -0,0 +1,134 @@ +/* + * 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.type.descriptor.sql.spi; + +import java.io.Serializable; +import java.sql.Types; +import java.util.HashMap; +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.Size; +import org.hibernate.type.descriptor.sql.DdlType; +import org.hibernate.type.spi.TypeConfiguration; + +import org.jboss.logging.Logger; + +/** + * Basically a map from SQL type code (int) -> {@link DdlType} + * + * @author Christian Beikov + * + * @since 6.0 + */ +public class DdlTypeRegistry implements Serializable { + private static final Logger log = Logger.getLogger( DdlTypeRegistry.class ); + + private final Map ddlTypes = new HashMap<>(); + + public DdlTypeRegistry(TypeConfiguration typeConfiguration) { +// this.typeConfiguration = typeConfiguration; + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // baseline descriptors + + public void addDescriptor(DdlType ddlType) { + final DdlType previous = ddlTypes.put( ddlType.getSqlTypeCode(), ddlType ); + if ( previous != null && previous != ddlType ) { + log.debugf( "addDescriptor(%s) replaced previous registration(%s)", ddlType, previous ); + } + } + + public void addDescriptor(int sqlTypeCode, DdlType ddlType) { + final DdlType previous = ddlTypes.put( sqlTypeCode, ddlType ); + if ( previous != null && previous != ddlType ) { + log.debugf( "addDescriptor(%d, %s) replaced previous registration(%s)", sqlTypeCode, ddlType, previous ); + } + } + + public void addDescriptorIfAbsent(DdlType jdbcType) { + ddlTypes.putIfAbsent( jdbcType.getSqlTypeCode(), jdbcType ); + } + + public void addDescriptorIfAbsent(int sqlTypeCode, DdlType jdbcType) { + ddlTypes.putIfAbsent( sqlTypeCode, jdbcType ); + } + + public DdlType getDescriptor(int sqlTypeCode) { + return ddlTypes.get( sqlTypeCode ); + } + + public String getTypeName(int typeCode, Dialect dialect) { + // explicitly enforce dialect's default precisions + switch ( typeCode ) { + case Types.DECIMAL: + case Types.NUMERIC: + return getTypeName( typeCode, Size.precision( dialect.getDefaultDecimalPrecision() ) ); + case Types.FLOAT: + case Types.REAL: + return getTypeName( typeCode, Size.precision( dialect.getFloatPrecision() ) ); + case Types.DOUBLE: + return getTypeName( typeCode, Size.precision( dialect.getDoublePrecision() ) ); + case Types.TIMESTAMP: + case Types.TIMESTAMP_WITH_TIMEZONE: + return getTypeName( typeCode, Size.precision( dialect.getDefaultTimestampPrecision() ) ); + default: + return getTypeName( typeCode, Size.nil() ); + } + } + + public String getTypeName(int typeCode, Size size) { + return getTypeName( typeCode, size.getLength(), size.getPrecision(), size.getScale() ); + } + + /** + * Get the SQL type name for the specified {@link java.sql.Types JDBC type code} + * and size, filling in the placemarkers {@code $l}, {@code $p}, and {@code $s} + * with the given length, precision, and scale. + * + * @param typeCode the JDBC type code + * @param size the SQL length, if any + * @param precision the SQL precision, if any + * @param scale the SQL scale, if any + * + * @return the associated name with smallest capacity >= size, if available and + * the default type name otherwise + */ + public String getTypeName(int typeCode, Long size, Integer precision, Integer scale) { + final DdlType descriptor = getDescriptor( typeCode ); + if ( descriptor == null ) { + throw new HibernateException( + String.format( + "No type mapping for java.sql.Types code: %s", + typeCode + ) + ); + } + return descriptor.getTypeName( size, precision, scale ); + } + + /** + * Whether or not the given type name has been registered for this dialect (including both hibernate type names and + * custom-registered type names). + * + * @param typeName the type name. + * + * @return true if the given string has been registered either as a hibernate type or as a custom-registered one + */ + public boolean isTypeNameRegistered(final String typeName) { + for ( DdlType value : ddlTypes.values() ) { + if ( value.getRawTypeName().equals( typeName ) ) { + return true; + } + } + + return false; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java b/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java index 4b7c0929a4..5ecb9054d5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java +++ b/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java @@ -63,6 +63,7 @@ import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.internal.BasicTypeImpl; import jakarta.persistence.TemporalType; @@ -99,6 +100,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable { // things available during both boot and runtime lifecycle phases private final transient JavaTypeRegistry javaTypeRegistry; private final transient JdbcTypeRegistry jdbcTypeRegistry; + private final transient DdlTypeRegistry ddlTypeRegistry; private final transient BasicTypeRegistry basicTypeRegistry; private final transient Map> jdbcToHibernateTypeContributionMap = new HashMap<>(); @@ -108,7 +110,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable { this.javaTypeRegistry = new JavaTypeRegistry( this ); this.jdbcTypeRegistry = new JdbcTypeRegistry( this ); - + this.ddlTypeRegistry = new DdlTypeRegistry( this ); this.basicTypeRegistry = new BasicTypeRegistry( this ); StandardBasicTypes.prime( this ); } @@ -121,7 +123,6 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable { return basicTypeRegistry; } - public JavaTypeRegistry getJavaTypeRegistry() { return javaTypeRegistry; } @@ -130,6 +131,10 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable { return jdbcTypeRegistry; } + public DdlTypeRegistry getDdlTypeRegistry() { + return ddlTypeRegistry; + } + public JdbcTypeIndicators getCurrentBaseSqlTypeIndicators() { return scope.getCurrentBaseSqlTypeIndicators(); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/DB2DialectTestCase.java b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/DB2DialectTestCase.java index c1b35f2c59..4080d62155 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/DB2DialectTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/DB2DialectTestCase.java @@ -11,7 +11,9 @@ import java.sql.Types; import org.hibernate.dialect.DB2Dialect; import org.hibernate.engine.jdbc.Size; import org.hibernate.query.spi.Limit; +import org.hibernate.type.spi.TypeConfiguration; +import org.junit.Before; import org.junit.Test; import org.hibernate.testing.TestForIssue; @@ -28,11 +30,18 @@ import static org.junit.Assert.assertTrue; public class DB2DialectTestCase extends BaseUnitTestCase { private final DB2Dialect dialect = new DB2Dialect(); + private TypeConfiguration typeConfiguration; + + @Before + public void setup() { + typeConfiguration = new TypeConfiguration(); + dialect.contributeTypes( () -> typeConfiguration, null ); + } @Test @TestForIssue(jiraKey = "HHH-6866") public void testGetDefaultBinaryTypeName() { - String actual = dialect.getTypeName( Types.BINARY ); + String actual = typeConfiguration.getDdlTypeRegistry().getTypeName( Types.BINARY, dialect ); assertEquals( "The default column length is 255, but char length on DB2 is limited to 254", "varchar($l) for bit data", @@ -44,7 +53,7 @@ public class DB2DialectTestCase extends BaseUnitTestCase { @TestForIssue(jiraKey = "HHH-6866") public void testGetExplicitBinaryTypeName() { // lower bound - String actual = dialect.getTypeName( Types.BINARY, Size.length(1) ); + String actual = typeConfiguration.getDdlTypeRegistry().getTypeName( Types.BINARY, Size.length( 1) ); assertEquals( "Wrong binary type", "char(1) for bit data", @@ -52,7 +61,7 @@ public class DB2DialectTestCase extends BaseUnitTestCase { ); // upper bound - actual = dialect.getTypeName( Types.BINARY, Size.length(254) ); + actual = typeConfiguration.getDdlTypeRegistry().getTypeName( Types.BINARY, Size.length( 254) ); assertEquals( "Wrong binary type. 254 is the max length in DB2", "char(254) for bit data", @@ -60,7 +69,7 @@ public class DB2DialectTestCase extends BaseUnitTestCase { ); // exceeding upper bound - actual = dialect.getTypeName( Types.BINARY, Size.length(255) ); + actual = typeConfiguration.getDdlTypeRegistry().getTypeName( Types.BINARY, Size.length( 255) ); assertEquals( "Wrong binary type. Should be varchar for length > 254", "varchar(255) for bit data", diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/DB2zDialectInitTestCase.java b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/DB2zDialectInitTestCase.java index 2de4dba02f..5d6664cbb2 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/DB2zDialectInitTestCase.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/DB2zDialectInitTestCase.java @@ -5,9 +5,6 @@ import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.junit.Test; -import java.util.List; - -import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; import static org.junit.Assert.assertNotNull; /** @@ -18,11 +15,7 @@ import static org.junit.Assert.assertNotNull; public class DB2zDialectInitTestCase { static class DB2zDialectWithExplicitTimezoneSupport extends DB2zDialect { - @Override - protected List getSupportedJdbcTypeCodes() { - return List.of(TIMESTAMP_WITH_TIMEZONE); - } - } + } @Test public void testInitWithTimezoneSupport() { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/id/enhanced/SequenceStyleConfigUnitTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/id/enhanced/SequenceStyleConfigUnitTest.java index c4c57724a3..511cc7cd8a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/id/enhanced/SequenceStyleConfigUnitTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/id/enhanced/SequenceStyleConfigUnitTest.java @@ -19,6 +19,7 @@ import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.sequence.ANSISequenceSupport; import org.hibernate.dialect.sequence.SequenceSupport; +import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.id.OptimizableGenerator; import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.enhanced.DatabaseStructure; @@ -64,6 +65,10 @@ public class SequenceStyleConfigUnitTest { .applySetting( AvailableSettings.DIALECT, PooledSequenceDialect.class.getName() ) .build()) { MetadataBuildingContextTestingImpl buildingContext = new MetadataBuildingContextTestingImpl( serviceRegistry ); + serviceRegistry.getService( JdbcServices.class ).getDialect().contributeTypes( + () -> buildingContext.getBootstrapContext().getTypeConfiguration(), + serviceRegistry + ); Properties props = buildGeneratorPropertiesBase( buildingContext ); SequenceStyleGenerator generator = new SequenceStyleGenerator(); generator.configure( @@ -110,6 +115,10 @@ public class SequenceStyleConfigUnitTest { .applySetting( AvailableSettings.DIALECT, TableDialect.class.getName() ) .build()) { MetadataBuildingContextTestingImpl buildingContext = new MetadataBuildingContextTestingImpl( serviceRegistry ); + serviceRegistry.getService( JdbcServices.class ).getDialect().contributeTypes( + () -> buildingContext.getBootstrapContext().getTypeConfiguration(), + serviceRegistry + ); Properties props = buildGeneratorPropertiesBase( buildingContext ); SequenceStyleGenerator generator = new SequenceStyleGenerator(); generator.configure( @@ -146,6 +155,10 @@ public class SequenceStyleConfigUnitTest { .applySetting( AvailableSettings.DIALECT, SequenceDialect.class.getName() ) .build()) { MetadataBuildingContextTestingImpl buildingContext = new MetadataBuildingContextTestingImpl( serviceRegistry ); + serviceRegistry.getService( JdbcServices.class ).getDialect().contributeTypes( + () -> buildingContext.getBootstrapContext().getTypeConfiguration(), + serviceRegistry + ); Properties props = buildGeneratorPropertiesBase( buildingContext ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" ); @@ -172,6 +185,10 @@ public class SequenceStyleConfigUnitTest { .applySetting( AvailableSettings.DIALECT, PooledSequenceDialect.class.getName() ) .build()) { MetadataBuildingContextTestingImpl buildingContext = new MetadataBuildingContextTestingImpl( serviceRegistry ); + serviceRegistry.getService( JdbcServices.class ).getDialect().contributeTypes( + () -> buildingContext.getBootstrapContext().getTypeConfiguration(), + serviceRegistry + ); Properties props = buildGeneratorPropertiesBase( buildingContext ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" ); @@ -204,6 +221,10 @@ public class SequenceStyleConfigUnitTest { .applySetting( AvailableSettings.DIALECT, TableDialect.class.getName() ) .build()) { MetadataBuildingContextTestingImpl buildingContext = new MetadataBuildingContextTestingImpl( serviceRegistry ); + serviceRegistry.getService( JdbcServices.class ).getDialect().contributeTypes( + () -> buildingContext.getBootstrapContext().getTypeConfiguration(), + serviceRegistry + ); Properties props = buildGeneratorPropertiesBase( buildingContext ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" ); @@ -234,6 +255,10 @@ public class SequenceStyleConfigUnitTest { .applySetting( AvailableSettings.DIALECT, SequenceDialect.class.getName() ) .build()) { MetadataBuildingContextTestingImpl buildingContext = new MetadataBuildingContextTestingImpl( serviceRegistry ); + serviceRegistry.getService( JdbcServices.class ).getDialect().contributeTypes( + () -> buildingContext.getBootstrapContext().getTypeConfiguration(), + serviceRegistry + ); Properties props = buildGeneratorPropertiesBase( buildingContext ); props.setProperty( SequenceStyleGenerator.FORCE_TBL_PARAM, "true" ); @@ -269,6 +294,10 @@ public class SequenceStyleConfigUnitTest { .applySetting( AvailableSettings.DIALECT, SequenceDialect.class.getName() ) .build()) { MetadataBuildingContextTestingImpl buildingContext = new MetadataBuildingContextTestingImpl( serviceRegistry ); + serviceRegistry.getService( JdbcServices.class ).getDialect().contributeTypes( + () -> buildingContext.getBootstrapContext().getTypeConfiguration(), + serviceRegistry + ); Properties props = buildGeneratorPropertiesBase( buildingContext ); props.setProperty( SequenceStyleGenerator.OPT_PARAM, StandardOptimizerDescriptor.NONE.getExternalName() ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); @@ -334,6 +363,10 @@ public class SequenceStyleConfigUnitTest { .applySetting( AvailableSettings.DIALECT, PooledSequenceDialect.class.getName() ) .build()) { MetadataBuildingContextTestingImpl buildingContext = new MetadataBuildingContextTestingImpl( serviceRegistry ); + serviceRegistry.getService( JdbcServices.class ).getDialect().contributeTypes( + () -> buildingContext.getBootstrapContext().getTypeConfiguration(), + serviceRegistry + ); Properties props = buildGeneratorPropertiesBase( buildingContext ); props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" ); SequenceStyleGenerator generator = new SequenceStyleGenerator(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/env/DefaultSchemaNameResolverTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/env/DefaultSchemaNameResolverTest.java index ee1d0c3ff7..f53a670d04 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/env/DefaultSchemaNameResolverTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jdbc/env/DefaultSchemaNameResolverTest.java @@ -36,12 +36,7 @@ public class DefaultSchemaNameResolverTest { ConnectionProxy.generateProxy( new ConnectionProxy( SCHEMA_NAME ) ); String schemaName = DefaultSchemaNameResolver.INSTANCE.resolveSchemaName( connectionSupportsGetSchemaName, - new Dialect() { - @Override - public DatabaseVersion getVersion() { - return ZERO_VERSION; - } - } + new Dialect( ZERO_VERSION ) {} ); assertEquals( SCHEMA_NAME, schemaName ); @@ -49,12 +44,7 @@ public class DefaultSchemaNameResolverTest { ConnectionProxy.generateProxy( new ConnectionProxy( null ) ); schemaName = DefaultSchemaNameResolver.INSTANCE.resolveSchemaName( connectionNotSupportGetSchemaName, - new Dialect() { - - @Override - public DatabaseVersion getVersion() { - return ZERO_VERSION; - } + new Dialect( ZERO_VERSION ) { @Override public String getCurrentSchemaCommand() { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/literal/AbstractCriteriaLiteralHandlingModeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/literal/AbstractCriteriaLiteralHandlingModeTest.java index 9f4b3575f9..833421d047 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/literal/AbstractCriteriaLiteralHandlingModeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/literal/AbstractCriteriaLiteralHandlingModeTest.java @@ -99,10 +99,11 @@ public abstract class AbstractCriteriaLiteralHandlingModeTest extends BaseEntity return getDialect().castPattern( CastType.OTHER, castType ) .replace( "?2", - getDialect().getUnboundedTypeName( - typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.VARCHAR ), - typeConfiguration.getJavaTypeRegistry().getDescriptor( String.class ) - ) + typeConfiguration.getDdlTypeRegistry().getDescriptor( SqlTypes.VARCHAR ) + .getCastTypeName( + typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.VARCHAR ), + typeConfiguration.getJavaTypeRegistry().getDescriptor( String.class ) + ) ) .replace( "?1", expression ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/type/AbstractJavaTimeTypeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/AbstractJavaTimeTypeTest.java index 69d16bd226..2b5211f288 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/type/AbstractJavaTimeTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/AbstractJavaTimeTypeTest.java @@ -57,12 +57,7 @@ public abstract class AbstractJavaTimeTypeTest extends BaseCoreFunctionalT return DialectContext.getDialect(); } catch (Exception e) { - return new Dialect() { - @Override - public DatabaseVersion getVersion(){ - return ZERO_VERSION; - } - }; + return new Dialect( ZERO_VERSION ) {}; } } diff --git a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/manytomany/sametable/BasicSametable.java b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/manytomany/sametable/BasicSametable.java index f579c8ca91..7d80f9fed8 100644 --- a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/manytomany/sametable/BasicSametable.java +++ b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/manytomany/sametable/BasicSametable.java @@ -11,12 +11,14 @@ import java.util.Arrays; import jakarta.persistence.EntityManager; import org.hibernate.Session; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase; import org.hibernate.orm.test.envers.Priority; import org.hibernate.orm.test.envers.entities.manytomany.sametable.Child1Entity; import org.hibernate.orm.test.envers.entities.manytomany.sametable.Child2Entity; import org.hibernate.orm.test.envers.entities.manytomany.sametable.ParentEntity; import org.hibernate.orm.test.envers.tools.TestTools; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.junit.Assert; import org.junit.Test; @@ -43,6 +45,8 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase { @Priority(10) public void initData() { EntityManager em = getEntityManager(); + DdlTypeRegistry ddlTypeRegistry = em.unwrap( SessionImplementor.class ).getTypeConfiguration() + .getDdlTypeRegistry(); em.getTransaction().begin(); Session session = (Session) em.getDelegate(); @@ -56,17 +60,17 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase { em.getTransaction().begin(); session = (Session) em.getDelegate(); session.createNativeQuery( - "CREATE TABLE children ( parent_id " + getDialect().getTypeName( Types.INTEGER ) + - ", child1_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + - ", child2_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + " )" + "CREATE TABLE children ( parent_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + + ", child1_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + + ", child2_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + " )" ).executeUpdate(); session.createNativeQuery( - "CREATE TABLE children_AUD ( REV " + getDialect().getTypeName( Types.INTEGER ) + " NOT NULL" + - ", REVEND " + getDialect().getTypeName( Types.INTEGER ) + - ", REVTYPE " + getDialect().getTypeName( Types.TINYINT ) + - ", parent_id " + getDialect().getTypeName( Types.INTEGER ) + - ", child1_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + - ", child2_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + " )" + "CREATE TABLE children_AUD ( REV " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + " NOT NULL" + + ", REVEND " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + + ", REVTYPE " + ddlTypeRegistry.getTypeName( Types.TINYINT, getDialect() ) + + ", parent_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + + ", child1_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + + ", child2_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + " )" ).executeUpdate(); em.getTransaction().commit(); em.clear(); diff --git a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTestCustomRevEnt.java b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTestCustomRevEnt.java index 23bd147e68..bdbed5e2a4 100644 --- a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTestCustomRevEnt.java +++ b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTestCustomRevEnt.java @@ -17,6 +17,7 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import org.hibernate.Session; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.envers.configuration.EnversSettings; import org.hibernate.envers.strategy.ValidityAuditStrategy; import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase; @@ -26,6 +27,7 @@ import org.hibernate.orm.test.envers.entities.manytomany.sametable.Child2Entity; import org.hibernate.orm.test.envers.entities.manytomany.sametable.ParentEntity; import org.hibernate.orm.test.envers.entities.reventity.CustomDateRevEntity; import org.hibernate.orm.test.envers.tools.TestTools; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.junit.Test; @@ -68,6 +70,8 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu @Priority(10) public void initData() { EntityManager em = getEntityManager(); + DdlTypeRegistry ddlTypeRegistry = em.unwrap( SessionImplementor.class ).getTypeConfiguration() + .getDdlTypeRegistry(); // We need first to modify the columns in the middle (join table) to // allow null values. Hbm2ddl doesn't seem @@ -82,19 +86,19 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu em.getTransaction().begin(); session = (Session) em.getDelegate(); session.createNativeQuery( - "CREATE TABLE children ( parent_id " + getDialect().getTypeName( Types.INTEGER ) + - ", child1_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + - ", child2_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + " )" + "CREATE TABLE children ( parent_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + + ", child1_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + + ", child2_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + " )" ) .executeUpdate(); session.createNativeQuery( - "CREATE TABLE children_AUD ( REV " + getDialect().getTypeName( Types.INTEGER ) + " NOT NULL" + - ", REVEND " + getDialect().getTypeName( Types.INTEGER ) + - ", " + revendTimestampColumName + " " + getDialect().getTypeName( Types.TIMESTAMP ) + - ", REVTYPE " + getDialect().getTypeName( Types.TINYINT ) + - ", parent_id " + getDialect().getTypeName( Types.INTEGER ) + - ", child1_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + - ", child2_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + " )" + "CREATE TABLE children_AUD ( REV " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + " NOT NULL" + + ", REVEND " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + + ", " + revendTimestampColumName + " " + ddlTypeRegistry.getTypeName( Types.TIMESTAMP, getDialect() ) + + ", REVTYPE " + ddlTypeRegistry.getTypeName( Types.TINYINT, getDialect() ) + + ", parent_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + + ", child1_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + + ", child2_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + " )" ) .executeUpdate(); em.getTransaction().commit(); diff --git a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTsTest.java b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTsTest.java index 8d23084ae1..060d52a02f 100644 --- a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTsTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTsTest.java @@ -21,6 +21,7 @@ import org.hibernate.dialect.Dialect; import org.hibernate.dialect.MariaDBDialect; import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.SybaseASEDialect; +import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.envers.configuration.EnversSettings; import org.hibernate.envers.enhanced.SequenceIdRevisionEntity; import org.hibernate.envers.strategy.ValidityAuditStrategy; @@ -30,6 +31,7 @@ import org.hibernate.orm.test.envers.entities.manytomany.sametable.Child1Entity; import org.hibernate.orm.test.envers.entities.manytomany.sametable.Child2Entity; import org.hibernate.orm.test.envers.entities.manytomany.sametable.ParentEntity; import org.hibernate.orm.test.envers.tools.TestTools; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.junit.Assert; import org.junit.Test; @@ -68,6 +70,8 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe @Priority(10) public void initData() { EntityManager em = getEntityManager(); + DdlTypeRegistry ddlTypeRegistry = em.unwrap( SessionImplementor.class ).getTypeConfiguration() + .getDdlTypeRegistry(); // We need first to modify the columns in the middle (join table) to // allow null values. Hbm2ddl doesn't seem @@ -82,19 +86,19 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe em.getTransaction().begin(); session = (Session) em.getDelegate(); session.createNativeQuery( - "CREATE TABLE children ( parent_id " + getDialect().getTypeName( Types.INTEGER ) + - ", child1_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + - ", child2_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + " )" + "CREATE TABLE children ( parent_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + + ", child1_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + + ", child2_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + " )" ) .executeUpdate(); session.createNativeQuery( - "CREATE TABLE children_AUD ( REV " + getDialect().getTypeName( Types.INTEGER ) + " NOT NULL" + - ", REVEND " + getDialect().getTypeName( Types.INTEGER ) + - ", " + revendTimestampColumName + " " + getDialect().getTypeName( Types.TIMESTAMP ) + - ", REVTYPE " + getDialect().getTypeName( Types.TINYINT ) + - ", parent_id " + getDialect().getTypeName( Types.INTEGER ) + - ", child1_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + - ", child2_id " + getDialect().getTypeName( Types.INTEGER ) + getDialect().getNullColumnString() + " )" + "CREATE TABLE children_AUD ( REV " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + " NOT NULL" + + ", REVEND " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + + ", " + revendTimestampColumName + " " + ddlTypeRegistry.getTypeName( Types.TIMESTAMP, getDialect() ) + + ", REVTYPE " + ddlTypeRegistry.getTypeName( Types.TINYINT, getDialect() ) + + ", parent_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + + ", child1_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + + ", child2_id " + ddlTypeRegistry.getTypeName( Types.INTEGER, getDialect() ) + getDialect().getNullColumnString() + " )" ) .executeUpdate(); em.getTransaction().commit(); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java index cb100392d8..8d11cb2513 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/CustomRunner.java @@ -233,12 +233,7 @@ public class CustomRunner extends BlockJUnit4ClassRunner { return DialectContext.getDialect(); } catch (Exception e) { - return new Dialect() { - @Override - public DatabaseVersion getVersion() { - return ZERO_VERSION; - } - }; + return new Dialect( ZERO_VERSION ) {}; } }