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;
|
package org.hibernate.userguide.mapping.basic;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
@ -18,7 +19,9 @@ import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.descriptor.jdbc.AdjustableJdbcType;
|
import org.hibernate.type.descriptor.jdbc.AdjustableJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
@ -51,7 +54,17 @@ public class DurationMappingTests {
|
||||||
final JdbcType realType;
|
final JdbcType realType;
|
||||||
if (intervalType instanceof AdjustableJdbcType) {
|
if (intervalType instanceof AdjustableJdbcType) {
|
||||||
realType = ( (AdjustableJdbcType) intervalType ).resolveIndicatedType(
|
realType = ( (AdjustableJdbcType) intervalType ).resolveIndicatedType(
|
||||||
() -> mappingMetamodel.getTypeConfiguration(),
|
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()
|
jdbcMapping.getJavaTypeDescriptor()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -69,6 +82,14 @@ public class DurationMappingTests {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
(session) -> session.find(EntityWithDuration.class, 1)
|
(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")
|
@Entity(name = "EntityWithDuration")
|
||||||
|
|
|
@ -39,7 +39,7 @@ import static org.hamcrest.Matchers.is;
|
||||||
public class InetAddressMappingTests {
|
public class InetAddressMappingTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void verifyMappings(SessionFactoryScope scope) {
|
public void verifyMappings(SessionFactoryScope scope) throws Exception {
|
||||||
final MappingMetamodelImplementor mappingMetamodel = scope.getSessionFactory()
|
final MappingMetamodelImplementor mappingMetamodel = scope.getSessionFactory()
|
||||||
.getRuntimeMetamodels()
|
.getRuntimeMetamodels()
|
||||||
.getMappingMetamodel();
|
.getMappingMetamodel();
|
||||||
|
@ -62,20 +62,27 @@ public class InetAddressMappingTests {
|
||||||
}
|
}
|
||||||
assertThat( jdbcMapping.getJdbcType(), is( realType));
|
assertThat( jdbcMapping.getJdbcType(), is( realType));
|
||||||
|
|
||||||
|
EntityWithInetAddress entity = new EntityWithInetAddress( 1, InetAddress.getLocalHost() );
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
(session) -> {
|
(session) -> {
|
||||||
try {
|
session.persist( entity );
|
||||||
session.persist( new EntityWithInetAddress( 1, InetAddress.getLocalHost() ) );
|
|
||||||
}
|
|
||||||
catch (UnknownHostException e) {
|
|
||||||
throw new RuntimeException( e );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
(session) -> session.find( EntityWithInetAddress.class, 1)
|
(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")
|
@Entity(name = "EntityWithInetAddress")
|
||||||
|
|
|
@ -168,6 +168,11 @@ public class InformixDialect extends Dialect {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useMaterializedLobWhenCapacityExceeded() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxVarbinaryLength() {
|
public int getMaxVarbinaryLength() {
|
||||||
//there's no varbinary type, only byte
|
//there's no varbinary type, only byte
|
||||||
|
|
|
@ -158,6 +158,11 @@ public class RDMSOS2200Dialect extends Dialect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useMaterializedLobWhenCapacityExceeded() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxVarbinaryLength() {
|
public int getMaxVarbinaryLength() {
|
||||||
//no varbinary type
|
//no varbinary type
|
||||||
|
|
|
@ -84,6 +84,11 @@ public class SybaseAnywhereDialect extends SybaseDialect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useMaterializedLobWhenCapacityExceeded() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||||
super.initializeFunctionRegistry( queryEngine );
|
super.initializeFunctionRegistry( queryEngine );
|
||||||
|
|
|
@ -196,7 +196,17 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLob() {
|
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
|
@Override
|
||||||
|
@ -239,7 +249,16 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isNationalized() {
|
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 );
|
basicValue = new BasicValue( buildingContext, table );
|
||||||
|
|
||||||
if ( isNationalized ) {
|
if ( isNationalized() ) {
|
||||||
basicValue.makeNationalized();
|
basicValue.makeNationalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isLob ) {
|
if ( isLob() ) {
|
||||||
basicValue.makeLob();
|
basicValue.makeLob();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1243,11 +1262,11 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
basicValue.setTemporalPrecision( temporalPrecision );
|
basicValue.setTemporalPrecision( temporalPrecision );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isLob ) {
|
if ( isLob() ) {
|
||||||
basicValue.makeLob();
|
basicValue.makeLob();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isNationalized ) {
|
if ( isNationalized() ) {
|
||||||
basicValue.makeNationalized();
|
basicValue.makeNationalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,9 +104,13 @@ public class InferredBasicValueResolver {
|
||||||
jdbcMapping = new SerializableType( explicitJavaType );
|
jdbcMapping = new SerializableType( explicitJavaType );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve(
|
jdbcMapping = resolveSqlTypeIndicators(
|
||||||
|
stdIndicators,
|
||||||
|
typeConfiguration.getBasicTypeRegistry().resolve(
|
||||||
explicitJavaType,
|
explicitJavaType,
|
||||||
inferredJdbcType
|
inferredJdbcType
|
||||||
|
),
|
||||||
|
explicitJavaType
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,9 +210,13 @@ public class InferredBasicValueResolver {
|
||||||
// one, to create a mapping
|
// one, to create a mapping
|
||||||
final JdbcType recommendedJdbcType = reflectedJtd.getRecommendedJdbcType( stdIndicators );
|
final JdbcType recommendedJdbcType = reflectedJtd.getRecommendedJdbcType( stdIndicators );
|
||||||
if ( recommendedJdbcType != null ) {
|
if ( recommendedJdbcType != null ) {
|
||||||
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve(
|
jdbcMapping = resolveSqlTypeIndicators(
|
||||||
|
stdIndicators,
|
||||||
|
typeConfiguration.getBasicTypeRegistry().resolve(
|
||||||
reflectedJtd,
|
reflectedJtd,
|
||||||
recommendedJdbcType
|
recommendedJdbcType
|
||||||
|
),
|
||||||
|
reflectedJtd
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if ( reflectedJtd instanceof SerializableJavaType
|
else if ( reflectedJtd instanceof SerializableJavaType
|
||||||
|
|
|
@ -450,6 +450,10 @@ public class MetadataBuildingProcess {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( JsonJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( JsonJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( XmlAsStringJdbcType.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();
|
final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry();
|
||||||
// Fallback to the biggest varchar DdlType when json is requested
|
// Fallback to the biggest varchar DdlType when json is requested
|
||||||
ddlTypeRegistry.addDescriptorIfAbsent(
|
ddlTypeRegistry.addDescriptorIfAbsent(
|
||||||
|
|
|
@ -168,49 +168,42 @@ public class DerbyDialect extends Dialect {
|
||||||
super.registerColumnTypes( typeContributions, serviceRegistry );
|
super.registerColumnTypes( typeContributions, serviceRegistry );
|
||||||
final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry();
|
final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry();
|
||||||
|
|
||||||
//long varchar is the right type to use for lengths between 32_672 and 32_700
|
int varcharDdlTypeCapacity = 32_672;
|
||||||
int maxLongVarcharLength = 32_700;
|
|
||||||
|
|
||||||
ddlTypeRegistry.addDescriptor(
|
ddlTypeRegistry.addDescriptor(
|
||||||
CapacityDependentDdlType.builder( VARBINARY, columnType( BLOB ), columnType( VARBINARY ), this )
|
CapacityDependentDdlType.builder( VARBINARY, columnType( LONG32VARBINARY ), columnType( VARBINARY ), this )
|
||||||
.withTypeCapacity( getMaxVarbinaryLength(), columnType( VARBINARY ) )
|
.withTypeCapacity( varcharDdlTypeCapacity, columnType( VARBINARY ) )
|
||||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARBINARY ) )
|
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
ddlTypeRegistry.addDescriptor(
|
ddlTypeRegistry.addDescriptor(
|
||||||
CapacityDependentDdlType.builder( VARCHAR, columnType( CLOB ), columnType( VARCHAR ), this )
|
CapacityDependentDdlType.builder( VARCHAR, columnType( LONG32VARCHAR ), columnType( VARCHAR ), this )
|
||||||
.withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) )
|
.withTypeCapacity( varcharDdlTypeCapacity, columnType( VARCHAR ) )
|
||||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARCHAR ) )
|
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
ddlTypeRegistry.addDescriptor(
|
ddlTypeRegistry.addDescriptor(
|
||||||
CapacityDependentDdlType.builder( NVARCHAR, columnType( CLOB ), columnType( NVARCHAR ), this )
|
CapacityDependentDdlType.builder( NVARCHAR, columnType( LONG32VARCHAR ), columnType( NVARCHAR ), this )
|
||||||
.withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) )
|
.withTypeCapacity( varcharDdlTypeCapacity, columnType( NVARCHAR ) )
|
||||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARCHAR ) )
|
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
ddlTypeRegistry.addDescriptor(
|
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( 254, "char($l) for bit data" )
|
||||||
.withTypeCapacity( getMaxVarbinaryLength(), columnType( VARBINARY ) )
|
.withTypeCapacity( varcharDdlTypeCapacity, columnType( VARBINARY ) )
|
||||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARBINARY ) )
|
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
// This is the maximum size for the CHAR datatype on Derby
|
// This is the maximum size for the CHAR datatype on Derby
|
||||||
ddlTypeRegistry.addDescriptor(
|
ddlTypeRegistry.addDescriptor(
|
||||||
CapacityDependentDdlType.builder( CHAR, columnType( CLOB ), columnType( CHAR ), this )
|
CapacityDependentDdlType.builder( CHAR, columnType( LONG32VARCHAR ), columnType( CHAR ), this )
|
||||||
.withTypeCapacity( 254, columnType( CHAR ) )
|
.withTypeCapacity( 254, columnType( CHAR ) )
|
||||||
.withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) )
|
.withTypeCapacity( getMaxVarcharLength(), columnType( VARCHAR ) )
|
||||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32VARCHAR ) )
|
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
ddlTypeRegistry.addDescriptor(
|
ddlTypeRegistry.addDescriptor(
|
||||||
CapacityDependentDdlType.builder( NCHAR, columnType( CLOB ), columnType( NCHAR ), this )
|
CapacityDependentDdlType.builder( NCHAR, columnType( LONG32NVARCHAR ), columnType( NCHAR ), this )
|
||||||
.withTypeCapacity( 254, columnType( NCHAR ) )
|
.withTypeCapacity( 254, columnType( NCHAR ) )
|
||||||
.withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) )
|
.withTypeCapacity( getMaxVarcharLength(), columnType( NVARCHAR ) )
|
||||||
.withTypeCapacity( maxLongVarcharLength, columnType( LONG32NVARCHAR ) )
|
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -220,6 +213,11 @@ public class DerbyDialect extends Dialect {
|
||||||
return 32_672;
|
return 32_672;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxVarcharCapacity() {
|
||||||
|
return 32_700;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDefaultDecimalPrecision() {
|
public int getDefaultDecimalPrecision() {
|
||||||
//this is the maximum allowed in Derby
|
//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.JavaType;
|
||||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
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.ClobJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampJdbcType;
|
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampWithTimeZoneJdbcType;
|
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampWithTimeZoneJdbcType;
|
||||||
|
@ -1396,29 +1397,35 @@ public abstract class Dialect implements ConversionContext {
|
||||||
// by default, not much to do...
|
// by default, not much to do...
|
||||||
registerColumnTypes( typeContributions, serviceRegistry );
|
registerColumnTypes( typeContributions, serviceRegistry );
|
||||||
final NationalizationSupport nationalizationSupport = getNationalizationSupport();
|
final NationalizationSupport nationalizationSupport = getNationalizationSupport();
|
||||||
|
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration().getJdbcTypeRegistry();
|
||||||
if ( nationalizationSupport == NationalizationSupport.EXPLICIT ) {
|
if ( nationalizationSupport == NationalizationSupport.EXPLICIT ) {
|
||||||
typeContributions.contributeJdbcType( NCharJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptor( NCharJdbcType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( NVarcharJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptor( NVarcharJdbcType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( LongNVarcharJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptor( LongNVarcharJdbcType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( NClobJdbcType.DEFAULT );
|
jdbcTypeRegistry.addDescriptor( NClobJdbcType.DEFAULT );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( useInputStreamToInsertBlob() ) {
|
if ( useInputStreamToInsertBlob() ) {
|
||||||
typeContributions.getTypeConfiguration().getJdbcTypeRegistry().addDescriptor(
|
jdbcTypeRegistry.addDescriptor(
|
||||||
Types.CLOB,
|
Types.CLOB,
|
||||||
ClobJdbcType.STREAM_BINDING
|
ClobJdbcType.STREAM_BINDING
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
|
if ( getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
|
||||||
typeContributions.contributeJdbcType( InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptor( InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
typeContributions.contributeJdbcType( InstantAsTimestampJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptor( InstantAsTimestampJdbcType.INSTANCE );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( supportsStandardArrays() ) {
|
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;
|
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
|
* 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
|
* For longer column lengths, use some sort of {@code text}-like type for the
|
||||||
* column.
|
* column.
|
||||||
*/
|
*/
|
||||||
|
@ -3905,8 +3938,8 @@ public abstract class Dialect implements ConversionContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The longest possible length of a {@link java.sql.Types#NVARCHAR}-like column.
|
* 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 text}-like type for the
|
* For longer column lengths, use some sort of {@code ntext}-like type for the
|
||||||
* column.
|
* column.
|
||||||
*/
|
*/
|
||||||
public int getMaxNVarcharLength() {
|
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
|
* For longer column lengths, use some sort of {@code image}-like type for the
|
||||||
* column.
|
* column.
|
||||||
*/
|
*/
|
||||||
|
@ -3924,6 +3957,33 @@ public abstract class Dialect implements ConversionContext {
|
||||||
return getMaxVarcharLength();
|
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() {
|
public long getDefaultLobLength() {
|
||||||
return Size.DEFAULT_LOB_LENGTH;
|
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
|
@Override
|
||||||
protected String castType(int sqlTypeCode) {
|
protected String castType(int sqlTypeCode) {
|
||||||
switch ( sqlTypeCode ) {
|
switch ( sqlTypeCode ) {
|
||||||
|
@ -304,9 +310,9 @@ public class MySQLDialect extends Dialect {
|
||||||
"char",
|
"char",
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
.withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
|
.withTypeCapacity( getVarcharDdlTypeCapacity(), "varchar($l)" )
|
||||||
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
|
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
|
||||||
if ( getMaxVarcharLength() < maxLobLen ) {
|
if ( getVarcharDdlTypeCapacity() < maxLobLen ) {
|
||||||
varcharBuilder.withTypeCapacity( maxLobLen, "text" );
|
varcharBuilder.withTypeCapacity( maxLobLen, "text" );
|
||||||
}
|
}
|
||||||
ddlTypeRegistry.addDescriptor( varcharBuilder.build() );
|
ddlTypeRegistry.addDescriptor( varcharBuilder.build() );
|
||||||
|
@ -317,9 +323,9 @@ public class MySQLDialect extends Dialect {
|
||||||
"char",
|
"char",
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
.withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
|
.withTypeCapacity( getVarcharDdlTypeCapacity(), "varchar($l)" )
|
||||||
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
|
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
|
||||||
if ( getMaxVarcharLength() < maxLobLen ) {
|
if ( getVarcharDdlTypeCapacity() < maxLobLen ) {
|
||||||
nvarcharBuilder.withTypeCapacity( maxLobLen, "text" );
|
nvarcharBuilder.withTypeCapacity( maxLobLen, "text" );
|
||||||
}
|
}
|
||||||
ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() );
|
ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() );
|
||||||
|
@ -330,9 +336,9 @@ public class MySQLDialect extends Dialect {
|
||||||
"binary",
|
"binary",
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
.withTypeCapacity( getMaxVarbinaryLength(), "varbinary($l)" )
|
.withTypeCapacity( getVarbinaryDdlTypeCapacity(), "varbinary($l)" )
|
||||||
.withTypeCapacity( maxMediumLobLen, "mediumblob" );
|
.withTypeCapacity( maxMediumLobLen, "mediumblob" );
|
||||||
if ( getMaxVarcharLength() < maxLobLen ) {
|
if ( getVarbinaryDdlTypeCapacity() < maxLobLen ) {
|
||||||
varbinaryBuilder.withTypeCapacity( maxLobLen, "blob" );
|
varbinaryBuilder.withTypeCapacity( maxLobLen, "blob" );
|
||||||
}
|
}
|
||||||
ddlTypeRegistry.addDescriptor( varbinaryBuilder.build() );
|
ddlTypeRegistry.addDescriptor( varbinaryBuilder.build() );
|
||||||
|
@ -425,13 +431,11 @@ public class MySQLDialect extends Dialect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public int getVarcharDdlTypeCapacity() {
|
||||||
public int getMaxVarcharLength() {
|
|
||||||
return maxVarcharLength;
|
return maxVarcharLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public int getVarbinaryDdlTypeCapacity() {
|
||||||
public int getMaxVarbinaryLength() {
|
|
||||||
return maxVarbinaryLength;
|
return maxVarbinaryLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,12 @@ public class PostgreSQLDialect extends Dialect {
|
||||||
return 10_485_760;
|
return 10_485_760;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxVarcharCapacity() {
|
||||||
|
// 1GB according to PostgreSQL docs
|
||||||
|
return 1_073_741_824;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxVarbinaryLength() {
|
public int getMaxVarbinaryLength() {
|
||||||
//postgres has no varbinary-like type
|
//postgres has no varbinary-like type
|
||||||
|
@ -1001,6 +1007,13 @@ public class PostgreSQLDialect extends Dialect {
|
||||||
return false;
|
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
|
@Override
|
||||||
public boolean supportsTemporalLiteralOffset() {
|
public boolean supportsTemporalLiteralOffset() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.sql.Types;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
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.JdbcLiteralFormatter;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christian Beikov
|
* @author Christian Beikov
|
||||||
|
@ -104,8 +104,22 @@ public class PostgreSQLIntervalSecondJdbcType implements AdjustableJdbcType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType<?> domainJtd) {
|
public JdbcType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType<?> domainJtd) {
|
||||||
// The default scale is 9
|
final int scale;
|
||||||
if ( indicators.getColumnScale() == JdbcTypeIndicators.NO_COLUMN_SCALE || indicators.getColumnScale() > 6 ) {
|
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 indicators.getJdbcType( indicators.resolveJdbcTypeCode( SqlTypes.NUMERIC ) );
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -10,6 +10,8 @@ import org.hibernate.Internal;
|
||||||
|
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
|
||||||
|
import org.hibernate.Internal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a list of constant type codes used to identify generic SQL types.
|
* 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
|
* 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;
|
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
|
// 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;
|
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() {
|
default boolean isInterval() {
|
||||||
return SqlTypes.isIntervalType( getDefaultSqlTypeCode() );
|
return SqlTypes.isIntervalType( getDefaultSqlTypeCode() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.type.descriptor.jdbc;
|
||||||
|
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
|
||||||
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
@ -46,6 +47,9 @@ public class LongNVarcharJdbcType extends NVarcharJdbcType {
|
||||||
if ( indicators.isLob() ) {
|
if ( indicators.isLob() ) {
|
||||||
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
||||||
}
|
}
|
||||||
|
else if ( shouldUseMaterializedLob( indicators ) ) {
|
||||||
|
jdbcTypeCode = indicators.isNationalized() ? SqlTypes.MATERIALIZED_NCLOB : SqlTypes.MATERIALIZED_CLOB;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeCode = indicators.isNationalized() ? Types.LONGNVARCHAR : Types.LONGVARCHAR;
|
jdbcTypeCode = indicators.isNationalized() ? Types.LONGNVARCHAR : Types.LONGVARCHAR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.type.descriptor.jdbc;
|
||||||
|
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
|
||||||
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
@ -53,6 +54,9 @@ public class LongVarcharJdbcType extends VarcharJdbcType {
|
||||||
if ( indicators.isLob() ) {
|
if ( indicators.isLob() ) {
|
||||||
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
||||||
}
|
}
|
||||||
|
else if ( shouldUseMaterializedLob( indicators ) ) {
|
||||||
|
jdbcTypeCode = indicators.isNationalized() ? SqlTypes.MATERIALIZED_NCLOB : SqlTypes.MATERIALIZED_CLOB;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeCode = indicators.isNationalized() ? Types.LONGNVARCHAR : Types.LONGVARCHAR;
|
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.SQLException;
|
||||||
import java.sql.Types;
|
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.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
@ -77,6 +80,9 @@ public class NVarcharJdbcType implements AdjustableJdbcType {
|
||||||
if ( indicators.isLob() ) {
|
if ( indicators.isLob() ) {
|
||||||
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
||||||
}
|
}
|
||||||
|
else if ( shouldUseMaterializedLob( indicators ) ) {
|
||||||
|
jdbcTypeCode = indicators.isNationalized() ? SqlTypes.MATERIALIZED_NCLOB : SqlTypes.MATERIALIZED_CLOB;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeCode = indicators.isNationalized() ? Types.NVARCHAR : Types.VARCHAR;
|
jdbcTypeCode = indicators.isNationalized() ? Types.NVARCHAR : Types.VARCHAR;
|
||||||
}
|
}
|
||||||
|
@ -84,6 +90,18 @@ public class NVarcharJdbcType implements AdjustableJdbcType {
|
||||||
return jdbcTypeRegistry.getDescriptor( jdbcTypeCode );
|
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
|
@Override
|
||||||
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
|
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
|
||||||
return String.class;
|
return String.class;
|
||||||
|
|
|
@ -12,6 +12,9 @@ import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
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.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
@ -75,9 +78,23 @@ public class VarbinaryJdbcType implements AdjustableJdbcType {
|
||||||
@Override
|
@Override
|
||||||
public JdbcType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType<?> domainJtd) {
|
public JdbcType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType<?> domainJtd) {
|
||||||
final JdbcTypeRegistry jdbcTypeRegistry = indicators.getTypeConfiguration().getJdbcTypeRegistry();
|
final JdbcTypeRegistry jdbcTypeRegistry = indicators.getTypeConfiguration().getJdbcTypeRegistry();
|
||||||
return indicators.isLob()
|
if ( indicators.isLob() ) {
|
||||||
? jdbcTypeRegistry.getDescriptor( indicators.resolveJdbcTypeCode( Types.BLOB ) )
|
return jdbcTypeRegistry.getDescriptor( indicators.resolveJdbcTypeCode( SqlTypes.BLOB ) );
|
||||||
: this;
|
}
|
||||||
|
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) {
|
public <X> ValueBinder<X> getBinder(final JavaType<X> javaType) {
|
||||||
|
|
|
@ -12,6 +12,9 @@ import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
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.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
@ -65,9 +68,7 @@ public class VarcharJdbcType implements AdjustableJdbcType {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcType resolveIndicatedType(
|
public JdbcType resolveIndicatedType(JdbcTypeIndicators indicators, JavaType<?> domainJtd) {
|
||||||
JdbcTypeIndicators indicators,
|
|
||||||
JavaType<?> domainJtd) {
|
|
||||||
assert domainJtd != null;
|
assert domainJtd != null;
|
||||||
|
|
||||||
final TypeConfiguration typeConfiguration = indicators.getTypeConfiguration();
|
final TypeConfiguration typeConfiguration = indicators.getTypeConfiguration();
|
||||||
|
@ -77,6 +78,9 @@ public class VarcharJdbcType implements AdjustableJdbcType {
|
||||||
if ( indicators.isLob() ) {
|
if ( indicators.isLob() ) {
|
||||||
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
jdbcTypeCode = indicators.isNationalized() ? Types.NCLOB : Types.CLOB;
|
||||||
}
|
}
|
||||||
|
else if ( shouldUseMaterializedLob( indicators ) ) {
|
||||||
|
jdbcTypeCode = indicators.isNationalized() ? SqlTypes.MATERIALIZED_NCLOB : SqlTypes.MATERIALIZED_CLOB;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeCode = indicators.isNationalized() ? Types.NVARCHAR : Types.VARCHAR;
|
jdbcTypeCode = indicators.isNationalized() ? Types.NVARCHAR : Types.VARCHAR;
|
||||||
}
|
}
|
||||||
|
@ -84,6 +88,18 @@ public class VarcharJdbcType implements AdjustableJdbcType {
|
||||||
return jdbcTypeRegistry.getDescriptor( indicators.resolveJdbcTypeCode( jdbcTypeCode ) );
|
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
|
@Override
|
||||||
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
|
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
|
||||||
return String.class;
|
return String.class;
|
||||||
|
|
|
@ -18,11 +18,12 @@ public class Scale6IntervalSecondDdlType extends DdlTypeImpl {
|
||||||
public Scale6IntervalSecondDdlType(String typeNamePattern, Dialect dialect) {
|
public Scale6IntervalSecondDdlType(String typeNamePattern, Dialect dialect) {
|
||||||
super( SqlTypes.INTERVAL_SECOND, typeNamePattern, dialect );
|
super( SqlTypes.INTERVAL_SECOND, typeNamePattern, dialect );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTypeName(Long size, Integer precision, Integer scale) {
|
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 ) {
|
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 );
|
return super.getTypeName( size, precision, scale );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
package org.hibernate.orm.test.length;
|
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.DomainModel;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
@ -12,6 +17,18 @@ import static org.junit.Assert.assertEquals;
|
||||||
public class LengthTest {
|
public class LengthTest {
|
||||||
@Test
|
@Test
|
||||||
public void testLength(SessionFactoryScope scope) {
|
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();
|
WithLongStrings strings = new WithLongStrings();
|
||||||
strings.longish = "hello world ".repeat(2500);
|
strings.longish = "hello world ".repeat(2500);
|
||||||
strings.long16 = "hello world ".repeat(2700);
|
strings.long16 = "hello world ".repeat(2700);
|
||||||
|
|
Loading…
Reference in New Issue