HHH-15463 Adjust JdbcType based on DDL capacity for varchar/varbinary like types
This commit is contained in:
parent
66b86ad315
commit
a094d4c5d5
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.userguide.mapping.basic;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
@ -18,7 +19,9 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.jdbc.AdjustableJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
|
@ -50,15 +53,25 @@ public class DurationMappingTests {
|
|||
final JdbcType intervalType = jdbcTypeRegistry.getDescriptor(SqlTypes.INTERVAL_SECOND);
|
||||
final JdbcType realType;
|
||||
if (intervalType instanceof AdjustableJdbcType) {
|
||||
realType = ((AdjustableJdbcType) intervalType).resolveIndicatedType(
|
||||
() -> mappingMetamodel.getTypeConfiguration(),
|
||||
realType = ( (AdjustableJdbcType) intervalType ).resolveIndicatedType(
|
||||
new JdbcTypeIndicators() {
|
||||
@Override
|
||||
public TypeConfiguration getTypeConfiguration() {
|
||||
return mappingMetamodel.getTypeConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnScale() {
|
||||
return duration.getScale() == null ? JdbcTypeIndicators.NO_COLUMN_SCALE : duration.getScale();
|
||||
}
|
||||
},
|
||||
jdbcMapping.getJavaTypeDescriptor()
|
||||
);
|
||||
}
|
||||
else {
|
||||
realType = intervalType;
|
||||
}
|
||||
assertThat( jdbcMapping.getJdbcType(), is( realType));
|
||||
assertThat( jdbcMapping.getJdbcType(), is( realType ) );
|
||||
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
|
@ -69,6 +82,14 @@ public class DurationMappingTests {
|
|||
scope.inTransaction(
|
||||
(session) -> session.find(EntityWithDuration.class, 1)
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
session.createQuery( "from EntityWithDuration e where e.duration = :param", EntityWithDuration.class )
|
||||
.setParameter( "param", Duration.ofHours( 3 ) )
|
||||
.getResultList();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "EntityWithDuration")
|
||||
|
|
|
@ -39,7 +39,7 @@ import static org.hamcrest.Matchers.is;
|
|||
public class InetAddressMappingTests {
|
||||
|
||||
@Test
|
||||
public void verifyMappings(SessionFactoryScope scope) {
|
||||
public void verifyMappings(SessionFactoryScope scope) throws Exception {
|
||||
final MappingMetamodelImplementor mappingMetamodel = scope.getSessionFactory()
|
||||
.getRuntimeMetamodels()
|
||||
.getMappingMetamodel();
|
||||
|
@ -62,20 +62,27 @@ public class InetAddressMappingTests {
|
|||
}
|
||||
assertThat( jdbcMapping.getJdbcType(), is( realType));
|
||||
|
||||
EntityWithInetAddress entity = new EntityWithInetAddress( 1, InetAddress.getLocalHost() );
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
try {
|
||||
session.persist( new EntityWithInetAddress( 1, InetAddress.getLocalHost() ) );
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
session.persist( entity );
|
||||
}
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
(session) -> session.find( EntityWithInetAddress.class, 1)
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
session.createQuery(
|
||||
"from EntityWithInetAddress e where e.address = :param",
|
||||
EntityWithInetAddress.class
|
||||
)
|
||||
.setParameter( "param", entity.address )
|
||||
.getResultList();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "EntityWithInetAddress")
|
||||
|
|
|
@ -168,6 +168,11 @@ public class InformixDialect extends Dialect {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useMaterializedLobWhenCapacityExceeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarbinaryLength() {
|
||||
//there's no varbinary type, only byte
|
||||
|
|
|
@ -158,6 +158,11 @@ public class RDMSOS2200Dialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useMaterializedLobWhenCapacityExceeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarbinaryLength() {
|
||||
//no varbinary type
|
||||
|
|
|
@ -84,6 +84,11 @@ public class SybaseAnywhereDialect extends SybaseDialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useMaterializedLobWhenCapacityExceeded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
super.initializeFunctionRegistry( queryEngine );
|
||||
|
|
|
@ -196,7 +196,17 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
|||
|
||||
@Override
|
||||
public boolean isLob() {
|
||||
return isLob;
|
||||
if ( isLob ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( explicitJdbcTypeAccess != null ) {
|
||||
final JdbcType type = explicitJdbcTypeAccess.apply( getTypeConfiguration() );
|
||||
if ( type != null ) {
|
||||
return type.isLob();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -239,7 +249,16 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
|||
|
||||
@Override
|
||||
public boolean isNationalized() {
|
||||
return isNationalized;
|
||||
if ( isNationalized ) {
|
||||
return true;
|
||||
}
|
||||
if ( explicitJdbcTypeAccess != null ) {
|
||||
final JdbcType type = explicitJdbcTypeAccess.apply( getTypeConfiguration() );
|
||||
if ( type != null ) {
|
||||
return type.isNationalized();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1093,11 +1112,11 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
|||
|
||||
basicValue = new BasicValue( buildingContext, table );
|
||||
|
||||
if ( isNationalized ) {
|
||||
if ( isNationalized() ) {
|
||||
basicValue.makeNationalized();
|
||||
}
|
||||
|
||||
if ( isLob ) {
|
||||
if ( isLob() ) {
|
||||
basicValue.makeLob();
|
||||
}
|
||||
|
||||
|
@ -1243,11 +1262,11 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
|||
basicValue.setTemporalPrecision( temporalPrecision );
|
||||
}
|
||||
|
||||
if ( isLob ) {
|
||||
if ( isLob() ) {
|
||||
basicValue.makeLob();
|
||||
}
|
||||
|
||||
if ( isNationalized ) {
|
||||
if ( isNationalized() ) {
|
||||
basicValue.makeNationalized();
|
||||
}
|
||||
|
||||
|
|
|
@ -104,9 +104,13 @@ public class InferredBasicValueResolver {
|
|||
jdbcMapping = new SerializableType( explicitJavaType );
|
||||
}
|
||||
else {
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
explicitJavaType,
|
||||
inferredJdbcType
|
||||
jdbcMapping = resolveSqlTypeIndicators(
|
||||
stdIndicators,
|
||||
typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
explicitJavaType,
|
||||
inferredJdbcType
|
||||
),
|
||||
explicitJavaType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -206,9 +210,13 @@ public class InferredBasicValueResolver {
|
|||
// one, to create a mapping
|
||||
final JdbcType recommendedJdbcType = reflectedJtd.getRecommendedJdbcType( stdIndicators );
|
||||
if ( recommendedJdbcType != null ) {
|
||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
reflectedJtd,
|
||||
recommendedJdbcType
|
||||
jdbcMapping = resolveSqlTypeIndicators(
|
||||
stdIndicators,
|
||||
typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
reflectedJtd,
|
||||
recommendedJdbcType
|
||||
),
|
||||
reflectedJtd
|
||||
);
|
||||
}
|
||||
else if ( reflectedJtd instanceof SerializableJavaType
|
||||
|
|
|
@ -450,6 +450,10 @@ public class MetadataBuildingProcess {
|
|||
jdbcTypeRegistry.addDescriptorIfAbsent( JsonJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( XmlAsStringJdbcType.INSTANCE );
|
||||
|
||||
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.MATERIALIZED_BLOB, SqlTypes.BLOB );
|
||||
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.MATERIALIZED_CLOB, SqlTypes.CLOB );
|
||||
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.MATERIALIZED_NCLOB, SqlTypes.NCLOB );
|
||||
|
||||
final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry();
|
||||
// Fallback to the biggest varchar DdlType when json is requested
|
||||
ddlTypeRegistry.addDescriptorIfAbsent(
|
||||
|
|
|
@ -168,49 +168,42 @@ public class DerbyDialect extends Dialect {
|
|||
super.registerColumnTypes( typeContributions, serviceRegistry );
|
||||
final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry();
|
||||
|
||||
//long varchar is the right type to use for lengths between 32_672 and 32_700
|
||||
int maxLongVarcharLength = 32_700;
|
||||
int varcharDdlTypeCapacity = 32_672;
|
||||
|
||||
ddlTypeRegistry.addDescriptor(
|
||||
CapacityDependentDdlType.builder( VARBINARY, columnType( BLOB ), columnType( VARBINARY ), this )
|
||||
.withTypeCapacity( getMaxVarbinaryLength(), columnType( VARBINARY ) )
|
||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARBINARY ) )
|
||||
CapacityDependentDdlType.builder( VARBINARY, columnType( LONG32VARBINARY ), columnType( VARBINARY ), this )
|
||||
.withTypeCapacity( varcharDdlTypeCapacity, columnType( VARBINARY ) )
|
||||
.build()
|
||||
);
|
||||
ddlTypeRegistry.addDescriptor(
|
||||
CapacityDependentDdlType.builder( VARCHAR, columnType( CLOB ), columnType( VARCHAR ), this )
|
||||
.withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) )
|
||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARCHAR ) )
|
||||
CapacityDependentDdlType.builder( VARCHAR, columnType( LONG32VARCHAR ), columnType( VARCHAR ), this )
|
||||
.withTypeCapacity( varcharDdlTypeCapacity, columnType( VARCHAR ) )
|
||||
.build()
|
||||
);
|
||||
ddlTypeRegistry.addDescriptor(
|
||||
CapacityDependentDdlType.builder( NVARCHAR, columnType( CLOB ), columnType( NVARCHAR ), this )
|
||||
.withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) )
|
||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARCHAR ) )
|
||||
CapacityDependentDdlType.builder( NVARCHAR, columnType( LONG32VARCHAR ), columnType( NVARCHAR ), this )
|
||||
.withTypeCapacity( varcharDdlTypeCapacity, columnType( NVARCHAR ) )
|
||||
.build()
|
||||
);
|
||||
|
||||
ddlTypeRegistry.addDescriptor(
|
||||
CapacityDependentDdlType.builder( BINARY, columnType( BLOB ), columnType( VARBINARY ), this )
|
||||
CapacityDependentDdlType.builder( BINARY, columnType( LONG32VARBINARY ), columnType( VARBINARY ), this )
|
||||
.withTypeCapacity( 254, "char($l) for bit data" )
|
||||
.withTypeCapacity( getMaxVarbinaryLength(), columnType( VARBINARY ) )
|
||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARBINARY ) )
|
||||
.withTypeCapacity( varcharDdlTypeCapacity, columnType( VARBINARY ) )
|
||||
.build()
|
||||
);
|
||||
|
||||
// This is the maximum size for the CHAR datatype on Derby
|
||||
ddlTypeRegistry.addDescriptor(
|
||||
CapacityDependentDdlType.builder( CHAR, columnType( CLOB ), columnType( CHAR ), this )
|
||||
CapacityDependentDdlType.builder( CHAR, columnType( LONG32VARCHAR ), columnType( CHAR ), this )
|
||||
.withTypeCapacity( 254, columnType( CHAR ) )
|
||||
.withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) )
|
||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARCHAR ) )
|
||||
.build()
|
||||
);
|
||||
ddlTypeRegistry.addDescriptor(
|
||||
CapacityDependentDdlType.builder( NCHAR, columnType( CLOB ), columnType( NCHAR ), this )
|
||||
CapacityDependentDdlType.builder( NCHAR, columnType( LONG32NVARCHAR ), columnType( NCHAR ), this )
|
||||
.withTypeCapacity( 254, columnType( NCHAR ) )
|
||||
.withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) )
|
||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32NVARCHAR ) )
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
@ -220,6 +213,11 @@ public class DerbyDialect extends Dialect {
|
|||
return 32_672;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharCapacity() {
|
||||
return 32_700;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultDecimalPrecision() {
|
||||
//this is the maximum allowed in Derby
|
||||
|
|
|
@ -171,6 +171,7 @@ import org.hibernate.type.descriptor.WrapperOptions;
|
|||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampWithTimeZoneJdbcType;
|
||||
|
@ -1396,29 +1397,35 @@ public abstract class Dialect implements ConversionContext {
|
|||
// by default, not much to do...
|
||||
registerColumnTypes( typeContributions, serviceRegistry );
|
||||
final NationalizationSupport nationalizationSupport = getNationalizationSupport();
|
||||
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration().getJdbcTypeRegistry();
|
||||
if ( nationalizationSupport == NationalizationSupport.EXPLICIT ) {
|
||||
typeContributions.contributeJdbcType( NCharJdbcType.INSTANCE );
|
||||
typeContributions.contributeJdbcType( NVarcharJdbcType.INSTANCE );
|
||||
typeContributions.contributeJdbcType( LongNVarcharJdbcType.INSTANCE );
|
||||
typeContributions.contributeJdbcType( NClobJdbcType.DEFAULT );
|
||||
jdbcTypeRegistry.addDescriptor( NCharJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptor( NVarcharJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptor( LongNVarcharJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptor( NClobJdbcType.DEFAULT );
|
||||
}
|
||||
|
||||
if ( useInputStreamToInsertBlob() ) {
|
||||
typeContributions.getTypeConfiguration().getJdbcTypeRegistry().addDescriptor(
|
||||
jdbcTypeRegistry.addDescriptor(
|
||||
Types.CLOB,
|
||||
ClobJdbcType.STREAM_BINDING
|
||||
);
|
||||
}
|
||||
|
||||
if ( getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
|
||||
typeContributions.contributeJdbcType( InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptor( InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
||||
}
|
||||
else {
|
||||
typeContributions.contributeJdbcType( InstantAsTimestampJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptor( InstantAsTimestampJdbcType.INSTANCE );
|
||||
}
|
||||
|
||||
if ( supportsStandardArrays() ) {
|
||||
typeContributions.contributeJdbcType( ArrayJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptor( ArrayJdbcType.INSTANCE );
|
||||
}
|
||||
if ( supportsMaterializedLobAccess() ) {
|
||||
jdbcTypeRegistry.addDescriptor( SqlTypes.MATERIALIZED_BLOB, BlobJdbcType.MATERIALIZED );
|
||||
jdbcTypeRegistry.addDescriptor( SqlTypes.MATERIALIZED_CLOB, ClobJdbcType.MATERIALIZED );
|
||||
jdbcTypeRegistry.addDescriptor( SqlTypes.MATERIALIZED_NCLOB, NClobJdbcType.MATERIALIZED );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3816,6 +3823,32 @@ public abstract class Dialect implements ConversionContext {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the JDBC driver allows setting LOBs via {@link PreparedStatement#setBytes(int, byte[])},
|
||||
* {@link PreparedStatement#setNString(int, String)} or {@link PreparedStatement#setString(int, String)} APIs.
|
||||
*
|
||||
* @return {@code true} if LOBs can be set with the materialized APIs.
|
||||
* @since 6.2
|
||||
*/
|
||||
public boolean supportsMaterializedLobAccess() {
|
||||
// Most drivers support this
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to switch from {@code VARCHAR}-like types to {@link SqlTypes#MATERIALIZED_CLOB},
|
||||
* {@code NVARCHAR}-like types to {@link SqlTypes#MATERIALIZED_NCLOB}
|
||||
* and {@code VARBINARY}-like types to {@link SqlTypes#MATERIALIZED_BLOB} types,
|
||||
* when the requested size for a type exceeds the {@link #getMaxVarcharCapacity()}, {@link #getMaxNVarcharCapacity()}
|
||||
* and {@link #getMaxVarbinaryCapacity()} respectively.
|
||||
*
|
||||
* @return {@code true} if materialized LOBs should be used for capacity exceeding types.
|
||||
* @since 6.2
|
||||
*/
|
||||
public boolean useMaterializedLobWhenCapacityExceeded() {
|
||||
return supportsMaterializedLobAccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the SQL, adding hints or comments, if necessary
|
||||
*/
|
||||
|
@ -3895,7 +3928,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* The longest possible length of a {@link java.sql.Types#VARCHAR}-like column.
|
||||
* The biggest size value that can be supplied as argument to a {@link java.sql.Types#VARCHAR}-like type.
|
||||
* For longer column lengths, use some sort of {@code text}-like type for the
|
||||
* column.
|
||||
*/
|
||||
|
@ -3905,8 +3938,8 @@ public abstract class Dialect implements ConversionContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* The longest possible length of a {@link java.sql.Types#NVARCHAR}-like column.
|
||||
* For longer column lengths, use some sort of {@code text}-like type for the
|
||||
* The biggest size value that can be supplied as argument to a {@link java.sql.Types#NVARCHAR}-like type.
|
||||
* For longer column lengths, use some sort of {@code ntext}-like type for the
|
||||
* column.
|
||||
*/
|
||||
public int getMaxNVarcharLength() {
|
||||
|
@ -3915,7 +3948,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* The longest possible length of a {@link java.sql.Types#VARBINARY}-like column.
|
||||
* The biggest size value that can be supplied as argument to a {@link java.sql.Types#VARBINARY}-like type.
|
||||
* For longer column lengths, use some sort of {@code image}-like type for the
|
||||
* column.
|
||||
*/
|
||||
|
@ -3924,6 +3957,33 @@ public abstract class Dialect implements ConversionContext {
|
|||
return getMaxVarcharLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* The longest possible length of a {@link java.sql.Types#VARCHAR}-like column.
|
||||
* For longer column lengths, use some sort of {@code clob}-like type for the
|
||||
* column.
|
||||
*/
|
||||
public int getMaxVarcharCapacity() {
|
||||
return getMaxVarcharLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* The longest possible length of a {@link java.sql.Types#NVARCHAR}-like column.
|
||||
* For longer column lengths, use some sort of {@code nclob}-like type for the
|
||||
* column.
|
||||
*/
|
||||
public int getMaxNVarcharCapacity() {
|
||||
return getMaxNVarcharLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* The longest possible length of a {@link java.sql.Types#VARBINARY}-like column.
|
||||
* For longer column lengths, use some sort of {@code blob}-like type for the
|
||||
* column.
|
||||
*/
|
||||
public int getMaxVarbinaryCapacity() {
|
||||
return getMaxVarbinaryLength();
|
||||
}
|
||||
|
||||
public long getDefaultLobLength() {
|
||||
return Size.DEFAULT_LOB_LENGTH;
|
||||
}
|
||||
|
|
|
@ -242,6 +242,12 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useMaterializedLobWhenCapacityExceeded() {
|
||||
// MySQL has no real concept of LOBs, so we can just use longtext/longblob with the materialized JDBC APIs
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String castType(int sqlTypeCode) {
|
||||
switch ( sqlTypeCode ) {
|
||||
|
@ -304,9 +310,9 @@ public class MySQLDialect extends Dialect {
|
|||
"char",
|
||||
this
|
||||
)
|
||||
.withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
|
||||
.withTypeCapacity( getVarcharDdlTypeCapacity(), "varchar($l)" )
|
||||
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
|
||||
if ( getMaxVarcharLength() < maxLobLen ) {
|
||||
if ( getVarcharDdlTypeCapacity() < maxLobLen ) {
|
||||
varcharBuilder.withTypeCapacity( maxLobLen, "text" );
|
||||
}
|
||||
ddlTypeRegistry.addDescriptor( varcharBuilder.build() );
|
||||
|
@ -317,9 +323,9 @@ public class MySQLDialect extends Dialect {
|
|||
"char",
|
||||
this
|
||||
)
|
||||
.withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
|
||||
.withTypeCapacity( getVarcharDdlTypeCapacity(), "varchar($l)" )
|
||||
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
|
||||
if ( getMaxVarcharLength() < maxLobLen ) {
|
||||
if ( getVarcharDdlTypeCapacity() < maxLobLen ) {
|
||||
nvarcharBuilder.withTypeCapacity( maxLobLen, "text" );
|
||||
}
|
||||
ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() );
|
||||
|
@ -330,9 +336,9 @@ public class MySQLDialect extends Dialect {
|
|||
"binary",
|
||||
this
|
||||
)
|
||||
.withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" )
|
||||
.withTypeCapacity( getVarbinaryDdlTypeCapacity(), "varbinary($l)" )
|
||||
.withTypeCapacity( maxMediumLobLen, "mediumblob" );
|
||||
if ( getMaxVarcharLength() < maxLobLen ) {
|
||||
if ( getVarbinaryDdlTypeCapacity() < maxLobLen ) {
|
||||
varbinaryBuilder.withTypeCapacity( maxLobLen, "blob" );
|
||||
}
|
||||
ddlTypeRegistry.addDescriptor( varbinaryBuilder.build() );
|
||||
|
@ -425,13 +431,11 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharLength() {
|
||||
public int getVarcharDdlTypeCapacity() {
|
||||
return maxVarcharLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarbinaryLength() {
|
||||
public int getVarbinaryDdlTypeCapacity() {
|
||||
return maxVarbinaryLength;
|
||||
}
|
||||
|
||||
|
|
|
@ -261,6 +261,12 @@ public class PostgreSQLDialect extends Dialect {
|
|||
return 10_485_760;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharCapacity() {
|
||||
// 1GB according to PostgreSQL docs
|
||||
return 1_073_741_824;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarbinaryLength() {
|
||||
//postgres has no varbinary-like type
|
||||
|
@ -1001,6 +1007,13 @@ public class PostgreSQLDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsMaterializedLobAccess() {
|
||||
// Prefer using text and bytea over oid (LOB), because oid is very restricted.
|
||||
// If someone really wants a type bigger than 1GB, they should ask for it by using @Lob explicitly
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTemporalLiteralOffset() {
|
||||
return true;
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.sql.Types;
|
|||
import java.time.Duration;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
|
@ -29,7 +30,6 @@ 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.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
|
@ -104,8 +104,22 @@ public class PostgreSQLIntervalSecondJdbcType implements AdjustableJdbcType {
|
|||
|
||||
@Override
|
||||
public JdbcType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType<?> domainJtd) {
|
||||
// The default scale is 9
|
||||
if ( indicators.getColumnScale() == JdbcTypeIndicators.NO_COLUMN_SCALE || indicators.getColumnScale() > 6 ) {
|
||||
final int scale;
|
||||
if ( indicators.getColumnScale() == JdbcTypeIndicators.NO_COLUMN_SCALE ) {
|
||||
scale = domainJtd.getDefaultSqlScale(
|
||||
indicators.getTypeConfiguration()
|
||||
.getServiceRegistry()
|
||||
.getService( JdbcServices.class )
|
||||
.getDialect(),
|
||||
this
|
||||
);
|
||||
}
|
||||
else {
|
||||
scale = indicators.getColumnScale();
|
||||
}
|
||||
if ( scale > 6 ) {
|
||||
// Since the maximum allowed scale on PostgreSQL is 6 (microsecond precision),
|
||||
// we have to switch to the numeric type if the value is greater
|
||||
return indicators.getJdbcType( indicators.resolveJdbcTypeCode( SqlTypes.NUMERIC ) );
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -10,6 +10,8 @@ import org.hibernate.Internal;
|
|||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.Internal;
|
||||
|
||||
/**
|
||||
* Defines a list of constant type codes used to identify generic SQL types.
|
||||
* This is an extension of the standard JDBC-defined {@link Types}, defining
|
||||
|
@ -446,6 +448,39 @@ public class SqlTypes {
|
|||
*/
|
||||
public static final int TIMESTAMP_UTC = 3003;
|
||||
|
||||
/**
|
||||
* The constant in the Java programming language, sometimes referred to
|
||||
* as a type code, that identifies the generic SQL type
|
||||
* {@code MATERIALIZED_BLOB}.
|
||||
*
|
||||
* This type is used when JDBC access should use {@link #VARBINARY} semantics,
|
||||
* but the {@link org.hibernate.type.descriptor.sql.DdlType} should be based on {@link #BLOB}.
|
||||
*/
|
||||
@Internal
|
||||
public static final int MATERIALIZED_BLOB = 3004;
|
||||
|
||||
/**
|
||||
* The constant in the Java programming language, sometimes referred to
|
||||
* as a type code, that identifies the generic SQL type
|
||||
* {@code MATERIALIZED_CLOB}.
|
||||
*
|
||||
* This type is used when JDBC access should use {@link #VARCHAR} semantics,
|
||||
* but the {@link org.hibernate.type.descriptor.sql.DdlType} should be based on {@link #CLOB}.
|
||||
*/
|
||||
@Internal
|
||||
public static final int MATERIALIZED_CLOB = 3005;
|
||||
|
||||
/**
|
||||
* The constant in the Java programming language, sometimes referred to
|
||||
* as a type code, that identifies the generic SQL type
|
||||
* {@code MATERIALIZED_NCLOB}.
|
||||
*
|
||||
* This type is used when JDBC access should use {@link #NVARCHAR} semantics,
|
||||
* but the {@link org.hibernate.type.descriptor.sql.DdlType} should be based on {@link #NCLOB}.
|
||||
*/
|
||||
@Internal
|
||||
public static final int MATERIALIZED_NCLOB = 3006;
|
||||
|
||||
// Interval types
|
||||
|
||||
/**
|
||||
|
|
|
@ -225,4 +225,54 @@ public abstract class BlobJdbcType implements JdbcType {
|
|||
}
|
||||
};
|
||||
|
||||
public static final BlobJdbcType MATERIALIZED = new BlobJdbcType() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BlobTypeDescriptor(MATERIALIZED)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
|
||||
return byte[].class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> BasicBinder<X> getBlobBinder(final JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
public void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setBytes( index, javaType.unwrap( value, byte[].class, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setBytes( name, javaType.unwrap( value, byte[].class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return javaType.wrap( rs.getBytes( paramIndex ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaType.wrap( statement.getBytes( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
return javaType.wrap( statement.getBytes( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -305,4 +305,55 @@ public abstract class ClobJdbcType implements AdjustableJdbcType {
|
|||
}
|
||||
};
|
||||
|
||||
public static final ClobJdbcType MATERIALIZED = new ClobJdbcType() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClobTypeDescriptor(MATERIALIZED)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> BasicBinder<X> getClobBinder(final JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setString( index, javaType.unwrap( value, String.class, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setString( name, javaType.unwrap( value, String.class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return javaType.wrap( rs.getString( paramIndex ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
return javaType.wrap( statement.getString( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
return javaType.wrap( statement.getString( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -192,6 +192,23 @@ public interface JdbcType extends Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
default boolean isNationalized() {
|
||||
return isNationalized( getJdbcTypeCode() );
|
||||
}
|
||||
|
||||
static boolean isNationalized(int jdbcTypeCode) {
|
||||
switch ( jdbcTypeCode ) {
|
||||
case SqlTypes.NCHAR:
|
||||
case SqlTypes.NVARCHAR:
|
||||
case SqlTypes.LONGNVARCHAR:
|
||||
case SqlTypes.LONG32NVARCHAR:
|
||||
case SqlTypes.NCLOB: {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean isInterval() {
|
||||
return SqlTypes.isIntervalType( getDefaultSqlTypeCode() );
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.type.descriptor.jdbc;
|
|||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -46,6 +47,9 @@ public class LongNVarcharJdbcType extends NVarcharJdbcType {
|
|||
if ( indicators.isLob() ) {
|
||||
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
||||
}
|
||||
else if ( shouldUseMaterializedLob( indicators ) ) {
|
||||
jdbcTypeCode = indicators.isNationalized() ? SqlTypes.MATERIALIZED_NCLOB : SqlTypes.MATERIALIZED_CLOB;
|
||||
}
|
||||
else {
|
||||
jdbcTypeCode = indicators.isNationalized() ? Types.LONGNVARCHAR : Types.LONGVARCHAR;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.type.descriptor.jdbc;
|
|||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -53,6 +54,9 @@ public class LongVarcharJdbcType extends VarcharJdbcType {
|
|||
if ( indicators.isLob() ) {
|
||||
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
||||
}
|
||||
else if ( shouldUseMaterializedLob( indicators ) ) {
|
||||
jdbcTypeCode = indicators.isNationalized() ? SqlTypes.MATERIALIZED_NCLOB : SqlTypes.MATERIALIZED_CLOB;
|
||||
}
|
||||
else {
|
||||
jdbcTypeCode = indicators.isNationalized() ? Types.LONGNVARCHAR : Types.LONGVARCHAR;
|
||||
}
|
||||
|
|
|
@ -179,4 +179,55 @@ public abstract class NClobJdbcType implements JdbcType {
|
|||
};
|
||||
}
|
||||
};
|
||||
|
||||
public static final NClobJdbcType MATERIALIZED = new NClobJdbcType() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NClobTypeDescriptor(MATERIALIZED)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> BasicBinder<X> getNClobBinder(final JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setNString( index, javaType.unwrap( value, String.class, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setNString( name, javaType.unwrap( value, String.class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return javaType.wrap( rs.getNString( paramIndex ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
return javaType.wrap( statement.getNString( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
return javaType.wrap( statement.getNString( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,6 +12,9 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
@ -77,6 +80,9 @@ public class NVarcharJdbcType implements AdjustableJdbcType {
|
|||
if ( indicators.isLob() ) {
|
||||
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
||||
}
|
||||
else if ( shouldUseMaterializedLob( indicators ) ) {
|
||||
jdbcTypeCode = indicators.isNationalized() ? SqlTypes.MATERIALIZED_NCLOB : SqlTypes.MATERIALIZED_CLOB;
|
||||
}
|
||||
else {
|
||||
jdbcTypeCode = indicators.isNationalized() ? Types.NVARCHAR : Types.VARCHAR;
|
||||
}
|
||||
|
@ -84,6 +90,18 @@ public class NVarcharJdbcType implements AdjustableJdbcType {
|
|||
return jdbcTypeRegistry.getDescriptor( jdbcTypeCode );
|
||||
}
|
||||
|
||||
protected boolean shouldUseMaterializedLob(JdbcTypeIndicators indicators) {
|
||||
final Dialect dialect = indicators.getTypeConfiguration()
|
||||
.getServiceRegistry()
|
||||
.getService( JdbcServices.class )
|
||||
.getDialect();
|
||||
final long length = indicators.getColumnLength();
|
||||
final long maxLength = indicators.isNationalized() ?
|
||||
dialect.getMaxNVarcharCapacity() :
|
||||
dialect.getMaxVarcharCapacity();
|
||||
return length > maxLength && dialect.useMaterializedLobWhenCapacityExceeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
|
||||
return String.class;
|
||||
|
|
|
@ -12,6 +12,9 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
@ -75,9 +78,23 @@ public class VarbinaryJdbcType implements AdjustableJdbcType {
|
|||
@Override
|
||||
public JdbcType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType<?> domainJtd) {
|
||||
final JdbcTypeRegistry jdbcTypeRegistry = indicators.getTypeConfiguration().getJdbcTypeRegistry();
|
||||
return indicators.isLob()
|
||||
? jdbcTypeRegistry.getDescriptor( indicators.resolveJdbcTypeCode( Types.BLOB ) )
|
||||
: this;
|
||||
if ( indicators.isLob() ) {
|
||||
return jdbcTypeRegistry.getDescriptor( indicators.resolveJdbcTypeCode( SqlTypes.BLOB ) );
|
||||
}
|
||||
else if ( shouldUseMaterializedLob( indicators ) ) {
|
||||
return jdbcTypeRegistry.getDescriptor( indicators.resolveJdbcTypeCode( SqlTypes.MATERIALIZED_BLOB ) );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected boolean shouldUseMaterializedLob(JdbcTypeIndicators indicators) {
|
||||
final Dialect dialect = indicators.getTypeConfiguration()
|
||||
.getServiceRegistry()
|
||||
.getService( JdbcServices.class )
|
||||
.getDialect();
|
||||
final long length = indicators.getColumnLength();
|
||||
final long maxLength = dialect.getMaxVarbinaryCapacity();
|
||||
return length > maxLength && dialect.useMaterializedLobWhenCapacityExceeded();
|
||||
}
|
||||
|
||||
public <X> ValueBinder<X> getBinder(final JavaType<X> javaType) {
|
||||
|
|
|
@ -12,6 +12,9 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
@ -65,9 +68,7 @@ public class VarcharJdbcType implements AdjustableJdbcType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JdbcType resolveIndicatedType(
|
||||
JdbcTypeIndicators indicators,
|
||||
JavaType<?> domainJtd) {
|
||||
public JdbcType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType<?> domainJtd) {
|
||||
assert domainJtd != null;
|
||||
|
||||
final TypeConfiguration typeConfiguration = indicators.getTypeConfiguration();
|
||||
|
@ -77,6 +78,9 @@ public class VarcharJdbcType implements AdjustableJdbcType {
|
|||
if ( indicators.isLob() ) {
|
||||
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
||||
}
|
||||
else if ( shouldUseMaterializedLob( indicators ) ) {
|
||||
jdbcTypeCode = indicators.isNationalized() ? SqlTypes.MATERIALIZED_NCLOB : SqlTypes.MATERIALIZED_CLOB;
|
||||
}
|
||||
else {
|
||||
jdbcTypeCode = indicators.isNationalized() ? Types.NVARCHAR : Types.VARCHAR;
|
||||
}
|
||||
|
@ -84,6 +88,18 @@ public class VarcharJdbcType implements AdjustableJdbcType {
|
|||
return jdbcTypeRegistry.getDescriptor( indicators.resolveJdbcTypeCode( jdbcTypeCode ) );
|
||||
}
|
||||
|
||||
protected boolean shouldUseMaterializedLob(JdbcTypeIndicators indicators) {
|
||||
final Dialect dialect = indicators.getTypeConfiguration()
|
||||
.getServiceRegistry()
|
||||
.getService( JdbcServices.class )
|
||||
.getDialect();
|
||||
final long length = indicators.getColumnLength();
|
||||
final long maxLength = indicators.isNationalized() ?
|
||||
dialect.getMaxNVarcharCapacity() :
|
||||
dialect.getMaxVarcharCapacity();
|
||||
return length > maxLength && dialect.useMaterializedLobWhenCapacityExceeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
|
||||
return String.class;
|
||||
|
|
|
@ -18,11 +18,12 @@ public class Scale6IntervalSecondDdlType extends DdlTypeImpl {
|
|||
public Scale6IntervalSecondDdlType(String typeNamePattern, Dialect dialect) {
|
||||
super( SqlTypes.INTERVAL_SECOND, typeNamePattern, dialect );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(Long size, Integer precision, Integer scale) {
|
||||
// The maximum scale for `interval second` is 6 unfortunately, so we have to use numeric by default
|
||||
// The maximum scale for `interval second` is 6 unfortunately
|
||||
if ( scale == null || scale > 6 ) {
|
||||
return DdlTypeImpl.replace( "numeric($p,$s)", size, precision, scale );
|
||||
throw new IllegalStateException( "Illegal attempt to use interval second type with scale > 6" );
|
||||
}
|
||||
return super.getTypeName( size, precision, scale );
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
package org.hibernate.orm.test.length;
|
||||
|
||||
import org.hibernate.Length;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
|
@ -12,6 +17,18 @@ import static org.junit.Assert.assertEquals;
|
|||
public class LengthTest {
|
||||
@Test
|
||||
public void testLength(SessionFactoryScope scope) {
|
||||
final Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect();
|
||||
final BasicValuedMapping mapping = (BasicValuedMapping) scope.getSessionFactory()
|
||||
.getRuntimeMetamodels()
|
||||
.getMappingMetamodel()
|
||||
.getEntityDescriptor( WithLongStrings.class )
|
||||
.findAttributeMapping( "long32" );
|
||||
if ( dialect.useMaterializedLobWhenCapacityExceeded() && Length.LONG32 > dialect.getMaxVarcharCapacity() ) {
|
||||
assertEquals( SqlTypes.CLOB, mapping.getJdbcMapping().getJdbcType().getJdbcTypeCode() );
|
||||
}
|
||||
else {
|
||||
assertEquals( SqlTypes.VARCHAR, mapping.getJdbcMapping().getJdbcType().getJdbcTypeCode() );
|
||||
}
|
||||
WithLongStrings strings = new WithLongStrings();
|
||||
strings.longish = "hello world ".repeat(2500);
|
||||
strings.long16 = "hello world ".repeat(2700);
|
||||
|
|
Loading…
Reference in New Issue