HHH-16125 Oracle array support using varray types
This commit is contained in:
parent
783e0772e6
commit
07268d6568
|
@ -70,6 +70,7 @@ import org.hibernate.sql.ast.spi.SqlAppender;
|
|||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
@ -294,7 +295,7 @@ public class CockroachLegacyDialect extends Dialect {
|
|||
jdbcTypeRegistry.getTypeConfiguration(),
|
||||
this,
|
||||
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
|
||||
null
|
||||
ColumnTypeInformation.EMPTY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -746,11 +746,8 @@ public class OracleLegacyDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getArrayTypeName(String elementTypeName) {
|
||||
// Return null to signal that there is no array type since Oracle only has named array types
|
||||
// TODO: discuss if it makes sense to parse a config parameter to a map which we can query here
|
||||
// e.g. `hibernate.oracle.array_types=numeric(10,0)=intarray,...`
|
||||
return null;
|
||||
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) {
|
||||
return javaElementTypeName + "Array";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -85,6 +85,7 @@ import org.hibernate.sql.ast.spi.SqlAppender;
|
|||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||
|
@ -346,7 +347,7 @@ public class PostgreSQLLegacyDialect extends Dialect {
|
|||
jdbcTypeRegistry.getTypeConfiguration(),
|
||||
this,
|
||||
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
|
||||
null
|
||||
ColumnTypeInformation.EMPTY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -695,7 +695,7 @@ public class MetadataBuildingProcess {
|
|||
ddlTypeRegistry.addDescriptorIfAbsent(
|
||||
new DdlTypeImpl(
|
||||
SqlTypes.GEOGRAPHY,
|
||||
geometryType.getTypeName( null, null, null ),
|
||||
geometryType.getTypeName( (Long) null, (Integer) null, (Integer) null ),
|
||||
dialect
|
||||
)
|
||||
);
|
||||
|
|
|
@ -57,6 +57,7 @@ import org.hibernate.sql.ast.spi.SqlAppender;
|
|||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
@ -313,7 +314,7 @@ public class CockroachDialect extends Dialect {
|
|||
jdbcTypeRegistry.getTypeConfiguration(),
|
||||
this,
|
||||
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
|
||||
null
|
||||
ColumnTypeInformation.EMPTY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,6 +152,7 @@ import org.hibernate.sql.model.internal.OptionalTableUpdate;
|
|||
import org.hibernate.sql.model.jdbc.OptionalTableUpdateOperation;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||
import org.hibernate.tool.schema.internal.HibernateSchemaManagementTool;
|
||||
import org.hibernate.tool.schema.internal.StandardAuxiliaryDatabaseObjectExporter;
|
||||
|
@ -188,6 +189,7 @@ import org.hibernate.type.descriptor.jdbc.TimeUtcAsOffsetTimeJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.TimestampUtcAsJdbcTimestampJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.TimestampUtcAsOffsetDateTimeJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.descriptor.sql.internal.ArrayDdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.internal.CapacityDependentDdlType;
|
||||
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
|
@ -441,6 +443,10 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
ddlTypeRegistry.addDescriptor( simpleSqlType( LONG32VARCHAR ) );
|
||||
ddlTypeRegistry.addDescriptor( simpleSqlType( LONG32NVARCHAR ) );
|
||||
ddlTypeRegistry.addDescriptor( simpleSqlType( LONG32VARBINARY ) );
|
||||
|
||||
if ( supportsStandardArrays() ) {
|
||||
ddlTypeRegistry.addDescriptor( new ArrayDdlTypeImpl( this ) );
|
||||
}
|
||||
}
|
||||
|
||||
private DdlTypeImpl simpleSqlType(int sqlTypeCode) {
|
||||
|
@ -701,7 +707,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
jdbcTypeRegistry.getTypeConfiguration(),
|
||||
this,
|
||||
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
|
||||
null
|
||||
ColumnTypeInformation.EMPTY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4183,7 +4189,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
*
|
||||
* @since 6.1
|
||||
*/
|
||||
public String getArrayTypeName(String elementTypeName) {
|
||||
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) {
|
||||
return supportsStandardArrays() ? elementTypeName + " array" : null;
|
||||
}
|
||||
|
||||
|
@ -4917,6 +4923,8 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
}
|
||||
|
||||
switch ( ddlTypeCode ) {
|
||||
case SqlTypes.ARRAY:
|
||||
break;
|
||||
case SqlTypes.BIT:
|
||||
case SqlTypes.CHAR:
|
||||
case SqlTypes.NCHAR:
|
||||
|
@ -4965,11 +4973,10 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
case SqlTypes.DECIMAL:
|
||||
case SqlTypes.INTERVAL_SECOND:
|
||||
size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) );
|
||||
size.setScale( javaType.getDefaultSqlScale( Dialect.this, jdbcType ) );
|
||||
break;
|
||||
}
|
||||
|
||||
size.setScale( javaType.getDefaultSqlScale( Dialect.this, jdbcType ) );
|
||||
|
||||
if ( precision != null ) {
|
||||
size.setPrecision( precision );
|
||||
}
|
||||
|
|
|
@ -1295,8 +1295,8 @@ public class DialectDelegateWrapper extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getArrayTypeName(String elementTypeName) {
|
||||
return wrapped.getArrayTypeName( elementTypeName );
|
||||
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) {
|
||||
return wrapped.getArrayTypeName( javaElementTypeName, elementTypeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -133,13 +133,25 @@ public class MySQLDialect extends Dialect {
|
|||
Integer scale,
|
||||
Long length) {
|
||||
switch ( jdbcType.getDdlTypeCode() ) {
|
||||
case Types.BIT:
|
||||
case BIT:
|
||||
// MySQL allows BIT with a length up to 64 (less the default length 255)
|
||||
if ( length != null ) {
|
||||
return Size.length( Math.min( Math.max( length, 1 ), 64 ) );
|
||||
}
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
case REAL:
|
||||
//MySQL doesn't let you cast to DOUBLE/FLOAT
|
||||
//but don't just return 'decimal' because
|
||||
//the default scale is 0 (no decimal places)
|
||||
Size size = super.resolveSize( jdbcType, javaType, precision, scale, length );
|
||||
//cast() on MySQL does not behave sensibly if
|
||||
//we set scale > 20
|
||||
size.setScale( Math.min( size.getPrecision(), 20 ) );
|
||||
return size;
|
||||
default:
|
||||
return super.resolveSize( jdbcType, javaType, precision, scale, length );
|
||||
}
|
||||
return super.resolveSize( jdbcType, javaType, precision, scale, length );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -11,12 +11,14 @@ import java.sql.CallableStatement;
|
|||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Objects;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicPluralJavaType;
|
||||
|
@ -25,11 +27,13 @@ import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import oracle.jdbc.OracleConnection;
|
||||
|
||||
import static java.sql.Types.ARRAY;
|
||||
import static java.util.Collections.emptySet;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Types#ARRAY ARRAY} handling.
|
||||
*
|
||||
|
@ -41,63 +45,61 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
|
|||
private final String typeName;
|
||||
|
||||
public OracleArrayJdbcType() {
|
||||
super( ObjectJdbcType.INSTANCE );
|
||||
this.typeName = null;
|
||||
this( null, null );
|
||||
}
|
||||
|
||||
private OracleArrayJdbcType(String typeName, JdbcType elementJdbcType) {
|
||||
public OracleArrayJdbcType(JdbcType elementJdbcType, String typeName) {
|
||||
super( elementJdbcType );
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaTypeDescriptor) {
|
||||
// No array literal support
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcType resolveType(
|
||||
TypeConfiguration typeConfiguration,
|
||||
Dialect dialect,
|
||||
JdbcType elementType,
|
||||
ColumnTypeInformation columnTypeInformation) {
|
||||
public JdbcType resolveType(TypeConfiguration typeConfiguration, Dialect dialect, BasicType<?> elementType, ColumnTypeInformation columnTypeInformation) {
|
||||
String typeName = columnTypeInformation.getTypeName();
|
||||
if ( typeName == null || typeName.isBlank() ) {
|
||||
typeName = dialect.getArrayTypeName(
|
||||
typeConfiguration.getDdlTypeRegistry().getTypeName(
|
||||
elementType.getDdlTypeCode(),
|
||||
dialect
|
||||
)
|
||||
);
|
||||
typeName = getTypeName( elementType.getJavaTypeDescriptor(), dialect );
|
||||
}
|
||||
if ( typeName == null ) {
|
||||
// Fallback to XML type for the representation of arrays as the native JSON type was only introduced in 21
|
||||
// Also, use the XML type if the Oracle JDBC driver classes are not visible
|
||||
return typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.SQLXML );
|
||||
}
|
||||
return new OracleArrayJdbcType( typeName, elementType );
|
||||
// if ( typeName == null ) {
|
||||
// // Fallback to XML type for the representation of arrays as the native JSON type was only introduced in 21
|
||||
// // Also, use the XML type if the Oracle JDBC driver classes are not visible
|
||||
// return typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.SQLXML );
|
||||
// }
|
||||
return new OracleArrayJdbcType( elementType.getJdbcType(), typeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcType resolveType(TypeConfiguration typeConfiguration, Dialect dialect, JdbcType elementType, ColumnTypeInformation columnTypeInformation) {
|
||||
// a bit wrong!
|
||||
return new OracleArrayJdbcType( elementType, columnTypeInformation.getTypeName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaType<X> javaTypeDescriptor) {
|
||||
//noinspection unchecked
|
||||
final BasicPluralJavaType<X> containerJavaType = (BasicPluralJavaType<X>) javaTypeDescriptor;
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
return new BasicBinder<>( javaTypeDescriptor, this ) {
|
||||
private String typeName(WrapperOptions options) {
|
||||
return ( typeName == null ? getTypeName( options, containerJavaType ) : typeName )
|
||||
.toUpperCase(Locale.ROOT);
|
||||
}
|
||||
@Override
|
||||
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {
|
||||
st.setNull( index, Types.ARRAY, typeName );
|
||||
st.setNull( index, ARRAY, typeName( options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException {
|
||||
st.setNull( name, Types.ARRAY, typeName );
|
||||
st.setNull( name, ARRAY, typeName( options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
final java.sql.Array arr = getArray( value, containerJavaType, options );
|
||||
st.setArray( index, arr );
|
||||
st.setArray( index, getArray( value, containerJavaType, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -105,7 +107,7 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
|
|||
throws SQLException {
|
||||
final java.sql.Array arr = getArray( value, containerJavaType, options );
|
||||
try {
|
||||
st.setObject( name, arr, Types.ARRAY );
|
||||
st.setObject( name, arr, ARRAY );
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
throw new HibernateException( "JDBC driver does not support named parameters for setArray. Use positional.", ex );
|
||||
|
@ -122,12 +124,13 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
|
|||
0
|
||||
).getClass();
|
||||
final Object[] objects = javaTypeDescriptor.unwrap( value, arrayClass, options );
|
||||
final String arrayTypeName = typeName( options ).toUpperCase(Locale.ROOT);
|
||||
|
||||
final SharedSessionContractImplementor session = options.getSession();
|
||||
final OracleConnection oracleConnection = session.getJdbcCoordinator().getLogicalConnection().getPhysicalConnection()
|
||||
final OracleConnection oracleConnection = options.getSession()
|
||||
.getJdbcCoordinator().getLogicalConnection().getPhysicalConnection()
|
||||
.unwrap( OracleConnection.class );
|
||||
try {
|
||||
return oracleConnection.createOracleArray( typeName, objects );
|
||||
return oracleConnection.createOracleArray( arrayTypeName, objects );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Couldn't create a java.sql.Array", e );
|
||||
|
@ -136,22 +139,54 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
private static String getTypeName(WrapperOptions options, BasicPluralJavaType<?> containerJavaType) {
|
||||
Dialect dialect = options.getSessionFactory().getJdbcServices().getDialect();
|
||||
return getTypeName( containerJavaType.getElementJavaType(), dialect );
|
||||
}
|
||||
|
||||
OracleArrayJdbcType that = (OracleArrayJdbcType) o;
|
||||
|
||||
return Objects.equals( typeName, that.typeName );
|
||||
private static String getTypeName(JavaType<?> elementJavaType, Dialect dialect) {
|
||||
return dialect.getArrayTypeName(
|
||||
elementJavaType.getJavaTypeClass().getSimpleName(),
|
||||
null // not needed by OracleDialect.getArrayTypeName()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return typeName != null ? typeName.hashCode() : 0;
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final Dialect dialect = database.getDialect();
|
||||
final BasicPluralJavaType<?> pluralJavaType = (BasicPluralJavaType<?>) javaType;
|
||||
final String elementTypeName = typeName==null
|
||||
? getTypeName( pluralJavaType.getElementJavaType(), dialect )
|
||||
: typeName;
|
||||
final String elementType =
|
||||
typeConfiguration.getDdlTypeRegistry().getTypeName(
|
||||
getElementJdbcType().getDdlTypeCode(),
|
||||
dialect.getSizeStrategy().resolveSize(
|
||||
getElementJdbcType(),
|
||||
pluralJavaType.getElementJavaType(),
|
||||
columnSize.getPrecision(),
|
||||
columnSize.getScale(),
|
||||
columnSize.getLength()
|
||||
)
|
||||
);
|
||||
final String[] create = new String[] { "create or replace type " + elementTypeName + " as varying array(255) of " + elementType };
|
||||
final String[] drop = new String[] {
|
||||
// "drop type " + elementTypeName
|
||||
};
|
||||
database.addAuxiliaryDatabaseObject(
|
||||
new NamedAuxiliaryDatabaseObject( elementTypeName, database.getDefaultNamespace(), create, drop, emptySet(), true )
|
||||
);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public String getExtraCreateTableInfo(JavaType<?> javaType, String columnName, String tableName, Database database) {
|
||||
// final Dialect dialect = database.getDialect();
|
||||
// final BasicPluralJavaType<?> pluralJavaType = (BasicPluralJavaType<?>) javaType;
|
||||
// String elementTypeName = getTypeName( pluralJavaType.getElementJavaType(), dialect );
|
||||
// return " nested table " + columnName + " store as " + tableName + columnName + elementTypeName;
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ import org.hibernate.type.descriptor.jdbc.NullJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.ObjectNullAsNullTypeJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.descriptor.sql.internal.ArrayDdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -685,6 +686,8 @@ public class OracleDialect extends Dialect {
|
|||
else if ( getVersion().isSameOrAfter( 12 ) ) {
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "blob", this ) );
|
||||
}
|
||||
|
||||
ddlTypeRegistry.addDescriptor( new ArrayDdlTypeImpl( this ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -781,11 +784,8 @@ public class OracleDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getArrayTypeName(String elementTypeName) {
|
||||
// Return null to signal that there is no array type since Oracle only has named array types
|
||||
// TODO: discuss if it makes sense to parse a config parameter to a map which we can query here
|
||||
// e.g. `hibernate.oracle.array_types=numeric(10,0)=intarray,...`
|
||||
return null;
|
||||
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) {
|
||||
return javaElementTypeName + "Array";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.dialect;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||
|
@ -21,7 +20,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteMaterialization;
|
||||
import org.hibernate.sql.ast.tree.expression.AggregateColumnWriteExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.FunctionExpression;
|
||||
|
@ -31,7 +29,6 @@ import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
|||
import org.hibernate.sql.ast.tree.expression.SqlTupleContainer;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
|
||||
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
||||
import org.hibernate.sql.ast.tree.from.QueryPartTableReference;
|
||||
import org.hibernate.sql.ast.tree.from.UnionTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.ValuesTableReference;
|
||||
|
@ -442,12 +439,42 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends SqlAstTrans
|
|||
rhs.accept( this );
|
||||
appendSql( ')' );
|
||||
break;
|
||||
case SqlTypes.ARRAY:
|
||||
switch ( operator ) {
|
||||
case DISTINCT_FROM:
|
||||
appendSql( "decode(" );
|
||||
arrayToString( lhs );
|
||||
appendSql( ',' );
|
||||
arrayToString( rhs );
|
||||
appendSql( ",0,1)=1" );
|
||||
break;
|
||||
case NOT_DISTINCT_FROM:
|
||||
appendSql( "decode(" );
|
||||
arrayToString( lhs );
|
||||
appendSql( ',' );
|
||||
arrayToString( rhs );
|
||||
appendSql( ",0,1)=0" );
|
||||
break;
|
||||
default:
|
||||
arrayToString( lhs );
|
||||
appendSql( operator.sqlText() );
|
||||
arrayToString( rhs );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
renderComparisonEmulateDecode( lhs, operator, rhs );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void arrayToString(Expression expression) {
|
||||
appendSql("case when ");
|
||||
expression.accept( this );
|
||||
appendSql(" is not null then (select listagg(column_value||',')||';' from table(");
|
||||
expression.accept( this );
|
||||
appendSql(")) else null end");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
|
|
|
@ -74,6 +74,7 @@ import org.hibernate.sql.exec.spi.JdbcOperation;
|
|||
import org.hibernate.sql.model.MutationOperation;
|
||||
import org.hibernate.sql.model.internal.OptionalTableUpdate;
|
||||
import org.hibernate.sql.model.jdbc.OptionalTableUpdateOperation;
|
||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||
|
@ -246,7 +247,7 @@ public class PostgreSQLDialect extends Dialect {
|
|||
// Prefer jsonb if possible
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "jsonb", this ) );
|
||||
|
||||
ddlTypeRegistry.addDescriptor( NAMED_ENUM, new NamedNativeEnumDdlTypeImpl( this ) );
|
||||
ddlTypeRegistry.addDescriptor( new NamedNativeEnumDdlTypeImpl( this ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -325,7 +326,7 @@ public class PostgreSQLDialect extends Dialect {
|
|||
jdbcTypeRegistry.getTypeConfiguration(),
|
||||
this,
|
||||
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
|
||||
null
|
||||
ColumnTypeInformation.EMPTY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -828,6 +829,7 @@ public class PostgreSQLDialect extends Dialect {
|
|||
|
||||
@Override
|
||||
public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) {
|
||||
// TODO: adapt this to handle named enum types!
|
||||
// Workaround for postgres bug #1453
|
||||
return "null::" + typeConfiguration.getDdlTypeRegistry().getDescriptor( sqlType ).getRawTypeName();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.dialect;
|
|||
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.model.relational.NamedAuxiliaryDatabaseObject;
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
@ -17,6 +17,7 @@ import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
|||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
|
@ -114,15 +115,19 @@ public class PostgreSQLEnumJdbcType implements JdbcType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addAuxiliaryDatabaseObjects(JavaType<?> javaType, InFlightMetadataCollector metadataCollector) {
|
||||
Database database = metadataCollector.getDatabase();
|
||||
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
|
||||
String name = enumClass.getSimpleName();
|
||||
String[] create = database.getDialect().getCreateEnumTypeCommand( enumClass );
|
||||
public void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
final Dialect dialect = database.getDialect();
|
||||
final Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) javaType.getJavaType();
|
||||
final String enumTypeName = enumClass.getSimpleName();
|
||||
final String[] create = dialect.getCreateEnumTypeCommand( enumClass );
|
||||
if ( create != null ) {
|
||||
String[] drop = database.getDialect().getDropEnumTypeCommand( enumClass );
|
||||
final String[] drop = dialect.getDropEnumTypeCommand( enumClass );
|
||||
database.addAuxiliaryDatabaseObject(
|
||||
new NamedAuxiliaryDatabaseObject( name, database.getDefaultNamespace(), create, drop, emptySet(), true )
|
||||
new NamedAuxiliaryDatabaseObject( enumTypeName, database.getDefaultNamespace(), create, drop, emptySet(), true )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ public class SpannerDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getArrayTypeName(String elementTypeName) {
|
||||
public String getArrayTypeName(String javaElementTypeName, String elementTypeName) {
|
||||
return "ARRAY<" + elementTypeName + ">";
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
|||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
|||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
|
@ -314,19 +315,38 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
|
|||
}
|
||||
|
||||
final Selectable selectable = getColumn();
|
||||
final Size size;
|
||||
if ( selectable instanceof Column ) {
|
||||
resolveColumn( (Column) selectable, getDialect() );
|
||||
Column column = (Column) selectable;
|
||||
resolveColumn( column, getDialect() );
|
||||
size = column.calculateColumnSize( getDialect(), getBuildingContext().getMetadataCollector() );
|
||||
}
|
||||
else {
|
||||
size = Size.nil();
|
||||
}
|
||||
|
||||
resolution.getJdbcType()
|
||||
.addAuxiliaryDatabaseObjects(
|
||||
resolution.getRelationalJavaType(),
|
||||
getBuildingContext().getMetadataCollector()
|
||||
size,
|
||||
getBuildingContext().getMetadataCollector().getDatabase(),
|
||||
getTypeConfiguration()
|
||||
);
|
||||
|
||||
return resolution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtraCreateTableInfo() {
|
||||
return resolution.getJdbcType()
|
||||
.getExtraCreateTableInfo(
|
||||
resolution.getRelationalJavaType(),
|
||||
getColumn().getText(),
|
||||
getTable().getName(),
|
||||
getBuildingContext().getMetadataCollector().getDatabase()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialect getDialect() {
|
||||
return getMetadata().getDatabase().getDialect();
|
||||
|
|
|
@ -13,7 +13,6 @@ import java.util.Locale;
|
|||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.model.TruthValue;
|
||||
|
@ -26,12 +25,9 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
|
|||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.sql.Template;
|
||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||
import org.hibernate.type.BasicPluralType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
|
@ -272,11 +268,11 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
|
|||
private String getSqlTypeName(DdlTypeRegistry ddlTypeRegistry, Dialect dialect, Mapping mapping) {
|
||||
if ( sqlTypeName == null ) {
|
||||
try {
|
||||
final Type type = getValue().getType();
|
||||
sqlTypeName = isArray( type )
|
||||
//TODO: remove the special case for array types, this should be handled by the DdlType!
|
||||
? dialect.getArrayTypeName( getArrayElementTypeName( dialect, ddlTypeRegistry, getArrayElementType( type ) ) )
|
||||
: ddlTypeRegistry.getTypeName( getSqlTypeCode( mapping ), getColumnSize( dialect, mapping ), getUnderlyingType( mapping, type, typeIndex ) );
|
||||
sqlTypeName = ddlTypeRegistry.getTypeName(
|
||||
getSqlTypeCode( mapping ),
|
||||
getColumnSize( dialect, mapping ),
|
||||
getUnderlyingType( mapping, getValue().getType(), typeIndex )
|
||||
);
|
||||
}
|
||||
catch ( Exception cause ) {
|
||||
throw new MappingException(
|
||||
|
@ -314,29 +310,6 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
|
|||
}
|
||||
}
|
||||
|
||||
private String getArrayElementTypeName(Dialect dialect, DdlTypeRegistry ddlTypeRegistry, BasicType<?> elementType) {
|
||||
return ddlTypeRegistry.getTypeName(
|
||||
elementType.getJdbcType().getDdlTypeCode(),
|
||||
dialect.getSizeStrategy().resolveSize(
|
||||
elementType.getJdbcMapping().getJdbcType(),
|
||||
elementType.getJavaTypeDescriptor(),
|
||||
precision,
|
||||
scale,
|
||||
length
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static BasicType<?> getArrayElementType(Type arrayType) {
|
||||
final BasicPluralType<?, ?> containerType = (BasicPluralType<?, ?>) arrayType;
|
||||
return containerType.getElementType();
|
||||
}
|
||||
|
||||
private static boolean isArray(Type type) {
|
||||
return type instanceof BasicPluralType<?,?>
|
||||
&& ((BasicType<?>) type).getJdbcType() instanceof ArrayJdbcType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@linkplain org.hibernate.type.SqlTypes SQL type code}
|
||||
* for this column, or {@code null} if the type code is unknown.
|
||||
|
@ -402,28 +375,32 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
|
|||
|
||||
public Size getColumnSize(Dialect dialect, Mapping mapping) {
|
||||
if ( columnSize == null ) {
|
||||
Type type = getValue().getType();
|
||||
if ( type instanceof EntityType ) {
|
||||
type = getTypeForEntityValue( mapping, type, getTypeIndex() );
|
||||
}
|
||||
if ( type instanceof ComponentType ) {
|
||||
type = getTypeForComponentValue( mapping, type, getTypeIndex() );
|
||||
}
|
||||
if ( type == null ) {
|
||||
throw new AssertionFailure( "no typing information available to determine column size" );
|
||||
}
|
||||
final JdbcMapping jdbcMapping = (JdbcMapping) type;
|
||||
columnSize = dialect.getSizeStrategy().resolveSize(
|
||||
jdbcMapping.getJdbcType(),
|
||||
jdbcMapping.getJdbcJavaType(),
|
||||
precision,
|
||||
scale,
|
||||
length
|
||||
);
|
||||
columnSize = calculateColumnSize( dialect, mapping );
|
||||
}
|
||||
return columnSize;
|
||||
}
|
||||
|
||||
Size calculateColumnSize(Dialect dialect, Mapping mapping) {
|
||||
Type type = getValue().getType();
|
||||
if ( type instanceof EntityType ) {
|
||||
type = getTypeForEntityValue( mapping, type, getTypeIndex() );
|
||||
}
|
||||
if ( type instanceof ComponentType ) {
|
||||
type = getTypeForComponentValue( mapping, type, getTypeIndex() );
|
||||
}
|
||||
if ( type == null ) {
|
||||
throw new AssertionFailure( "no typing information available to determine column size" );
|
||||
}
|
||||
final JdbcMapping jdbcMapping = (JdbcMapping) type;
|
||||
return dialect.getSizeStrategy().resolveSize(
|
||||
jdbcMapping.getJdbcType(),
|
||||
jdbcMapping.getJdbcJavaType(),
|
||||
precision,
|
||||
scale,
|
||||
length
|
||||
);
|
||||
}
|
||||
|
||||
private Type getTypeForComponentValue(Mapping mapping, Type type, int typeIndex) {
|
||||
final Type[] subtypes = ( (ComponentType) type ).getSubtypes();
|
||||
int typeStartIndex = 0;
|
||||
|
|
|
@ -174,4 +174,9 @@ public interface Value extends Serializable {
|
|||
boolean isColumnInsertable(int index);
|
||||
|
||||
boolean isColumnUpdateable(int index);
|
||||
|
||||
@Incubating
|
||||
default String getExtraCreateTableInfo() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,6 +183,10 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
|
|||
executionContext.getSession()
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JdbcParameter(" + name + ")";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
|||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.SqmVisitableNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
|
@ -115,7 +114,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
final ArrayList<SqlAstNode> sqlAstArguments = new ArrayList<>( sqmArguments.size() );
|
||||
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
||||
sqlAstArguments.add(
|
||||
(SqlAstNode) ( (SqmVisitableNode) sqmArguments.get( i ) ).accept( walker )
|
||||
(SqlAstNode) sqmArguments.get( i ).accept( walker )
|
||||
);
|
||||
}
|
||||
return sqlAstArguments;
|
||||
|
@ -129,7 +128,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
||||
typeAccess.argumentIndex = i;
|
||||
sqlAstArguments.add(
|
||||
(SqlAstNode) walker.visitWithInferredType( (SqmVisitableNode) sqmArguments.get( i ), typeAccess )
|
||||
(SqlAstNode) walker.visitWithInferredType( sqmArguments.get( i ), typeAccess )
|
||||
);
|
||||
}
|
||||
return sqlAstArguments;
|
||||
|
|
|
@ -279,7 +279,6 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||
import org.hibernate.sql.ast.SqlTreeCreationException;
|
||||
import org.hibernate.sql.ast.SqlTreeCreationLogger;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||
|
|
|
@ -204,6 +204,7 @@ import org.hibernate.type.BasicType;
|
|||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicPluralJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
@ -6117,6 +6118,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
final SqlExpressible expressionType = (SqlExpressible) castTarget.getExpressionType();
|
||||
if ( expressionType instanceof BasicPluralType<?, ?> ) {
|
||||
final BasicPluralType<?, ?> containerType = (BasicPluralType<?, ?>) expressionType;
|
||||
final BasicPluralJavaType<?> javaTypeDescriptor = (BasicPluralJavaType<?>) containerType.getJavaTypeDescriptor();
|
||||
final BasicType<?> elementType = containerType.getElementType();
|
||||
final String elementTypeName = sessionFactory.getTypeConfiguration().getDdlTypeRegistry()
|
||||
.getDescriptor( elementType.getJdbcType().getDdlTypeCode() )
|
||||
|
@ -6126,7 +6128,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
castTarget.getPrecision(),
|
||||
castTarget.getScale()
|
||||
);
|
||||
final String arrayTypeName = dialect.getArrayTypeName( elementTypeName );
|
||||
final String arrayTypeName = dialect.getArrayTypeName(
|
||||
javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(),
|
||||
elementTypeName
|
||||
);
|
||||
if ( arrayTypeName != null ) {
|
||||
appendSql( arrayTypeName );
|
||||
return;
|
||||
|
|
|
@ -56,6 +56,8 @@ public class StandardTableExporter implements Exporter<Table> {
|
|||
try {
|
||||
final String formattedTableName = context.format( tableName );
|
||||
|
||||
final StringBuilder extra = new StringBuilder();
|
||||
|
||||
final StringBuilder createTable =
|
||||
new StringBuilder( tableCreateString( table.hasPrimaryKey() ) )
|
||||
.append( ' ' )
|
||||
|
@ -71,6 +73,8 @@ public class StandardTableExporter implements Exporter<Table> {
|
|||
createTable.append( ", " );
|
||||
}
|
||||
appendColumn( createTable, column, table, metadata, dialect, context );
|
||||
|
||||
extra.append( column.getValue().getExtraCreateTableInfo() );
|
||||
}
|
||||
if ( table.getRowId() != null ) {
|
||||
String rowIdColumn = dialect.getRowIdColumnString( table.getRowId() );
|
||||
|
@ -88,6 +92,8 @@ public class StandardTableExporter implements Exporter<Table> {
|
|||
|
||||
createTable.append( ')' );
|
||||
|
||||
createTable.append( extra );
|
||||
|
||||
if ( table.getComment() != null ) {
|
||||
createTable.append( dialect.getTableComment( table.getComment() ) );
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
|||
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.internal.BasicTypeImpl;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
public abstract class AbstractArrayJavaType<T, E> extends AbstractClassJavaType<T>
|
||||
|
@ -53,7 +54,7 @@ public abstract class AbstractArrayJavaType<T, E> extends AbstractClassJavaType<
|
|||
return ( (ArrayJdbcType) jdbcType ).resolveType(
|
||||
typeConfiguration,
|
||||
indicators.getDialect(),
|
||||
recommendedComponentJdbcType,
|
||||
new BasicTypeImpl<>( getElementJavaType(), recommendedComponentJdbcType ),
|
||||
ColumnTypeInformation.EMPTY
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.type.descriptor.jdbc;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -111,7 +110,7 @@ public class ArrayJdbcType implements JdbcType {
|
|||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaType<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
return new BasicBinder<>( javaTypeDescriptor, this ) {
|
||||
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
|
@ -197,7 +196,7 @@ public class ArrayJdbcType implements JdbcType {
|
|||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaType<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||
return new BasicExtractor<>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( rs.getArray( paramIndex ), options );
|
||||
|
@ -230,7 +229,7 @@ public class ArrayJdbcType implements JdbcType {
|
|||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
if ( !(o instanceof ArrayJdbcType) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import java.sql.SQLException;
|
|||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.query.sqm.CastType;
|
||||
|
@ -327,6 +327,15 @@ public interface JdbcType extends Serializable {
|
|||
}
|
||||
|
||||
@Incubating
|
||||
default void addAuxiliaryDatabaseObjects(JavaType<?> javaType, InFlightMetadataCollector metadataCollector) {
|
||||
default void addAuxiliaryDatabaseObjects(
|
||||
JavaType<?> javaType,
|
||||
Size columnSize,
|
||||
Database database,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
}
|
||||
|
||||
@Incubating
|
||||
default String getExtraCreateTableInfo(JavaType<?> javaType, String columnName, String tableName, Database database) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,10 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.metamodel.mapping.SqlExpressible;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
|
||||
/**
|
||||
* Descriptor for a DDL column type. An instance of this type abstracts over
|
||||
|
@ -36,7 +38,14 @@ public interface DdlType extends Serializable {
|
|||
*/
|
||||
int getSqlTypeCode();
|
||||
|
||||
default String getTypeName(Size columnSize, Class<?> returnedClass) {
|
||||
/**
|
||||
* Return a type with length, precision, and scale specified by the given
|
||||
* {@linkplain Size size object}. The given type may be used to
|
||||
* determine additional aspects of the returned SQL type.
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
default String getTypeName(Size columnSize, Type type, DdlTypeRegistry ddlTypeRegistry) {
|
||||
return getTypeName( columnSize );
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.type.descriptor.sql.internal;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.type.BasicPluralType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.BasicPluralJavaType;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
|
||||
import static java.sql.Types.ARRAY;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class ArrayDdlTypeImpl extends DdlTypeImpl {
|
||||
|
||||
public ArrayDdlTypeImpl(Dialect dialect) {
|
||||
super( ARRAY, "array", dialect );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(Size columnSize, Type type, DdlTypeRegistry ddlTypeRegistry) {
|
||||
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) type;
|
||||
final BasicPluralJavaType<?> javaTypeDescriptor = (BasicPluralJavaType<?>) pluralType.getJavaTypeDescriptor();
|
||||
final BasicType<?> elementType = pluralType.getElementType();
|
||||
final String arrayElementTypeName =
|
||||
ddlTypeRegistry.getTypeName(
|
||||
elementType.getJdbcType().getDdlTypeCode(),
|
||||
dialect.getSizeStrategy().resolveSize(
|
||||
elementType.getJdbcMapping().getJdbcType(),
|
||||
elementType.getJavaTypeDescriptor(),
|
||||
columnSize.getPrecision(),
|
||||
columnSize.getScale(),
|
||||
columnSize.getLength()
|
||||
)
|
||||
);
|
||||
return dialect.getArrayTypeName(
|
||||
javaTypeDescriptor.getElementJavaType().getJavaTypeClass().getSimpleName(),
|
||||
arrayElementTypeName
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -25,7 +25,7 @@ public class DdlTypeImpl implements DdlType {
|
|||
private final String typeNamePattern;
|
||||
private final String castTypeNamePattern;
|
||||
private final boolean castTypeNameIsStatic;
|
||||
private final Dialect dialect;
|
||||
final Dialect dialect;
|
||||
|
||||
public DdlTypeImpl(int sqlTypeCode, String typeNamePattern, Dialect dialect) {
|
||||
this( sqlTypeCode, typeNamePattern, typeNamePattern, dialect );
|
||||
|
|
|
@ -8,16 +8,18 @@ package org.hibernate.type.descriptor.sql.internal;
|
|||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.sql.DdlType;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.ENUM;
|
||||
import static org.hibernate.type.SqlTypes.NAMED_ENUM;
|
||||
|
||||
/**
|
||||
* A {@link DdlType} representing a native SQL {@code enum} type.
|
||||
* A {@link DdlType} representing a named native SQL {@code enum} type,
|
||||
* one that often <em>cannot</em> be treated as a {@code varchar}.
|
||||
*
|
||||
* @see org.hibernate.type.SqlTypes#ENUM
|
||||
* @see org.hibernate.type.SqlTypes#NAMED_ENUM
|
||||
* @see Dialect#getEnumTypeDeclaration(Class)
|
||||
*
|
||||
|
@ -33,17 +35,16 @@ public class NamedNativeEnumDdlTypeImpl implements DdlType {
|
|||
@Override
|
||||
public int getSqlTypeCode() {
|
||||
// note: also used for NAMED_ENUM
|
||||
return ENUM;
|
||||
return NAMED_ENUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(Size columnSize, Class<?> returnedClass) {
|
||||
return dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) returnedClass );
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
public String getTypeName(Size columnSize, Type type, DdlTypeRegistry ddlTypeRegistry) {
|
||||
return dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) type.getReturnedClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRawTypeName() {
|
||||
// this
|
||||
return "enum";
|
||||
}
|
||||
|
||||
|
|
|
@ -8,15 +8,24 @@ package org.hibernate.type.descriptor.sql.internal;
|
|||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.sql.DdlType;
|
||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||
|
||||
import static org.hibernate.type.SqlTypes.ENUM;
|
||||
|
||||
/**
|
||||
* A {@link DdlType} representing a SQL {@code enum} type that
|
||||
* may be treated as {@code varchar} for most purposes.
|
||||
*
|
||||
* @see org.hibernate.type.SqlTypes#ENUM
|
||||
* @see Dialect#getEnumTypeDeclaration(Class)
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
|
||||
public class NativeEnumDdlTypeImpl implements DdlType {
|
||||
private final Dialect dialect;
|
||||
|
||||
|
@ -29,9 +38,9 @@ public class NativeEnumDdlTypeImpl implements DdlType {
|
|||
return ENUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName(Size columnSize, Class<?> returnedClass) {
|
||||
return dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) returnedClass );
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
public String getTypeName(Size columnSize, Type type, DdlTypeRegistry ddlTypeRegistry) {
|
||||
return dialect.getEnumTypeDeclaration( (Class<? extends Enum<?>>) type.getReturnedClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -148,6 +148,12 @@ public class DdlTypeRegistry implements Serializable {
|
|||
public String getTypeName(int typeCode, Dialect dialect) {
|
||||
// explicitly enforce dialect's default precisions
|
||||
switch ( typeCode ) {
|
||||
case SqlTypes.CHAR:
|
||||
case SqlTypes.NCHAR:
|
||||
case SqlTypes.VARCHAR:
|
||||
case SqlTypes.NVARCHAR:
|
||||
case SqlTypes.VARBINARY:
|
||||
return getTypeName( typeCode, Size.length( Size.DEFAULT_LENGTH ) );
|
||||
case SqlTypes.DECIMAL:
|
||||
case SqlTypes.NUMERIC:
|
||||
return getTypeName( typeCode, Size.precision( dialect.getDefaultDecimalPrecision() ) );
|
||||
|
@ -188,6 +194,22 @@ public class DdlTypeRegistry implements Serializable {
|
|||
return getTypeName( typeCode, size.getLength(), size.getPrecision(), size.getScale() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL type name for the specified {@link java.sql.Types JDBC type code}
|
||||
* and size, filling in the placemarkers {@code $l}, {@code $p}, and {@code $s}
|
||||
* with the length, precision, and scale determined by the given {@linkplain Size
|
||||
* size object}. The returned type name should be of a SQL type large enough to
|
||||
* accommodate values of the specified size.
|
||||
*
|
||||
* @param typeCode the JDBC type code
|
||||
* @param columnSize an object which determines the length, precision, and scale
|
||||
* @param type the {@link Type} mapped to the column
|
||||
*
|
||||
* @return the associated type name with the smallest capacity that accommodates
|
||||
* the given size, if available, and the default type name otherwise
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
public String getTypeName(int typeCode, Size columnSize, Type type) {
|
||||
final DdlType descriptor = getDescriptor( typeCode );
|
||||
if ( descriptor == null ) {
|
||||
|
@ -199,7 +221,7 @@ public class DdlTypeRegistry implements Serializable {
|
|||
)
|
||||
);
|
||||
}
|
||||
return descriptor.getTypeName( columnSize, type.getReturnedClass() );
|
||||
return descriptor.getTypeName( columnSize, type, this );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue