From cb0aad7c7cbf1fea268247a001e3583f281c7dd6 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 29 Sep 2023 10:30:32 +0200 Subject: [PATCH] HHH-17276 Expose size based lob-ness in DdlType and retain info in runtime model --- gradle/databases.gradle | 2 +- .../community/dialect/CUBRIDDialect.java | 7 +- .../community/dialect/DerbyLegacyDialect.java | 60 +++++++++++++-- .../community/dialect/MimerSQLDialect.java | 11 ++- .../community/dialect/MySQLLegacyDialect.java | 30 ++++++-- .../dialect/AbstractHANADialect.java | 2 +- .../org/hibernate/dialect/DerbyDialect.java | 60 +++++++++++++-- .../java/org/hibernate/dialect/Dialect.java | 33 +++++++- .../org/hibernate/dialect/MySQLDialect.java | 30 ++++++-- .../java/org/hibernate/mapping/Column.java | 33 ++++++-- .../metamodel/mapping/SqlTypedMapping.java | 3 + .../internal/AbstractEmbeddableMapping.java | 6 +- .../internal/BasicAttributeMapping.java | 9 +++ .../DiscriminatedAssociationMapping.java | 4 +- .../internal/EmbeddableMappingTypeImpl.java | 11 ++- .../internal/ManyToManyCollectionPart.java | 12 ++- .../internal/MappingModelCreationHelper.java | 29 ++++--- .../internal/SelectableMappingImpl.java | 36 +++++++-- .../internal/SelectableMappingsImpl.java | 16 ++-- .../collection/OneToManyPersister.java | 6 +- .../entity/AbstractEntityPersister.java | 18 +++-- .../entity/JoinedSubclassEntityPersister.java | 2 +- .../mutation/AbstractMutationCoordinator.java | 3 +- .../builder/AbstractTableInsertBuilder.java | 4 +- .../builder/AbstractTableUpdateBuilder.java | 5 +- .../ColumnValuesTableMutationBuilder.java | 11 ++- .../builder/TableUpdateBuilderSkipped.java | 2 +- .../internal/AbstractSchemaValidator.java | 2 +- .../type/descriptor/jdbc/JdbcType.java | 18 +++++ .../type/descriptor/sql/DdlType.java | 5 ++ .../internal/CapacityDependentDdlType.java | 77 ++++++++++++++++++- .../descriptor/sql/internal/DdlTypeImpl.java | 26 +++++++ .../hibernate/orm/test/rowid/RowIdType.java | 2 +- 33 files changed, 487 insertions(+), 88 deletions(-) diff --git a/gradle/databases.gradle b/gradle/databases.gradle index 65f0123548..f97dadd084 100644 --- a/gradle/databases.gradle +++ b/gradle/databases.gradle @@ -174,7 +174,7 @@ ext { // // To avoid hibernate-spatial tests failure, JVM must be enabled as stated in documentation: // https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/autonomous-oracle-java.html - 'jdbc.url' : 'jdbc:oracle:thin:@(description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1521)(host=' + dbHost + '.oraclecloud.com))(connect_data=(service_name=' + dbService + '_tp.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))', + 'jdbc.url' : 'jdbc:oracle:thin:@(description=(retry_count=5)(retry_delay=1)(address=(protocol=tcps)(port=1521)(host=' + dbHost + '.oraclecloud.com))(connect_data=(service_name=' + dbService + '_tp.adb.oraclecloud.com))(security=(ssl_server_dn_match=no)))?oracle.jdbc.enableQueryResultCache=false&oracle.jdbc.thinForceDNSLoadBalancing=true&tcp.nodelay=yes', 'connection.init_sql' : '' ], oracle_cloud_db19c : [ 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 13ca6a723e..d73897a57a 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 @@ -106,7 +106,12 @@ public class CUBRIDDialect extends Dialect { //length parameter is measured in bits, not bytes) ddlTypeRegistry.addDescriptor( new DdlTypeImpl( BINARY, "bit($l)", this ) ); ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( VARBINARY, columnType( BLOB ), this ) + CapacityDependentDdlType.builder( + VARBINARY, + CapacityDependentDdlType.LobKind.BIGGEST_LOB, + columnType( BLOB ), + this + ) .withTypeCapacity( getMaxVarbinaryLength(), "bit varying($l)" ) .build() ); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java index 48ea03c1e4..0125723c42 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java @@ -185,23 +185,55 @@ public class DerbyLegacyDialect extends Dialect { int varcharDdlTypeCapacity = 32_672; ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( VARBINARY, columnType( LONG32VARBINARY ), columnType( VARBINARY ), this ) + CapacityDependentDdlType.builder( + VARBINARY, + isLob( LONG32VARBINARY ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARBINARY ), + columnType( VARBINARY ), + this + ) .withTypeCapacity( varcharDdlTypeCapacity, columnType( VARBINARY ) ) .build() ); ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( VARCHAR, columnType( LONG32VARCHAR ), columnType( VARCHAR ), this ) + CapacityDependentDdlType.builder( + VARCHAR, + isLob( LONG32VARCHAR ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARCHAR ), + columnType( VARCHAR ), + this + ) .withTypeCapacity( varcharDdlTypeCapacity, columnType( VARCHAR ) ) .build() ); ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( NVARCHAR, columnType( LONG32VARCHAR ), columnType( NVARCHAR ), this ) + CapacityDependentDdlType.builder( + NVARCHAR, + isLob( LONG32NVARCHAR ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARCHAR ), + columnType( NVARCHAR ), + this + ) .withTypeCapacity( varcharDdlTypeCapacity, columnType( NVARCHAR ) ) .build() ); ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( BINARY, columnType( LONG32VARBINARY ), columnType( VARBINARY ), this ) + CapacityDependentDdlType.builder( + BINARY, + isLob( LONG32VARBINARY ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARBINARY ), + columnType( VARBINARY ), + this + ) .withTypeCapacity( 254, "char($l) for bit data" ) .withTypeCapacity( varcharDdlTypeCapacity, columnType( VARBINARY ) ) .build() @@ -209,13 +241,29 @@ public class DerbyLegacyDialect extends Dialect { // This is the maximum size for the CHAR datatype on Derby ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( CHAR, columnType( LONG32VARCHAR ), columnType( CHAR ), this ) + CapacityDependentDdlType.builder( + CHAR, + isLob( LONG32VARCHAR ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARCHAR ), + columnType( CHAR ), + this + ) .withTypeCapacity( 254, columnType( CHAR ) ) .withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) ) .build() ); ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( NCHAR, columnType( LONG32NVARCHAR ), columnType( NCHAR ), this ) + CapacityDependentDdlType.builder( + NCHAR, + isLob( LONG32NVARCHAR ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32NVARCHAR ), + columnType( NCHAR ), + this + ) .withTypeCapacity( 254, columnType( NCHAR ) ) .withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) ) .build() 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 44ce68c3c5..65eb290918 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 @@ -42,6 +42,7 @@ import static org.hibernate.type.SqlTypes.BLOB; 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.NCHAR; import static org.hibernate.type.SqlTypes.NCLOB; @@ -113,7 +114,15 @@ public class MimerSQLDialect extends Dialect { //Mimer CHARs are ASCII!! ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( VARCHAR, columnType( LONG32VARCHAR ), "nvarchar(" + getMaxNVarcharLength() + ")", this ) + CapacityDependentDdlType.builder( + VARCHAR, + isLob( LONG32VARCHAR ) ? + CapacityDependentDdlType.LobKind.BIGGEST_LOB : + CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARCHAR ), + "nvarchar(" + getMaxNVarcharLength() + ")", + this + ) .withTypeCapacity( getMaxNVarcharLength(), columnType( VARCHAR ) ) .build() ); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java index 4f8c88b92c..38613a865f 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java @@ -300,8 +300,14 @@ public class MySQLLegacyDialect extends Dialect { final int maxMediumLobLen = 16_777_215; final CapacityDependentDdlType.Builder varcharBuilder = - CapacityDependentDdlType.builder( VARCHAR, - columnType( CLOB ), columnType( CHAR ), castType( CHAR ), this ) + CapacityDependentDdlType.builder( + VARCHAR, + CapacityDependentDdlType.LobKind.BIGGEST_LOB, + columnType( CLOB ), + columnType( CHAR ), + castType( CHAR ), + this + ) .withTypeCapacity( getMaxVarcharLength(), "varchar($l)" ) .withTypeCapacity( maxMediumLobLen, "mediumtext" ); if ( getMaxVarcharLength() < maxLobLen ) { @@ -310,8 +316,14 @@ public class MySQLLegacyDialect extends Dialect { ddlTypeRegistry.addDescriptor( varcharBuilder.build() ); final CapacityDependentDdlType.Builder nvarcharBuilder = - CapacityDependentDdlType.builder( NVARCHAR, - columnType( NCLOB ), columnType( NCHAR ), castType( NCHAR ), this ) + CapacityDependentDdlType.builder( + NVARCHAR, + CapacityDependentDdlType.LobKind.BIGGEST_LOB, + columnType( NCLOB ), + columnType( NCHAR ), + castType( NCHAR ), + this + ) .withTypeCapacity( getMaxVarcharLength(), "varchar($l)" ) .withTypeCapacity( maxMediumLobLen, "mediumtext" ); if ( getMaxVarcharLength() < maxLobLen ) { @@ -320,8 +332,14 @@ public class MySQLLegacyDialect extends Dialect { ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() ); final CapacityDependentDdlType.Builder varbinaryBuilder = - CapacityDependentDdlType.builder( VARBINARY, - columnType( BLOB ), columnType( BINARY ), castType( BINARY ), this ) + CapacityDependentDdlType.builder( + VARBINARY, + CapacityDependentDdlType.LobKind.BIGGEST_LOB, + columnType( BLOB ), + columnType( BINARY ), + castType( BINARY ), + this + ) .withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" ) .withTypeCapacity( maxMediumLobLen, "mediumblob" ); if ( getMaxVarbinaryLength() < maxLobLen ) { 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 1c3ebdffd6..88d1f9824b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java @@ -299,7 +299,7 @@ public abstract class AbstractHANADialect extends Dialect { // varbinary max length 5000 ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( BINARY, "blob", this ) + CapacityDependentDdlType.builder( BINARY, CapacityDependentDdlType.LobKind.BIGGEST_LOB, "blob", this ) .withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" ) .build() ); 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 d70927c5e3..9c7b983655 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java @@ -182,23 +182,55 @@ public class DerbyDialect extends Dialect { int varcharDdlTypeCapacity = 32_672; ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( VARBINARY, columnType( LONG32VARBINARY ), columnType( VARBINARY ), this ) + CapacityDependentDdlType.builder( + VARBINARY, + isLob( LONG32VARBINARY ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARBINARY ), + columnType( VARBINARY ), + this + ) .withTypeCapacity( varcharDdlTypeCapacity, columnType( VARBINARY ) ) .build() ); ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( VARCHAR, columnType( LONG32VARCHAR ), columnType( VARCHAR ), this ) + CapacityDependentDdlType.builder( + VARCHAR, + isLob( LONG32VARCHAR ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARCHAR ), + columnType( VARCHAR ), + this + ) .withTypeCapacity( varcharDdlTypeCapacity, columnType( VARCHAR ) ) .build() ); ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( NVARCHAR, columnType( LONG32VARCHAR ), columnType( NVARCHAR ), this ) + CapacityDependentDdlType.builder( + NVARCHAR, + isLob( LONG32NVARCHAR ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARCHAR ), + columnType( NVARCHAR ), + this + ) .withTypeCapacity( varcharDdlTypeCapacity, columnType( NVARCHAR ) ) .build() ); ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( BINARY, columnType( LONG32VARBINARY ), columnType( VARBINARY ), this ) + CapacityDependentDdlType.builder( + BINARY, + isLob( LONG32VARBINARY ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARBINARY ), + columnType( VARBINARY ), + this + ) .withTypeCapacity( 254, "char($l) for bit data" ) .withTypeCapacity( varcharDdlTypeCapacity, columnType( VARBINARY ) ) .build() @@ -206,13 +238,29 @@ public class DerbyDialect extends Dialect { // This is the maximum size for the CHAR datatype on Derby ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( CHAR, columnType( LONG32VARCHAR ), columnType( CHAR ), this ) + CapacityDependentDdlType.builder( + CHAR, + isLob( LONG32VARCHAR ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32VARCHAR ), + columnType( CHAR ), + this + ) .withTypeCapacity( 254, columnType( CHAR ) ) .withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) ) .build() ); ddlTypeRegistry.addDescriptor( - CapacityDependentDdlType.builder( NCHAR, columnType( LONG32NVARCHAR ), columnType( NCHAR ), this ) + CapacityDependentDdlType.builder( + NCHAR, + isLob( LONG32NVARCHAR ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, + columnType( LONG32NVARCHAR ), + columnType( NCHAR ), + this + ) .withTypeCapacity( 254, columnType( NCHAR ) ) .withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) ) .build() 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 9637e2c62d..c669eef1fb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -446,10 +446,33 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun if ( supportsStandardArrays() ) { ddlTypeRegistry.addDescriptor( new ArrayDdlTypeImpl( this ) ); } + if ( rowId( null ) != null ) { + ddlTypeRegistry.addDescriptor( simpleSqlType( ROWID ) ); + } + } + + protected boolean isLob(int sqlTypeCode) { + switch ( sqlTypeCode ) { + case LONG32VARBINARY: + case LONG32VARCHAR: + case LONG32NVARCHAR: + case BLOB: + case CLOB: + case NCLOB: + return true; + default: + return false; + } } private DdlTypeImpl simpleSqlType(int sqlTypeCode) { - return new DdlTypeImpl( sqlTypeCode, columnType( sqlTypeCode ), castType( sqlTypeCode ), this ); + return new DdlTypeImpl( + sqlTypeCode, + isLob( sqlTypeCode ), + columnType( sqlTypeCode ), + castType( sqlTypeCode ), + this + ); } /** @@ -463,6 +486,11 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun private CapacityDependentDdlType.Builder sqlTypeBuilder(int sqlTypeCode, int biggestSqlTypeCode, int castTypeCode) { return CapacityDependentDdlType.builder( sqlTypeCode, + isLob( sqlTypeCode ) + ? CapacityDependentDdlType.LobKind.ALL_LOB + : isLob( biggestSqlTypeCode ) + ? CapacityDependentDdlType.LobKind.BIGGEST_LOB + : CapacityDependentDdlType.LobKind.NONE, columnType( biggestSqlTypeCode ), castType( castTypeCode ), this @@ -510,6 +538,9 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun */ protected String columnType(int sqlTypeCode) { switch ( sqlTypeCode ) { + case ROWID: + return "rowid"; + case BOOLEAN: return "boolean"; 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 8ffe75d128..5ee5542504 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -334,8 +334,14 @@ public class MySQLDialect extends Dialect { final int maxMediumLobLen = 16_777_215; final CapacityDependentDdlType.Builder varcharBuilder = - CapacityDependentDdlType.builder( VARCHAR, - columnType( CLOB ), columnType( CHAR ), castType( CHAR ), this ) + CapacityDependentDdlType.builder( + VARCHAR, + CapacityDependentDdlType.LobKind.BIGGEST_LOB, + columnType( CLOB ), + columnType( CHAR ), + castType( CHAR ), + this + ) .withTypeCapacity( getMaxVarcharLength(), "varchar($l)" ) .withTypeCapacity( maxMediumLobLen, "mediumtext" ); if ( getMaxVarcharLength() < maxLobLen ) { @@ -346,8 +352,14 @@ public class MySQLDialect extends Dialect { // do not use nchar/nvarchar/ntext because these // types use a deprecated character set on MySQL 8 final CapacityDependentDdlType.Builder nvarcharBuilder = - CapacityDependentDdlType.builder( NVARCHAR, - columnType( NCLOB ), columnType( NCHAR ), castType( NCHAR ), this ) + CapacityDependentDdlType.builder( + NVARCHAR, + CapacityDependentDdlType.LobKind.BIGGEST_LOB, + columnType( NCLOB ), + columnType( NCHAR ), + castType( NCHAR ), + this + ) .withTypeCapacity( getMaxVarcharLength(), "varchar($l) character set utf8" ) .withTypeCapacity( maxMediumLobLen, "mediumtext character set utf8" ); if ( getMaxVarcharLength() < maxLobLen ) { @@ -356,8 +368,14 @@ public class MySQLDialect extends Dialect { ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() ); final CapacityDependentDdlType.Builder varbinaryBuilder = - CapacityDependentDdlType.builder( VARBINARY, - columnType( BLOB ), columnType( BINARY ), castType( BINARY ), this ) + CapacityDependentDdlType.builder( + VARBINARY, + CapacityDependentDdlType.LobKind.BIGGEST_LOB, + columnType( BLOB ), + columnType( BINARY ), + castType( BINARY ), + this + ) .withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" ) .withTypeCapacity( maxMediumLobLen, "mediumblob" ); if ( getMaxVarbinaryLength() < maxLobLen ) { 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 43f16b6e18..4f1bf85d4d 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java @@ -28,6 +28,8 @@ import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; import org.hibernate.type.ComponentType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; +import org.hibernate.type.descriptor.JdbcTypeNameMapper; +import org.hibernate.type.descriptor.sql.DdlType; import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; @@ -56,6 +58,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn private boolean unique; private String sqlTypeName; private Integer sqlTypeCode; + private boolean sqlTypeLob; private boolean quoted; private boolean explicit; int uniqueInteger; @@ -284,13 +287,29 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn private String getSqlTypeName(DdlTypeRegistry ddlTypeRegistry, Dialect dialect, Mapping mapping) { if ( sqlTypeName == null ) { - try { - sqlTypeName = ddlTypeRegistry.getTypeName( - getSqlTypeCode( mapping ), - getColumnSize( dialect, mapping ), - getUnderlyingType( mapping, getValue().getType(), typeIndex ) + final int typeCode = getSqlTypeCode( mapping ); + final DdlType descriptor = ddlTypeRegistry.getDescriptor( getSqlTypeCode( mapping ) ); + if ( descriptor == null ) { + throw new MappingException( + String.format( + Locale.ROOT, + "Unable to determine SQL type name for column '%s' of table '%s' because there is no type mapping for org.hibernate.type.SqlTypes code: %s (%s)", + getName(), + getValue().getTable().getName(), + typeCode, + JdbcTypeNameMapper.getTypeName( typeCode ) + ) ); } + try { + final Size size = getColumnSize( dialect, mapping ); + sqlTypeName = descriptor.getTypeName( + size, + getUnderlyingType( mapping, getValue().getType(), typeIndex ), + ddlTypeRegistry + ); + sqlTypeLob = descriptor.isLob( size ); + } catch ( Exception cause ) { throw new MappingException( String.format( @@ -489,6 +508,10 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn sqlTypeName = typeName; } + public boolean isSqlTypeLob() { + return sqlTypeLob; + } + public void setUnique(boolean unique) { this.unique = unique; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SqlTypedMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SqlTypedMapping.java index 3ac8245d7d..6e6f9475cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SqlTypedMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SqlTypedMapping.java @@ -16,5 +16,8 @@ public interface SqlTypedMapping { Long getLength(); Integer getPrecision(); Integer getScale(); + default boolean isLob() { + return getJdbcMapping().getJdbcType().isLob(); + } JdbcMapping getJdbcMapping(); } 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 782337d382..2fbd14706b 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 @@ -283,14 +283,16 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType final Long length; final Integer precision; final Integer scale; + final boolean isLob; final boolean nullable; if ( selectable instanceof Column ) { final Column column = (Column) selectable; - columnDefinition = column.getSqlType(); + columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); length = column.getLength(); precision = column.getPrecision(); scale = column.getScale(); nullable = column.isNullable(); + isLob = column.isSqlTypeLob(); selectablePath = basicValue.createSelectablePath( column.getQuotedName( dialect ) ); } else { @@ -299,6 +301,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType precision = null; scale = null; nullable = true; + isLob = false; selectablePath = basicValue.createSelectablePath( bootPropertyDescriptor.getName() ); } @@ -320,6 +323,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType length, precision, scale, + isLob, nullable, value.isColumnInsertable( 0 ), value.isColumnUpdateable( 0 ), diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicAttributeMapping.java index 40ee2a194d..980ecb6a7b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicAttributeMapping.java @@ -60,6 +60,7 @@ public class BasicAttributeMapping private final Integer scale; private final JdbcMapping jdbcMapping; + private final boolean isLob; private final boolean nullable; private final boolean insertable; private final boolean updateable; @@ -85,6 +86,7 @@ public class BasicAttributeMapping Long length, Integer precision, Integer scale, + boolean isLob, boolean nullable, boolean insertable, boolean updateable, @@ -116,6 +118,7 @@ public class BasicAttributeMapping this.length = length; this.precision = precision; this.scale = scale; + this.isLob = isLob; this.nullable = nullable; this.insertable = insertable; this.updateable = updateable; @@ -183,6 +186,7 @@ public class BasicAttributeMapping selectableMapping.getLength(), selectableMapping.getPrecision(), selectableMapping.getScale(), + selectableMapping.isLob(), selectableMapping.isNullable(), insertable, updateable, @@ -223,6 +227,11 @@ public class BasicAttributeMapping return selectablePath; } + @Override + public boolean isLob() { + return isLob; + } + @Override public boolean isFormula() { return isFormula; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/DiscriminatedAssociationMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/DiscriminatedAssociationMapping.java index 85500909ad..937c39fc87 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/DiscriminatedAssociationMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/DiscriminatedAssociationMapping.java @@ -86,7 +86,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption declaringModelPart, tableName, metaColumn.getText( dialect ), - metaColumn.getSqlType(), + metaColumn.getSqlType( creationProcess.getCreationContext().getMetadata() ), metaColumn.getLength(), metaColumn.getPrecision(), metaColumn.getScale(), @@ -105,7 +105,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption declaringModelPart, tableName, keyColumn.getText( dialect ), - keyColumn.getSqlType(), + keyColumn.getSqlType( creationProcess.getCreationContext().getMetadata() ), keyColumn.getLength(), keyColumn.getPrecision(), keyColumn.getScale(), 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 a93d43dfba..b4f8a5cb88 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 @@ -193,7 +193,8 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme updatable, false, dialect, - null + null, + creationContext ); final AggregateSupport aggregateSupport = dialect.getAggregateSupport(); final int sqlTypeCode = aggregateColumn.getSqlTypeCode(); @@ -227,7 +228,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme typeConfiguration.getJdbcTypeRegistry().resolveAggregateDescriptor( aggregateColumn.getSqlTypeCode(), aggregateColumn.getSqlTypeCode() == SqlTypes.STRUCT - ? aggregateColumn.getSqlType() + ? aggregateColumn.getSqlType( creationContext.getMetadata() ) : null, this, creationContext @@ -378,13 +379,15 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme final Long length; final Integer precision; final Integer scale; + final boolean isLob; final boolean nullable; if ( selectable instanceof Column ) { final Column column = (Column) selectable; - columnDefinition = column.getSqlType(); + columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); length = column.getLength(); precision = column.getPrecision(); scale = column.getScale(); + isLob = column.isSqlTypeLob(); nullable = bootPropertyDescriptor.isOptional() && column.isNullable() ; selectablePath = basicValue.createSelectablePath( column.getQuotedName( dialect ) ); } @@ -393,6 +396,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme length = null; precision = null; scale = null; + isLob = false; nullable = bootPropertyDescriptor.isOptional(); selectablePath = basicValue.createSelectablePath( bootPropertyDescriptor.getName() ); } @@ -414,6 +418,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme length, precision, scale, + isLob, nullable, insertability[columnPosition], updateability[columnPosition], diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java index 3e24dab83c..7374c743f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java @@ -502,7 +502,8 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple false, false, creationProcess.getCreationContext().getDialect(), - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); final BasicAttributeMapping keyModelPart = BasicAttributeMapping.withSelectableMapping( @@ -538,7 +539,8 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple elementBootDescriptor.getColumnInsertability(), elementBootDescriptor.getColumnUpdateability(), creationProcess.getCreationContext().getDialect(), - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); return new EmbeddedForeignKeyDescriptor( @@ -676,7 +678,8 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple fkBootDescriptorSource.getColumnInsertability(), fkBootDescriptorSource.getColumnUpdateability(), creationProcess.getCreationContext().getDialect(), - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); return foreignKeyDescriptor.withKeySelectionMapping( declaringType, @@ -718,7 +721,8 @@ public class ManyToManyCollectionPart extends AbstractEntityCollectionPart imple columnUpdateable, fkValue.isPartitionKey(), dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); // here we build a ModelPart that represents the many-to-many table key referring to the element table 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 b049796ae6..3b5801c8a2 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 @@ -194,6 +194,7 @@ public class MappingModelCreationHelper { Long length, Integer precision, Integer scale, + boolean isLob, boolean nullable, boolean insertable, boolean updateable, @@ -243,6 +244,7 @@ public class MappingModelCreationHelper { length, precision, scale, + isLob, nullable, insertable, updateable, @@ -512,7 +514,8 @@ public class MappingModelCreationHelper { index.isColumnUpdateable( 0 ), false, dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); indexDescriptor = new BasicValuedCollectionPart( collectionDescriptor, @@ -565,7 +568,8 @@ public class MappingModelCreationHelper { index.isColumnUpdateable( 0 ), false, dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); indexDescriptor = new BasicValuedCollectionPart( collectionDescriptor, @@ -776,7 +780,8 @@ public class MappingModelCreationHelper { bootValueMappingKey.isColumnUpdateable( 0 ), false, dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); final SimpleForeignKeyDescriptor keyDescriptor = new SimpleForeignKeyDescriptor( @@ -952,7 +957,8 @@ public class MappingModelCreationHelper { value.isColumnUpdateable( i ), ((SimpleValue) value).isPartitionKey(), dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); i++; } @@ -967,7 +973,8 @@ public class MappingModelCreationHelper { value.isColumnUpdateable( 0 ), ((SimpleValue) value).isPartitionKey(), dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); } @@ -1114,7 +1121,8 @@ public class MappingModelCreationHelper { insertable, updateable, dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); } else { @@ -1138,7 +1146,8 @@ public class MappingModelCreationHelper { insertable, updateable, dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); } if ( inverse ) { @@ -1318,7 +1327,8 @@ public class MappingModelCreationHelper { updatable, false, dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); return new BasicValuedCollectionPart( collectionDescriptor, @@ -1415,7 +1425,8 @@ public class MappingModelCreationHelper { basicElement.isPartitionKey(), true, // element collection does not support null elements dialect, - creationProcess.getSqmFunctionRegistry() + creationProcess.getSqmFunctionRegistry(), + creationProcess.getCreationContext() ); return new BasicValuedCollectionPart( collectionDescriptor, 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 f319cc7864..34cd94d37b 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 @@ -14,6 +14,7 @@ import org.hibernate.mapping.Selectable; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectablePath; +import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.type.spi.TypeConfiguration; @@ -27,6 +28,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select private final SelectablePath selectablePath; private final String customReadExpression; private final String customWriteExpression; + private final boolean isLob; private final boolean nullable; private final boolean insertable; private final boolean updateable; @@ -43,6 +45,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select Long length, Integer precision, Integer scale, + boolean isLob, boolean nullable, boolean insertable, boolean updateable, @@ -57,6 +60,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select this.selectablePath = selectablePath == null ? new SelectablePath( selectionExpression ) : selectablePath; this.customReadExpression = customReadExpression == null ? null : customReadExpression.intern(); this.customWriteExpression = customWriteExpression == null || isFormula ? null : customWriteExpression.intern(); + this.isLob = isLob; this.nullable = nullable; this.insertable = insertable; this.updateable = updateable; @@ -73,7 +77,8 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select boolean updateable, boolean partitioned, final Dialect dialect, - final SqmFunctionRegistry sqmFunctionRegistry) { + final SqmFunctionRegistry sqmFunctionRegistry, + RuntimeModelCreationContext creationContext) { return from( containingTableExpression, selectable, @@ -84,7 +89,8 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select updateable, partitioned, dialect, - sqmFunctionRegistry + sqmFunctionRegistry, + creationContext ); } @@ -98,7 +104,8 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select boolean partitioned, boolean forceNotNullable, final Dialect dialect, - final SqmFunctionRegistry sqmFunctionRegistry) { + final SqmFunctionRegistry sqmFunctionRegistry, + RuntimeModelCreationContext creationContext) { return from( containingTableExpression, selectable, @@ -110,7 +117,8 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select partitioned, forceNotNullable, dialect, - sqmFunctionRegistry + sqmFunctionRegistry, + creationContext ); } @@ -124,7 +132,8 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select boolean updateable, boolean partitioned, final Dialect dialect, - final SqmFunctionRegistry sqmFunctionRegistry) { + final SqmFunctionRegistry sqmFunctionRegistry, + RuntimeModelCreationContext creationContext) { return from( containingTableExpression, selectable, @@ -136,7 +145,8 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select partitioned, false, dialect, - sqmFunctionRegistry + sqmFunctionRegistry, + creationContext ); } @@ -151,13 +161,15 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select boolean partitioned, boolean forceNotNullable, final Dialect dialect, - final SqmFunctionRegistry sqmFunctionRegistry) { + final SqmFunctionRegistry sqmFunctionRegistry, + RuntimeModelCreationContext creationContext) { final String columnExpression; final String columnDefinition; final Long length; final Integer precision; final Integer scale; final String selectableName; + final boolean isLob; final boolean isNullable; if ( selectable.isFormula() ) { columnExpression = selectable.getTemplate( dialect, typeConfiguration, sqmFunctionRegistry ); @@ -166,17 +178,19 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select precision = null; scale = null; isNullable = true; + isLob = false; selectableName = selectable.getText(); } else { Column column = (Column) selectable; columnExpression = selectable.getText( dialect ); - columnDefinition = column.getSqlType(); + columnDefinition = column.getSqlType( creationContext.getMetadata() ); length = column.getLength(); precision = column.getPrecision(); scale = column.getScale(); isNullable = forceNotNullable ? false : column.isNullable(); + isLob = column.isSqlTypeLob(); selectableName = column.getQuotedName( dialect ); } return new SelectableMappingImpl( @@ -191,6 +205,7 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select length, precision, scale, + isLob, isNullable, insertable, updateable, @@ -245,6 +260,11 @@ public class SelectableMappingImpl extends SqlTypedMappingImpl implements Select return customWriteExpression; } + @Override + public boolean isLob() { + return isLob; + } + @Override public boolean isFormula() { return isFormula; 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 55e8712066..7ff282dd78 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 @@ -19,6 +19,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectableMappings; +import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.type.CompositeType; import org.hibernate.type.EntityType; @@ -64,7 +65,8 @@ public class SelectableMappingsImpl implements SelectableMappings { boolean[] insertable, boolean[] updateable, Dialect dialect, - SqmFunctionRegistry sqmFunctionRegistry) { + SqmFunctionRegistry sqmFunctionRegistry, + RuntimeModelCreationContext creationContext) { if ( insertable.length == 0 ) { return from( containingTableExpression, @@ -73,7 +75,8 @@ public class SelectableMappingsImpl implements SelectableMappings { mapping, typeConfiguration, dialect, - sqmFunctionRegistry + sqmFunctionRegistry, + creationContext ); } final List jdbcMappings = new ArrayList<>(); @@ -92,7 +95,8 @@ public class SelectableMappingsImpl implements SelectableMappings { updateable[i], false, dialect, - sqmFunctionRegistry + sqmFunctionRegistry, + creationContext ); } @@ -106,7 +110,8 @@ public class SelectableMappingsImpl implements SelectableMappings { Mapping mapping, TypeConfiguration typeConfiguration, Dialect dialect, - SqmFunctionRegistry sqmFunctionRegistry) { + SqmFunctionRegistry sqmFunctionRegistry, + RuntimeModelCreationContext creationContext) { final List jdbcMappings = new ArrayList<>(); resolveJdbcMappings( jdbcMappings, mapping, value.getType() ); @@ -123,7 +128,8 @@ public class SelectableMappingsImpl implements SelectableMappings { false, false, dialect, - sqmFunctionRegistry + sqmFunctionRegistry, + creationContext ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java index 70957ab352..1caf208f6b 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java @@ -555,7 +555,8 @@ public class OneToManyPersister extends AbstractCollectionPersister { updateBuilder.addValueColumn( selectable.getSelectionExpression(), NULL, - selectable.getJdbcMapping() + selectable.getJdbcMapping(), + selectable.isLob() ); } @@ -578,7 +579,8 @@ public class OneToManyPersister extends AbstractCollectionPersister { updateBuilder.addValueColumn( selectable.getSelectionExpression(), NULL, - selectable.getJdbcMapping() + selectable.getJdbcMapping(), + selectable.isLob() ); } } 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 1973d0474e..d901744996 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 @@ -5202,7 +5202,7 @@ public abstract class AbstractEntityPersister scale = null; } else { - columnDefinition = column.getSqlType(); + columnDefinition = column.getSqlType( modelCreationProcess.getCreationContext().getMetadata() ); length = column.getLength(); precision = column.getPrecision(); scale = column.getScale(); @@ -5379,7 +5379,7 @@ public abstract class AbstractEntityPersister } else { Column column = bootEntityDescriptor.getIdentifier().getColumns().get( 0 ); - columnDefinition = column.getSqlType(); + columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); length = column.getLength(); precision = column.getPrecision(); scale = column.getScale(); @@ -5438,7 +5438,7 @@ public abstract class AbstractEntityPersister bootModelRootEntityDescriptor.getVersion().getName(), entityPersister.getTableName(), column.getText( dialect ), - column.getSqlType(), + column.getSqlType( creationProcess.getCreationContext().getMetadata() ), column.getLength(), column.getPrecision(), column.getScale(), @@ -5483,10 +5483,11 @@ public abstract class AbstractEntityPersister false, null, "?", - column.getSqlType(), + column.getSqlType( creationProcess.getCreationContext().getMetadata() ), column.getLength(), column.getPrecision(), column.getScale(), + column.isSqlTypeLob(), column.isNullable(), value.isColumnInsertable( 0 ), value.isColumnUpdateable( 0 ), @@ -5505,6 +5506,7 @@ public abstract class AbstractEntityPersister final Long length; final Integer precision; final Integer scale; + final boolean isLob; final boolean nullable; if ( value instanceof DependantValue ) { @@ -5513,10 +5515,11 @@ public abstract class AbstractEntityPersister customReadExpr = null; customWriteExpr = "?"; Column column = value.getColumns().get( 0 ); - columnDefinition = column.getSqlType(); + columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); length = column.getLength(); precision = column.getPrecision(); scale = column.getScale(); + isLob = column.isSqlTypeLob(); nullable = column.isNullable(); } else { @@ -5539,11 +5542,12 @@ public abstract class AbstractEntityPersister ); customWriteExpr = selectable.getWriteExpr( (JdbcMapping) attrType, creationContext.getDialect() ); Column column = value.getColumns().get( 0 ); - columnDefinition = column.getSqlType(); + columnDefinition = column.getSqlType( creationContext.getMetadata() ); length = column.getLength(); precision = column.getPrecision(); scale = column.getScale(); nullable = column.isNullable(); + isLob = column.isSqlTypeLob(); } else { final String[] attrColumnFormulaTemplate = propertyColumnFormulaTemplates[ propertyIndex ]; @@ -5556,6 +5560,7 @@ public abstract class AbstractEntityPersister precision = null; scale = null; nullable = true; + isLob = false; } } @@ -5577,6 +5582,7 @@ public abstract class AbstractEntityPersister length, precision, scale, + isLob, nullable, value.isColumnInsertable( 0 ), value.isColumnUpdateable( 0 ), 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 6ce853182a..e9206f9e3b 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 @@ -1187,7 +1187,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { } else { final Column column = bootEntityDescriptor.getIdentifier().getColumns().get( 0 ); - columnDefinition = column.getSqlType(); + columnDefinition = column.getSqlType( creationProcess.getCreationContext().getMetadata() ); length = column.getLength(); precision = column.getPrecision(); scale = column.getScale(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java index fc2cad69f9..faff64b750 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java @@ -130,7 +130,8 @@ public abstract class AbstractMutationCoordinator { tableUpdateBuilder.addValueColumn( mapping.getSelectionExpression(), writePropertyValue ? "?" : columnValues[j], - mapping.getJdbcMapping() + mapping.getJdbcMapping(), + mapping.isLob() ); } ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java index 7d64e4d94e..47d8f10491 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java @@ -70,10 +70,10 @@ public abstract class AbstractTableInsertBuilder } @Override - public void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { + public void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob) { final ColumnValueBinding valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping ); - if ( jdbcMapping.getJdbcType().isLob() && getJdbcServices().getDialect().forceLobAsLastValue() ) { + if ( isLob && getJdbcServices().getDialect().forceLobAsLastValue() ) { if ( lobValueBindingList == null ) { lobValueBindingList = new ArrayList<>(); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableUpdateBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableUpdateBuilder.java index 4bade25276..6bd54b6522 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableUpdateBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableUpdateBuilder.java @@ -90,10 +90,11 @@ public abstract class AbstractTableUpdateBuilder public void addValueColumn( String columnName, String columnWriteFragment, - JdbcMapping jdbcMapping) { + JdbcMapping jdbcMapping, + boolean isLob) { final ColumnValueBinding valueBinding = createValueBinding( columnName, columnWriteFragment, jdbcMapping ); - if ( jdbcMapping.getJdbcType().isLob() && getJdbcServices().getDialect().forceLobAsLastValue() ) { + if ( isLob && getJdbcServices().getDialect().forceLobAsLastValue() ) { if ( lobValueBindings == null ) { lobValueBindings = new ArrayList<>(); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValuesTableMutationBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValuesTableMutationBuilder.java index b7d73db018..d7ce9a6864 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValuesTableMutationBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/ColumnValuesTableMutationBuilder.java @@ -19,7 +19,13 @@ public interface ColumnValuesTableMutationBuilder { /** * Add a column as part of the values list */ - void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping); + void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob); + /** + * Add a column as part of the values list + */ + default void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { + addValueColumn( columnName, columnWriteFragment, jdbcMapping, jdbcMapping.getJdbcType().isLob() ); + } /** * Add a column as part of the values list @@ -28,7 +34,8 @@ public interface ColumnValuesTableMutationBuilder { addValueColumn( selectableMapping.getSelectionExpression(), selectableMapping.getWriteExpression(), - selectableMapping.getJdbcMapping() + selectableMapping.getJdbcMapping(), + selectableMapping.isLob() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableUpdateBuilderSkipped.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableUpdateBuilderSkipped.java index 0027e4c3af..6fdd69a968 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableUpdateBuilderSkipped.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/TableUpdateBuilderSkipped.java @@ -64,7 +64,7 @@ public class TableUpdateBuilderSkipped implements TableUpdateBuilder { } @Override - public void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) { + public void addValueColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping, boolean isLob) { // nothing to do } 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 85a35f31bd..b88967b163 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 @@ -169,7 +169,7 @@ public abstract class AbstractSchemaValidator implements SchemaValidator { table.getQualifiedTableName(), columnInformation.getTypeName().toLowerCase(Locale.ROOT), JdbcTypeNameMapper.getTypeName( columnInformation.getTypeCode() ), - column.getSqlType().toLowerCase(Locale.ROOT), + column.getSqlType( metadata ).toLowerCase(Locale.ROOT), JdbcTypeNameMapper.getTypeName( column.getSqlTypeCode( metadata ) ) ) ); 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 fda5267cb8..dd03a423ac 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 @@ -248,6 +248,24 @@ public interface JdbcType extends Serializable { return false; } + default boolean isLobOrLong() { + return isLobOrLong( getDdlTypeCode() ); + } + + static boolean isLobOrLong(int jdbcTypeCode) { + switch ( jdbcTypeCode ) { + case BLOB: + case CLOB: + case NCLOB: + case LONG32VARBINARY: + case LONG32VARCHAR: + case LONG32NVARCHAR: { + return true; + } + } + return false; + } + default boolean isNationalized() { return isNationalized( getDdlTypeCode() ); } 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 611818296f..164022a126 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 @@ -89,6 +89,11 @@ public interface DdlType extends Serializable { @Deprecated(since = "6.3") String getTypeName(Long size, Integer precision, Integer scale); + default boolean isLob(Size size) { + // Let's be defensive and assume that LONG32 are LOBs as well + return JdbcType.isLobOrLong( getSqlTypeCode() ); + } + /** * Return the database type corresponding to the given {@link JdbcType} * that may be used as a target type in casting operations using the SQL 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 index 9a6d27c131..83dabad422 100644 --- 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 @@ -11,6 +11,8 @@ import java.util.Comparator; import java.util.List; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.Size; +import org.hibernate.type.descriptor.jdbc.JdbcType; /** * Descriptor for a SQL type. @@ -19,6 +21,7 @@ import org.hibernate.dialect.Dialect; */ public class CapacityDependentDdlType extends DdlTypeImpl { + private final LobKind lobKind; private final TypeEntry[] typeEntries; private CapacityDependentDdlType(Builder builder) { @@ -29,6 +32,7 @@ public class CapacityDependentDdlType extends DdlTypeImpl { builder.castTypeName, builder.dialect ); + this.lobKind = builder.lobKind; builder.typeEntries.sort( Comparator.naturalOrder() ); this.typeEntries = builder.typeEntries.toArray(new TypeEntry[0]); } @@ -73,8 +77,34 @@ public class CapacityDependentDdlType extends DdlTypeImpl { return super.getTypeName( size, precision, scale ); } + @Override + public boolean isLob(Size size) { + if ( lobKind == LobKind.ALL_LOB ) { + return true; + } + final Long length = size.getLength(); + if ( length != null && length > 0 ) { + for ( TypeEntry typeEntry : typeEntries ) { + if ( length <= typeEntry.capacity ) { + return false; + } + } + } + return lobKind == LobKind.BIGGEST_LOB; + } + public static Builder builder(int sqlTypeCode, String typeNamePattern, Dialect dialect) { - return builder( sqlTypeCode, typeNamePattern, typeNamePattern, dialect ); + return builder( + sqlTypeCode, + JdbcType.isLob( sqlTypeCode ) ? LobKind.ALL_LOB : LobKind.NONE, + typeNamePattern, + typeNamePattern, + dialect + ); + } + + public static Builder builder(int sqlTypeCode, LobKind lobKind, String typeNamePattern, Dialect dialect) { + return builder( sqlTypeCode, lobKind, typeNamePattern, typeNamePattern, dialect ); } public static Builder builder( @@ -82,7 +112,22 @@ public class CapacityDependentDdlType extends DdlTypeImpl { String typeNamePattern, String castTypeName, Dialect dialect) { - return new Builder( sqlTypeCode, typeNamePattern, null, castTypeName, dialect ); + return builder( + sqlTypeCode, + JdbcType.isLob( sqlTypeCode ) ? LobKind.ALL_LOB : LobKind.NONE, + typeNamePattern, + castTypeName, + dialect + ); + } + + public static Builder builder( + int sqlTypeCode, + LobKind lobKind, + String typeNamePattern, + String castTypeName, + Dialect dialect) { + return builder( sqlTypeCode, lobKind, typeNamePattern, null, castTypeName, dialect ); } public static Builder builder( @@ -91,11 +136,29 @@ public class CapacityDependentDdlType extends DdlTypeImpl { String castTypeNamePattern, String castTypeName, Dialect dialect) { - return new Builder( sqlTypeCode, typeNamePattern, castTypeNamePattern, castTypeName, dialect ); + return builder( + sqlTypeCode, + JdbcType.isLob( sqlTypeCode ) ? LobKind.ALL_LOB : LobKind.NONE, + typeNamePattern, + castTypeNamePattern, + castTypeName, + dialect + ); + } + + public static Builder builder( + int sqlTypeCode, + LobKind lobKind, + String typeNamePattern, + String castTypeNamePattern, + String castTypeName, + Dialect dialect) { + return new Builder( sqlTypeCode, lobKind, typeNamePattern, castTypeNamePattern, castTypeName, dialect ); } public static class Builder { private final int sqlTypeCode; + private final LobKind lobKind; private final String typeNamePattern; private final String castTypeNamePattern; private final String castTypeName; @@ -104,11 +167,13 @@ public class CapacityDependentDdlType extends DdlTypeImpl { private Builder( int sqlTypeCode, + LobKind lobKind, String typeNamePattern, String castTypeNamePattern, String castTypeName, Dialect dialect) { this.sqlTypeCode = sqlTypeCode; + this.lobKind = lobKind; this.typeNamePattern = typeNamePattern; this.castTypeNamePattern = castTypeNamePattern; this.castTypeName = castTypeName; @@ -140,4 +205,10 @@ public class CapacityDependentDdlType extends DdlTypeImpl { return Long.compare( capacity, o.capacity ); } } + + public enum LobKind { + BIGGEST_LOB, + ALL_LOB, + NONE + } } 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 1795b7cb4b..4a7c0d56fe 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 @@ -23,6 +23,7 @@ import org.hibernate.type.descriptor.sql.DdlType; public class DdlTypeImpl implements DdlType { private final int sqlTypeCode; + private final boolean isLob; private final String typeNamePattern; private final String castTypeNamePattern; private final String castTypeName; @@ -43,11 +44,31 @@ public class DdlTypeImpl implements DdlType { public DdlTypeImpl( int sqlTypeCode, + boolean isLob, + String typeNamePattern, + String castTypeName, + Dialect dialect) { + this( sqlTypeCode, isLob, typeNamePattern, null, castTypeName, dialect ); + } + + public DdlTypeImpl( + int sqlTypeCode, + String typeNamePattern, + String castTypeNamePattern, //optional, usually null + String castTypeName, + Dialect dialect) { + this( sqlTypeCode, JdbcType.isLob( sqlTypeCode ), typeNamePattern, castTypeNamePattern, castTypeName, dialect ); + } + + public DdlTypeImpl( + int sqlTypeCode, + boolean isLob, String typeNamePattern, String castTypeNamePattern, //optional, usually null String castTypeName, Dialect dialect) { this.sqlTypeCode = sqlTypeCode; + this.isLob = isLob; this.typeNamePattern = typeNamePattern; this.castTypeNamePattern = castTypeNamePattern; this.castTypeName = castTypeName; @@ -76,6 +97,11 @@ public class DdlTypeImpl implements DdlType { return typeNamePattern; } + @Override + public boolean isLob(Size size) { + return isLob; + } + @Override public String getTypeName(Long size, Integer precision, Integer scale) { return replace( typeNamePattern, size, precision, scale ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/rowid/RowIdType.java b/hibernate-core/src/test/java/org/hibernate/orm/test/rowid/RowIdType.java index a44b7cd2b4..1c3748520c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/rowid/RowIdType.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/rowid/RowIdType.java @@ -25,7 +25,7 @@ public class RowIdType implements UserType{ @Override public int getSqlType() { - return Types.JAVA_OBJECT; + return Types.ROWID; } public Class returnedClass() {