HHH-17662 Replace JdbcTypeConstructor uses for arrays with uniform resolve method

This commit is contained in:
Christian Beikov 2024-01-24 11:38:08 +01:00
parent 5d348fc723
commit 2661e5cd18
13 changed files with 228 additions and 172 deletions

View File

@ -300,15 +300,13 @@ public class CockroachLegacyDialect extends Dialect {
}
break;
case ARRAY:
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
// PostgreSQL names array types by prepending an underscore to the base name
if ( jdbcTypeConstructor != null && columnTypeName.charAt( 0 ) == '_' ) {
if ( columnTypeName.charAt( 0 ) == '_' ) {
final String componentTypeName = columnTypeName.substring( 1 );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) {
return jdbcTypeConstructor.resolveType(
jdbcTypeRegistry.getTypeConfiguration(),
this,
return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeCode,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY
);

View File

@ -100,7 +100,6 @@ import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType;
import org.hibernate.type.descriptor.jdbc.NullJdbcType;
import org.hibernate.type.descriptor.jdbc.ObjectNullAsNullTypeJdbcType;
@ -760,15 +759,11 @@ public class OracleLegacyDialect extends Dialect {
break;
case ARRAY:
if ( "MDSYS.SDO_ORDINATE_ARRAY".equals( columnTypeName ) ) {
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
if ( jdbcTypeConstructor != null ) {
return jdbcTypeConstructor.resolveType(
jdbcTypeRegistry.getTypeConfiguration(),
this,
jdbcTypeRegistry.getDescriptor( NUMERIC ),
ColumnTypeInformation.EMPTY
);
}
return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeCode,
jdbcTypeRegistry.getDescriptor( NUMERIC ),
ColumnTypeInformation.EMPTY
);
}
break;
case Types.NUMERIC:

View File

@ -328,15 +328,13 @@ public class PostgreSQLLegacyDialect extends Dialect {
}
break;
case ARRAY:
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
// PostgreSQL names array types by prepending an underscore to the base name
if ( jdbcTypeConstructor != null && columnTypeName.charAt( 0 ) == '_' ) {
if ( columnTypeName.charAt( 0 ) == '_' ) {
final String componentTypeName = columnTypeName.substring( 1 );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) {
return jdbcTypeConstructor.resolveType(
jdbcTypeRegistry.getTypeConfiguration(),
this,
return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeCode,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY
);

View File

@ -318,15 +318,13 @@ public class CockroachDialect extends Dialect {
}
break;
case ARRAY:
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
// PostgreSQL names array types by prepending an underscore to the base name
if ( jdbcTypeConstructor != null && columnTypeName.charAt( 0 ) == '_' ) {
if ( columnTypeName.charAt( 0 ) == '_' ) {
final String componentTypeName = columnTypeName.substring( 1 );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) {
return jdbcTypeConstructor.resolveType(
jdbcTypeRegistry.getTypeConfiguration(),
this,
return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeCode,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY
);

View File

@ -725,22 +725,18 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
int scale,
JdbcTypeRegistry jdbcTypeRegistry) {
if ( jdbcTypeCode == ARRAY ) {
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
if ( jdbcTypeConstructor != null ) {
// Special handling for array types, because we need the proper element/component type
// To determine the element JdbcType, we pass the database reported type to #resolveSqlTypeCode
final int arraySuffixIndex = columnTypeName.toLowerCase( Locale.ROOT ).indexOf( " array" );
if ( arraySuffixIndex != -1 ) {
final String componentTypeName = columnTypeName.substring( 0, arraySuffixIndex );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) {
return jdbcTypeConstructor.resolveType(
jdbcTypeRegistry.getTypeConfiguration(),
this,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY
);
}
// Special handling for array types, because we need the proper element/component type
// To determine the element JdbcType, we pass the database reported type to #resolveSqlTypeCode
final int arraySuffixIndex = columnTypeName.toLowerCase( Locale.ROOT ).indexOf( " array" );
if ( arraySuffixIndex != -1 ) {
final String componentTypeName = columnTypeName.substring( 0, arraySuffixIndex );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) {
return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeCode,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY
);
}
}
}

View File

@ -46,10 +46,21 @@ public class OracleArrayJdbcTypeConstructor implements JdbcTypeConstructor {
JdbcType elementType,
ColumnTypeInformation columnTypeInformation) {
// a bit wrong, since columnTypeInformation.getTypeName() is typically null!
return new OracleArrayJdbcType(
elementType,
columnTypeInformation == null ? null : columnTypeInformation.getTypeName()
);
String typeName = columnTypeInformation == null ? null : columnTypeInformation.getTypeName();
if ( typeName == null || typeName.isBlank() ) {
Integer precision = null;
Integer scale = null;
if ( columnTypeInformation != null ) {
precision = columnTypeInformation.getColumnSize();
scale = columnTypeInformation.getDecimalDigits();
}
typeName = OracleArrayJdbcType.getTypeName( elementType.getJdbcRecommendedJavaTypeMapping(
precision,
scale,
typeConfiguration
), dialect );
}
return new OracleArrayJdbcType( elementType, typeName );
}
@Override

View File

@ -799,15 +799,11 @@ public class OracleDialect extends Dialect {
break;
case ARRAY:
if ( "MDSYS.SDO_ORDINATE_ARRAY".equals( columnTypeName ) ) {
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
if ( jdbcTypeConstructor != null ) {
return jdbcTypeConstructor.resolveType(
jdbcTypeRegistry.getTypeConfiguration(),
this,
jdbcTypeRegistry.getDescriptor( NUMERIC ),
ColumnTypeInformation.EMPTY
);
}
return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeCode,
jdbcTypeRegistry.getDescriptor( NUMERIC ),
ColumnTypeInformation.EMPTY
);
}
break;
case NUMERIC:

View File

@ -40,10 +40,21 @@ public class OracleNestedTableJdbcTypeConstructor implements JdbcTypeConstructor
JdbcType elementType,
ColumnTypeInformation columnTypeInformation) {
// a bit wrong, since columnTypeInformation.getTypeName() is typically null!
return new OracleNestedTableJdbcType(
elementType,
columnTypeInformation == null ? null : columnTypeInformation.getTypeName()
);
String typeName = columnTypeInformation == null ? null : columnTypeInformation.getTypeName();
if ( typeName == null || typeName.isBlank() ) {
Integer precision = null;
Integer scale = null;
if ( columnTypeInformation != null ) {
precision = columnTypeInformation.getColumnSize();
scale = columnTypeInformation.getDecimalDigits();
}
typeName = OracleArrayJdbcType.getTypeName( elementType.getJdbcRecommendedJavaTypeMapping(
precision,
scale,
typeConfiguration
), dialect );
}
return new OracleNestedTableJdbcType( elementType, typeName );
}
@Override

View File

@ -347,15 +347,13 @@ public class PostgreSQLDialect extends Dialect {
}
break;
case ARRAY:
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
// PostgreSQL names array types by prepending an underscore to the base name
if ( jdbcTypeConstructor != null && columnTypeName.charAt( 0 ) == '_' ) {
if ( columnTypeName.charAt( 0 ) == '_' ) {
final String componentTypeName = columnTypeName.substring( 1 );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) {
return jdbcTypeConstructor.resolveType(
jdbcTypeRegistry.getTypeConfiguration(),
this,
return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeCode,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY
);

View File

@ -17,9 +17,7 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.ConvertedBasicArrayType;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import org.hibernate.type.internal.BasicTypeImpl;
import org.hibernate.type.spi.TypeConfiguration;
@ -41,11 +39,9 @@ public abstract class AbstractArrayJavaType<T, E> extends AbstractClassJavaType<
@Override
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) {
// Always determine the recommended type to make sure this is a valid basic java type
return getArrayJdbcType(
indicators.getTypeConfiguration(),
indicators.getDialect(),
return indicators.getTypeConfiguration().getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
indicators.getPreferredSqlTypeCodeForArray(),
new BasicTypeImpl<>( getElementJavaType(), componentJavaType.getRecommendedJdbcType( indicators ) ),
new BasicTypeImpl<>( componentJavaType, componentJavaType.getRecommendedJdbcType( indicators ) ),
ColumnTypeInformation.EMPTY
);
}
@ -86,9 +82,7 @@ public abstract class AbstractArrayJavaType<T, E> extends AbstractClassJavaType<
final JavaType<?> relationalJavaType = typeConfiguration.getJavaTypeRegistry().getDescriptor( convertedArrayClass );
return new ConvertedBasicArrayType<>(
elementType,
getArrayJdbcType(
typeConfiguration,
dialect,
typeConfiguration.getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
stdIndicators.getExplicitJdbcTypeCode(),
elementType,
columnTypeInformation
@ -105,9 +99,7 @@ public abstract class AbstractArrayJavaType<T, E> extends AbstractClassJavaType<
BasicType<E> elementType,
ColumnTypeInformation columnTypeInformation,
JdbcTypeIndicators stdIndicators) {
final JdbcType arrayJdbcType = getArrayJdbcType(
typeConfiguration,
dialect,
final JdbcType arrayJdbcType = typeConfiguration.getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
stdIndicators.getExplicitJdbcTypeCode(),
elementType,
columnTypeInformation
@ -117,53 +109,6 @@ public abstract class AbstractArrayJavaType<T, E> extends AbstractClassJavaType<
arrayJdbcType,
() -> new BasicArrayType<>( elementType, arrayJdbcType, arrayJavaType )
);
// return typeConfiguration.getBasicTypeRegistry().getRegisteredType( elementType.getName() ) == elementType
// ? typeConfiguration.standardBasicTypeForJavaType(
// arrayJavaType.getJavaType(),
// javaType -> basicArrayType( typeConfiguration, dialect, elementType, columnTypeInformation, stdIndicators, arrayJavaType )
// )
// : basicArrayType( typeConfiguration, dialect, elementType, columnTypeInformation, stdIndicators, arrayJavaType );
}
// BasicType<T> basicArrayType(
// TypeConfiguration typeConfiguration,
// Dialect dialect,
// BasicType<E> elementType,
// ColumnTypeInformation columnTypeInformation,
// JdbcTypeIndicators stdIndicators,
// JavaType<T> javaType) {
// return new BasicArrayType<>(
// elementType,
// getArrayJdbcType(
// typeConfiguration,
// dialect,
// stdIndicators.getExplicitJdbcTypeCode(),
// elementType,
// columnTypeInformation
// ),
// javaType
// );
// }
static JdbcType getArrayJdbcType(
TypeConfiguration typeConfiguration,
Dialect dialect,
int preferredSqlTypeCodeForArray,
BasicType<?> elementType,
ColumnTypeInformation columnTypeInformation) {
final JdbcTypeRegistry jdbcTypeRegistry = typeConfiguration.getJdbcTypeRegistry();
final JdbcTypeConstructor arrayJdbcTypeConstructor =
jdbcTypeRegistry.getConstructor( preferredSqlTypeCodeForArray );
if ( arrayJdbcTypeConstructor != null ) {
return arrayJdbcTypeConstructor.resolveType(
typeConfiguration,
dialect,
elementType,
columnTypeInformation
);
}
else {
return jdbcTypeRegistry.getDescriptor( preferredSqlTypeCodeForArray );
}
}
}

View File

@ -10,11 +10,9 @@ import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Function;
import org.hibernate.HibernateException;
import org.hibernate.Incubating;
@ -27,7 +25,6 @@ import org.hibernate.internal.util.SerializationHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
import org.hibernate.type.BasicArrayType;
import org.hibernate.type.BasicCollectionType;
import org.hibernate.type.BasicPluralType;
import org.hibernate.type.BasicType;
@ -40,9 +37,7 @@ import org.hibernate.type.descriptor.java.BasicPluralJavaType;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import org.hibernate.type.internal.BasicTypeImpl;
import org.hibernate.type.spi.TypeConfiguration;
@ -73,11 +68,9 @@ public class BasicCollectionJavaType<C extends Collection<E>, E> extends Abstrac
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) {
// Always determine the recommended type to make sure this is a valid basic java type
// (even though we only use this inside the if block, we want it to throw here if something wrong)
return getArrayJdbcType(
indicators.getTypeConfiguration(),
indicators.getDialect(),
return indicators.getTypeConfiguration().getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
indicators.getPreferredSqlTypeCodeForArray(),
new BasicTypeImpl<>( getElementJavaType(), componentJavaType.getRecommendedJdbcType( indicators ) ),
new BasicTypeImpl<>( componentJavaType, componentJavaType.getRecommendedJdbcType( indicators ) ),
ColumnTypeInformation.EMPTY
);
}
@ -119,23 +112,11 @@ public class BasicCollectionJavaType<C extends Collection<E>, E> extends Abstrac
}
final BasicValueConverter<E, ?> valueConverter = elementType.getValueConverter();
if ( valueConverter == null ) {
final JdbcType arrayJdbcType = getArrayJdbcType(
typeConfiguration,
dialect,
final JdbcType arrayJdbcType = typeConfiguration.getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
stdIndicators.getPreferredSqlTypeCodeForArray(),
elementType,
columnTypeInformation
);
final Function<JavaType<Object>, BasicType<Object>> creator = javaType -> {
//noinspection unchecked,rawtypes
return new BasicCollectionType( elementType, arrayJdbcType, collectionJavaType );
};
// if ( typeConfiguration.getBasicTypeRegistry().getRegisteredType( elementType.getName() ) == elementType ) {
// return typeConfiguration.standardBasicTypeForJavaType( collectionJavaType.getJavaType(), creator );
// }
// //noinspection unchecked
// return creator.apply( (JavaType<Object>) (JavaType<?>) collectionJavaType );
return typeConfiguration.getBasicTypeRegistry().resolve(
collectionJavaType,
arrayJdbcType,
@ -149,9 +130,7 @@ public class BasicCollectionJavaType<C extends Collection<E>, E> extends Abstrac
//noinspection unchecked,rawtypes
return new ConvertedBasicCollectionType(
elementType,
getArrayJdbcType(
typeConfiguration,
dialect,
typeConfiguration.getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
stdIndicators.getPreferredSqlTypeCodeForArray(),
elementType,
columnTypeInformation
@ -162,29 +141,6 @@ public class BasicCollectionJavaType<C extends Collection<E>, E> extends Abstrac
}
}
//TODO: copy/pasted from AbstractArrayJavaType
private static JdbcType getArrayJdbcType(
TypeConfiguration typeConfiguration,
Dialect dialect,
int preferredSqlTypeCodeForArray,
BasicType<?> elementType,
ColumnTypeInformation columnTypeInformation) {
final JdbcTypeRegistry jdbcTypeRegistry = typeConfiguration.getJdbcTypeRegistry();
final JdbcTypeConstructor arrayJdbcTypeConstructor =
jdbcTypeRegistry.getConstructor( preferredSqlTypeCodeForArray );
if ( arrayJdbcTypeConstructor != null ) {
return arrayJdbcTypeConstructor.resolveType(
typeConfiguration,
dialect,
elementType,
columnTypeInformation
);
}
else {
return jdbcTypeRegistry.getDescriptor( preferredSqlTypeCodeForArray );
}
}
@Override
public String extractLoggableRepresentation(C value) {
if ( value == null ) {

View File

@ -214,11 +214,11 @@ public class ArrayJdbcType implements JdbcType {
public boolean equals(Object o) {
return o != null &&
getClass() == o.getClass() &&
getElementJdbcType().equals( ((ArrayJdbcType) o).getElementJdbcType() );
getElementJdbcType().equals( ( (ArrayJdbcType) o ).getElementJdbcType() );
}
@Override
public int hashCode() {
return getJdbcTypeCode() + getElementJdbcType().hashCode();
return getJdbcTypeCode() + 31 * getElementJdbcType().hashCode();
}
}

View File

@ -7,13 +7,20 @@
package org.hibernate.type.descriptor.jdbc.spi;
import java.io.Serializable;
import java.sql.Types;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.boot.model.TruthValue;
import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.JdbcTypeNameMapper;
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
import org.hibernate.type.descriptor.jdbc.JdbcTypeFamilyInformation;
@ -23,6 +30,8 @@ import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A registry mapping {@link org.hibernate.type.SqlTypes JDBC type codes}
* to implementations of the {@link JdbcType} interface.
@ -39,6 +48,13 @@ public class JdbcTypeRegistry implements JdbcTypeBaseline.BaselineTarget, Serial
private final ConcurrentHashMap<Integer, JdbcType> descriptorMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Integer, JdbcTypeConstructor> descriptorConstructorMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, AggregateJdbcType> aggregateDescriptorMap = new ConcurrentHashMap<>();
/**
* A registry for storing the constructed {@link JdbcType} for both
* {@link JdbcTypeConstructor#resolveType(TypeConfiguration, Dialect, JdbcType, ColumnTypeInformation)} and
* {@link JdbcTypeConstructor#resolveType(TypeConfiguration, Dialect, BasicType, ColumnTypeInformation)} in a single
* map.
*/
private final ConcurrentHashMap<TypeConstructedJdbcTypeKey, JdbcType> typeConstructorDescriptorMap = new ConcurrentHashMap<>();
public JdbcTypeRegistry(TypeConfiguration typeConfiguration) {
this.typeConfiguration = typeConfiguration;
@ -174,6 +190,68 @@ public class JdbcTypeRegistry implements JdbcTypeBaseline.BaselineTarget, Serial
return aggregateDescriptorMap.get( typeName.toLowerCase( Locale.ROOT ) );
}
/**
* Construct a {@link JdbcType} via {@link JdbcTypeConstructor#resolveType(TypeConfiguration, Dialect, BasicType, ColumnTypeInformation)}
* or return a compatible one from this registry.
*/
public JdbcType resolveTypeConstructorDescriptor(
int jdbcTypeConstructorCode,
BasicType<?> elementType,
@Nullable ColumnTypeInformation columnTypeInformation) {
return resolveTypeConstructorDescriptor( jdbcTypeConstructorCode, (Object) elementType, columnTypeInformation );
}
/**
* Construct a {@link JdbcType} via {@link JdbcTypeConstructor#resolveType(TypeConfiguration, Dialect, JdbcType, ColumnTypeInformation)}
* or return a compatible one from this registry.
*/
public JdbcType resolveTypeConstructorDescriptor(
int jdbcTypeConstructorCode,
JdbcType elementType,
@Nullable ColumnTypeInformation columnTypeInformation) {
return resolveTypeConstructorDescriptor( jdbcTypeConstructorCode, (Object) elementType, columnTypeInformation );
}
private JdbcType resolveTypeConstructorDescriptor(
int jdbcTypeConstructorCode,
Object elementType,
@Nullable ColumnTypeInformation columnTypeInformation) {
final TypeConstructedJdbcTypeKey key = new TypeConstructedJdbcTypeKey(
jdbcTypeConstructorCode,
elementType,
columnTypeInformation
);
final JdbcType descriptor = typeConstructorDescriptorMap.get( key );
if ( descriptor != null ) {
return descriptor;
}
final JdbcTypeConstructor jdbcTypeConstructor = getConstructor( jdbcTypeConstructorCode );
if ( jdbcTypeConstructor != null ) {
final JdbcType jdbcType;
if ( elementType instanceof BasicType<?> ) {
jdbcType = jdbcTypeConstructor.resolveType(
typeConfiguration,
typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect(),
(BasicType<?>) elementType,
columnTypeInformation
);
}
else {
jdbcType = jdbcTypeConstructor.resolveType(
typeConfiguration,
typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect(),
(JdbcType) elementType,
columnTypeInformation
);
}
final JdbcType existingType = typeConstructorDescriptorMap.putIfAbsent( key, jdbcType );
return existingType != null ? existingType : jdbcType;
}
else {
return getDescriptor( jdbcTypeConstructorCode );
}
}
public boolean hasRegisteredDescriptor(int jdbcTypeCode) {
return descriptorMap.containsKey( jdbcTypeCode )
|| JdbcTypeNameMapper.isStandardTypeCode( jdbcTypeCode )
@ -191,4 +269,80 @@ public class JdbcTypeRegistry implements JdbcTypeBaseline.BaselineTarget, Serial
public void addTypeConstructor(JdbcTypeConstructor jdbcTypeConstructor) {
addTypeConstructor( jdbcTypeConstructor.getDefaultSqlTypeCode(), jdbcTypeConstructor );
}
private static final class TypeConstructedJdbcTypeKey {
private final int typeConstructorTypeCode;
private final Object jdbcTypeOrBasicType;
private final TruthValue nullable;
private final int typeCode;
private final @Nullable String typeName;
private final int columnSize;
private final int decimalDigits;
public TypeConstructedJdbcTypeKey(
int typeConstructorTypeCode,
Object jdbcTypeOrBasicType,
@Nullable ColumnTypeInformation columnTypeInformation) {
this.typeConstructorTypeCode = typeConstructorTypeCode;
this.jdbcTypeOrBasicType = jdbcTypeOrBasicType;
if ( columnTypeInformation == null ) {
this.nullable = TruthValue.UNKNOWN;
this.typeCode = Types.OTHER;
this.typeName = null;
this.columnSize = 0;
this.decimalDigits = 0;
}
else {
this.nullable = columnTypeInformation.getNullable();
this.typeCode = columnTypeInformation.getTypeCode();
this.typeName = columnTypeInformation.getTypeName();
this.columnSize = columnTypeInformation.getColumnSize();
this.decimalDigits = columnTypeInformation.getDecimalDigits();
}
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
TypeConstructedJdbcTypeKey that = (TypeConstructedJdbcTypeKey) o;
if ( typeConstructorTypeCode != that.typeConstructorTypeCode ) {
return false;
}
if ( typeCode != that.typeCode ) {
return false;
}
if ( columnSize != that.columnSize ) {
return false;
}
if ( decimalDigits != that.decimalDigits ) {
return false;
}
if ( !jdbcTypeOrBasicType.equals( that.jdbcTypeOrBasicType ) ) {
return false;
}
if ( nullable != that.nullable ) {
return false;
}
return Objects.equals( typeName, that.typeName );
}
@Override
public int hashCode() {
int result = typeConstructorTypeCode;
result = 31 * result + jdbcTypeOrBasicType.hashCode();
result = 31 * result + ( nullable != null ? nullable.hashCode() : 0 );
result = 31 * result + typeCode;
result = 31 * result + ( typeName != null ? typeName.hashCode() : 0 );
result = 31 * result + columnSize;
result = 31 * result + decimalDigits;
return result;
}
}
}