diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java index 699d9b6265..c326d1c727 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java @@ -477,8 +477,8 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio functionFactory.arrayRemoveIndex_unnest( true ); functionFactory.arraySlice_operator(); functionFactory.arrayReplace(); - functionFactory.arrayTrim_trim_array(); - functionFactory.arrayFill_postgresql(); + functionFactory.arrayTrim_unnest(); + functionFactory.arrayFill_cockroachdb(); functionFactory.arrayToString_postgresql(); functionContributions.getFunctionRegistry().register( diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java index 7b411c2ebc..00668348ac 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java @@ -597,7 +597,12 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio functionFactory.arrayRemoveIndex_unnest( true ); functionFactory.arraySlice_operator(); functionFactory.arrayReplace(); - functionFactory.arrayTrim_trim_array(); + if ( getVersion().isSameOrAfter( 14 ) ) { + functionFactory.arrayTrim_trim_array(); + } + else { + functionFactory.arrayTrim_unnest(); + } functionFactory.arrayFill_postgresql(); functionFactory.arrayToString_postgresql(); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java index fe4db8f233..20818c35b5 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java @@ -464,8 +464,8 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio functionFactory.arrayRemoveIndex_unnest( true ); functionFactory.arraySlice_operator(); functionFactory.arrayReplace(); - functionFactory.arrayTrim_trim_array(); - functionFactory.arrayFill_postgresql(); + functionFactory.arrayTrim_unnest(); + functionFactory.arrayFill_cockroachdb(); functionFactory.arrayToString_postgresql(); functionContributions.getFunctionRegistry().register( diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java index f4144580d6..5c5059fcb8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java @@ -46,7 +46,7 @@ public static String getSqlType(CastTarget castTarget, Dialect dialect) { } public static String getSqlType(CastTarget castTarget, SessionFactoryImplementor factory) { - final String sqlType = getCastTypeName( castTarget, factory ); + final String sqlType = getCastTypeName( castTarget, factory.getTypeConfiguration() ); return getSqlType( castTarget, sqlType, factory.getJdbcServices().getDialect() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index 0f2c6a729a..e0f984e246 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -645,7 +645,12 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio functionFactory.arrayRemoveIndex_unnest( true ); functionFactory.arraySlice_operator(); functionFactory.arrayReplace(); - functionFactory.arrayTrim_trim_array(); + if ( getVersion().isSameOrAfter( 14 ) ) { + functionFactory.arrayTrim_trim_array(); + } + else { + functionFactory.arrayTrim_unnest(); + } functionFactory.arrayFill_postgresql(); functionFactory.arrayToString_postgresql(); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java index ab2fc0171b..71356da931 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java @@ -30,6 +30,7 @@ import org.hibernate.dialect.function.array.ArraySliceUnnestFunction; import org.hibernate.dialect.function.array.ArrayToStringFunction; import org.hibernate.dialect.function.array.ArrayViaArgumentReturnTypeResolver; +import org.hibernate.dialect.function.array.CockroachArrayFillFunction; import org.hibernate.dialect.function.array.ElementViaArrayArgumentReturnTypeResolver; import org.hibernate.dialect.function.array.H2ArrayContainsFunction; import org.hibernate.dialect.function.array.H2ArrayFillFunction; @@ -72,6 +73,7 @@ import org.hibernate.dialect.function.array.OracleArrayConstructorFunction; import org.hibernate.dialect.function.array.OracleArrayContainsFunction; import org.hibernate.dialect.function.array.PostgreSQLArrayPositionsFunction; +import org.hibernate.dialect.function.array.PostgreSQLArrayTrimEmulation; import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; @@ -3166,6 +3168,13 @@ public void arrayTrim_trim_array() { .register(); } + /** + * PostgreSQL array_trim() emulation for versions before 14 + */ + public void arrayTrim_unnest() { + functionRegistry.register( "array_trim", new PostgreSQLArrayTrimEmulation() ); + } + /** * Oracle array_trim() function */ @@ -3197,6 +3206,14 @@ public void arrayFill_postgresql() { functionRegistry.register( "array_fill_list", new PostgreSQLArrayFillFunction( true ) ); } + /** + * Cockroach array_fill() function + */ + public void arrayFill_cockroachdb() { + functionRegistry.register( "array_fill", new CockroachArrayFillFunction( false ) ); + functionRegistry.register( "array_fill_list", new CockroachArrayFillFunction( true ) ); + } + /** * Oracle array_fill() function */ diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/AbstractArrayTrimFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/AbstractArrayTrimFunction.java new file mode 100644 index 0000000000..40c6f9695c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/AbstractArrayTrimFunction.java @@ -0,0 +1,37 @@ +/* + * 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.dialect.function.array; + +import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; +import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; +import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; +import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; + +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.ANY; +import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; + +/** + * Encapsulates the validator, return type and argument type resolvers for the array_remove functions. + * Subclasses only have to implement the rendering. + */ +public abstract class AbstractArrayTrimFunction extends AbstractSqmSelfRenderingFunctionDescriptor { + + public AbstractArrayTrimFunction() { + super( + "array_trim", + StandardArgumentsValidators.composite( + new ArgumentTypesValidator( null, ANY, INTEGER ), + ArrayArgumentValidator.DEFAULT_INSTANCE + ), + ArrayViaArgumentReturnTypeResolver.DEFAULT_INSTANCE, + StandardFunctionArgumentTypeResolvers.composite( + StandardFunctionArgumentTypeResolvers.invariant( ANY, INTEGER ), + StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE + ) + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayContainsOperatorFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayContainsOperatorFunction.java index 524cf323ff..48b87295dd 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayContainsOperatorFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayContainsOperatorFunction.java @@ -65,7 +65,7 @@ public void render( sqlAppender.append( "] as " ); sqlAppender.append( DdlTypeHelper.getCastTypeName( haystackExpression.getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ) ); sqlAppender.append( ')' ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayRemoveIndexUnnestFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayRemoveIndexUnnestFunction.java index 7fc6913c30..33cec0d7f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayRemoveIndexUnnestFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayRemoveIndexUnnestFunction.java @@ -61,7 +61,10 @@ public void render( sqlAppender.append( "),"); if ( castEmptyArrayLiteral ) { sqlAppender.append( "cast(array[] as " ); - sqlAppender.append( DdlTypeHelper.getCastTypeName( returnType, walker ) ); + sqlAppender.append( DdlTypeHelper.getCastTypeName( + returnType, + walker.getSessionFactory().getTypeConfiguration() + ) ); sqlAppender.append( ')' ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArraySliceUnnestFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArraySliceUnnestFunction.java index d6e693d1e6..365930736a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArraySliceUnnestFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArraySliceUnnestFunction.java @@ -68,7 +68,10 @@ public void render( sqlAppender.append( "),"); if ( castEmptyArrayLiteral ) { sqlAppender.append( "cast(array[] as " ); - sqlAppender.append( DdlTypeHelper.getCastTypeName( returnType, walker ) ); + sqlAppender.append( DdlTypeHelper.getCastTypeName( + returnType, + walker.getSessionFactory().getTypeConfiguration() + ) ); sqlAppender.append( ')' ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/CockroachArrayFillFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/CockroachArrayFillFunction.java new file mode 100644 index 0000000000..405c893ced --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/CockroachArrayFillFunction.java @@ -0,0 +1,66 @@ +/* + * 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.dialect.function.array; + +import java.util.List; + +import org.hibernate.query.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.sql.ast.tree.expression.Expression; +import org.hibernate.sql.ast.tree.expression.Literal; + +/** + * Implement the array fill function by using {@code generate_series}. + */ +public class CockroachArrayFillFunction extends AbstractArrayFillFunction { + + public CockroachArrayFillFunction(boolean list) { + super( list ); + } + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + sqlAppender.append( "coalesce(case when " ); + sqlAstArguments.get( 1 ).accept( walker ); + sqlAppender.append( "<>0 then (select array_agg(" ); + final String elementCastType; + final Expression elementExpression = (Expression) sqlAstArguments.get( 0 ); + if ( needsElementCasting( elementExpression ) ) { + elementCastType = DdlTypeHelper.getCastTypeName( + elementExpression.getExpressionType(), + walker.getSessionFactory().getTypeConfiguration() + ); + sqlAppender.append( "cast(" ); + } + else { + elementCastType = null; + } + sqlAstArguments.get( 0 ).accept( walker ); + if ( elementCastType != null ) { + sqlAppender.append( " as " ); + sqlAppender.append( elementCastType ); + sqlAppender.append( ')' ); + } + sqlAppender.append( ") from generate_series(1," ); + sqlAstArguments.get( 1 ).accept( walker ); + sqlAppender.append( ",1))) end,array[])" ); + } + + private static boolean needsElementCasting(Expression elementExpression) { + // PostgreSQL needs casting of null and string literal expressions + return elementExpression instanceof Literal && ( + elementExpression.getExpressionType().getSingleJdbcMapping().getJdbcType().isString() + || ( (Literal) elementExpression ).getLiteralValue() == null + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/DdlTypeHelper.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/DdlTypeHelper.java index ef86508f32..8c7a86830b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/DdlTypeHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/DdlTypeHelper.java @@ -16,7 +16,6 @@ import org.hibernate.metamodel.mapping.SqlTypedMapping; import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.query.ReturnableType; -import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator; import org.hibernate.type.BasicType; import org.hibernate.type.descriptor.java.BasicPluralJavaType; @@ -60,71 +59,91 @@ public static BasicType resolveListType(DomainType elementType, TypeConfig ); } - public static String getTypeName(BasicType type, SqlAstTranslator walker) { - return getTypeName( (JdbcMappingContainer) type, walker ); + public static String getTypeName(BasicType type, TypeConfiguration typeConfiguration) { + return getTypeName( (JdbcMappingContainer) type, typeConfiguration ); } - public static String getTypeName(JdbcMappingContainer type, SqlAstTranslator walker) { + public static String getTypeName(BasicType type, Size size, TypeConfiguration typeConfiguration) { + return getTypeName( (JdbcMappingContainer) type, size, typeConfiguration ); + } + + public static String getTypeName(JdbcMappingContainer type, TypeConfiguration typeConfiguration) { + return getTypeName( type, Size.nil(), typeConfiguration ); + } + + public static String getTypeName(JdbcMappingContainer type, Size size, TypeConfiguration typeConfiguration) { if ( type instanceof SqlTypedMapping ) { - return AbstractSqlAstTranslator.getSqlTypeName( (SqlTypedMapping) type, walker.getSessionFactory() ); + return AbstractSqlAstTranslator.getSqlTypeName( (SqlTypedMapping) type, typeConfiguration ); } else { final BasicType basicType = (BasicType) type.getSingleJdbcMapping(); - final TypeConfiguration typeConfiguration = walker.getSessionFactory().getTypeConfiguration(); final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry(); final DdlType ddlType = ddlTypeRegistry.getDescriptor( basicType.getJdbcType().getDdlTypeCode() ); - return ddlType.getTypeName( Size.nil(), basicType, ddlTypeRegistry ); + return ddlType.getTypeName( size, basicType, ddlTypeRegistry ); } } - public static String getTypeName(ReturnableType type, SqlAstTranslator walker) { + public static String getTypeName(ReturnableType type, TypeConfiguration typeConfiguration) { + return getTypeName( type, Size.nil(), typeConfiguration ); + } + + public static String getTypeName(ReturnableType type, Size size, TypeConfiguration typeConfiguration) { if ( type instanceof SqlTypedMapping ) { - return AbstractSqlAstTranslator.getSqlTypeName( (SqlTypedMapping) type, walker.getSessionFactory() ); + return AbstractSqlAstTranslator.getSqlTypeName( (SqlTypedMapping) type, typeConfiguration ); } else { final BasicType basicType = (BasicType) ( (JdbcMappingContainer) type ).getSingleJdbcMapping(); - final TypeConfiguration typeConfiguration = walker.getSessionFactory().getTypeConfiguration(); final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry(); final DdlType ddlType = ddlTypeRegistry.getDescriptor( basicType.getJdbcType().getDdlTypeCode() ); - return ddlType.getTypeName( Size.nil(), basicType, ddlTypeRegistry ); + return ddlType.getTypeName( size, basicType, ddlTypeRegistry ); } } - public static String getCastTypeName(BasicType type, SqlAstTranslator walker) { - return getCastTypeName( (JdbcMappingContainer) type, walker ); + public static String getCastTypeName(BasicType type, TypeConfiguration typeConfiguration) { + return getCastTypeName( (JdbcMappingContainer) type, typeConfiguration ); } - public static String getCastTypeName(JdbcMappingContainer type, SqlAstTranslator walker) { + public static String getCastTypeName(BasicType type, Size size, TypeConfiguration typeConfiguration) { + return getCastTypeName( (JdbcMappingContainer) type, size, typeConfiguration ); + } + + public static String getCastTypeName(JdbcMappingContainer type, TypeConfiguration typeConfiguration) { + return getCastTypeName( type, Size.nil(), typeConfiguration ); + } + + public static String getCastTypeName(JdbcMappingContainer type, Size size, TypeConfiguration typeConfiguration) { if ( type instanceof SqlTypedMapping ) { - return AbstractSqlAstTranslator.getCastTypeName( (SqlTypedMapping) type, walker.getSessionFactory() ); + return AbstractSqlAstTranslator.getCastTypeName( (SqlTypedMapping) type, typeConfiguration ); } else { final BasicType basicType = (BasicType) type.getSingleJdbcMapping(); - final TypeConfiguration typeConfiguration = walker.getSessionFactory().getTypeConfiguration(); final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry(); final DdlType ddlType = ddlTypeRegistry.getDescriptor( basicType.getJdbcType().getDdlTypeCode() ); - return ddlType.getCastTypeName( Size.nil(), basicType, ddlTypeRegistry ); + return ddlType.getCastTypeName( size, basicType, ddlTypeRegistry ); } } - public static String getCastTypeName(ReturnableType type, SqlAstTranslator walker) { + public static String getCastTypeName(ReturnableType type, TypeConfiguration typeConfiguration) { + return getCastTypeName( type, Size.nil(), typeConfiguration ); + } + + public static String getCastTypeName(ReturnableType type, Size size, TypeConfiguration typeConfiguration) { if ( type instanceof SqlTypedMapping ) { - return AbstractSqlAstTranslator.getCastTypeName( (SqlTypedMapping) type, walker.getSessionFactory() ); + return AbstractSqlAstTranslator.getCastTypeName( (SqlTypedMapping) type, typeConfiguration ); } else { final BasicType basicType = (BasicType) ( (JdbcMappingContainer) type ).getSingleJdbcMapping(); - final TypeConfiguration typeConfiguration = walker.getSessionFactory().getTypeConfiguration(); final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry(); final DdlType ddlType = ddlTypeRegistry.getDescriptor( basicType.getJdbcType().getDdlTypeCode() ); - return ddlType.getCastTypeName( Size.nil(), basicType, ddlTypeRegistry ); + return ddlType.getCastTypeName( size, basicType, ddlTypeRegistry ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/HSQLArrayConstructorFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/HSQLArrayConstructorFunction.java index 2c8eb0dbe9..b6900e04a8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/HSQLArrayConstructorFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/HSQLArrayConstructorFunction.java @@ -29,7 +29,10 @@ public void render( SqlAstTranslator walker) { final String castTypeName; if ( returnType != null && hasOnlyBottomArguments( arguments ) ) { - castTypeName = DdlTypeHelper.getCastTypeName( returnType, walker ); + castTypeName = DdlTypeHelper.getCastTypeName( + returnType, + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.append( "cast(" ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConcatElementFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConcatElementFunction.java index e052291721..1d48cabef4 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConcatElementFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConcatElementFunction.java @@ -34,7 +34,7 @@ public void render( final String arrayTypeName = DdlTypeHelper.getTypeName( prepend ? secondArgument.getExpressionType() : firstArgument.getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_concat(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConcatFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConcatFunction.java index cab164f383..6a11bb1c03 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConcatFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConcatFunction.java @@ -29,7 +29,10 @@ public void render( List sqlAstArguments, ReturnableType returnType, SqlAstTranslator walker) { - final String arrayTypeName = DdlTypeHelper.getTypeName( (JdbcMappingContainer) returnType, walker ); + final String arrayTypeName = DdlTypeHelper.getTypeName( + (JdbcMappingContainer) returnType, + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_concat" ); super.render( sqlAppender, sqlAstArguments, returnType, walker ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConstructorFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConstructorFunction.java index 6b1a1c6fe1..0c8f0ee245 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConstructorFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConstructorFunction.java @@ -40,7 +40,10 @@ public void render( ); } final BasicPluralType pluralType = (BasicPluralType) type; - final String arrayTypeName = DdlTypeHelper.getCastTypeName( pluralType, walker ); + final String arrayTypeName = DdlTypeHelper.getCastTypeName( + pluralType, + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.appendSql( arrayTypeName ); final int size = sqlAstArguments.size(); if ( size == 0 ) { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayContainsFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayContainsFunction.java index 715446d88b..df8b943de3 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayContainsFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayContainsFunction.java @@ -34,7 +34,10 @@ public void render( final Expression needleExpression = (Expression) sqlAstArguments.get( 1 ); final JdbcMappingContainer needleTypeContainer = needleExpression.getExpressionType(); final JdbcMapping needleType = needleTypeContainer == null ? null : needleTypeContainer.getSingleJdbcMapping(); - final String arrayTypeName = DdlTypeHelper.getTypeName( haystackExpression.getExpressionType(), walker ); + final String arrayTypeName = DdlTypeHelper.getTypeName( + haystackExpression.getExpressionType(), + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.appendSql( arrayTypeName ); if ( needleType == null || needleType instanceof BasicPluralType ) { sqlAppender.append( "_contains(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayFillFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayFillFunction.java index 0597e5f8c1..11ea0b1ebd 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayFillFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayFillFunction.java @@ -29,7 +29,10 @@ public void render( List sqlAstArguments, ReturnableType returnType, SqlAstTranslator walker) { - final String arrayTypeName = DdlTypeHelper.getTypeName( returnType, walker ); + final String arrayTypeName = DdlTypeHelper.getTypeName( + returnType, + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_fill(" ); sqlAstArguments.get( 0 ).accept( walker ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayGetFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayGetFunction.java index 9f1ddf41f4..dc202f41f9 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayGetFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayGetFunction.java @@ -30,7 +30,7 @@ public void render( SqlAstTranslator walker) { final String arrayTypeName = DdlTypeHelper.getTypeName( ( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_get(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayLengthFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayLengthFunction.java index 1ad5e38798..85c639e52a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayLengthFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayLengthFunction.java @@ -39,7 +39,10 @@ public void render( ReturnableType returnType, SqlAstTranslator walker) { final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); - final String arrayTypeName = DdlTypeHelper.getTypeName( arrayExpression.getExpressionType(), walker ); + final String arrayTypeName = DdlTypeHelper.getTypeName( + arrayExpression.getExpressionType(), + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.appendSql( arrayTypeName ); sqlAppender.append( "_length(" ); arrayExpression.accept( walker ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayOverlapsFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayOverlapsFunction.java index 0e8e5c01a4..89e7863051 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayOverlapsFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayOverlapsFunction.java @@ -28,7 +28,10 @@ public void render( ReturnableType returnType, SqlAstTranslator walker) { final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 ); - final String arrayTypeName = DdlTypeHelper.getTypeName( haystackExpression.getExpressionType(), walker ); + final String arrayTypeName = DdlTypeHelper.getTypeName( + haystackExpression.getExpressionType(), + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.appendSql( arrayTypeName ); sqlAppender.append( "_overlaps(" ); haystackExpression.accept( walker ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayPositionFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayPositionFunction.java index 9e18ab0f2d..2dd453d99b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayPositionFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayPositionFunction.java @@ -28,7 +28,10 @@ public void render( ReturnableType returnType, SqlAstTranslator walker) { final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); - final String arrayTypeName = DdlTypeHelper.getTypeName( arrayExpression.getExpressionType(), walker ); + final String arrayTypeName = DdlTypeHelper.getTypeName( + arrayExpression.getExpressionType(), + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.appendSql( arrayTypeName ); sqlAppender.append( "_position(" ); arrayExpression.accept( walker ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayPositionsFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayPositionsFunction.java index 5f5b3042ee..687505953b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayPositionsFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayPositionsFunction.java @@ -28,7 +28,10 @@ public void render( ReturnableType returnType, SqlAstTranslator walker) { final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); - final String arrayTypeName = DdlTypeHelper.getTypeName( arrayExpression.getExpressionType(), walker ); + final String arrayTypeName = DdlTypeHelper.getTypeName( + arrayExpression.getExpressionType(), + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.appendSql( arrayTypeName ); sqlAppender.append( "_positions(" ); arrayExpression.accept( walker ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayRemoveFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayRemoveFunction.java index 3f35efd2b4..8045244092 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayRemoveFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayRemoveFunction.java @@ -30,7 +30,7 @@ public void render( SqlAstTranslator walker) { final String arrayTypeName = DdlTypeHelper.getTypeName( ( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_remove(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayRemoveIndexFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayRemoveIndexFunction.java index 410cadc78b..1c5d757a53 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayRemoveIndexFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayRemoveIndexFunction.java @@ -31,7 +31,7 @@ public void render( SqlAstTranslator walker) { final String arrayTypeName = DdlTypeHelper.getTypeName( ( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_remove_index(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayReplaceFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayReplaceFunction.java index edaee54d9e..9e77fc9a01 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayReplaceFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayReplaceFunction.java @@ -27,7 +27,7 @@ public void render( SqlAstTranslator walker) { final String arrayTypeName = DdlTypeHelper.getTypeName( ( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_replace(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArraySetFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArraySetFunction.java index 16d9930a4c..c065fba812 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArraySetFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArraySetFunction.java @@ -30,7 +30,7 @@ public void render( SqlAstTranslator walker) { final String arrayTypeName = DdlTypeHelper.getTypeName( ( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_set(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArraySliceFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArraySliceFunction.java index 7414336710..c12e510510 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArraySliceFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArraySliceFunction.java @@ -31,7 +31,7 @@ public void render( SqlAstTranslator walker) { final String arrayTypeName = DdlTypeHelper.getTypeName( ( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_slice(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayToStringFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayToStringFunction.java index 0eb41bbe45..97efaadef4 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayToStringFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayToStringFunction.java @@ -39,7 +39,7 @@ public void render( SqlAstTranslator walker) { final String arrayTypeName = DdlTypeHelper.getTypeName( ( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_to_string(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayTrimFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayTrimFunction.java index 2eca876f55..8145bad418 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayTrimFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayTrimFunction.java @@ -9,37 +9,15 @@ import java.util.List; import org.hibernate.query.ReturnableType; -import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; -import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; -import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; -import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.expression.Expression; -import static org.hibernate.query.sqm.produce.function.FunctionParameterType.ANY; -import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER; - /** * Oracle array_trim function. */ -public class OracleArrayTrimFunction extends AbstractSqmSelfRenderingFunctionDescriptor { - - public OracleArrayTrimFunction() { - super( - "array_trim", - StandardArgumentsValidators.composite( - new ArgumentTypesValidator( null, ANY, INTEGER ), - ArrayArgumentValidator.DEFAULT_INSTANCE - ), - ArrayViaArgumentReturnTypeResolver.DEFAULT_INSTANCE, - StandardFunctionArgumentTypeResolvers.composite( - StandardFunctionArgumentTypeResolvers.invariant( ANY, INTEGER ), - StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE - ) - ); - } +public class OracleArrayTrimFunction extends AbstractArrayTrimFunction { @Override public void render( @@ -49,7 +27,7 @@ public void render( SqlAstTranslator walker) { final String arrayTypeName = DdlTypeHelper.getTypeName( ( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(), - walker + walker.getSessionFactory().getTypeConfiguration() ); sqlAppender.append( arrayTypeName ); sqlAppender.append( "_trim(" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayConcatElementFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayConcatElementFunction.java index 52d5544626..175530ee30 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayConcatElementFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayConcatElementFunction.java @@ -8,8 +8,11 @@ import java.util.List; -import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.engine.jdbc.Size; +import org.hibernate.metamodel.mapping.JdbcMappingContainer; +import org.hibernate.metamodel.mapping.SqlTypedMapping; import org.hibernate.query.ReturnableType; +import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.tree.SqlAstNode; @@ -47,44 +50,40 @@ public void render( } final String elementCastType; if ( needsElementCasting( elementArgument ) ) { - final JdbcMapping elementType = elementArgument.getExpressionType().getSingleJdbcMapping(); - if ( elementType instanceof BottomType ) { - elementCastType = DdlTypeHelper.getCastTypeName( - ( (BasicPluralType) arrayArgument.getExpressionType().getSingleJdbcMapping() ) - .getElementType(), - walker - ); - } - else { - elementCastType = DdlTypeHelper.getCastTypeName( elementType, walker ); - } + final JdbcMappingContainer arrayType = arrayArgument.getExpressionType(); + final Size size = arrayType instanceof SqlTypedMapping ? ( (SqlTypedMapping) arrayType ).toSize() : null; + elementCastType = DdlTypeHelper.getCastTypeName( + ( (BasicPluralType) returnType ).getElementType(), + size, + walker.getSessionFactory().getTypeConfiguration() + ); } else { elementCastType = null; } sqlAppender.append( "case when " ); - arrayArgument.accept( walker ); + walker.render( arrayArgument, SqlAstNodeRenderingMode.DEFAULT ); sqlAppender.append( " is not null then " ); if ( prepend && elementCastType != null) { sqlAppender.append( "cast(" ); - firstArgument.accept( walker ); + walker.render( firstArgument, SqlAstNodeRenderingMode.DEFAULT ); sqlAppender.append( " as " ); sqlAppender.append( elementCastType ); sqlAppender.append( ')' ); } else { - firstArgument.accept( walker ); + walker.render( firstArgument, SqlAstNodeRenderingMode.DEFAULT ); } sqlAppender.append( "||" ); if ( !prepend && elementCastType != null) { sqlAppender.append( "cast(" ); - secondArgument.accept( walker ); + walker.render( secondArgument, SqlAstNodeRenderingMode.DEFAULT ); sqlAppender.append( " as " ); sqlAppender.append( elementCastType ); sqlAppender.append( ')' ); } else { - secondArgument.accept( walker ); + walker.render( secondArgument, SqlAstNodeRenderingMode.DEFAULT ); } sqlAppender.append( " end" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayConstructorFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayConstructorFunction.java index cf0fc8150f..cd48881a62 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayConstructorFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayConstructorFunction.java @@ -39,7 +39,10 @@ public void render( if ( type instanceof BasicPluralType ) { final BasicPluralType pluralType = (BasicPluralType) type; if ( needsArrayCasting( pluralType.getElementType() ) ) { - arrayTypeName = DdlTypeHelper.getCastTypeName( pluralType, walker ); + arrayTypeName = DdlTypeHelper.getCastTypeName( + returnType, + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.append( "cast(" ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayFillFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayFillFunction.java index 5bd057eeef..17e3a954b8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayFillFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayFillFunction.java @@ -16,7 +16,7 @@ import org.hibernate.sql.ast.tree.expression.Literal; /** - * Implement the array get function by using {@code unnest}. + * Custom casting for the array fill function. */ public class PostgreSQLArrayFillFunction extends AbstractArrayFillFunction { @@ -34,7 +34,10 @@ public void render( final String elementCastType; final Expression elementExpression = (Expression) sqlAstArguments.get( 0 ); if ( needsElementCasting( elementExpression ) ) { - elementCastType = DdlTypeHelper.getCastTypeName( elementExpression.getExpressionType(), walker ); + elementCastType = DdlTypeHelper.getCastTypeName( + elementExpression.getExpressionType(), + walker.getSessionFactory().getTypeConfiguration() + ); sqlAppender.append( "cast(" ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayPositionFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayPositionFunction.java index 9189acbbca..6761ae08fb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayPositionFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayPositionFunction.java @@ -9,6 +9,7 @@ import java.util.List; import org.hibernate.query.ReturnableType; +import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.tree.SqlAstNode; @@ -35,9 +36,9 @@ public void render( sqlAppender.append( "case when " ); arrayExpression.accept( walker ); sqlAppender.append( " is not null then coalesce(array_position(" ); - arrayExpression.accept( walker ); + walker.render( arrayExpression, SqlAstNodeRenderingMode.DEFAULT ); sqlAppender.append( ',' ); - elementExpression.accept( walker ); + walker.render( elementExpression, SqlAstNodeRenderingMode.DEFAULT ); if ( sqlAstArguments.size() > 2 ) { sqlAppender.append( ',' ); sqlAstArguments.get( 2 ).accept( walker ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayPositionsFunction.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayPositionsFunction.java index 156dcb51af..962dbef26b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayPositionsFunction.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayPositionsFunction.java @@ -9,6 +9,7 @@ import java.util.List; import org.hibernate.query.ReturnableType; +import org.hibernate.sql.ast.SqlAstNodeRenderingMode; import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.tree.SqlAstNode; @@ -33,9 +34,9 @@ public void render( final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression elementExpression = (Expression) sqlAstArguments.get( 1 ); sqlAppender.append( "array_positions(" ); - arrayExpression.accept( walker ); + walker.render( arrayExpression, SqlAstNodeRenderingMode.DEFAULT ); sqlAppender.append( ',' ); - elementExpression.accept( walker ); + walker.render( elementExpression, SqlAstNodeRenderingMode.DEFAULT ); sqlAppender.append( ')' ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayTrimEmulation.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayTrimEmulation.java new file mode 100644 index 0000000000..11e891365b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayTrimEmulation.java @@ -0,0 +1,66 @@ +/* + * 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.dialect.function.array; + +import java.util.List; + +import org.hibernate.metamodel.model.domain.DomainType; +import org.hibernate.query.ReturnableType; +import org.hibernate.sql.ast.SqlAstTranslator; +import org.hibernate.sql.ast.spi.SqlAppender; +import org.hibernate.sql.ast.tree.SqlAstNode; +import org.hibernate.type.BasicPluralType; +import org.hibernate.type.BasicType; + +/** + * PostgreSQL array_trim emulation, since the function was only introduced in version 14. + */ +public class PostgreSQLArrayTrimEmulation extends AbstractArrayTrimFunction { + + @Override + public void render( + SqlAppender sqlAppender, + List sqlAstArguments, + ReturnableType returnType, + SqlAstTranslator walker) { + final SqlAstNode arrayExpression = sqlAstArguments.get( 0 ); + final SqlAstNode elementCountExpression = sqlAstArguments.get( 1 ); + sqlAppender.append( "coalesce((select array_agg(t.val order by t.idx) from unnest(" ); + arrayExpression.accept( walker ); + sqlAppender.append( ") with ordinality t(val,idx) where t.idx<=cardinality(" ); + arrayExpression.accept( walker ); + sqlAppender.append( ")-" ); + elementCountExpression.accept( walker ); + + String arrayTypeName = null; + if ( returnType != null ) { + final DomainType type = returnType.getSqmType(); + if ( type instanceof BasicPluralType ) { + final BasicPluralType pluralType = (BasicPluralType) type; + if ( needsArrayCasting( pluralType.getElementType() ) ) { + arrayTypeName = DdlTypeHelper.getCastTypeName( + returnType, + walker.getSessionFactory().getTypeConfiguration() + ); + } + } + } + if ( arrayTypeName != null ) { + sqlAppender.append( "),cast(array[] as " ); + sqlAppender.appendSql( arrayTypeName ); + sqlAppender.appendSql( "))" ); + } + else { + sqlAppender.append( "),array[])" ); + } + } + + private static boolean needsArrayCasting(BasicType elementType) { + // PostgreSQL doesn't do implicit conversion between text[] and varchar[], so we need casting + return elementType.getJdbcType().isString(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index e28bb9fbfe..8437265d29 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -5830,11 +5830,17 @@ protected MappingModelExpressible determineValueMapping(SqmParameter sqmPa final QueryParameterBinding binding = domainParameterBindings.getBinding( queryParameter ); BindableType paramType = binding.getBindType(); + final boolean bindingTypeExplicit; + bindingTypeExplicit = binding.getExplicitTemporalPrecision() != null; if ( paramType == null ) { paramType = queryParameter.getHibernateType(); if ( paramType == null ) { paramType = sqmParameter.getAnticipatedType(); } +// bindingTypeExplicit = false; + } + else { +// bindingTypeExplicit = binding.getExplicitTemporalPrecision() != null; } if ( paramType == null ) { @@ -5852,8 +5858,10 @@ else if ( paramType instanceof MappingModelExpressible ) { if ( inferredValueMapping instanceof ModelPart ) { final JdbcMapping paramJdbcMapping = paramModelType.getSingleJdbcMapping(); final JdbcMapping inferredJdbcMapping = inferredValueMapping.getSingleJdbcMapping(); - // If the bind type has a different JDBC type, we prefer that - if ( paramJdbcMapping.getJdbcType() == inferredJdbcMapping.getJdbcType() ) { + // Only use the inferred mapping as parameter type when the JavaType accepts values of the bind type + if ( inferredJdbcMapping.getMappedJavaType().isWider( paramJdbcMapping.getMappedJavaType() ) + // and the bind type is not explicit or the bind type has the same JDBC type + && ( !bindingTypeExplicit || paramJdbcMapping.getJdbcType() == inferredJdbcMapping.getJdbcType() ) ) { return resolveInferredValueMappingForParameter( inferredValueMapping ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index 53fa675bba..01de7cacbb 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -218,6 +218,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.sql.DdlType; import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry; +import org.hibernate.type.spi.TypeConfiguration; import static org.hibernate.query.sqm.TemporalUnit.NANOSECOND; import static org.hibernate.sql.ast.SqlTreePrinter.logSqlAst; @@ -6248,16 +6249,24 @@ public void visitTrimSpecification(TrimSpecification trimSpecification) { @Override public void visitCastTarget(CastTarget castTarget) { - appendSql( getCastTypeName( castTarget, sessionFactory ) ); + appendSql( getCastTypeName( castTarget, sessionFactory.getTypeConfiguration() ) ); } + /** + * @deprecated Use {@link #getSqlTypeName(SqlTypedMapping, TypeConfiguration)} instead + */ + @Deprecated(forRemoval = true) public static String getSqlTypeName(SqlTypedMapping castTarget, SessionFactoryImplementor factory) { + return getSqlTypeName( castTarget, factory.getTypeConfiguration() ); + } + + public static String getSqlTypeName(SqlTypedMapping castTarget, TypeConfiguration typeConfiguration) { if ( castTarget.getColumnDefinition() != null ) { return castTarget.getColumnDefinition(); } else { final Size castTargetSize = castTarget.toSize(); - final DdlTypeRegistry ddlTypeRegistry = factory.getTypeConfiguration().getDdlTypeRegistry(); + final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry(); final BasicType expressionType = (BasicType) castTarget.getJdbcMapping(); DdlType ddlType = ddlTypeRegistry.getDescriptor( expressionType.getJdbcType().getDdlTypeCode() ); if ( ddlType == null ) { @@ -6270,13 +6279,21 @@ public static String getSqlTypeName(SqlTypedMapping castTarget, SessionFactoryIm } } + /** + * @deprecated Use {@link #getCastTypeName(SqlTypedMapping, TypeConfiguration)} instead + */ + @Deprecated(forRemoval = true) public static String getCastTypeName(SqlTypedMapping castTarget, SessionFactoryImplementor factory) { + return getCastTypeName( castTarget, factory.getTypeConfiguration() ); + } + + public static String getCastTypeName(SqlTypedMapping castTarget, TypeConfiguration typeConfiguration) { if ( castTarget.getColumnDefinition() != null ) { return castTarget.getColumnDefinition(); } else { final Size castTargetSize = castTarget.toSize(); - final DdlTypeRegistry ddlTypeRegistry = factory.getTypeConfiguration().getDdlTypeRegistry(); + final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry(); final BasicType expressionType = (BasicType) castTarget.getJdbcMapping(); DdlType ddlType = ddlTypeRegistry.getDescriptor( expressionType.getJdbcType().getDdlTypeCode() ); if ( ddlType == null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java index 802d24c6f0..1011e5ec6f 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java @@ -50,6 +50,12 @@ public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) { ); } + @Override + public boolean isWider(JavaType javaType) { + // Support binding single element value + return this == javaType || componentJavaType == javaType; + } + @Override public BasicType resolveType( TypeConfiguration typeConfiguration, diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java index 8ede8f7e1a..80fa4b9ca8 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java @@ -86,6 +86,12 @@ public CollectionSemantics getSemantics() { return semantics; } + @Override + public boolean isWider(JavaType javaType) { + // Support binding single element value + return this == javaType || componentJavaType == javaType; + } + @Override public BasicType resolveType( TypeConfiguration typeConfiguration, diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayTrimTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayTrimTest.java index 29eedd037f..514dcf40ee 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayTrimTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayTrimTest.java @@ -11,6 +11,7 @@ import java.util.List; import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.sqm.NodeBuilder; @@ -22,6 +23,7 @@ import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.Setting; +import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -87,6 +89,7 @@ public void testTrimAll(SessionFactoryScope scope) { } @Test + @SkipForDialect(dialectClass = PostgreSQLDialect.class, majorVersion = 12, reason = "The PostgreSQL emulation for version < 14 doesn't throw an error") public void testTrimOutOfRange(SessionFactoryScope scope) { scope.inSession( em -> { try {