HHH-18799 Add XML aggregate support for Oracle
This commit is contained in:
parent
6d1b9c475a
commit
eeba7edf32
|
@ -53,7 +53,9 @@ import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
||||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
import org.hibernate.mapping.AggregateColumn;
|
||||||
import org.hibernate.mapping.CheckConstraint;
|
import org.hibernate.mapping.CheckConstraint;
|
||||||
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.mapping.UserDefinedType;
|
import org.hibernate.mapping.UserDefinedType;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
|
@ -81,6 +83,7 @@ import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
|
||||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||||
|
import org.hibernate.tool.schema.internal.StandardTableExporter;
|
||||||
import org.hibernate.tool.schema.spi.Exporter;
|
import org.hibernate.tool.schema.spi.Exporter;
|
||||||
import org.hibernate.type.JavaObjectType;
|
import org.hibernate.type.JavaObjectType;
|
||||||
import org.hibernate.type.NullType;
|
import org.hibernate.type.NullType;
|
||||||
|
@ -172,6 +175,17 @@ public class OracleLegacyDialect extends Dialect {
|
||||||
private final OracleUserDefinedTypeExporter userDefinedTypeExporter = new OracleUserDefinedTypeExporter( this );
|
private final OracleUserDefinedTypeExporter userDefinedTypeExporter = new OracleUserDefinedTypeExporter( this );
|
||||||
private final UniqueDelegate uniqueDelegate = new CreateTableUniqueDelegate(this);
|
private final UniqueDelegate uniqueDelegate = new CreateTableUniqueDelegate(this);
|
||||||
private final SequenceSupport oracleSequenceSupport = OracleSequenceSupport.getInstance(this);
|
private final SequenceSupport oracleSequenceSupport = OracleSequenceSupport.getInstance(this);
|
||||||
|
private final StandardTableExporter oracleTableExporter = new StandardTableExporter( this ) {
|
||||||
|
@Override
|
||||||
|
protected void applyAggregateColumnCheck(StringBuilder buf, AggregateColumn aggregateColumn) {
|
||||||
|
final JdbcType jdbcType = aggregateColumn.getType().getJdbcType();
|
||||||
|
if ( dialect.getVersion().isBefore( 23, 6 ) && jdbcType.isXml() ) {
|
||||||
|
// ORA-00600 when selecting XML columns that have a check constraint was fixed in 23.6
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.applyAggregateColumnCheck( buf, aggregateColumn );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public OracleLegacyDialect() {
|
public OracleLegacyDialect() {
|
||||||
this( DatabaseVersion.make( 8, 0 ) );
|
this( DatabaseVersion.make( 8, 0 ) );
|
||||||
|
@ -503,6 +517,8 @@ public class OracleLegacyDialect extends Dialect {
|
||||||
return "to_timestamp_tz(?1,'YYYY-MM-DD HH24:MI:SS.FF9 TZR')";
|
return "to_timestamp_tz(?1,'YYYY-MM-DD HH24:MI:SS.FF9 TZR')";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case XML:
|
||||||
|
return "xmlparse(document ?1)";
|
||||||
}
|
}
|
||||||
return super.castPattern(from, to);
|
return super.castPattern(from, to);
|
||||||
}
|
}
|
||||||
|
@ -1042,6 +1058,11 @@ public class OracleLegacyDialect extends Dialect {
|
||||||
return oracleSequenceSupport;
|
return oracleSequenceSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Exporter<Table> getTableExporter() {
|
||||||
|
return oracleTableExporter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getQuerySequencesString() {
|
public String getQuerySequencesString() {
|
||||||
return "select * from all_sequences";
|
return "select * from all_sequences";
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.sql.SQLException;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
@ -31,6 +32,11 @@ public class H2JsonJdbcType extends JsonJdbcType {
|
||||||
super( embeddableMappingType );
|
super( embeddableMappingType );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getJdbcTypeCode() {
|
||||||
|
return SqlTypes.VARBINARY;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "H2JsonJdbcType";
|
return "H2JsonJdbcType";
|
||||||
|
|
|
@ -253,6 +253,7 @@ public class OracleArrayJdbcType extends ArrayJdbcType implements SqlTypedJdbcTy
|
||||||
userDefinedArrayType.setArraySqlTypeCode( getDdlTypeCode() );
|
userDefinedArrayType.setArraySqlTypeCode( getDdlTypeCode() );
|
||||||
userDefinedArrayType.setElementTypeName( elementTypeName );
|
userDefinedArrayType.setElementTypeName( elementTypeName );
|
||||||
userDefinedArrayType.setElementSqlTypeCode( elementJdbcType.getDefaultSqlTypeCode() );
|
userDefinedArrayType.setElementSqlTypeCode( elementJdbcType.getDefaultSqlTypeCode() );
|
||||||
|
userDefinedArrayType.setElementDdlTypeCode( elementJdbcType.getDdlTypeCode() );
|
||||||
userDefinedArrayType.setArrayLength( columnSize.getArrayLength() == null ? 127 : columnSize.getArrayLength() );
|
userDefinedArrayType.setArrayLength( columnSize.getArrayLength() == null ? 127 : columnSize.getArrayLength() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,8 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
||||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
|
import org.hibernate.mapping.AggregateColumn;
|
||||||
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.mapping.UserDefinedType;
|
import org.hibernate.mapping.UserDefinedType;
|
||||||
import org.hibernate.mapping.CheckConstraint;
|
import org.hibernate.mapping.CheckConstraint;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
@ -78,6 +80,7 @@ import org.hibernate.sql.model.internal.OptionalTableUpdate;
|
||||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
|
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
|
||||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||||
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
|
||||||
|
import org.hibernate.tool.schema.internal.StandardTableExporter;
|
||||||
import org.hibernate.tool.schema.spi.Exporter;
|
import org.hibernate.tool.schema.spi.Exporter;
|
||||||
import org.hibernate.type.JavaObjectType;
|
import org.hibernate.type.JavaObjectType;
|
||||||
import org.hibernate.type.NullType;
|
import org.hibernate.type.NullType;
|
||||||
|
@ -181,6 +184,17 @@ public class OracleDialect extends Dialect {
|
||||||
private final OracleUserDefinedTypeExporter userDefinedTypeExporter = new OracleUserDefinedTypeExporter( this );
|
private final OracleUserDefinedTypeExporter userDefinedTypeExporter = new OracleUserDefinedTypeExporter( this );
|
||||||
private final UniqueDelegate uniqueDelegate = new CreateTableUniqueDelegate(this);
|
private final UniqueDelegate uniqueDelegate = new CreateTableUniqueDelegate(this);
|
||||||
private final SequenceSupport oracleSequenceSupport = OracleSequenceSupport.getInstance(this);
|
private final SequenceSupport oracleSequenceSupport = OracleSequenceSupport.getInstance(this);
|
||||||
|
private final StandardTableExporter oracleTableExporter = new StandardTableExporter( this ) {
|
||||||
|
@Override
|
||||||
|
protected void applyAggregateColumnCheck(StringBuilder buf, AggregateColumn aggregateColumn) {
|
||||||
|
final JdbcType jdbcType = aggregateColumn.getType().getJdbcType();
|
||||||
|
if ( dialect.getVersion().isBefore( 23, 6 ) && jdbcType.isXml() ) {
|
||||||
|
// ORA-00600 when selecting XML columns that have a check constraint was fixed in 23.6
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.applyAggregateColumnCheck( buf, aggregateColumn );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Is it an Autonomous Database Cloud Service?
|
// Is it an Autonomous Database Cloud Service?
|
||||||
protected final boolean autonomous;
|
protected final boolean autonomous;
|
||||||
|
@ -589,6 +603,8 @@ public class OracleDialect extends Dialect {
|
||||||
return "to_timestamp_tz(?1,'YYYY-MM-DD HH24:MI:SS.FF9 TZR')";
|
return "to_timestamp_tz(?1,'YYYY-MM-DD HH24:MI:SS.FF9 TZR')";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case XML:
|
||||||
|
return "xmlparse(document ?1)";
|
||||||
}
|
}
|
||||||
return super.castPattern(from, to);
|
return super.castPattern(from, to);
|
||||||
}
|
}
|
||||||
|
@ -988,6 +1004,7 @@ public class OracleDialect extends Dialect {
|
||||||
typeContributions.contributeJdbcType( OracleBooleanJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( OracleBooleanJdbcType.INSTANCE );
|
||||||
}
|
}
|
||||||
typeContributions.contributeJdbcType( OracleXmlJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( OracleXmlJdbcType.INSTANCE );
|
||||||
|
typeContributions.contributeJdbcTypeConstructor( OracleXmlArrayJdbcTypeConstructor.INSTANCE );
|
||||||
if ( OracleJdbcHelper.isUsable( serviceRegistry ) ) {
|
if ( OracleJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
typeContributions.contributeJdbcType( OracleJdbcHelper.getStructJdbcType( serviceRegistry ) );
|
typeContributions.contributeJdbcType( OracleJdbcHelper.getStructJdbcType( serviceRegistry ) );
|
||||||
}
|
}
|
||||||
|
@ -1132,6 +1149,11 @@ public class OracleDialect extends Dialect {
|
||||||
return oracleSequenceSupport;
|
return oracleSequenceSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Exporter<Table> getTableExporter() {
|
||||||
|
return oracleTableExporter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getQuerySequencesString() {
|
public String getQuerySequencesString() {
|
||||||
return "select * from all_sequences";
|
return "select * from all_sequences";
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
|
@ -20,6 +21,11 @@ public class OracleJsonArrayJdbcType extends OracleJsonArrayBlobJdbcType {
|
||||||
super( elementJdbcType );
|
super( elementJdbcType );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDdlTypeCode() {
|
||||||
|
return SqlTypes.JSON;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "OracleJsonJdbcType";
|
return "OracleJsonJdbcType";
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.hibernate.boot.Metadata;
|
import org.hibernate.boot.Metadata;
|
||||||
import org.hibernate.boot.model.naming.Identifier;
|
import org.hibernate.boot.model.naming.Identifier;
|
||||||
import org.hibernate.boot.model.relational.QualifiedName;
|
import org.hibernate.boot.model.relational.QualifiedName;
|
||||||
|
@ -16,18 +14,16 @@ import org.hibernate.tool.schema.internal.StandardUserDefinedTypeExporter;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
|
|
||||||
import static java.sql.Types.BOOLEAN;
|
import static java.sql.Types.BOOLEAN;
|
||||||
import static org.hibernate.type.SqlTypes.BIGINT;
|
|
||||||
import static org.hibernate.type.SqlTypes.BINARY;
|
import static org.hibernate.type.SqlTypes.BINARY;
|
||||||
|
import static org.hibernate.type.SqlTypes.BIT;
|
||||||
|
import static org.hibernate.type.SqlTypes.BLOB;
|
||||||
import static org.hibernate.type.SqlTypes.DATE;
|
import static org.hibernate.type.SqlTypes.DATE;
|
||||||
import static org.hibernate.type.SqlTypes.INTEGER;
|
|
||||||
import static org.hibernate.type.SqlTypes.LONG32VARBINARY;
|
import static org.hibernate.type.SqlTypes.LONG32VARBINARY;
|
||||||
import static org.hibernate.type.SqlTypes.SMALLINT;
|
|
||||||
import static org.hibernate.type.SqlTypes.TABLE;
|
import static org.hibernate.type.SqlTypes.TABLE;
|
||||||
import static org.hibernate.type.SqlTypes.TIME;
|
import static org.hibernate.type.SqlTypes.TIME;
|
||||||
import static org.hibernate.type.SqlTypes.TIMESTAMP;
|
import static org.hibernate.type.SqlTypes.TIMESTAMP;
|
||||||
import static org.hibernate.type.SqlTypes.TIMESTAMP_UTC;
|
import static org.hibernate.type.SqlTypes.TIMESTAMP_UTC;
|
||||||
import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE;
|
import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE;
|
||||||
import static org.hibernate.type.SqlTypes.TINYINT;
|
|
||||||
import static org.hibernate.type.SqlTypes.UUID;
|
import static org.hibernate.type.SqlTypes.UUID;
|
||||||
import static org.hibernate.type.SqlTypes.VARBINARY;
|
import static org.hibernate.type.SqlTypes.VARBINARY;
|
||||||
|
|
||||||
|
@ -61,11 +57,13 @@ public class OracleUserDefinedTypeExporter extends StandardUserDefinedTypeExport
|
||||||
}
|
}
|
||||||
final int arrayLength = userDefinedType.getArrayLength();
|
final int arrayLength = userDefinedType.getArrayLength();
|
||||||
final Integer elementSqlTypeCode = userDefinedType.getElementSqlTypeCode();
|
final Integer elementSqlTypeCode = userDefinedType.getElementSqlTypeCode();
|
||||||
|
final Integer elementDdlTypeCode = userDefinedType.getElementDdlTypeCode();
|
||||||
final String jsonTypeName = metadata.getDatabase().getTypeConfiguration().getDdlTypeRegistry().getTypeName(
|
final String jsonTypeName = metadata.getDatabase().getTypeConfiguration().getDdlTypeRegistry().getTypeName(
|
||||||
SqlTypes.JSON,
|
SqlTypes.JSON,
|
||||||
dialect
|
dialect
|
||||||
);
|
);
|
||||||
final String valueExpression = determineValueExpression( "t.value", elementSqlTypeCode, elementType );
|
final String valueExpression = determineValueExpression( "t.value", elementSqlTypeCode, elementDdlTypeCode, elementType );
|
||||||
|
final String jsonElementType = determineJsonElementType( elementSqlTypeCode, elementDdlTypeCode, elementType );
|
||||||
return new String[] {
|
return new String[] {
|
||||||
"create or replace type " + arrayTypeName + " as varying array(" + arrayLength + ") of " + elementType,
|
"create or replace type " + arrayTypeName + " as varying array(" + arrayLength + ") of " + elementType,
|
||||||
"create or replace function " + arrayTypeName + "_cmp(a in " + arrayTypeName +
|
"create or replace function " + arrayTypeName + "_cmp(a in " + arrayTypeName +
|
||||||
|
@ -266,7 +264,7 @@ public class OracleUserDefinedTypeExporter extends StandardUserDefinedTypeExport
|
||||||
"res " + arrayTypeName + ":=" + arrayTypeName + "(); begin " +
|
"res " + arrayTypeName + ":=" + arrayTypeName + "(); begin " +
|
||||||
"if arr is null then return null; end if; " +
|
"if arr is null then return null; end if; " +
|
||||||
"select " + valueExpression + " bulk collect into res " +
|
"select " + valueExpression + " bulk collect into res " +
|
||||||
"from json_table(arr,'$[*]' columns (value path '$')) t; " +
|
"from json_table(arr,'$[*]' columns (value " + jsonElementType + " path '$')) t; " +
|
||||||
"return res; " +
|
"return res; " +
|
||||||
"end;"
|
"end;"
|
||||||
};
|
};
|
||||||
|
@ -332,17 +330,8 @@ public class OracleUserDefinedTypeExporter extends StandardUserDefinedTypeExport
|
||||||
return dialect.getVersion().isSameOrAfter( 23 );
|
return dialect.getVersion().isSameOrAfter( 23 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private String determineValueExpression(String expression, int elementSqlTypeCode, String elementType) {
|
private String determineValueExpression(String expression, int elementSqlTypeCode, Integer elementDdlTypeCode, String elementType) {
|
||||||
switch ( elementSqlTypeCode ) {
|
switch ( elementSqlTypeCode ) {
|
||||||
case BOOLEAN:
|
|
||||||
if ( elementType.toLowerCase( Locale.ROOT ).trim().startsWith( "number" ) ) {
|
|
||||||
return "decode(" + expression + ",'true',1,'false',0,null)";
|
|
||||||
}
|
|
||||||
case TINYINT:
|
|
||||||
case SMALLINT:
|
|
||||||
case INTEGER:
|
|
||||||
case BIGINT:
|
|
||||||
return "cast(" + expression + " as " + elementType + ")";
|
|
||||||
case DATE:
|
case DATE:
|
||||||
return "to_date(" + expression + ",'YYYY-MM-DD')";
|
return "to_date(" + expression + ",'YYYY-MM-DD')";
|
||||||
case TIME:
|
case TIME:
|
||||||
|
@ -355,14 +344,47 @@ public class OracleUserDefinedTypeExporter extends StandardUserDefinedTypeExport
|
||||||
case BINARY:
|
case BINARY:
|
||||||
case VARBINARY:
|
case VARBINARY:
|
||||||
case LONG32VARBINARY:
|
case LONG32VARBINARY:
|
||||||
return "hextoraw(" + expression + ")";
|
case BLOB:
|
||||||
|
return "xmlcast(xmlcdata(" + expression + ") as " + elementType + ")";
|
||||||
case UUID:
|
case UUID:
|
||||||
return "hextoraw(replace(" + expression + ",'-',''))";
|
return "hextoraw(replace(" + expression + ",'-',''))";
|
||||||
|
case BIT:
|
||||||
|
return "decode(" + expression + ",'true',1,'false',0,null)";
|
||||||
|
case BOOLEAN:
|
||||||
|
if ( SqlTypes.isNumericType( elementDdlTypeCode ) ) {
|
||||||
|
return "decode(" + expression + ",'true',1,'false',0,null)";
|
||||||
|
}
|
||||||
|
// Fall-through intended
|
||||||
default:
|
default:
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String determineJsonElementType(Integer elementSqlTypeCode, Integer elementDdlTypeCode, String elementType) {
|
||||||
|
switch ( elementSqlTypeCode ) {
|
||||||
|
case BINARY:
|
||||||
|
case VARBINARY:
|
||||||
|
case LONG32VARBINARY:
|
||||||
|
case BLOB:
|
||||||
|
return "clob";
|
||||||
|
case BOOLEAN:
|
||||||
|
if ( !SqlTypes.isNumericType( elementDdlTypeCode ) ) {
|
||||||
|
return elementType;
|
||||||
|
}
|
||||||
|
// Fall-through intended
|
||||||
|
case BIT:
|
||||||
|
case DATE:
|
||||||
|
case TIME:
|
||||||
|
case TIMESTAMP:
|
||||||
|
case TIMESTAMP_WITH_TIMEZONE:
|
||||||
|
case TIMESTAMP_UTC:
|
||||||
|
case UUID:
|
||||||
|
return "varchar2(4000)";
|
||||||
|
default:
|
||||||
|
return elementType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected String createOrReplaceConcatFunction(String arrayTypeName) {
|
protected String createOrReplaceConcatFunction(String arrayTypeName) {
|
||||||
// Since Oracle has no builtin concat function for varrays and doesn't support varargs,
|
// Since Oracle has no builtin concat function for varrays and doesn't support varargs,
|
||||||
// we have to create a function with a fixed amount of arguments with default that fits "most" cases.
|
// we have to create a function with a fixed amount of arguments with default that fits "most" cases.
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.XmlArrayJdbcType;
|
||||||
|
|
||||||
|
import java.sql.CallableStatement;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public class OracleXmlArrayJdbcType extends XmlArrayJdbcType {
|
||||||
|
|
||||||
|
public OracleXmlArrayJdbcType(JdbcType elementJdbcType) {
|
||||||
|
super( elementJdbcType );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||||
|
// Seems the Oracle JDBC driver doesn't support `setNull(index, Types.SQLXML)`
|
||||||
|
// but it seems that the following works fine
|
||||||
|
return new XmlArrayBinder<>( javaType, this ) {
|
||||||
|
@Override
|
||||||
|
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {
|
||||||
|
st.setNull( index, Types.VARCHAR );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException {
|
||||||
|
st.setNull( name, Types.VARCHAR );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
|
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
|
import org.hibernate.type.SqlTypes;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for {@link OracleXmlArrayJdbcType}.
|
||||||
|
*/
|
||||||
|
public class OracleXmlArrayJdbcTypeConstructor implements JdbcTypeConstructor {
|
||||||
|
|
||||||
|
public static final OracleXmlArrayJdbcTypeConstructor INSTANCE = new OracleXmlArrayJdbcTypeConstructor();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcType resolveType(
|
||||||
|
TypeConfiguration typeConfiguration,
|
||||||
|
Dialect dialect,
|
||||||
|
BasicType<?> elementType,
|
||||||
|
ColumnTypeInformation columnTypeInformation) {
|
||||||
|
return resolveType( typeConfiguration, dialect, elementType.getJdbcType(), columnTypeInformation );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcType resolveType(
|
||||||
|
TypeConfiguration typeConfiguration,
|
||||||
|
Dialect dialect,
|
||||||
|
JdbcType elementType,
|
||||||
|
ColumnTypeInformation columnTypeInformation) {
|
||||||
|
return new OracleXmlArrayJdbcType( elementType );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDefaultSqlTypeCode() {
|
||||||
|
return SqlTypes.XML_ARRAY;
|
||||||
|
}
|
||||||
|
}
|
|
@ -91,6 +91,14 @@ public class XmlHelper {
|
||||||
sb.append( '&' );
|
sb.append( '&' );
|
||||||
i += 4;
|
i += 4;
|
||||||
}
|
}
|
||||||
|
else if ( i + 5 < end
|
||||||
|
&& string.charAt( i + 2 ) == 'p'
|
||||||
|
&& string.charAt( i + 3 ) == 'o'
|
||||||
|
&& string.charAt( i + 4 ) == 's'
|
||||||
|
&& string.charAt( i + 5 ) == ';' ) {
|
||||||
|
sb.append( '\'' );
|
||||||
|
i += 5;
|
||||||
|
}
|
||||||
break OUTER;
|
break OUTER;
|
||||||
case 'g':
|
case 'g':
|
||||||
if ( string.charAt( i + 2 ) == 't' && string.charAt( i + 3 ) == ';' ) {
|
if ( string.charAt( i + 2 ) == 't' && string.charAt( i + 3 ) == ';' ) {
|
||||||
|
@ -274,7 +282,14 @@ public class XmlHelper {
|
||||||
if ( NULL_TAG.equals( string ) ) {
|
if ( NULL_TAG.equals( string ) ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ( !string.startsWith( START_TAG ) || !string.endsWith( END_TAG ) ) {
|
int contentEnd = string.length() - 1;
|
||||||
|
while ( contentEnd >= 0 ) {
|
||||||
|
if ( !Character.isWhitespace( string.charAt( contentEnd ) ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
contentEnd--;
|
||||||
|
}
|
||||||
|
if ( !string.startsWith( START_TAG ) || !string.regionMatches( contentEnd - END_TAG.length()+ 1, END_TAG, 0, END_TAG.length() ) ) {
|
||||||
throw new IllegalArgumentException( "XML not properly formatted: " + string );
|
throw new IllegalArgumentException( "XML not properly formatted: " + string );
|
||||||
}
|
}
|
||||||
int end;
|
int end;
|
||||||
|
@ -289,7 +304,7 @@ public class XmlHelper {
|
||||||
array = new Object[embeddableMappingType.getJdbcValueCount() + ( embeddableMappingType.isPolymorphic() ? 1 : 0 )];
|
array = new Object[embeddableMappingType.getJdbcValueCount() + ( embeddableMappingType.isPolymorphic() ? 1 : 0 )];
|
||||||
end = fromString( embeddableMappingType, string, returnEmbeddable, options, array, START_TAG.length() );
|
end = fromString( embeddableMappingType, string, returnEmbeddable, options, array, START_TAG.length() );
|
||||||
}
|
}
|
||||||
assert end + END_TAG.length() == string.length();
|
assert end + END_TAG.length() == contentEnd + 1;
|
||||||
|
|
||||||
if ( returnEmbeddable ) {
|
if ( returnEmbeddable ) {
|
||||||
final StructAttributeValues attributeValues = StructHelper.getAttributeValues( embeddableMappingType, array, options );
|
final StructAttributeValues attributeValues = StructHelper.getAttributeValues( embeddableMappingType, array, options );
|
||||||
|
|
|
@ -13,9 +13,14 @@ import org.hibernate.mapping.AggregateColumn;
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||||
import org.hibernate.metamodel.mapping.SqlTypedMapping;
|
import org.hibernate.metamodel.mapping.SqlTypedMapping;
|
||||||
import org.hibernate.type.SqlTypes;
|
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import static org.hibernate.type.SqlTypes.ARRAY;
|
||||||
|
import static org.hibernate.type.SqlTypes.JSON;
|
||||||
|
import static org.hibernate.type.SqlTypes.JSON_ARRAY;
|
||||||
|
import static org.hibernate.type.SqlTypes.SQLXML;
|
||||||
|
import static org.hibernate.type.SqlTypes.XML_ARRAY;
|
||||||
|
|
||||||
public class AggregateSupportImpl implements AggregateSupport {
|
public class AggregateSupportImpl implements AggregateSupport {
|
||||||
|
|
||||||
public static final AggregateSupport INSTANCE = new AggregateSupportImpl();
|
public static final AggregateSupport INSTANCE = new AggregateSupportImpl();
|
||||||
|
@ -85,7 +90,8 @@ public class AggregateSupportImpl implements AggregateSupport {
|
||||||
@Override
|
@Override
|
||||||
public int aggregateComponentSqlTypeCode(int aggregateColumnSqlTypeCode, int columnSqlTypeCode) {
|
public int aggregateComponentSqlTypeCode(int aggregateColumnSqlTypeCode, int columnSqlTypeCode) {
|
||||||
return switch (aggregateColumnSqlTypeCode) {
|
return switch (aggregateColumnSqlTypeCode) {
|
||||||
case SqlTypes.JSON -> columnSqlTypeCode == SqlTypes.ARRAY ? SqlTypes.JSON_ARRAY : columnSqlTypeCode;
|
case JSON -> columnSqlTypeCode == ARRAY ? JSON_ARRAY : columnSqlTypeCode;
|
||||||
|
case SQLXML -> columnSqlTypeCode == ARRAY ? XML_ARRAY : columnSqlTypeCode;
|
||||||
default -> columnSqlTypeCode;
|
default -> columnSqlTypeCode;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,7 +308,7 @@ public class DB2AggregateSupport extends AggregateSupportImpl {
|
||||||
// We need to know what array this is STRUCT_ARRAY/JSON_ARRAY/XML_ARRAY,
|
// We need to know what array this is STRUCT_ARRAY/JSON_ARRAY/XML_ARRAY,
|
||||||
// which we can easily get from the type code of the aggregate column
|
// which we can easily get from the type code of the aggregate column
|
||||||
final int sqlTypeCode = aggregateColumn.getType().getJdbcType().getDefaultSqlTypeCode();
|
final int sqlTypeCode = aggregateColumn.getType().getJdbcType().getDefaultSqlTypeCode();
|
||||||
switch ( sqlTypeCode == SqlTypes.ARRAY ? aggregateColumn.getTypeCode() : sqlTypeCode ) {
|
switch ( sqlTypeCode == ARRAY ? aggregateColumn.getTypeCode() : sqlTypeCode ) {
|
||||||
case JSON:
|
case JSON:
|
||||||
case JSON_ARRAY:
|
case JSON_ARRAY:
|
||||||
if ( jsonSupport ) {
|
if ( jsonSupport ) {
|
||||||
|
@ -350,19 +350,13 @@ public class DB2AggregateSupport extends AggregateSupportImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int aggregateComponentSqlTypeCode(int aggregateColumnSqlTypeCode, int columnSqlTypeCode) {
|
public int aggregateComponentSqlTypeCode(int aggregateColumnSqlTypeCode, int columnSqlTypeCode) {
|
||||||
if ( aggregateColumnSqlTypeCode == STRUCT ) {
|
return switch (aggregateColumnSqlTypeCode) {
|
||||||
// DB2 doesn't support booleans in structs
|
// DB2 doesn't support booleans in structs
|
||||||
return columnSqlTypeCode == BOOLEAN ? SMALLINT : columnSqlTypeCode;
|
case STRUCT -> columnSqlTypeCode == BOOLEAN ? SMALLINT : columnSqlTypeCode;
|
||||||
}
|
case JSON -> columnSqlTypeCode == ARRAY ? JSON_ARRAY : columnSqlTypeCode;
|
||||||
else if ( aggregateColumnSqlTypeCode == JSON ) {
|
case SQLXML -> columnSqlTypeCode == ARRAY ? XML_ARRAY : columnSqlTypeCode;
|
||||||
return columnSqlTypeCode == ARRAY ? JSON_ARRAY : columnSqlTypeCode;
|
default -> columnSqlTypeCode;
|
||||||
}
|
};
|
||||||
else if ( aggregateColumnSqlTypeCode == SQLXML ) {
|
|
||||||
return columnSqlTypeCode == ARRAY ? XML_ARRAY : columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,7 +27,6 @@ import java.util.Map;
|
||||||
|
|
||||||
import static org.hibernate.dialect.function.json.HANAJsonValueFunction.jsonValueReturningType;
|
import static org.hibernate.dialect.function.json.HANAJsonValueFunction.jsonValueReturningType;
|
||||||
import static org.hibernate.dialect.function.xml.HANAXmlTableFunction.xmlValueReturningType;
|
import static org.hibernate.dialect.function.xml.HANAXmlTableFunction.xmlValueReturningType;
|
||||||
import static org.hibernate.type.SqlTypes.ARRAY;
|
|
||||||
import static org.hibernate.type.SqlTypes.BIGINT;
|
import static org.hibernate.type.SqlTypes.BIGINT;
|
||||||
import static org.hibernate.type.SqlTypes.BINARY;
|
import static org.hibernate.type.SqlTypes.BINARY;
|
||||||
import static org.hibernate.type.SqlTypes.BLOB;
|
import static org.hibernate.type.SqlTypes.BLOB;
|
||||||
|
@ -284,19 +283,6 @@ public class HANAAggregateSupport extends AggregateSupportImpl {
|
||||||
throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateColumn.getTypeCode() );
|
throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateColumn.getTypeCode() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int aggregateComponentSqlTypeCode(int aggregateColumnSqlTypeCode, int columnSqlTypeCode) {
|
|
||||||
if ( aggregateColumnSqlTypeCode == JSON ) {
|
|
||||||
return columnSqlTypeCode == ARRAY ? JSON_ARRAY : columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
if ( aggregateColumnSqlTypeCode == SQLXML ) {
|
|
||||||
return columnSqlTypeCode == ARRAY ? XML_ARRAY : columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) {
|
public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) {
|
||||||
return aggregateSqlTypeCode == JSON || aggregateSqlTypeCode == SQLXML;
|
return aggregateSqlTypeCode == JSON || aggregateSqlTypeCode == SQLXML;
|
||||||
|
|
|
@ -4,17 +4,13 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect.aggregate;
|
package org.hibernate.dialect.aggregate;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.hibernate.boot.model.naming.Identifier;
|
import org.hibernate.boot.model.naming.Identifier;
|
||||||
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
||||||
import org.hibernate.boot.model.relational.Namespace;
|
import org.hibernate.boot.model.relational.Namespace;
|
||||||
import org.hibernate.dialect.DatabaseVersion;
|
import org.hibernate.dialect.DatabaseVersion;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.OracleArrayJdbcType;
|
import org.hibernate.dialect.OracleArrayJdbcType;
|
||||||
|
import org.hibernate.dialect.XmlHelper;
|
||||||
import org.hibernate.engine.jdbc.Size;
|
import org.hibernate.engine.jdbc.Size;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.mapping.AggregateColumn;
|
import org.hibernate.mapping.AggregateColumn;
|
||||||
|
@ -27,45 +23,29 @@ import org.hibernate.metamodel.mapping.SelectablePath;
|
||||||
import org.hibernate.metamodel.mapping.SqlTypedMapping;
|
import org.hibernate.metamodel.mapping.SqlTypedMapping;
|
||||||
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||||
import org.hibernate.type.BasicPluralType;
|
import org.hibernate.type.BasicPluralType;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.StructJdbcType;
|
import org.hibernate.type.descriptor.jdbc.StructJdbcType;
|
||||||
import org.hibernate.type.descriptor.sql.DdlType;
|
import org.hibernate.type.descriptor.sql.DdlType;
|
||||||
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
|
||||||
|
import org.hibernate.type.internal.TypeConfigurationWrapperOptions;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import static org.hibernate.type.SqlTypes.ARRAY;
|
import java.util.LinkedHashMap;
|
||||||
import static org.hibernate.type.SqlTypes.BIGINT;
|
import java.util.List;
|
||||||
import static org.hibernate.type.SqlTypes.BINARY;
|
import java.util.Locale;
|
||||||
import static org.hibernate.type.SqlTypes.BIT;
|
import java.util.Map;
|
||||||
import static org.hibernate.type.SqlTypes.BLOB;
|
|
||||||
import static org.hibernate.type.SqlTypes.BOOLEAN;
|
import static org.hibernate.type.SqlTypes.*;
|
||||||
import static org.hibernate.type.SqlTypes.CLOB;
|
|
||||||
import static org.hibernate.type.SqlTypes.DATE;
|
|
||||||
import static org.hibernate.type.SqlTypes.INTEGER;
|
|
||||||
import static org.hibernate.type.SqlTypes.JSON;
|
|
||||||
import static org.hibernate.type.SqlTypes.JSON_ARRAY;
|
|
||||||
import static org.hibernate.type.SqlTypes.LONG32VARBINARY;
|
|
||||||
import static org.hibernate.type.SqlTypes.NCLOB;
|
|
||||||
import static org.hibernate.type.SqlTypes.SMALLINT;
|
|
||||||
import static org.hibernate.type.SqlTypes.STRUCT;
|
|
||||||
import static org.hibernate.type.SqlTypes.STRUCT_ARRAY;
|
|
||||||
import static org.hibernate.type.SqlTypes.STRUCT_TABLE;
|
|
||||||
import static org.hibernate.type.SqlTypes.TABLE;
|
|
||||||
import static org.hibernate.type.SqlTypes.TIME;
|
|
||||||
import static org.hibernate.type.SqlTypes.TIMESTAMP;
|
|
||||||
import static org.hibernate.type.SqlTypes.TIMESTAMP_UTC;
|
|
||||||
import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE;
|
|
||||||
import static org.hibernate.type.SqlTypes.TINYINT;
|
|
||||||
import static org.hibernate.type.SqlTypes.UUID;
|
|
||||||
import static org.hibernate.type.SqlTypes.VARBINARY;
|
|
||||||
|
|
||||||
public class OracleAggregateSupport extends AggregateSupportImpl {
|
public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
|
|
||||||
|
@ -79,6 +59,12 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
private static final String JSON_QUERY_START = "json_query(";
|
private static final String JSON_QUERY_START = "json_query(";
|
||||||
private static final String JSON_QUERY_JSON_END = "' returning json)";
|
private static final String JSON_QUERY_JSON_END = "' returning json)";
|
||||||
private static final String JSON_QUERY_BLOB_END = "' returning blob)";
|
private static final String JSON_QUERY_BLOB_END = "' returning blob)";
|
||||||
|
private static final String XML_EXTRACT_START = "xmlelement(\"" + XmlHelper.ROOT_TAG + "\",xmlquery(";
|
||||||
|
private static final String XML_EXTRACT_SEPARATOR = "/*' passing ";
|
||||||
|
private static final String XML_EXTRACT_END = " returning content))";
|
||||||
|
private static final String XML_QUERY_START = "xmlquery(";
|
||||||
|
private static final String XML_QUERY_SEPARATOR = "' passing ";
|
||||||
|
private static final String XML_QUERY_END = " returning content)";
|
||||||
|
|
||||||
private final boolean checkConstraintSupport;
|
private final boolean checkConstraintSupport;
|
||||||
private final JsonSupport jsonSupport;
|
private final JsonSupport jsonSupport;
|
||||||
|
@ -141,22 +127,24 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
}
|
}
|
||||||
switch ( column.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode() ) {
|
switch ( column.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode() ) {
|
||||||
case BIT:
|
case BIT:
|
||||||
|
case BOOLEAN:
|
||||||
|
//noinspection unchecked
|
||||||
|
final JdbcLiteralFormatter<Boolean> jdbcLiteralFormatter = (JdbcLiteralFormatter<Boolean>) column.getJdbcMapping().getJdbcType()
|
||||||
|
.getJdbcLiteralFormatter( column.getJdbcMapping().getMappedJavaType() );
|
||||||
|
final Dialect dialect = typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect();
|
||||||
|
final WrapperOptions wrapperOptions = new TypeConfigurationWrapperOptions( typeConfiguration );
|
||||||
|
final String trueLiteral = jdbcLiteralFormatter.toJdbcLiteral( true, dialect, wrapperOptions );
|
||||||
|
final String falseLiteral = jdbcLiteralFormatter.toJdbcLiteral( false, dialect, wrapperOptions );
|
||||||
return template.replace(
|
return template.replace(
|
||||||
placeholder,
|
placeholder,
|
||||||
"decode(json_value(" + parentPartExpression + columnExpression + "'),'true',1,'false',0,null)"
|
"decode(json_value(" + parentPartExpression + columnExpression + "'),'true'," + trueLiteral + ",'false'," + falseLiteral + ",null)"
|
||||||
);
|
);
|
||||||
case BOOLEAN:
|
|
||||||
if ( column.getColumnDefinition().toLowerCase( Locale.ROOT ).trim().startsWith( "number" ) ) {
|
|
||||||
return template.replace(
|
|
||||||
placeholder,
|
|
||||||
"decode(json_value(" + parentPartExpression + columnExpression + "'),'true',1,'false',0,null)"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Fall-through intended
|
|
||||||
case TINYINT:
|
case TINYINT:
|
||||||
case SMALLINT:
|
case SMALLINT:
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
case BIGINT:
|
case BIGINT:
|
||||||
|
case CLOB:
|
||||||
|
case NCLOB:
|
||||||
return template.replace(
|
return template.replace(
|
||||||
placeholder,
|
placeholder,
|
||||||
"json_value(" + parentPartExpression + columnExpression + "' returning " + column.getColumnDefinition() + ')'
|
"json_value(" + parentPartExpression + columnExpression + "' returning " + column.getColumnDefinition() + ')'
|
||||||
|
@ -182,26 +170,29 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
placeholder,
|
placeholder,
|
||||||
"to_timestamp_tz(json_value(" + parentPartExpression + columnExpression + "'),'YYYY-MM-DD\"T\"hh24:mi:ss.FF9TZH:TZM')"
|
"to_timestamp_tz(json_value(" + parentPartExpression + columnExpression + "'),'YYYY-MM-DD\"T\"hh24:mi:ss.FF9TZH:TZM')"
|
||||||
);
|
);
|
||||||
case BINARY:
|
|
||||||
case VARBINARY:
|
|
||||||
case LONG32VARBINARY:
|
|
||||||
// We encode binary data as hex, so we have to decode here
|
|
||||||
return template.replace(
|
|
||||||
placeholder,
|
|
||||||
"hextoraw(json_value(" + parentPartExpression + columnExpression + "'))"
|
|
||||||
);
|
|
||||||
case UUID:
|
case UUID:
|
||||||
return template.replace(
|
return template.replace(
|
||||||
placeholder,
|
placeholder,
|
||||||
"hextoraw(replace(json_value(" + parentPartExpression + columnExpression + "'),'-',''))"
|
"hextoraw(replace(json_value(" + parentPartExpression + columnExpression + "'),'-',''))"
|
||||||
);
|
);
|
||||||
case CLOB:
|
case BINARY:
|
||||||
case NCLOB:
|
case VARBINARY:
|
||||||
|
case LONG32VARBINARY:
|
||||||
|
// We encode binary data as hex, so we have to decode here
|
||||||
|
if ( determineLength( column ) * 2 < 4000L ) {
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"hextoraw(json_value(" + parentPartExpression + columnExpression + "'))"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Fall-through intended
|
||||||
case BLOB:
|
case BLOB:
|
||||||
// We encode binary data as hex, so we have to decode here
|
// We encode binary data as hex, so we have to decode here
|
||||||
return template.replace(
|
return template.replace(
|
||||||
placeholder,
|
placeholder,
|
||||||
"(select * from json_table(" + aggregateParentReadExpression + ",'$' columns (" + columnExpression + " " + column.getColumnDefinition() + " path '$." + columnExpression + "')))"
|
// returning binary data is not yet implemented in the json functions,
|
||||||
|
// so use the xml implementation
|
||||||
|
"xmlcast(xmlcdata(json_value(" + parentPartExpression + columnExpression + "' returning clob))) as " + column.getColumnDefinition() + ')'
|
||||||
);
|
);
|
||||||
case ARRAY:
|
case ARRAY:
|
||||||
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) column.getJdbcMapping();
|
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) column.getJdbcMapping();
|
||||||
|
@ -242,6 +233,83 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
case NONE:
|
case NONE:
|
||||||
throw new UnsupportedOperationException( "The Oracle version doesn't support JSON aggregates!" );
|
throw new UnsupportedOperationException( "The Oracle version doesn't support JSON aggregates!" );
|
||||||
}
|
}
|
||||||
|
case SQLXML:
|
||||||
|
case XML_ARRAY:
|
||||||
|
switch ( column.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode() ) {
|
||||||
|
case BIT:
|
||||||
|
case BOOLEAN:
|
||||||
|
//noinspection unchecked
|
||||||
|
final JdbcLiteralFormatter<Boolean> jdbcLiteralFormatter = (JdbcLiteralFormatter<Boolean>) column.getJdbcMapping().getJdbcType()
|
||||||
|
.getJdbcLiteralFormatter( column.getJdbcMapping().getMappedJavaType() );
|
||||||
|
final Dialect dialect = typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect();
|
||||||
|
final WrapperOptions wrapperOptions = new TypeConfigurationWrapperOptions( typeConfiguration );
|
||||||
|
final String trueLiteral = jdbcLiteralFormatter.toJdbcLiteral( true, dialect, wrapperOptions );
|
||||||
|
final String falseLiteral = jdbcLiteralFormatter.toJdbcLiteral( false, dialect, wrapperOptions );
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"decode(xmlcast(xmlquery(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/text()" ) + ") as varchar(5)),'true'," + trueLiteral + ",'false'," + falseLiteral + ",null)"
|
||||||
|
);
|
||||||
|
case FLOAT:
|
||||||
|
case REAL:
|
||||||
|
case DOUBLE:
|
||||||
|
// Since cast is the only way to do optional exponential form parsing, we have to use that.
|
||||||
|
// Unfortunately, the parsing is nationalized, so we need to replace the standard decimal separator dot with the nationalized one first
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"cast(replace(xmlcast(xmlquery(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/text()" ) + ") as varchar2(255)),'.',substr(to_char(0.1),1,1)) as " + column.getColumnDefinition() + ")"
|
||||||
|
);
|
||||||
|
case DATE:
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"to_date(xmlcast(xmlquery(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/text()" ) + ") as varchar(35)),'YYYY-MM-DD')"
|
||||||
|
);
|
||||||
|
case TIME:
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"to_timestamp(xmlcast(xmlquery(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/text()" ) + ") as varchar(35)),'hh24:mi:ss')"
|
||||||
|
);
|
||||||
|
case TIMESTAMP:
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"to_timestamp(xmlcast(xmlquery(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/text()" ) + ") as varchar(35)),'YYYY-MM-DD\"T\"hh24:mi:ss.FF9')"
|
||||||
|
);
|
||||||
|
case TIMESTAMP_WITH_TIMEZONE:
|
||||||
|
case TIMESTAMP_UTC:
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"to_timestamp_tz(xmlcast(xmlquery(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/text()" ) + ") as varchar(35)),'YYYY-MM-DD\"T\"hh24:mi:ss.FF9TZH:TZM')"
|
||||||
|
);
|
||||||
|
case ARRAY:
|
||||||
|
throw new UnsupportedOperationException( "Transforming XML_ARRAY to native arrays is not supported on Oracle!" );
|
||||||
|
case SQLXML:
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
XML_EXTRACT_START + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/*" ) + "))"
|
||||||
|
);
|
||||||
|
case XML_ARRAY:
|
||||||
|
if ( typeConfiguration.getCurrentBaseSqlTypeIndicators().isXmlFormatMapperLegacyFormatEnabled() ) {
|
||||||
|
throw new IllegalArgumentException( "XML array '" + columnExpression + "' in '" + aggregateParentReadExpression + "' is not supported with legacy format enabled." );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"xmlelement(\"Collection\",xmlquery(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/*" ) + "))"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case UUID:
|
||||||
|
if ( SqlTypes.isBinaryType( column.getJdbcMapping().getJdbcType().getDdlTypeCode() ) ) {
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"hextoraw(replace(xmlcast(xmlquery(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/text()" ) + ") as varchar(36)),'-',''))"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Fall-through intended
|
||||||
|
default:
|
||||||
|
return template.replace(
|
||||||
|
placeholder,
|
||||||
|
"xmlcast(xmlquery(" + xmlExtractArguments( aggregateParentReadExpression, columnExpression + "/text()" ) + ") as " + column.getColumnDefinition() + ")"
|
||||||
|
);
|
||||||
|
}
|
||||||
case STRUCT:
|
case STRUCT:
|
||||||
case STRUCT_ARRAY:
|
case STRUCT_ARRAY:
|
||||||
case STRUCT_TABLE:
|
case STRUCT_TABLE:
|
||||||
|
@ -250,6 +318,58 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateColumnTypeCode );
|
throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateColumnTypeCode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String xmlExtractArguments(String aggregateParentReadExpression, String xpathFragment) {
|
||||||
|
final String extractArguments;
|
||||||
|
int separatorIndex;
|
||||||
|
if ( aggregateParentReadExpression.startsWith( XML_EXTRACT_START )
|
||||||
|
&& aggregateParentReadExpression.endsWith( XML_EXTRACT_END )
|
||||||
|
&& (separatorIndex = aggregateParentReadExpression.indexOf( XML_EXTRACT_SEPARATOR )) != -1 ) {
|
||||||
|
final StringBuilder sb = new StringBuilder( aggregateParentReadExpression.length() - XML_EXTRACT_START.length() + xpathFragment.length() );
|
||||||
|
sb.append( aggregateParentReadExpression, XML_EXTRACT_START.length(), separatorIndex );
|
||||||
|
sb.append( '/' );
|
||||||
|
sb.append( xpathFragment );
|
||||||
|
sb.append( aggregateParentReadExpression, separatorIndex + 2, aggregateParentReadExpression.length() - 2 );
|
||||||
|
extractArguments = sb.toString();
|
||||||
|
}
|
||||||
|
else if ( aggregateParentReadExpression.startsWith( XML_QUERY_START )
|
||||||
|
&& aggregateParentReadExpression.endsWith( XML_QUERY_END )
|
||||||
|
&& (separatorIndex = aggregateParentReadExpression.indexOf( XML_QUERY_SEPARATOR )) != -1 ) {
|
||||||
|
final StringBuilder sb = new StringBuilder( aggregateParentReadExpression.length() - XML_QUERY_START.length() + xpathFragment.length() );
|
||||||
|
sb.append( aggregateParentReadExpression, XML_QUERY_START.length(), separatorIndex );
|
||||||
|
sb.append( '/' );
|
||||||
|
sb.append( xpathFragment );
|
||||||
|
sb.append( aggregateParentReadExpression, separatorIndex, aggregateParentReadExpression.length() - 1 );
|
||||||
|
extractArguments = sb.toString();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
extractArguments = "'/" + XmlHelper.ROOT_TAG + "/" + xpathFragment + "' passing " + aggregateParentReadExpression + " returning content";
|
||||||
|
}
|
||||||
|
return extractArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long determineLength(SqlTypedMapping column) {
|
||||||
|
final Long length = column.getLength();
|
||||||
|
if ( length != null ) {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final String columnDefinition = column.getColumnDefinition();
|
||||||
|
assert columnDefinition != null;
|
||||||
|
final int parenthesisIndex = columnDefinition.indexOf( '(' );
|
||||||
|
if ( parenthesisIndex != -1 ) {
|
||||||
|
int end;
|
||||||
|
for ( end = parenthesisIndex + 1; end < columnDefinition.length(); end++ ) {
|
||||||
|
if ( !Character.isDigit( columnDefinition.charAt( end ) ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Long.parseLong( columnDefinition.substring( parenthesisIndex + 1, end ) );
|
||||||
|
}
|
||||||
|
// Default to the max varchar length
|
||||||
|
return 4000L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String aggregateComponentAssignmentExpression(
|
public String aggregateComponentAssignmentExpression(
|
||||||
String aggregateParentAssignmentExpression,
|
String aggregateParentAssignmentExpression,
|
||||||
|
@ -259,7 +379,9 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
switch ( aggregateColumnTypeCode ) {
|
switch ( aggregateColumnTypeCode ) {
|
||||||
case JSON:
|
case JSON:
|
||||||
case JSON_ARRAY:
|
case JSON_ARRAY:
|
||||||
// For JSON we always have to replace the whole object
|
case SQLXML:
|
||||||
|
case XML_ARRAY:
|
||||||
|
// For JSON/XML we always have to replace the whole object
|
||||||
return aggregateParentAssignmentExpression;
|
return aggregateParentAssignmentExpression;
|
||||||
case STRUCT:
|
case STRUCT:
|
||||||
case STRUCT_ARRAY:
|
case STRUCT_ARRAY:
|
||||||
|
@ -307,10 +429,14 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
case BIT:
|
case BIT:
|
||||||
return "decode(" + customWriteExpression + ",1,'true',0,'false',null)";
|
return "decode(" + customWriteExpression + ",1,'true',0,'false',null)";
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
final String sqlTypeName = AbstractSqlAstTranslator.getSqlTypeName( column, typeConfiguration );
|
//noinspection unchecked
|
||||||
if ( sqlTypeName.toLowerCase( Locale.ROOT ).trim().startsWith( "number" ) ) {
|
final JdbcLiteralFormatter<Boolean> jdbcLiteralFormatter = (JdbcLiteralFormatter<Boolean>) jdbcMapping.getJdbcType()
|
||||||
return "decode(" + customWriteExpression + ",1,'true',0,'false',null)";
|
.getJdbcLiteralFormatter( jdbcMapping.getMappedJavaType() );
|
||||||
}
|
final Dialect dialect = typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect();
|
||||||
|
final WrapperOptions wrapperOptions = new TypeConfigurationWrapperOptions( typeConfiguration );
|
||||||
|
final String trueLiteral = jdbcLiteralFormatter.toJdbcLiteral( true, dialect, wrapperOptions );
|
||||||
|
final String falseLiteral = jdbcLiteralFormatter.toJdbcLiteral( false, dialect, wrapperOptions );
|
||||||
|
return "decode(" + customWriteExpression + "," + trueLiteral + ",'true'," + falseLiteral + ",'false')";
|
||||||
// Fall-through intended
|
// Fall-through intended
|
||||||
default:
|
default:
|
||||||
return customWriteExpression;
|
return customWriteExpression;
|
||||||
|
@ -319,6 +445,34 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
throw new IllegalStateException( "JSON not supported!" );
|
throw new IllegalStateException( "JSON not supported!" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String xmlCustomWriteExpression(String customWriteExpression, JdbcMapping jdbcMapping, TypeConfiguration typeConfiguration) {
|
||||||
|
final int sqlTypeCode = jdbcMapping.getJdbcType().getDefaultSqlTypeCode();
|
||||||
|
switch ( sqlTypeCode ) {
|
||||||
|
case UUID:
|
||||||
|
return "regexp_replace(lower(rawtohex(" + customWriteExpression + ")),'^(.{8})(.{4})(.{4})(.{4})(.{12})$','\\1-\\2-\\3-\\4-\\5')";
|
||||||
|
// case ARRAY:
|
||||||
|
// case XML_ARRAY:
|
||||||
|
// return "(" + customWriteExpression + ") format json";
|
||||||
|
case BOOLEAN:
|
||||||
|
//noinspection unchecked
|
||||||
|
final JdbcLiteralFormatter<Boolean> jdbcLiteralFormatter = (JdbcLiteralFormatter<Boolean>) jdbcMapping.getJdbcType()
|
||||||
|
.getJdbcLiteralFormatter( jdbcMapping.getMappedJavaType() );
|
||||||
|
final Dialect dialect = typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect();
|
||||||
|
final WrapperOptions wrapperOptions = new TypeConfigurationWrapperOptions( typeConfiguration );
|
||||||
|
final String trueLiteral = jdbcLiteralFormatter.toJdbcLiteral( true, dialect, wrapperOptions );
|
||||||
|
final String falseLiteral = jdbcLiteralFormatter.toJdbcLiteral( false, dialect, wrapperOptions );
|
||||||
|
return "decode(" + customWriteExpression + "," + trueLiteral + ",'true'," + falseLiteral + ",'false')";
|
||||||
|
// case TIME:
|
||||||
|
// return "varchar_format(timestamp('1970-01-01'," + customWriteExpression + "),'HH24:MI:SS')";
|
||||||
|
// case TIMESTAMP:
|
||||||
|
// return "replace(varchar_format(" + customWriteExpression + ",'YYYY-MM-DD HH24:MI:SS.FF9'),' ','T')";
|
||||||
|
// case TIMESTAMP_UTC:
|
||||||
|
// return "replace(varchar_format(" + customWriteExpression + ",'YYYY-MM-DD HH24:MI:SS.FF9'),' ','T')||'Z'";
|
||||||
|
default:
|
||||||
|
return customWriteExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static String determineElementTypeName(
|
private static String determineElementTypeName(
|
||||||
Size castTargetSize,
|
Size castTargetSize,
|
||||||
BasicPluralType<?, ?> pluralType,
|
BasicPluralType<?, ?> pluralType,
|
||||||
|
@ -337,7 +491,7 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) {
|
public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) {
|
||||||
return aggregateSqlTypeCode == JSON;
|
return aggregateSqlTypeCode == JSON || aggregateSqlTypeCode == SQLXML;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -348,7 +502,9 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
final int aggregateSqlTypeCode = aggregateColumn.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode();
|
final int aggregateSqlTypeCode = aggregateColumn.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode();
|
||||||
switch ( aggregateSqlTypeCode ) {
|
switch ( aggregateSqlTypeCode ) {
|
||||||
case JSON:
|
case JSON:
|
||||||
return jsonAggregateColumnWriter( aggregateColumn, columnsToUpdate, typeConfiguration );
|
return new RootJsonWriteExpression( aggregateColumn, columnsToUpdate, this, typeConfiguration );
|
||||||
|
case SQLXML:
|
||||||
|
return new RootXmlWriteExpression( aggregateColumn, columnsToUpdate, typeConfiguration );
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateSqlTypeCode );
|
throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateSqlTypeCode );
|
||||||
}
|
}
|
||||||
|
@ -381,6 +537,7 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
}
|
}
|
||||||
arrayType.setElementTypeName( elementJdbcType.getStructTypeName() );
|
arrayType.setElementTypeName( elementJdbcType.getStructTypeName() );
|
||||||
arrayType.setElementSqlTypeCode( elementJdbcType.getDefaultSqlTypeCode() );
|
arrayType.setElementSqlTypeCode( elementJdbcType.getDefaultSqlTypeCode() );
|
||||||
|
arrayType.setElementDdlTypeCode( elementJdbcType.getDdlTypeCode() );
|
||||||
}
|
}
|
||||||
return super.aggregateAuxiliaryDatabaseObjects(
|
return super.aggregateAuxiliaryDatabaseObjects(
|
||||||
namespace,
|
namespace,
|
||||||
|
@ -416,13 +573,6 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
NONE;
|
NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private WriteExpressionRenderer jsonAggregateColumnWriter(
|
|
||||||
SelectableMapping aggregateColumn,
|
|
||||||
SelectableMapping[] columns,
|
|
||||||
TypeConfiguration typeConfiguration) {
|
|
||||||
return new RootJsonWriteExpression( aggregateColumn, columns, this, typeConfiguration );
|
|
||||||
}
|
|
||||||
|
|
||||||
interface JsonWriteExpression {
|
interface JsonWriteExpression {
|
||||||
void append(
|
void append(
|
||||||
SqlAppender sb,
|
SqlAppender sb,
|
||||||
|
@ -615,4 +765,198 @@ public class OracleAggregateSupport extends AggregateSupportImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface XmlWriteExpression {
|
||||||
|
void append(
|
||||||
|
SqlAppender sb,
|
||||||
|
String path,
|
||||||
|
SqlAstTranslator<?> translator,
|
||||||
|
AggregateColumnWriteExpression expression);
|
||||||
|
}
|
||||||
|
private static class AggregateXmlWriteExpression implements XmlWriteExpression {
|
||||||
|
|
||||||
|
private final SelectableMapping selectableMapping;
|
||||||
|
private final String columnDefinition;
|
||||||
|
private final LinkedHashMap<String, XmlWriteExpression> subExpressions = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
private AggregateXmlWriteExpression(SelectableMapping selectableMapping, String columnDefinition) {
|
||||||
|
this.selectableMapping = selectableMapping;
|
||||||
|
this.columnDefinition = columnDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initializeSubExpressions(SelectableMapping aggregateColumn, SelectableMapping[] columns, TypeConfiguration typeConfiguration) {
|
||||||
|
for ( SelectableMapping column : columns ) {
|
||||||
|
final SelectablePath selectablePath = column.getSelectablePath();
|
||||||
|
final SelectablePath[] parts = selectablePath.getParts();
|
||||||
|
AggregateXmlWriteExpression currentAggregate = this;
|
||||||
|
for ( int i = 1; i < parts.length - 1; i++ ) {
|
||||||
|
final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) currentAggregate.selectableMapping.getJdbcMapping().getJdbcType();
|
||||||
|
final EmbeddableMappingType embeddableMappingType = aggregateJdbcType.getEmbeddableMappingType();
|
||||||
|
final int selectableIndex = embeddableMappingType.getSelectableIndex( parts[i].getSelectableName() );
|
||||||
|
currentAggregate = (AggregateXmlWriteExpression) currentAggregate.subExpressions.computeIfAbsent(
|
||||||
|
parts[i].getSelectableName(),
|
||||||
|
k -> new AggregateXmlWriteExpression( embeddableMappingType.getJdbcValueSelectable( selectableIndex ), columnDefinition )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final String customWriteExpression = column.getWriteExpression();
|
||||||
|
currentAggregate.subExpressions.put(
|
||||||
|
parts[parts.length - 1].getSelectableName(),
|
||||||
|
new BasicXmlWriteExpression(
|
||||||
|
column,
|
||||||
|
xmlCustomWriteExpression( customWriteExpression, column.getJdbcMapping(), typeConfiguration )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
passThroughUnsetSubExpressions( aggregateColumn );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void passThroughUnsetSubExpressions(SelectableMapping aggregateColumn) {
|
||||||
|
final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) aggregateColumn.getJdbcMapping().getJdbcType();
|
||||||
|
final EmbeddableMappingType embeddableMappingType = aggregateJdbcType.getEmbeddableMappingType();
|
||||||
|
final int jdbcValueCount = embeddableMappingType.getJdbcValueCount();
|
||||||
|
for ( int i = 0; i < jdbcValueCount; i++ ) {
|
||||||
|
final SelectableMapping selectableMapping = embeddableMappingType.getJdbcValueSelectable( i );
|
||||||
|
|
||||||
|
final XmlWriteExpression xmlWriteExpression = subExpressions.get( selectableMapping.getSelectableName() );
|
||||||
|
if ( xmlWriteExpression == null ) {
|
||||||
|
subExpressions.put(
|
||||||
|
selectableMapping.getSelectableName(),
|
||||||
|
new PassThroughXmlWriteExpression( selectableMapping )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( xmlWriteExpression instanceof AggregateXmlWriteExpression writeExpression ) {
|
||||||
|
writeExpression.passThroughUnsetSubExpressions( selectableMapping );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getTagName() {
|
||||||
|
return selectableMapping.getSelectableName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void append(
|
||||||
|
SqlAppender sb,
|
||||||
|
String path,
|
||||||
|
SqlAstTranslator<?> translator,
|
||||||
|
AggregateColumnWriteExpression expression) {
|
||||||
|
sb.append( "xmlelement(" );
|
||||||
|
sb.appendDoubleQuoteEscapedString( getTagName() );
|
||||||
|
sb.append( ",xmlconcat" );
|
||||||
|
char separator = '(';
|
||||||
|
for ( Map.Entry<String, XmlWriteExpression> entry : subExpressions.entrySet() ) {
|
||||||
|
sb.append( separator );
|
||||||
|
|
||||||
|
final XmlWriteExpression value = entry.getValue();
|
||||||
|
if ( value instanceof AggregateXmlWriteExpression ) {
|
||||||
|
final String subPath = "xmlquery(" + xmlExtractArguments( path, entry.getKey() ) + ")";
|
||||||
|
value.append( sb, subPath, translator, expression );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value.append( sb, path, translator, expression );
|
||||||
|
}
|
||||||
|
separator = ',';
|
||||||
|
}
|
||||||
|
sb.append( "))" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class RootXmlWriteExpression extends AggregateXmlWriteExpression
|
||||||
|
implements WriteExpressionRenderer {
|
||||||
|
private final String path;
|
||||||
|
|
||||||
|
RootXmlWriteExpression(SelectableMapping aggregateColumn, SelectableMapping[] columns, TypeConfiguration typeConfiguration) {
|
||||||
|
super( aggregateColumn, aggregateColumn.getColumnDefinition() );
|
||||||
|
path = aggregateColumn.getSelectionExpression();
|
||||||
|
initializeSubExpressions( aggregateColumn, columns, typeConfiguration );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTagName() {
|
||||||
|
return XmlHelper.ROOT_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(
|
||||||
|
SqlAppender sqlAppender,
|
||||||
|
SqlAstTranslator<?> translator,
|
||||||
|
AggregateColumnWriteExpression aggregateColumnWriteExpression,
|
||||||
|
String qualifier) {
|
||||||
|
final String basePath;
|
||||||
|
if ( qualifier == null || qualifier.isBlank() ) {
|
||||||
|
basePath = path;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
basePath = qualifier + "." + path;
|
||||||
|
}
|
||||||
|
append( sqlAppender, "xmlquery('/" + getTagName() + "' passing " + basePath + " returning content)", translator, aggregateColumnWriteExpression );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static class BasicXmlWriteExpression implements XmlWriteExpression {
|
||||||
|
|
||||||
|
private final SelectableMapping selectableMapping;
|
||||||
|
private final String[] customWriteExpressionParts;
|
||||||
|
|
||||||
|
BasicXmlWriteExpression(SelectableMapping selectableMapping, String customWriteExpression) {
|
||||||
|
this.selectableMapping = selectableMapping;
|
||||||
|
if ( customWriteExpression.equals( "?" ) ) {
|
||||||
|
this.customWriteExpressionParts = new String[]{ "", "" };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert !customWriteExpression.startsWith( "?" );
|
||||||
|
final String[] parts = StringHelper.split( "?", customWriteExpression );
|
||||||
|
assert parts.length == 2 || (parts.length & 1) == 1;
|
||||||
|
this.customWriteExpressionParts = parts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void append(
|
||||||
|
SqlAppender sb,
|
||||||
|
String path,
|
||||||
|
SqlAstTranslator<?> translator,
|
||||||
|
AggregateColumnWriteExpression expression) {
|
||||||
|
final JdbcType jdbcType = selectableMapping.getJdbcMapping().getJdbcType();
|
||||||
|
final boolean isArray = jdbcType.getDefaultSqlTypeCode() == XML_ARRAY;
|
||||||
|
sb.append( "xmlelement(" );
|
||||||
|
sb.appendDoubleQuoteEscapedString( selectableMapping.getSelectableName() );
|
||||||
|
sb.append( ',' );
|
||||||
|
if ( isArray ) {
|
||||||
|
// Remove the <Collection> tag to wrap the value into the selectable specific tag
|
||||||
|
sb.append( "xmlquery('/Collection/*' passing " );
|
||||||
|
}
|
||||||
|
sb.append( customWriteExpressionParts[0] );
|
||||||
|
for ( int i = 1; i < customWriteExpressionParts.length; i++ ) {
|
||||||
|
// We use NO_UNTYPED here so that expressions which require type inference are casted explicitly,
|
||||||
|
// since we don't know how the custom write expression looks like where this is embedded,
|
||||||
|
// so we have to be pessimistic and avoid ambiguities
|
||||||
|
translator.render( expression.getValueExpression( selectableMapping ), SqlAstNodeRenderingMode.NO_UNTYPED );
|
||||||
|
sb.append( customWriteExpressionParts[i] );
|
||||||
|
}
|
||||||
|
if ( isArray ) {
|
||||||
|
sb.append( " returning content)" );
|
||||||
|
}
|
||||||
|
sb.append( ')' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PassThroughXmlWriteExpression implements XmlWriteExpression {
|
||||||
|
|
||||||
|
private final SelectableMapping selectableMapping;
|
||||||
|
|
||||||
|
PassThroughXmlWriteExpression(SelectableMapping selectableMapping) {
|
||||||
|
this.selectableMapping = selectableMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void append(
|
||||||
|
SqlAppender sb,
|
||||||
|
String path,
|
||||||
|
SqlAstTranslator<?> translator,
|
||||||
|
AggregateColumnWriteExpression expression) {
|
||||||
|
sb.append( "xmlquery(" );
|
||||||
|
sb.append( xmlExtractArguments( path, selectableMapping.getSelectableName() ) );
|
||||||
|
sb.append( ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,19 +279,6 @@ public class SQLServerAggregateSupport extends AggregateSupportImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int aggregateComponentSqlTypeCode(int aggregateColumnSqlTypeCode, int columnSqlTypeCode) {
|
|
||||||
if ( aggregateColumnSqlTypeCode == JSON ) {
|
|
||||||
return columnSqlTypeCode == ARRAY ? JSON_ARRAY : columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
else if ( aggregateColumnSqlTypeCode == SQLXML ) {
|
|
||||||
return columnSqlTypeCode == ARRAY ? XML_ARRAY : columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) {
|
public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) {
|
||||||
return aggregateSqlTypeCode == JSON || aggregateSqlTypeCode == SQLXML;
|
return aggregateSqlTypeCode == JSON || aggregateSqlTypeCode == SQLXML;
|
||||||
|
|
|
@ -26,7 +26,6 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.hibernate.type.SqlTypes.ARRAY;
|
|
||||||
import static org.hibernate.type.SqlTypes.BINARY;
|
import static org.hibernate.type.SqlTypes.BINARY;
|
||||||
import static org.hibernate.type.SqlTypes.BLOB;
|
import static org.hibernate.type.SqlTypes.BLOB;
|
||||||
import static org.hibernate.type.SqlTypes.BOOLEAN;
|
import static org.hibernate.type.SqlTypes.BOOLEAN;
|
||||||
|
@ -280,16 +279,6 @@ public class SybaseASEAggregateSupport extends AggregateSupportImpl {
|
||||||
throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateColumn.getTypeCode() );
|
throw new IllegalArgumentException( "Unsupported aggregate SQL type: " + aggregateColumn.getTypeCode() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int aggregateComponentSqlTypeCode(int aggregateColumnSqlTypeCode, int columnSqlTypeCode) {
|
|
||||||
if ( aggregateColumnSqlTypeCode == SQLXML ) {
|
|
||||||
return columnSqlTypeCode == ARRAY ? XML_ARRAY : columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return columnSqlTypeCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) {
|
public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) {
|
||||||
return aggregateSqlTypeCode == SQLXML;
|
return aggregateSqlTypeCode == SQLXML;
|
||||||
|
|
|
@ -17,6 +17,7 @@ public class UserDefinedArrayType extends AbstractUserDefinedType {
|
||||||
private Integer arraySqlTypeCode;
|
private Integer arraySqlTypeCode;
|
||||||
private String elementTypeName;
|
private String elementTypeName;
|
||||||
private Integer elementSqlTypeCode;
|
private Integer elementSqlTypeCode;
|
||||||
|
private Integer elementDdlTypeCode;
|
||||||
private Integer arrayLength;
|
private Integer arrayLength;
|
||||||
|
|
||||||
public UserDefinedArrayType(String contributor, Namespace namespace, Identifier physicalTypeName) {
|
public UserDefinedArrayType(String contributor, Namespace namespace, Identifier physicalTypeName) {
|
||||||
|
@ -47,6 +48,14 @@ public class UserDefinedArrayType extends AbstractUserDefinedType {
|
||||||
this.elementSqlTypeCode = elementSqlTypeCode;
|
this.elementSqlTypeCode = elementSqlTypeCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getElementDdlTypeCode() {
|
||||||
|
return elementDdlTypeCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setElementDdlTypeCode(Integer elementDdlTypeCode) {
|
||||||
|
this.elementDdlTypeCode = elementDdlTypeCode;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getArrayLength() {
|
public Integer getArrayLength() {
|
||||||
return arrayLength;
|
return arrayLength;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public enum CastType {
|
||||||
DATE, TIME, TIMESTAMP,
|
DATE, TIME, TIMESTAMP,
|
||||||
OFFSET_TIMESTAMP, ZONE_TIMESTAMP,
|
OFFSET_TIMESTAMP, ZONE_TIMESTAMP,
|
||||||
JSON,
|
JSON,
|
||||||
|
XML,
|
||||||
NULL,
|
NULL,
|
||||||
OTHER;
|
OTHER;
|
||||||
|
|
||||||
|
|
|
@ -350,6 +350,9 @@ public interface JdbcType extends Serializable {
|
||||||
case JSON:
|
case JSON:
|
||||||
case JSON_ARRAY:
|
case JSON_ARRAY:
|
||||||
return CastType.JSON;
|
return CastType.JSON;
|
||||||
|
case SQLXML:
|
||||||
|
case XML_ARRAY:
|
||||||
|
return CastType.XML;
|
||||||
case NULL:
|
case NULL:
|
||||||
return CastType.NULL;
|
return CastType.NULL;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -34,6 +34,11 @@ public class OracleJsonArrayBlobJdbcType extends JsonArrayJdbcType {
|
||||||
return SqlTypes.BLOB;
|
return SqlTypes.BLOB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDdlTypeCode() {
|
||||||
|
return SqlTypes.BLOB;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "JsonArrayBlobJdbcType";
|
return "JsonArrayBlobJdbcType";
|
||||||
|
|
|
@ -87,25 +87,7 @@ public class XmlArrayJdbcType extends ArrayJdbcType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||||
return new BasicBinder<>( javaType, this ) {
|
return new XmlArrayBinder<>( javaType, this );
|
||||||
@Override
|
|
||||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
|
||||||
throws SQLException {
|
|
||||||
final String xml = ( (XmlArrayJdbcType ) getJdbcType() ).toString( value, getJavaType(), options );
|
|
||||||
SQLXML sqlxml = st.getConnection().createSQLXML();
|
|
||||||
sqlxml.setString( xml );
|
|
||||||
st.setSQLXML( index, sqlxml );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
|
||||||
throws SQLException {
|
|
||||||
final String xml = ( (XmlArrayJdbcType ) getJdbcType() ).toString( value, getJavaType(), options );
|
|
||||||
SQLXML sqlxml = st.getConnection().createSQLXML();
|
|
||||||
sqlxml.setString( xml );
|
|
||||||
st.setSQLXML( name, sqlxml );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -139,4 +121,28 @@ public class XmlArrayJdbcType extends ArrayJdbcType {
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static class XmlArrayBinder<X> extends BasicBinder<X> {
|
||||||
|
public XmlArrayBinder(JavaType<X> javaType, XmlArrayJdbcType jdbcType) {
|
||||||
|
super( javaType, jdbcType );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
final String xml = ( (XmlArrayJdbcType) getJdbcType() ).toString( value, getJavaType(), options );
|
||||||
|
SQLXML sqlxml = st.getConnection().createSQLXML();
|
||||||
|
sqlxml.setString( xml );
|
||||||
|
st.setSQLXML( index, sqlxml );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
final String xml = ( (XmlArrayJdbcType ) getJdbcType() ).toString( value, getJavaType(), options );
|
||||||
|
SQLXML sqlxml = st.getConnection().createSQLXML();
|
||||||
|
sqlxml.setString( xml );
|
||||||
|
st.setSQLXML( name, sqlxml );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
* Copyright Red Hat Inc. and Hibernate Authors
|
||||||
|
*/
|
||||||
|
package org.hibernate.type.internal;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.engine.jdbc.LobCreator;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
public class TypeConfigurationWrapperOptions implements WrapperOptions {
|
||||||
|
|
||||||
|
private final TypeConfiguration typeConfiguration;
|
||||||
|
|
||||||
|
public TypeConfigurationWrapperOptions(TypeConfiguration typeConfiguration) {
|
||||||
|
this.typeConfiguration = typeConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialect getDialect() {
|
||||||
|
return typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SharedSessionContractImplementor getSession() {
|
||||||
|
return typeConfiguration.getSessionFactory().getWrapperOptions().getSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionFactoryImplementor getSessionFactory() {
|
||||||
|
return typeConfiguration.getSessionFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useStreamForLobBinding() {
|
||||||
|
return typeConfiguration.getSessionFactory().getWrapperOptions().useStreamForLobBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPreferredSqlTypeCodeForBoolean() {
|
||||||
|
return typeConfiguration.getCurrentBaseSqlTypeIndicators().getPreferredSqlTypeCodeForBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LobCreator getLobCreator() {
|
||||||
|
return typeConfiguration.getSessionFactory().getWrapperOptions().getLobCreator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return typeConfiguration.getSessionFactory().getWrapperOptions().getJdbcTimeZone();
|
||||||
|
}
|
||||||
|
}
|
|
@ -108,10 +108,10 @@ public class XmlEmbeddableTest extends BaseSessionFactoryFunctionalTest {
|
||||||
public void testFetchNull() {
|
public void testFetchNull() {
|
||||||
sessionFactoryScope().inSession(
|
sessionFactoryScope().inSession(
|
||||||
entityManager -> {
|
entityManager -> {
|
||||||
List<XmlHolder> XmlHolders = entityManager.createQuery( "from XmlHolder b where b.id = 2", XmlHolder.class ).getResultList();
|
List<XmlHolder> xmlHolders = entityManager.createQuery( "from XmlHolder b where b.id = 2", XmlHolder.class ).getResultList();
|
||||||
assertEquals( 1, XmlHolders.size() );
|
assertEquals( 1, xmlHolders.size() );
|
||||||
assertEquals( 2L, XmlHolders.get( 0 ).getId() );
|
assertEquals( 2L, xmlHolders.get( 0 ).getId() );
|
||||||
EmbeddableAggregate.assertEquals( EmbeddableAggregate.createAggregate2(), XmlHolders.get( 0 ).getAggregate() );
|
EmbeddableAggregate.assertEquals( EmbeddableAggregate.createAggregate2(), xmlHolders.get( 0 ).getAggregate() );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue