From 07268d6568fdc61ea2ef263b56e638ce35397541 Mon Sep 17 00:00:00 2001 From: Gavin Date: Sat, 29 Apr 2023 17:00:47 +0200 Subject: [PATCH] HHH-16125 Oracle array support using varray types --- .../dialect/CockroachLegacyDialect.java | 3 +- .../dialect/OracleLegacyDialect.java | 7 +- .../dialect/PostgreSQLLegacyDialect.java | 3 +- .../process/spi/MetadataBuildingProcess.java | 2 +- .../hibernate/dialect/CockroachDialect.java | 3 +- .../java/org/hibernate/dialect/Dialect.java | 15 +- .../dialect/DialectDelegateWrapper.java | 4 +- .../org/hibernate/dialect/MySQLDialect.java | 16 ++- .../dialect/OracleArrayJdbcType.java | 129 +++++++++++------- .../org/hibernate/dialect/OracleDialect.java | 10 +- .../dialect/OracleSqlAstTranslator.java | 33 ++++- .../hibernate/dialect/PostgreSQLDialect.java | 6 +- .../dialect/PostgreSQLEnumJdbcType.java | 21 +-- .../org/hibernate/dialect/SpannerDialect.java | 2 +- .../aggregate/OracleAggregateSupport.java | 1 - .../org/hibernate/mapping/BasicValue.java | 24 +++- .../java/org/hibernate/mapping/Column.java | 77 ++++------- .../java/org/hibernate/mapping/Value.java | 5 + .../internal/ProcedureParameterImpl.java | 4 + .../function/SelfRenderingSqmFunction.java | 5 +- .../sqm/sql/BaseSqmToSqlAstConverter.java | 1 - .../sql/ast/spi/AbstractSqlAstTranslator.java | 7 +- .../internal/StandardTableExporter.java | 6 + .../java/AbstractArrayJavaType.java | 3 +- .../type/descriptor/jdbc/ArrayJdbcType.java | 7 +- .../type/descriptor/jdbc/JdbcType.java | 13 +- .../type/descriptor/sql/DdlType.java | 11 +- .../sql/internal/ArrayDdlTypeImpl.java | 50 +++++++ .../descriptor/sql/internal/DdlTypeImpl.java | 2 +- .../internal/NamedNativeEnumDdlTypeImpl.java | 17 +-- .../sql/internal/NativeEnumDdlTypeImpl.java | 15 +- .../descriptor/sql/spi/DdlTypeRegistry.java | 24 +++- 32 files changed, 364 insertions(+), 162 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/ArrayDdlTypeImpl.java diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java index 510c19611f..9b872a3477 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java @@ -70,6 +70,7 @@ 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.ColumnTypeInformation; import org.hibernate.type.JavaObjectType; import org.hibernate.type.descriptor.jdbc.ArrayJdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType; @@ -294,7 +295,7 @@ public JdbcType resolveSqlTypeDescriptor( jdbcTypeRegistry.getTypeConfiguration(), this, jdbcTypeRegistry.getDescriptor( sqlTypeCode ), - null + ColumnTypeInformation.EMPTY ); } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java index 942e84e844..39905aa3d1 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java @@ -746,11 +746,8 @@ public boolean supportsBitType() { } @Override - public String getArrayTypeName(String elementTypeName) { - // Return null to signal that there is no array type since Oracle only has named array types - // TODO: discuss if it makes sense to parse a config parameter to a map which we can query here - // e.g. `hibernate.oracle.array_types=numeric(10,0)=intarray,...` - return null; + public String getArrayTypeName(String javaElementTypeName, String elementTypeName) { + return javaElementTypeName + "Array"; } @Override diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java index c9d608fbf6..29d3148e58 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java @@ -85,6 +85,7 @@ 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.ColumnTypeInformation; import org.hibernate.type.JavaObjectType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; @@ -346,7 +347,7 @@ public JdbcType resolveSqlTypeDescriptor( jdbcTypeRegistry.getTypeConfiguration(), this, jdbcTypeRegistry.getDescriptor( sqlTypeCode ), - null + ColumnTypeInformation.EMPTY ); } } 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 3465b3c5e4..a2ef14f5d5 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 @@ -695,7 +695,7 @@ public void contributeAttributeConverter(Class 20 + size.setScale( Math.min( size.getPrecision(), 20 ) ); + return size; + default: + return super.resolveSize( jdbcType, javaType, precision, scale, length ); } - return super.resolveSize( jdbcType, javaType, precision, scale, length ); } }; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleArrayJdbcType.java index 088f94a26b..c99dfcd941 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleArrayJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleArrayJdbcType.java @@ -11,12 +11,14 @@ import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Types; -import java.util.Objects; +import java.util.Locale; import org.hibernate.HibernateException; -import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.boot.model.relational.Database; +import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject; +import org.hibernate.engine.jdbc.Size; import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; -import org.hibernate.type.SqlTypes; +import org.hibernate.type.BasicType; import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.java.BasicPluralJavaType; @@ -25,11 +27,13 @@ import org.hibernate.type.descriptor.jdbc.BasicBinder; import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; import org.hibernate.type.descriptor.jdbc.JdbcType; -import org.hibernate.type.descriptor.jdbc.ObjectJdbcType; import org.hibernate.type.spi.TypeConfiguration; import oracle.jdbc.OracleConnection; +import static java.sql.Types.ARRAY; +import static java.util.Collections.emptySet; + /** * Descriptor for {@link Types#ARRAY ARRAY} handling. * @@ -41,63 +45,61 @@ public class OracleArrayJdbcType extends ArrayJdbcType { private final String typeName; public OracleArrayJdbcType() { - super( ObjectJdbcType.INSTANCE ); - this.typeName = null; + this( null, null ); } - private OracleArrayJdbcType(String typeName, JdbcType elementJdbcType) { + public OracleArrayJdbcType(JdbcType elementJdbcType, String typeName) { super( elementJdbcType ); this.typeName = typeName; } @Override public JdbcLiteralFormatter getJdbcLiteralFormatter(JavaType javaTypeDescriptor) { - // No array literal support return null; } @Override - public JdbcType resolveType( - TypeConfiguration typeConfiguration, - Dialect dialect, - JdbcType elementType, - ColumnTypeInformation columnTypeInformation) { + public JdbcType resolveType(TypeConfiguration typeConfiguration, Dialect dialect, BasicType elementType, ColumnTypeInformation columnTypeInformation) { String typeName = columnTypeInformation.getTypeName(); if ( typeName == null || typeName.isBlank() ) { - typeName = dialect.getArrayTypeName( - typeConfiguration.getDdlTypeRegistry().getTypeName( - elementType.getDdlTypeCode(), - dialect - ) - ); + typeName = getTypeName( elementType.getJavaTypeDescriptor(), dialect ); } - if ( typeName == null ) { - // Fallback to XML type for the representation of arrays as the native JSON type was only introduced in 21 - // Also, use the XML type if the Oracle JDBC driver classes are not visible - return typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.SQLXML ); - } - return new OracleArrayJdbcType( typeName, elementType ); +// if ( typeName == null ) { +// // Fallback to XML type for the representation of arrays as the native JSON type was only introduced in 21 +// // Also, use the XML type if the Oracle JDBC driver classes are not visible +// return typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.SQLXML ); +// } + return new OracleArrayJdbcType( elementType.getJdbcType(), typeName ); + } + + @Override + public JdbcType resolveType(TypeConfiguration typeConfiguration, Dialect dialect, JdbcType elementType, ColumnTypeInformation columnTypeInformation) { + // a bit wrong! + return new OracleArrayJdbcType( elementType, columnTypeInformation.getTypeName() ); } @Override public ValueBinder getBinder(final JavaType javaTypeDescriptor) { //noinspection unchecked final BasicPluralJavaType containerJavaType = (BasicPluralJavaType) javaTypeDescriptor; - return new BasicBinder( javaTypeDescriptor, this ) { + return new BasicBinder<>( javaTypeDescriptor, this ) { + private String typeName(WrapperOptions options) { + return ( typeName == null ? getTypeName( options, containerJavaType ) : typeName ) + .toUpperCase(Locale.ROOT); + } @Override protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException { - st.setNull( index, Types.ARRAY, typeName ); + st.setNull( index, ARRAY, typeName( options ) ); } @Override protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException { - st.setNull( name, Types.ARRAY, typeName ); + st.setNull( name, ARRAY, typeName( options ) ); } @Override protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException { - final java.sql.Array arr = getArray( value, containerJavaType, options ); - st.setArray( index, arr ); + st.setArray( index, getArray( value, containerJavaType, options ) ); } @Override @@ -105,7 +107,7 @@ protected void doBind(CallableStatement st, X value, String name, WrapperOptions throws SQLException { final java.sql.Array arr = getArray( value, containerJavaType, options ); try { - st.setObject( name, arr, Types.ARRAY ); + st.setObject( name, arr, ARRAY ); } catch (SQLException ex) { throw new HibernateException( "JDBC driver does not support named parameters for setArray. Use positional.", ex ); @@ -122,12 +124,13 @@ private java.sql.Array getArray( 0 ).getClass(); final Object[] objects = javaTypeDescriptor.unwrap( value, arrayClass, options ); + final String arrayTypeName = typeName( options ).toUpperCase(Locale.ROOT); - final SharedSessionContractImplementor session = options.getSession(); - final OracleConnection oracleConnection = session.getJdbcCoordinator().getLogicalConnection().getPhysicalConnection() + final OracleConnection oracleConnection = options.getSession() + .getJdbcCoordinator().getLogicalConnection().getPhysicalConnection() .unwrap( OracleConnection.class ); try { - return oracleConnection.createOracleArray( typeName, objects ); + return oracleConnection.createOracleArray( arrayTypeName, objects ); } catch (Exception e) { throw new HibernateException( "Couldn't create a java.sql.Array", e ); @@ -136,22 +139,54 @@ private java.sql.Array getArray( }; } - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } + private static String getTypeName(WrapperOptions options, BasicPluralJavaType containerJavaType) { + Dialect dialect = options.getSessionFactory().getJdbcServices().getDialect(); + return getTypeName( containerJavaType.getElementJavaType(), dialect ); + } - OracleArrayJdbcType that = (OracleArrayJdbcType) o; - - return Objects.equals( typeName, that.typeName ); + private static String getTypeName(JavaType elementJavaType, Dialect dialect) { + return dialect.getArrayTypeName( + elementJavaType.getJavaTypeClass().getSimpleName(), + null // not needed by OracleDialect.getArrayTypeName() + ); } @Override - public int hashCode() { - return typeName != null ? typeName.hashCode() : 0; + public void addAuxiliaryDatabaseObjects( + JavaType javaType, + Size columnSize, + Database database, + TypeConfiguration typeConfiguration) { + final Dialect dialect = database.getDialect(); + final BasicPluralJavaType pluralJavaType = (BasicPluralJavaType) javaType; + final String elementTypeName = typeName==null + ? getTypeName( pluralJavaType.getElementJavaType(), dialect ) + : typeName; + final String elementType = + typeConfiguration.getDdlTypeRegistry().getTypeName( + getElementJdbcType().getDdlTypeCode(), + dialect.getSizeStrategy().resolveSize( + getElementJdbcType(), + pluralJavaType.getElementJavaType(), + columnSize.getPrecision(), + columnSize.getScale(), + columnSize.getLength() + ) + ); + final String[] create = new String[] { "create or replace type " + elementTypeName + " as varying array(255) of " + elementType }; + final String[] drop = new String[] { +// "drop type " + elementTypeName + }; + database.addAuxiliaryDatabaseObject( + new NamedAuxiliaryDatabaseObject( elementTypeName, database.getDefaultNamespace(), create, drop, emptySet(), true ) + ); } + +// @Override +// public String getExtraCreateTableInfo(JavaType javaType, String columnName, String tableName, Database database) { +// final Dialect dialect = database.getDialect(); +// final BasicPluralJavaType pluralJavaType = (BasicPluralJavaType) javaType; +// String elementTypeName = getTypeName( pluralJavaType.getElementJavaType(), dialect ); +// return " nested table " + columnName + " store as " + tableName + columnName + elementTypeName; +// } } 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 a90efa9d63..63c595539d 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -87,6 +87,7 @@ import org.hibernate.type.descriptor.jdbc.ObjectNullAsNullTypeJdbcType; import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; +import org.hibernate.type.descriptor.sql.internal.ArrayDdlTypeImpl; import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl; import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; @@ -685,6 +686,8 @@ protected void registerColumnTypes(TypeContributions typeContributions, ServiceR else if ( getVersion().isSameOrAfter( 12 ) ) { ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "blob", this ) ); } + + ddlTypeRegistry.addDescriptor( new ArrayDdlTypeImpl( this ) ); } @Override @@ -781,11 +784,8 @@ public boolean supportsBitType() { } @Override - public String getArrayTypeName(String elementTypeName) { - // Return null to signal that there is no array type since Oracle only has named array types - // TODO: discuss if it makes sense to parse a config parameter to a map which we can query here - // e.g. `hibernate.oracle.array_types=numeric(10,0)=intarray,...` - return null; + public String getArrayTypeName(String javaElementTypeName, String elementTypeName) { + return javaElementTypeName + "Array"; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java index 6cc303d48c..77df6c199e 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java @@ -8,7 +8,6 @@ import java.util.List; -import org.hibernate.LockMode; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.util.collections.Stack; import org.hibernate.metamodel.mapping.JdbcMappingContainer; @@ -21,7 +20,6 @@ import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.ast.tree.cte.CteMaterialization; -import org.hibernate.sql.ast.tree.expression.AggregateColumnWriteExpression; import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.FunctionExpression; @@ -31,7 +29,6 @@ import org.hibernate.sql.ast.tree.expression.SqlTupleContainer; import org.hibernate.sql.ast.tree.expression.Summarization; import org.hibernate.sql.ast.tree.from.FunctionTableReference; -import org.hibernate.sql.ast.tree.from.NamedTableReference; import org.hibernate.sql.ast.tree.from.QueryPartTableReference; import org.hibernate.sql.ast.tree.from.UnionTableGroup; import org.hibernate.sql.ast.tree.from.ValuesTableReference; @@ -442,12 +439,42 @@ protected void renderComparison(Expression lhs, ComparisonOperator operator, Exp rhs.accept( this ); appendSql( ')' ); break; + case SqlTypes.ARRAY: + switch ( operator ) { + case DISTINCT_FROM: + appendSql( "decode(" ); + arrayToString( lhs ); + appendSql( ',' ); + arrayToString( rhs ); + appendSql( ",0,1)=1" ); + break; + case NOT_DISTINCT_FROM: + appendSql( "decode(" ); + arrayToString( lhs ); + appendSql( ',' ); + arrayToString( rhs ); + appendSql( ",0,1)=0" ); + break; + default: + arrayToString( lhs ); + appendSql( operator.sqlText() ); + arrayToString( rhs ); + } + break; default: renderComparisonEmulateDecode( lhs, operator, rhs ); break; } } + private void arrayToString(Expression expression) { + appendSql("case when "); + expression.accept( this ); + appendSql(" is not null then (select listagg(column_value||',')||';' from table("); + expression.accept( this ); + appendSql(")) else null end"); + } + @Override protected void renderSelectTupleComparison( List lhsExpressions, 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 991562fbe2..9ad926f5d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -74,6 +74,7 @@ import org.hibernate.sql.model.MutationOperation; import org.hibernate.sql.model.internal.OptionalTableUpdate; import org.hibernate.sql.model.jdbc.OptionalTableUpdateOperation; +import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; import org.hibernate.type.JavaObjectType; import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType; import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; @@ -246,7 +247,7 @@ protected void registerColumnTypes(TypeContributions typeContributions, ServiceR // Prefer jsonb if possible ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "jsonb", this ) ); - ddlTypeRegistry.addDescriptor( NAMED_ENUM, new NamedNativeEnumDdlTypeImpl( this ) ); + ddlTypeRegistry.addDescriptor( new NamedNativeEnumDdlTypeImpl( this ) ); } @Override @@ -325,7 +326,7 @@ public JdbcType resolveSqlTypeDescriptor( jdbcTypeRegistry.getTypeConfiguration(), this, jdbcTypeRegistry.getDescriptor( sqlTypeCode ), - null + ColumnTypeInformation.EMPTY ); } } @@ -828,6 +829,7 @@ public boolean useInputStreamToInsertBlob() { @Override public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) { + // TODO: adapt this to handle named enum types! // Workaround for postgres bug #1453 return "null::" + typeConfiguration.getDdlTypeRegistry().getDescriptor( sqlType ).getRawTypeName(); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLEnumJdbcType.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLEnumJdbcType.java index 611ce3b863..2f3eac2420 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLEnumJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLEnumJdbcType.java @@ -8,7 +8,7 @@ import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject; -import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.engine.jdbc.Size; import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.WrapperOptions; @@ -17,6 +17,7 @@ import org.hibernate.type.descriptor.jdbc.BasicExtractor; import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.spi.TypeConfiguration; import java.sql.CallableStatement; import java.sql.PreparedStatement; @@ -114,15 +115,19 @@ protected X doExtract(CallableStatement statement, String name, WrapperOptions o } @Override - public void addAuxiliaryDatabaseObjects(JavaType javaType, InFlightMetadataCollector metadataCollector) { - Database database = metadataCollector.getDatabase(); - Class> enumClass = (Class>) javaType.getJavaType(); - String name = enumClass.getSimpleName(); - String[] create = database.getDialect().getCreateEnumTypeCommand( enumClass ); + public void addAuxiliaryDatabaseObjects( + JavaType javaType, + Size columnSize, + Database database, + TypeConfiguration typeConfiguration) { + final Dialect dialect = database.getDialect(); + final Class> enumClass = (Class>) javaType.getJavaType(); + final String enumTypeName = enumClass.getSimpleName(); + final String[] create = dialect.getCreateEnumTypeCommand( enumClass ); if ( create != null ) { - String[] drop = database.getDialect().getDropEnumTypeCommand( enumClass ); + final String[] drop = dialect.getDropEnumTypeCommand( enumClass ); database.addAuxiliaryDatabaseObject( - new NamedAuxiliaryDatabaseObject( name, database.getDefaultNamespace(), create, drop, emptySet(), true ) + new NamedAuxiliaryDatabaseObject( enumTypeName, database.getDefaultNamespace(), create, drop, emptySet(), true ) ); } } 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 7ece118abb..b66cd7922d 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java @@ -188,7 +188,7 @@ public boolean supportsStandardArrays() { } @Override - public String getArrayTypeName(String elementTypeName) { + public String getArrayTypeName(String javaElementTypeName, String elementTypeName) { return "ARRAY<" + elementTypeName + ">"; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/OracleAggregateSupport.java b/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/OracleAggregateSupport.java index 827e18c1e5..eacb4e67b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/OracleAggregateSupport.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/aggregate/OracleAggregateSupport.java @@ -19,7 +19,6 @@ import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; -import org.hibernate.type.SqlTypes; import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; import org.hibernate.type.spi.TypeConfiguration; diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java index d06975d1e2..7435f2b9bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java @@ -31,6 +31,7 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.Size; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; @@ -314,19 +315,38 @@ public Resolution resolve() { } final Selectable selectable = getColumn(); + final Size size; if ( selectable instanceof Column ) { - resolveColumn( (Column) selectable, getDialect() ); + Column column = (Column) selectable; + resolveColumn( column, getDialect() ); + size = column.calculateColumnSize( getDialect(), getBuildingContext().getMetadataCollector() ); + } + else { + size = Size.nil(); } resolution.getJdbcType() .addAuxiliaryDatabaseObjects( resolution.getRelationalJavaType(), - getBuildingContext().getMetadataCollector() + size, + getBuildingContext().getMetadataCollector().getDatabase(), + getTypeConfiguration() ); return resolution; } + @Override + public String getExtraCreateTableInfo() { + return resolution.getJdbcType() + .getExtraCreateTableInfo( + resolution.getRelationalJavaType(), + getColumn().getText(), + getTable().getName(), + getBuildingContext().getMetadataCollector().getDatabase() + ); + } + @Override public Dialect getDialect() { return getMetadata().getDatabase().getDialect(); 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 7f27220c3f..1ac3410eaf 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java @@ -13,7 +13,6 @@ import java.util.Objects; import org.hibernate.AssertionFailure; -import org.hibernate.Incubating; import org.hibernate.MappingException; import org.hibernate.boot.Metadata; import org.hibernate.boot.model.TruthValue; @@ -26,12 +25,9 @@ import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.sql.Template; import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; -import org.hibernate.type.BasicPluralType; -import org.hibernate.type.BasicType; import org.hibernate.type.ComponentType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; -import org.hibernate.type.descriptor.jdbc.ArrayJdbcType; import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; @@ -272,11 +268,11 @@ public int getSqlTypeCode(Mapping mapping) throws MappingException { private String getSqlTypeName(DdlTypeRegistry ddlTypeRegistry, Dialect dialect, Mapping mapping) { if ( sqlTypeName == null ) { try { - final Type type = getValue().getType(); - sqlTypeName = isArray( type ) - //TODO: remove the special case for array types, this should be handled by the DdlType! - ? dialect.getArrayTypeName( getArrayElementTypeName( dialect, ddlTypeRegistry, getArrayElementType( type ) ) ) - : ddlTypeRegistry.getTypeName( getSqlTypeCode( mapping ), getColumnSize( dialect, mapping ), getUnderlyingType( mapping, type, typeIndex ) ); + sqlTypeName = ddlTypeRegistry.getTypeName( + getSqlTypeCode( mapping ), + getColumnSize( dialect, mapping ), + getUnderlyingType( mapping, getValue().getType(), typeIndex ) + ); } catch ( Exception cause ) { throw new MappingException( @@ -314,29 +310,6 @@ else if ( type.isEntityType() ) { } } - private String getArrayElementTypeName(Dialect dialect, DdlTypeRegistry ddlTypeRegistry, BasicType elementType) { - return ddlTypeRegistry.getTypeName( - elementType.getJdbcType().getDdlTypeCode(), - dialect.getSizeStrategy().resolveSize( - elementType.getJdbcMapping().getJdbcType(), - elementType.getJavaTypeDescriptor(), - precision, - scale, - length - ) - ); - } - - private static BasicType getArrayElementType(Type arrayType) { - final BasicPluralType containerType = (BasicPluralType) arrayType; - return containerType.getElementType(); - } - - private static boolean isArray(Type type) { - return type instanceof BasicPluralType - && ((BasicType) type).getJdbcType() instanceof ArrayJdbcType; - } - /** * Returns {@linkplain org.hibernate.type.SqlTypes SQL type code} * for this column, or {@code null} if the type code is unknown. @@ -402,28 +375,32 @@ public int getDecimalDigits() { public Size getColumnSize(Dialect dialect, Mapping mapping) { if ( columnSize == null ) { - Type type = getValue().getType(); - if ( type instanceof EntityType ) { - type = getTypeForEntityValue( mapping, type, getTypeIndex() ); - } - if ( type instanceof ComponentType ) { - type = getTypeForComponentValue( mapping, type, getTypeIndex() ); - } - if ( type == null ) { - throw new AssertionFailure( "no typing information available to determine column size" ); - } - final JdbcMapping jdbcMapping = (JdbcMapping) type; - columnSize = dialect.getSizeStrategy().resolveSize( - jdbcMapping.getJdbcType(), - jdbcMapping.getJdbcJavaType(), - precision, - scale, - length - ); + columnSize = calculateColumnSize( dialect, mapping ); } return columnSize; } + Size calculateColumnSize(Dialect dialect, Mapping mapping) { + Type type = getValue().getType(); + if ( type instanceof EntityType ) { + type = getTypeForEntityValue( mapping, type, getTypeIndex() ); + } + if ( type instanceof ComponentType ) { + type = getTypeForComponentValue( mapping, type, getTypeIndex() ); + } + if ( type == null ) { + throw new AssertionFailure( "no typing information available to determine column size" ); + } + final JdbcMapping jdbcMapping = (JdbcMapping) type; + return dialect.getSizeStrategy().resolveSize( + jdbcMapping.getJdbcType(), + jdbcMapping.getJdbcJavaType(), + precision, + scale, + length + ); + } + private Type getTypeForComponentValue(Mapping mapping, Type type, int typeIndex) { final Type[] subtypes = ( (ComponentType) type ).getSubtypes(); int typeStartIndex = 0; diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Value.java b/hibernate-core/src/main/java/org/hibernate/mapping/Value.java index 7183288b57..2bc959f945 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Value.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Value.java @@ -174,4 +174,9 @@ default MetadataBuildingContext getBuildingContext() { boolean isColumnInsertable(int index); boolean isColumnUpdateable(int index); + + @Incubating + default String getExtraCreateTableInfo() { + return ""; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureParameterImpl.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureParameterImpl.java index 90af07e315..c7678e8eda 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureParameterImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureParameterImpl.java @@ -183,6 +183,10 @@ protected void bindParameterValue( executionContext.getSession() ); } + @Override + public String toString() { + return "JdbcParameter(" + name + ")"; + } }; } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmFunction.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmFunction.java index f266101da9..1d2b27fb03 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmFunction.java @@ -22,7 +22,6 @@ import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmTypedNode; -import org.hibernate.query.sqm.tree.SqmVisitableNode; import org.hibernate.query.sqm.tree.expression.SqmFunction; import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.expression.Expression; @@ -115,7 +114,7 @@ protected List resolveSqlAstArguments(List final ArrayList sqlAstArguments = new ArrayList<>( sqmArguments.size() ); for ( int i = 0; i < sqmArguments.size(); i++ ) { sqlAstArguments.add( - (SqlAstNode) ( (SqmVisitableNode) sqmArguments.get( i ) ).accept( walker ) + (SqlAstNode) sqmArguments.get( i ).accept( walker ) ); } return sqlAstArguments; @@ -129,7 +128,7 @@ protected List resolveSqlAstArguments(List for ( int i = 0; i < sqmArguments.size(); i++ ) { typeAccess.argumentIndex = i; sqlAstArguments.add( - (SqlAstNode) walker.visitWithInferredType( (SqmVisitableNode) sqmArguments.get( i ), typeAccess ) + (SqlAstNode) walker.visitWithInferredType( sqmArguments.get( i ), typeAccess ) ); } return sqlAstArguments; diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index 5518d01000..a8e681f4f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -279,7 +279,6 @@ import org.hibernate.sql.ast.SqlAstJoinType; import org.hibernate.sql.ast.SqlTreeCreationException; import org.hibernate.sql.ast.SqlTreeCreationLogger; -import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator; import org.hibernate.sql.ast.spi.FromClauseAccess; import org.hibernate.sql.ast.spi.SqlAliasBase; import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator; 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 3bd9f0e348..1f151cce31 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 @@ -204,6 +204,7 @@ import org.hibernate.type.SqlTypes; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.BasicPluralJavaType; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; import org.hibernate.type.descriptor.jdbc.JdbcType; @@ -6117,6 +6118,7 @@ public void visitCastTarget(CastTarget castTarget) { final SqlExpressible expressionType = (SqlExpressible) castTarget.getExpressionType(); if ( expressionType instanceof BasicPluralType ) { final BasicPluralType containerType = (BasicPluralType) expressionType; + final BasicPluralJavaType javaTypeDescriptor = (BasicPluralJavaType) containerType.getJavaTypeDescriptor(); final BasicType elementType = containerType.getElementType(); final String elementTypeName = sessionFactory.getTypeConfiguration().getDdlTypeRegistry() .getDescriptor( elementType.getJdbcType().getDdlTypeCode() ) @@ -6126,7 +6128,10 @@ public void visitCastTarget(CastTarget castTarget) { castTarget.getPrecision(), castTarget.getScale() ); - final String arrayTypeName = dialect.getArrayTypeName( elementTypeName ); + final String arrayTypeName = dialect.getArrayTypeName( + javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(), + elementTypeName + ); if ( arrayTypeName != null ) { appendSql( arrayTypeName ); return; 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 7a5a6af2d5..1e2adc912f 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 @@ -56,6 +56,8 @@ public String[] getSqlCreateStrings( try { final String formattedTableName = context.format( tableName ); + final StringBuilder extra = new StringBuilder(); + final StringBuilder createTable = new StringBuilder( tableCreateString( table.hasPrimaryKey() ) ) .append( ' ' ) @@ -71,6 +73,8 @@ public String[] getSqlCreateStrings( createTable.append( ", " ); } appendColumn( createTable, column, table, metadata, dialect, context ); + + extra.append( column.getValue().getExtraCreateTableInfo() ); } if ( table.getRowId() != null ) { String rowIdColumn = dialect.getRowIdColumnString( table.getRowId() ); @@ -88,6 +92,8 @@ public String[] getSqlCreateStrings( createTable.append( ')' ); + createTable.append( extra ); + if ( table.getComment() != null ) { createTable.append( dialect.getTableComment( table.getComment() ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java index 7b7d572d78..1ae62e07c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java @@ -21,6 +21,7 @@ import org.hibernate.type.descriptor.jdbc.ArrayJdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; +import org.hibernate.type.internal.BasicTypeImpl; import org.hibernate.type.spi.TypeConfiguration; public abstract class AbstractArrayJavaType extends AbstractClassJavaType @@ -53,7 +54,7 @@ public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) { return ( (ArrayJdbcType) jdbcType ).resolveType( typeConfiguration, indicators.getDialect(), - recommendedComponentJdbcType, + new BasicTypeImpl<>( getElementJavaType(), recommendedComponentJdbcType ), ColumnTypeInformation.EMPTY ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java index a8e498cdf3..ca5772d3a9 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java @@ -7,7 +7,6 @@ package org.hibernate.type.descriptor.jdbc; import java.lang.reflect.Array; -import java.lang.reflect.Method; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -111,7 +110,7 @@ public Class getPreferredJavaTypeClass(WrapperOptions options) { @Override public ValueBinder getBinder(final JavaType javaTypeDescriptor) { - return new BasicBinder( javaTypeDescriptor, this ) { + return new BasicBinder<>( javaTypeDescriptor, this ) { @Override protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException { @@ -197,7 +196,7 @@ private java.sql.Array getArray( @Override public ValueExtractor getExtractor(final JavaType javaTypeDescriptor) { - return new BasicExtractor( javaTypeDescriptor, this ) { + return new BasicExtractor<>( javaTypeDescriptor, this ) { @Override protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException { return javaTypeDescriptor.wrap( rs.getArray( paramIndex ), options ); @@ -230,7 +229,7 @@ public boolean equals(Object o) { if ( this == o ) { return true; } - if ( o == null || getClass() != o.getClass() ) { + if ( !(o instanceof ArrayJdbcType) ) { return false; } 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 13ce4ec918..b3fd77e0f8 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 @@ -12,7 +12,7 @@ import java.sql.Types; import org.hibernate.Incubating; -import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.boot.model.relational.Database; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.Size; import org.hibernate.query.sqm.CastType; @@ -327,6 +327,15 @@ default void registerOutParameter(CallableStatement callableStatement, int index } @Incubating - default void addAuxiliaryDatabaseObjects(JavaType javaType, InFlightMetadataCollector metadataCollector) { + default void addAuxiliaryDatabaseObjects( + JavaType javaType, + Size columnSize, + Database database, + TypeConfiguration typeConfiguration) { + } + + @Incubating + default String getExtraCreateTableInfo(JavaType javaType, String columnName, String tableName, Database database) { + return ""; } } 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 index 2c3ebd2974..01c6752646 100644 --- 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 @@ -13,8 +13,10 @@ import org.hibernate.engine.jdbc.Size; import org.hibernate.metamodel.mapping.SqlExpressible; import org.hibernate.type.SqlTypes; +import org.hibernate.type.Type; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; /** * Descriptor for a DDL column type. An instance of this type abstracts over @@ -36,7 +38,14 @@ public interface DdlType extends Serializable { */ int getSqlTypeCode(); - default String getTypeName(Size columnSize, Class returnedClass) { + /** + * Return a type with length, precision, and scale specified by the given + * {@linkplain Size size object}. The given type may be used to + * determine additional aspects of the returned SQL type. + * + * @since 6.3 + */ + default String getTypeName(Size columnSize, Type type, DdlTypeRegistry ddlTypeRegistry) { return getTypeName( columnSize ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/ArrayDdlTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/ArrayDdlTypeImpl.java new file mode 100644 index 0000000000..e76119b805 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/ArrayDdlTypeImpl.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.type.descriptor.sql.internal; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.Size; +import org.hibernate.type.BasicPluralType; +import org.hibernate.type.BasicType; +import org.hibernate.type.Type; +import org.hibernate.type.descriptor.java.BasicPluralJavaType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; + +import static java.sql.Types.ARRAY; + +/** + * @author Gavin King + */ +public class ArrayDdlTypeImpl extends DdlTypeImpl { + + public ArrayDdlTypeImpl(Dialect dialect) { + super( ARRAY, "array", dialect ); + } + + @Override + public String getTypeName(Size columnSize, Type type, DdlTypeRegistry ddlTypeRegistry) { + final BasicPluralType pluralType = (BasicPluralType) type; + final BasicPluralJavaType javaTypeDescriptor = (BasicPluralJavaType) pluralType.getJavaTypeDescriptor(); + final BasicType elementType = pluralType.getElementType(); + final String arrayElementTypeName = + ddlTypeRegistry.getTypeName( + elementType.getJdbcType().getDdlTypeCode(), + dialect.getSizeStrategy().resolveSize( + elementType.getJdbcMapping().getJdbcType(), + elementType.getJavaTypeDescriptor(), + columnSize.getPrecision(), + columnSize.getScale(), + columnSize.getLength() + ) + ); + return dialect.getArrayTypeName( + javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(), + arrayElementTypeName + ); + } + +} 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 index 25f257361f..ef81090faf 100644 --- 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 @@ -25,7 +25,7 @@ public class DdlTypeImpl implements DdlType { private final String typeNamePattern; private final String castTypeNamePattern; private final boolean castTypeNameIsStatic; - private final Dialect dialect; + final Dialect dialect; public DdlTypeImpl(int sqlTypeCode, String typeNamePattern, Dialect dialect) { this( sqlTypeCode, typeNamePattern, typeNamePattern, dialect ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/NamedNativeEnumDdlTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/NamedNativeEnumDdlTypeImpl.java index c81ee33ecf..1438c2f6bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/NamedNativeEnumDdlTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/NamedNativeEnumDdlTypeImpl.java @@ -8,16 +8,18 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.Size; +import org.hibernate.type.Type; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.sql.DdlType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; -import static org.hibernate.type.SqlTypes.ENUM; +import static org.hibernate.type.SqlTypes.NAMED_ENUM; /** - * A {@link DdlType} representing a native SQL {@code enum} type. + * A {@link DdlType} representing a named native SQL {@code enum} type, + * one that often cannot be treated as a {@code varchar}. * - * @see org.hibernate.type.SqlTypes#ENUM * @see org.hibernate.type.SqlTypes#NAMED_ENUM * @see Dialect#getEnumTypeDeclaration(Class) * @@ -33,17 +35,16 @@ public NamedNativeEnumDdlTypeImpl(Dialect dialect) { @Override public int getSqlTypeCode() { // note: also used for NAMED_ENUM - return ENUM; + return NAMED_ENUM; } - @Override - public String getTypeName(Size columnSize, Class returnedClass) { - return dialect.getEnumTypeDeclaration( (Class>) returnedClass ); + @Override @SuppressWarnings("unchecked") + public String getTypeName(Size columnSize, Type type, DdlTypeRegistry ddlTypeRegistry) { + return dialect.getEnumTypeDeclaration( (Class>) type.getReturnedClass() ); } @Override public String getRawTypeName() { - // this return "enum"; } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/NativeEnumDdlTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/NativeEnumDdlTypeImpl.java index 7e7a690a2d..c097f444e9 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/NativeEnumDdlTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/internal/NativeEnumDdlTypeImpl.java @@ -8,15 +8,24 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.Size; +import org.hibernate.type.Type; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.sql.DdlType; +import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import static org.hibernate.type.SqlTypes.ENUM; /** + * A {@link DdlType} representing a SQL {@code enum} type that + * may be treated as {@code varchar} for most purposes. + * + * @see org.hibernate.type.SqlTypes#ENUM + * @see Dialect#getEnumTypeDeclaration(Class) + * * @author Gavin King */ + public class NativeEnumDdlTypeImpl implements DdlType { private final Dialect dialect; @@ -29,9 +38,9 @@ public int getSqlTypeCode() { return ENUM; } - @Override - public String getTypeName(Size columnSize, Class returnedClass) { - return dialect.getEnumTypeDeclaration( (Class>) returnedClass ); + @Override @SuppressWarnings("unchecked") + public String getTypeName(Size columnSize, Type type, DdlTypeRegistry ddlTypeRegistry) { + return dialect.getEnumTypeDeclaration( (Class>) type.getReturnedClass() ); } @Override 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 index 9781eb0046..f88a482bfd 100644 --- 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 @@ -148,6 +148,12 @@ public DdlType getDescriptor(int sqlTypeCode) { public String getTypeName(int typeCode, Dialect dialect) { // explicitly enforce dialect's default precisions switch ( typeCode ) { + case SqlTypes.CHAR: + case SqlTypes.NCHAR: + case SqlTypes.VARCHAR: + case SqlTypes.NVARCHAR: + case SqlTypes.VARBINARY: + return getTypeName( typeCode, Size.length( Size.DEFAULT_LENGTH ) ); case SqlTypes.DECIMAL: case SqlTypes.NUMERIC: return getTypeName( typeCode, Size.precision( dialect.getDefaultDecimalPrecision() ) ); @@ -188,6 +194,22 @@ 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 length, precision, and scale determined by the given {@linkplain Size + * size object}. The returned type name should be of a SQL type large enough to + * accommodate values of the specified size. + * + * @param typeCode the JDBC type code + * @param columnSize an object which determines the length, precision, and scale + * @param type the {@link Type} mapped to the column + * + * @return the associated type name with the smallest capacity that accommodates + * the given size, if available, and the default type name otherwise + * + * @since 6.3 + */ public String getTypeName(int typeCode, Size columnSize, Type type) { final DdlType descriptor = getDescriptor( typeCode ); if ( descriptor == null ) { @@ -199,7 +221,7 @@ public String getTypeName(int typeCode, Size columnSize, Type type) { ) ); } - return descriptor.getTypeName( columnSize, type.getReturnedClass() ); + return descriptor.getTypeName( columnSize, type, this ); } /**