HHH-17355 Unify array_contains and array_contains_all as well as deprecate FunctionRenderingSupport in favor of new FunctionRenderer contract

This commit is contained in:
Christian Beikov 2023-10-26 16:40:07 +02:00
parent 5506714611
commit bfb9fcc0f6
144 changed files with 1617 additions and 1241 deletions

View File

@ -1233,7 +1233,7 @@ The result of `array_contains` is undefined when the second argument is an array
==== ====
[source, JAVA, indent=0] [source, JAVA, indent=0]
---- ----
include::{array-example-dir-hql}/ArrayContainsAllTest.java[tags=hql-array-contains-all-example] include::{array-example-dir-hql}/ArrayContainsArrayTest.java[tags=hql-array-contains-array-example]
---- ----
==== ====
@ -1243,7 +1243,7 @@ To search for `null` elements, the `array_contains_nullable` function must be us
==== ====
[source, JAVA, indent=0] [source, JAVA, indent=0]
---- ----
include::{array-example-dir-hql}/ArrayContainsAllTest.java[tags=hql-array-contains-all-nullable-example] include::{array-example-dir-hql}/ArrayContainsArrayTest.java[tags=hql-array-contains-array-nullable-example]
---- ----
==== ====

View File

@ -461,19 +461,15 @@ public class CockroachLegacyDialect extends Dialect {
functionFactory.listagg_stringAgg( "string" ); functionFactory.listagg_stringAgg( "string" );
functionFactory.inverseDistributionOrderedSetAggregates(); functionFactory.inverseDistributionOrderedSetAggregates();
functionFactory.hypotheticalOrderedSetAggregates_windowEmulation(); functionFactory.hypotheticalOrderedSetAggregates_windowEmulation();
functionFactory.array_casting(); functionFactory.array_postgresql();
functionFactory.arrayAggregate(); functionFactory.arrayAggregate();
functionFactory.arrayContains_operator();
functionFactory.arrayContainsNull_array_position();
functionFactory.arrayPosition_postgresql(); functionFactory.arrayPosition_postgresql();
functionFactory.arrayLength_cardinality(); functionFactory.arrayLength_cardinality();
functionFactory.arrayConcat_postgresql(); functionFactory.arrayConcat_postgresql();
functionFactory.arrayPrepend_postgresql(); functionFactory.arrayPrepend_postgresql();
functionFactory.arrayAppend_postgresql(); functionFactory.arrayAppend_postgresql();
functionFactory.arrayContainsAll_operator(); functionFactory.arrayContains_postgresql();
functionFactory.arrayOverlaps_operator(); functionFactory.arrayOverlaps_postgresql();
functionFactory.arrayContainsAllNullable_operator();
functionFactory.arrayOverlapsNullable_unnest();
functionFactory.arrayGet_bracket(); functionFactory.arrayGet_bracket();
functionFactory.arraySet_unnest(); functionFactory.arraySet_unnest();
functionFactory.arrayRemove(); functionFactory.arrayRemove();

View File

@ -372,22 +372,18 @@ public class H2LegacyDialect extends Dialect {
functionFactory.listagg( null ); functionFactory.listagg( null );
functionFactory.array(); functionFactory.array();
functionFactory.arrayAggregate(); functionFactory.arrayAggregate();
functionFactory.arrayContains();
functionFactory.arrayContainsNull();
functionFactory.arrayLength_cardinality(); functionFactory.arrayLength_cardinality();
functionFactory.arrayConcat_operator(); functionFactory.arrayConcat_operator();
functionFactory.arrayPrepend_operator(); functionFactory.arrayPrepend_operator();
functionFactory.arrayAppend_operator(); functionFactory.arrayAppend_operator();
functionFactory.arrayContainsAll_h2(); functionFactory.arrayContains_h2( getMaximumArraySize() );
functionFactory.arrayOverlaps_h2(); functionFactory.arrayOverlaps_h2( getMaximumArraySize() );
functionFactory.arrayContainsAllNullable_h2();
functionFactory.arrayOverlapsNullable_h2();
functionFactory.arrayGet_h2(); functionFactory.arrayGet_h2();
functionFactory.arraySet_h2(); functionFactory.arraySet_h2( getMaximumArraySize() );
functionFactory.arrayRemove_h2(); functionFactory.arrayRemove_h2( getMaximumArraySize() );
functionFactory.arrayRemoveIndex_h2(); functionFactory.arrayRemoveIndex_h2( getMaximumArraySize() );
functionFactory.arraySlice(); functionFactory.arraySlice();
functionFactory.arrayReplace_h2(); functionFactory.arrayReplace_h2( getMaximumArraySize() );
} }
else { else {
// Use group_concat until 2.x as listagg was buggy // Use group_concat until 2.x as listagg was buggy
@ -399,6 +395,16 @@ public class H2LegacyDialect extends Dialect {
} }
} }
/**
* H2 requires a very special emulation, because {@code unnest} is pretty much useless,
* due to https://github.com/h2database/h2database/issues/1815.
* This emulation uses {@code array_get}, {@code array_length} and {@code system_range} functions to roughly achieve the same,
* but requires that {@code system_range} is fed with a "maximum array size".
*/
protected int getMaximumArraySize() {
return 1000;
}
@Override @Override
public void augmentPhysicalTableTypes(List<String> tableTypesList) { public void augmentPhysicalTableTypes(List<String> tableTypesList) {
if ( getVersion().isSameOrAfter( 2 ) ) { if ( getVersion().isSameOrAfter( 2 ) ) {

View File

@ -247,19 +247,15 @@ public class HSQLLegacyDialect extends Dialect {
functionFactory.rownum(); functionFactory.rownum();
} }
functionFactory.listagg_groupConcat(); functionFactory.listagg_groupConcat();
functionFactory.array(); functionFactory.array_hsql();
functionFactory.arrayAggregate(); functionFactory.arrayAggregate();
functionFactory.arrayContains_hsql();
functionFactory.arrayContainsNull_hsql();
functionFactory.arrayPosition_hsql(); functionFactory.arrayPosition_hsql();
functionFactory.arrayLength_cardinality(); functionFactory.arrayLength_cardinality();
functionFactory.arrayConcat_operator(); functionFactory.arrayConcat_operator();
functionFactory.arrayPrepend_operator(); functionFactory.arrayPrepend_operator();
functionFactory.arrayAppend_operator(); functionFactory.arrayAppend_operator();
functionFactory.arrayContainsAll_hsql(); functionFactory.arrayContains_hsql();
functionFactory.arrayOverlaps_hsql(); functionFactory.arrayOverlaps_hsql();
functionFactory.arrayContainsAllNullable_hsql();
functionFactory.arrayOverlapsNullable_unnest();
functionFactory.arrayGet_unnest(); functionFactory.arrayGet_unnest();
functionFactory.arraySet_hsql(); functionFactory.arraySet_hsql();
functionFactory.arrayRemove_hsql(); functionFactory.arrayRemove_hsql();

View File

@ -285,17 +285,13 @@ public class OracleLegacyDialect extends Dialect {
functionFactory.array_oracle(); functionFactory.array_oracle();
functionFactory.arrayAggregate_jsonArrayagg(); functionFactory.arrayAggregate_jsonArrayagg();
functionFactory.arrayContains_oracle();
functionFactory.arrayContainsNull_oracle();
functionFactory.arrayPosition_oracle(); functionFactory.arrayPosition_oracle();
functionFactory.arrayLength_oracle(); functionFactory.arrayLength_oracle();
functionFactory.arrayConcat_oracle(); functionFactory.arrayConcat_oracle();
functionFactory.arrayPrepend_oracle(); functionFactory.arrayPrepend_oracle();
functionFactory.arrayAppend_oracle(); functionFactory.arrayAppend_oracle();
functionFactory.arrayContainsAll_oracle(); functionFactory.arrayContains_oracle();
functionFactory.arrayOverlaps_oracle(); functionFactory.arrayOverlaps_oracle();
functionFactory.arrayContainsAllNullable_oracle();
functionFactory.arrayOverlapsNullable_oracle();
functionFactory.arrayGet_oracle(); functionFactory.arrayGet_oracle();
functionFactory.arraySet_oracle(); functionFactory.arraySet_oracle();
functionFactory.arrayRemove_oracle(); functionFactory.arrayRemove_oracle();

View File

@ -581,19 +581,15 @@ public class PostgreSQLLegacyDialect extends Dialect {
functionFactory.locate_positionSubstring(); functionFactory.locate_positionSubstring();
functionFactory.windowFunctions(); functionFactory.windowFunctions();
functionFactory.listagg_stringAgg( "varchar" ); functionFactory.listagg_stringAgg( "varchar" );
functionFactory.array_casting(); functionFactory.array_postgresql();
functionFactory.arrayAggregate(); functionFactory.arrayAggregate();
functionFactory.arrayContains_operator();
functionFactory.arrayContainsNull_array_position();
functionFactory.arrayPosition_postgresql(); functionFactory.arrayPosition_postgresql();
functionFactory.arrayLength_cardinality(); functionFactory.arrayLength_cardinality();
functionFactory.arrayConcat_postgresql(); functionFactory.arrayConcat_postgresql();
functionFactory.arrayPrepend_postgresql(); functionFactory.arrayPrepend_postgresql();
functionFactory.arrayAppend_postgresql(); functionFactory.arrayAppend_postgresql();
functionFactory.arrayContainsAll_operator(); functionFactory.arrayContains_postgresql();
functionFactory.arrayOverlaps_operator(); functionFactory.arrayOverlaps_postgresql();
functionFactory.arrayContainsAllNullable_operator();
functionFactory.arrayOverlapsNullable_unnest();
functionFactory.arrayGet_bracket(); functionFactory.arrayGet_bracket();
functionFactory.arraySet_unnest(); functionFactory.arraySet_unnest();
functionFactory.arrayRemove(); functionFactory.arrayRemove();

View File

@ -448,19 +448,15 @@ public class CockroachDialect extends Dialect {
functionFactory.listagg_stringAgg( "string" ); functionFactory.listagg_stringAgg( "string" );
functionFactory.inverseDistributionOrderedSetAggregates(); functionFactory.inverseDistributionOrderedSetAggregates();
functionFactory.hypotheticalOrderedSetAggregates_windowEmulation(); functionFactory.hypotheticalOrderedSetAggregates_windowEmulation();
functionFactory.array_casting(); functionFactory.array_postgresql();
functionFactory.arrayAggregate(); functionFactory.arrayAggregate();
functionFactory.arrayContains_operator();
functionFactory.arrayContainsNull_array_position();
functionFactory.arrayPosition_postgresql(); functionFactory.arrayPosition_postgresql();
functionFactory.arrayLength_cardinality(); functionFactory.arrayLength_cardinality();
functionFactory.arrayConcat_postgresql(); functionFactory.arrayConcat_postgresql();
functionFactory.arrayPrepend_postgresql(); functionFactory.arrayPrepend_postgresql();
functionFactory.arrayAppend_postgresql(); functionFactory.arrayAppend_postgresql();
functionFactory.arrayContainsAll_operator(); functionFactory.arrayContains_postgresql();
functionFactory.arrayOverlaps_operator(); functionFactory.arrayOverlaps_postgresql();
functionFactory.arrayContainsAllNullable_operator();
functionFactory.arrayOverlapsNullable_unnest();
functionFactory.arrayGet_bracket(); functionFactory.arrayGet_bracket();
functionFactory.arraySet_unnest(); functionFactory.arraySet_unnest();
functionFactory.arrayRemove(); functionFactory.arrayRemove();

View File

@ -311,22 +311,28 @@ public class H2Dialect extends Dialect {
functionFactory.hypotheticalOrderedSetAggregates(); functionFactory.hypotheticalOrderedSetAggregates();
functionFactory.array(); functionFactory.array();
functionFactory.arrayAggregate(); functionFactory.arrayAggregate();
functionFactory.arrayContains();
functionFactory.arrayContainsNull();
functionFactory.arrayLength_cardinality(); functionFactory.arrayLength_cardinality();
functionFactory.arrayConcat_operator(); functionFactory.arrayConcat_operator();
functionFactory.arrayPrepend_operator(); functionFactory.arrayPrepend_operator();
functionFactory.arrayAppend_operator(); functionFactory.arrayAppend_operator();
functionFactory.arrayContainsAll_h2(); functionFactory.arrayContains_h2( getMaximumArraySize() );
functionFactory.arrayOverlaps_h2(); functionFactory.arrayOverlaps_h2( getMaximumArraySize() );
functionFactory.arrayContainsAllNullable_h2();
functionFactory.arrayOverlapsNullable_h2();
functionFactory.arrayGet_h2(); functionFactory.arrayGet_h2();
functionFactory.arraySet_h2(); functionFactory.arraySet_h2( getMaximumArraySize() );
functionFactory.arrayRemove_h2(); functionFactory.arrayRemove_h2( getMaximumArraySize() );
functionFactory.arrayRemoveIndex_h2(); functionFactory.arrayRemoveIndex_h2( getMaximumArraySize() );
functionFactory.arraySlice(); functionFactory.arraySlice();
functionFactory.arrayReplace_h2(); functionFactory.arrayReplace_h2( getMaximumArraySize() );
}
/**
* H2 requires a very special emulation, because {@code unnest} is pretty much useless,
* due to https://github.com/h2database/h2database/issues/1815.
* This emulation uses {@code array_get}, {@code array_length} and {@code system_range} functions to roughly achieve the same,
* but requires that {@code system_range} is fed with a "maximum array size".
*/
protected int getMaximumArraySize() {
return 1000;
} }
@Override @Override

View File

@ -187,19 +187,15 @@ public class HSQLDialect extends Dialect {
// from v. 2.2.0 ROWNUM() is supported in all modes as the equivalent of Oracle ROWNUM // from v. 2.2.0 ROWNUM() is supported in all modes as the equivalent of Oracle ROWNUM
functionFactory.rownum(); functionFactory.rownum();
functionFactory.listagg_groupConcat(); functionFactory.listagg_groupConcat();
functionFactory.array(); functionFactory.array_hsql();
functionFactory.arrayAggregate(); functionFactory.arrayAggregate();
functionFactory.arrayContains_hsql();
functionFactory.arrayContainsNull_hsql();
functionFactory.arrayPosition_hsql(); functionFactory.arrayPosition_hsql();
functionFactory.arrayLength_cardinality(); functionFactory.arrayLength_cardinality();
functionFactory.arrayConcat_operator(); functionFactory.arrayConcat_operator();
functionFactory.arrayPrepend_operator(); functionFactory.arrayPrepend_operator();
functionFactory.arrayAppend_operator(); functionFactory.arrayAppend_operator();
functionFactory.arrayContainsAll_hsql(); functionFactory.arrayContains_hsql();
functionFactory.arrayOverlaps_hsql(); functionFactory.arrayOverlaps_hsql();
functionFactory.arrayContainsAllNullable_hsql();
functionFactory.arrayOverlapsNullable_unnest();
functionFactory.arrayGet_unnest(); functionFactory.arrayGet_unnest();
functionFactory.arraySet_hsql(); functionFactory.arraySet_hsql();
functionFactory.arrayRemove_hsql(); functionFactory.arrayRemove_hsql();

View File

@ -284,10 +284,10 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
); );
database.addAuxiliaryDatabaseObject( database.addAuxiliaryDatabaseObject(
new NamedAuxiliaryDatabaseObject( new NamedAuxiliaryDatabaseObject(
arrayTypeName + "_contains_all", arrayTypeName + "_contains",
database.getDefaultNamespace(), database.getDefaultNamespace(),
new String[]{ new String[]{
"create or replace function " + arrayTypeName + "_contains_all(haystack in " + arrayTypeName + "create or replace function " + arrayTypeName + "_contains(haystack in " + arrayTypeName +
", needle in " + arrayTypeName + ", nullable in number) return number deterministic is found number(1,0); begin " + ", needle in " + arrayTypeName + ", nullable in number) return number deterministic is found number(1,0); begin " +
"if haystack is null or needle is null then return null; end if; " + "if haystack is null or needle is null then return null; end if; " +
"for i in 1 .. needle.count loop " + "for i in 1 .. needle.count loop " +
@ -300,7 +300,7 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
"return 1; " + "return 1; " +
"end;" "end;"
}, },
new String[] { "drop function " + arrayTypeName + "_contains_all" }, new String[] { "drop function " + arrayTypeName + "_contains" },
emptySet(), emptySet(),
false false
) )

View File

@ -314,17 +314,13 @@ public class OracleDialect extends Dialect {
functionFactory.array_oracle(); functionFactory.array_oracle();
functionFactory.arrayAggregate_jsonArrayagg(); functionFactory.arrayAggregate_jsonArrayagg();
functionFactory.arrayContains_oracle();
functionFactory.arrayContainsNull_oracle();
functionFactory.arrayPosition_oracle(); functionFactory.arrayPosition_oracle();
functionFactory.arrayLength_oracle(); functionFactory.arrayLength_oracle();
functionFactory.arrayConcat_oracle(); functionFactory.arrayConcat_oracle();
functionFactory.arrayPrepend_oracle(); functionFactory.arrayPrepend_oracle();
functionFactory.arrayAppend_oracle(); functionFactory.arrayAppend_oracle();
functionFactory.arrayContainsAll_oracle(); functionFactory.arrayContains_oracle();
functionFactory.arrayOverlaps_oracle(); functionFactory.arrayOverlaps_oracle();
functionFactory.arrayContainsAllNullable_oracle();
functionFactory.arrayOverlapsNullable_oracle();
functionFactory.arrayGet_oracle(); functionFactory.arrayGet_oracle();
functionFactory.arraySet_oracle(); functionFactory.arraySet_oracle();
functionFactory.arrayRemove_oracle(); functionFactory.arrayRemove_oracle();

View File

@ -629,19 +629,15 @@ public class PostgreSQLDialect extends Dialect {
functionFactory.locate_positionSubstring(); functionFactory.locate_positionSubstring();
functionFactory.windowFunctions(); functionFactory.windowFunctions();
functionFactory.listagg_stringAgg( "varchar" ); functionFactory.listagg_stringAgg( "varchar" );
functionFactory.array_casting(); functionFactory.array_postgresql();
functionFactory.arrayAggregate(); functionFactory.arrayAggregate();
functionFactory.arrayContains_operator();
functionFactory.arrayContainsNull_array_position();
functionFactory.arrayPosition_postgresql(); functionFactory.arrayPosition_postgresql();
functionFactory.arrayLength_cardinality(); functionFactory.arrayLength_cardinality();
functionFactory.arrayConcat_postgresql(); functionFactory.arrayConcat_postgresql();
functionFactory.arrayPrepend_postgresql(); functionFactory.arrayPrepend_postgresql();
functionFactory.arrayAppend_postgresql(); functionFactory.arrayAppend_postgresql();
functionFactory.arrayContainsAll_operator(); functionFactory.arrayContains_postgresql();
functionFactory.arrayOverlaps_operator(); functionFactory.arrayOverlaps_postgresql();
functionFactory.arrayContainsAllNullable_operator();
functionFactory.arrayOverlapsNullable_unnest();
functionFactory.arrayGet_bracket(); functionFactory.arrayGet_bracket();
functionFactory.arraySet_unnest(); functionFactory.arraySet_unnest();
functionFactory.arrayRemove(); functionFactory.arrayRemove();

View File

@ -479,7 +479,7 @@ public class SpannerDialect extends Dialect {
functionFactory.listagg_stringAgg( "string" ); functionFactory.listagg_stringAgg( "string" );
functionFactory.inverseDistributionOrderedSetAggregates(); functionFactory.inverseDistributionOrderedSetAggregates();
functionFactory.hypotheticalOrderedSetAggregates(); functionFactory.hypotheticalOrderedSetAggregates();
functionFactory.array_withoutKeyword(); functionFactory.array_spanner();
} }
@Override @Override

View File

@ -129,7 +129,7 @@ public class AggregateWindowEmulationQueryTransformer implements QueryTransforme
if ( expression == windowFunction ) { if ( expression == windowFunction ) {
finalExpression = new SelfRenderingAggregateFunctionSqlAstExpression( finalExpression = new SelfRenderingAggregateFunctionSqlAstExpression(
"min", "min",
(sqlAppender, sqlAstArguments, walker1) -> { (sqlAppender, sqlAstArguments, returnType, walker1) -> {
sqlAppender.appendSql( "min(" ); sqlAppender.appendSql( "min(" );
sqlAstArguments.get( 0 ).accept( walker1 ); sqlAstArguments.get( 0 ).accept( walker1 );
sqlAppender.append( ')' ); sqlAppender.append( ')' );

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
@ -62,8 +63,12 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
} }
@Override @Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) { public void render(
render( sqlAppender, sqlAstArguments, null, walker ); SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, returnType, walker );
} }
@Override @Override
@ -71,6 +76,7 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
final boolean caseWrapper = filter != null && !translator.supportsFilterClause(); final boolean caseWrapper = filter != null && !translator.supportsFilterClause();
sqlAppender.appendSql( "avg(" ); sqlAppender.appendSql( "avg(" );
@ -108,7 +114,12 @@ public class AvgFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
final JdbcMapping sourceMapping = realArg.getExpressionType().getSingleJdbcMapping(); final JdbcMapping sourceMapping = realArg.getExpressionType().getSingleJdbcMapping();
// Only cast to float/double if this is an integer // Only cast to float/double if this is an integer
if ( sourceMapping.getJdbcType().isInteger() ) { if ( sourceMapping.getJdbcType().isInteger() ) {
castFunction.render( sqlAppender, Arrays.asList( realArg, new CastTarget(doubleType) ), translator ); castFunction.render(
sqlAppender,
Arrays.asList( realArg, new CastTarget( doubleType ) ),
doubleType,
translator
);
} }
else { else {
translator.render( realArg, defaultArgumentRenderingMode ); translator.render( realArg, defaultArgumentRenderingMode );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -44,6 +45,7 @@ public class CaseLeastGreatestEmulation
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final int numberOfArguments = arguments.size(); final int numberOfArguments = arguments.size();
if ( numberOfArguments > 1 ) { if ( numberOfArguments > 1 ) {

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -57,7 +58,11 @@ public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
} }
@Override @Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> arguments, SqlAstTranslator<?> walker) { public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final Expression source = (Expression) arguments.get( 0 ); final Expression source = (Expression) arguments.get( 0 );
final JdbcMapping sourceMapping = source.getExpressionType().getSingleJdbcMapping(); final JdbcMapping sourceMapping = source.getExpressionType().getSingleJdbcMapping();
final CastType sourceType = getCastType( sourceMapping ); final CastType sourceType = getCastType( sourceMapping );

View File

@ -12,6 +12,7 @@ import java.util.List;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.Size;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -64,7 +65,11 @@ public class CastingConcatFunction extends AbstractSqmSelfRenderingFunctionDescr
} }
@Override @Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) { public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
// Apache Derby and DB2 add up the sizes of operands for concat operations and has a limit of 4000/32k until // Apache Derby and DB2 add up the sizes of operands for concat operations and has a limit of 4000/32k until
// it changes the data type to long varchar, at which point problems start arising, because a long varchar // it changes the data type to long varchar, at which point problems start arising, because a long varchar
// can't be compared with a regular varchar for some reason. // can't be compared with a regular varchar for some reason.

View File

@ -10,6 +10,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
@ -68,6 +69,7 @@ public class ChrLiteralEmulation extends AbstractSqmSelfRenderingFunctionDescrip
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final QueryLiteral<Number> literal = (QueryLiteral<Number>) arguments.get( 0 ); final QueryLiteral<Number> literal = (QueryLiteral<Number>) arguments.get( 0 );

View File

@ -19,9 +19,10 @@ import org.hibernate.dialect.function.array.ArrayArgumentValidator;
import org.hibernate.dialect.function.array.ArrayConcatElementFunction; import org.hibernate.dialect.function.array.ArrayConcatElementFunction;
import org.hibernate.dialect.function.array.ArrayConcatFunction; import org.hibernate.dialect.function.array.ArrayConcatFunction;
import org.hibernate.dialect.function.array.ArrayConstructorFunction; import org.hibernate.dialect.function.array.ArrayConstructorFunction;
import org.hibernate.dialect.function.array.ArrayContainsQuantifiedOperatorFunction;
import org.hibernate.dialect.function.array.ArrayContainsOperatorFunction; import org.hibernate.dialect.function.array.ArrayContainsOperatorFunction;
import org.hibernate.dialect.function.array.ArrayContainsQuantifiedUnnestFunction; import org.hibernate.dialect.function.array.ArrayContainsUnnestFunction;
import org.hibernate.dialect.function.array.ArrayOverlapsOperatorFunction;
import org.hibernate.dialect.function.array.ArrayOverlapsUnnestFunction;
import org.hibernate.dialect.function.array.ArrayGetUnnestFunction; import org.hibernate.dialect.function.array.ArrayGetUnnestFunction;
import org.hibernate.dialect.function.array.ArrayRemoveIndexUnnestFunction; import org.hibernate.dialect.function.array.ArrayRemoveIndexUnnestFunction;
import org.hibernate.dialect.function.array.ArrayReplaceUnnestFunction; import org.hibernate.dialect.function.array.ArrayReplaceUnnestFunction;
@ -29,17 +30,18 @@ import org.hibernate.dialect.function.array.ArraySetUnnestFunction;
import org.hibernate.dialect.function.array.ArraySliceUnnestFunction; import org.hibernate.dialect.function.array.ArraySliceUnnestFunction;
import org.hibernate.dialect.function.array.ArrayViaArgumentReturnTypeResolver; import org.hibernate.dialect.function.array.ArrayViaArgumentReturnTypeResolver;
import org.hibernate.dialect.function.array.ElementViaArrayArgumentReturnTypeResolver; import org.hibernate.dialect.function.array.ElementViaArrayArgumentReturnTypeResolver;
import org.hibernate.dialect.function.array.H2ArrayContainsQuantifiedEmulation; import org.hibernate.dialect.function.array.H2ArrayContainsFunction;
import org.hibernate.dialect.function.array.H2ArrayOverlapsFunction;
import org.hibernate.dialect.function.array.H2ArrayRemoveFunction; import org.hibernate.dialect.function.array.H2ArrayRemoveFunction;
import org.hibernate.dialect.function.array.H2ArrayRemoveIndexFunction; import org.hibernate.dialect.function.array.H2ArrayRemoveIndexFunction;
import org.hibernate.dialect.function.array.H2ArrayReplaceFunction; import org.hibernate.dialect.function.array.H2ArrayReplaceFunction;
import org.hibernate.dialect.function.array.H2ArraySetFunction; import org.hibernate.dialect.function.array.H2ArraySetFunction;
import org.hibernate.dialect.function.array.HSQLArrayConstructorFunction;
import org.hibernate.dialect.function.array.HSQLArrayPositionFunction; import org.hibernate.dialect.function.array.HSQLArrayPositionFunction;
import org.hibernate.dialect.function.array.HSQLArrayRemoveFunction; import org.hibernate.dialect.function.array.HSQLArrayRemoveFunction;
import org.hibernate.dialect.function.array.HSQLArraySetFunction; import org.hibernate.dialect.function.array.HSQLArraySetFunction;
import org.hibernate.dialect.function.array.OracleArrayConcatElementFunction; import org.hibernate.dialect.function.array.OracleArrayConcatElementFunction;
import org.hibernate.dialect.function.array.OracleArrayConcatFunction; import org.hibernate.dialect.function.array.OracleArrayConcatFunction;
import org.hibernate.dialect.function.array.OracleArrayContainsAllFunction;
import org.hibernate.dialect.function.array.OracleArrayOverlapsFunction; import org.hibernate.dialect.function.array.OracleArrayOverlapsFunction;
import org.hibernate.dialect.function.array.OracleArrayGetFunction; import org.hibernate.dialect.function.array.OracleArrayGetFunction;
import org.hibernate.dialect.function.array.OracleArrayLengthFunction; import org.hibernate.dialect.function.array.OracleArrayLengthFunction;
@ -52,11 +54,10 @@ import org.hibernate.dialect.function.array.OracleArraySliceFunction;
import org.hibernate.dialect.function.array.PostgreSQLArrayConcatElementFunction; import org.hibernate.dialect.function.array.PostgreSQLArrayConcatElementFunction;
import org.hibernate.dialect.function.array.PostgreSQLArrayConcatFunction; import org.hibernate.dialect.function.array.PostgreSQLArrayConcatFunction;
import org.hibernate.dialect.function.array.PostgreSQLArrayPositionFunction; import org.hibernate.dialect.function.array.PostgreSQLArrayPositionFunction;
import org.hibernate.dialect.function.array.CastingArrayConstructorFunction; import org.hibernate.dialect.function.array.PostgreSQLArrayConstructorFunction;
import org.hibernate.dialect.function.array.OracleArrayAggEmulation; import org.hibernate.dialect.function.array.OracleArrayAggEmulation;
import org.hibernate.dialect.function.array.OracleArrayConstructorFunction; import org.hibernate.dialect.function.array.OracleArrayConstructorFunction;
import org.hibernate.dialect.function.array.OracleArrayContainsFunction; import org.hibernate.dialect.function.array.OracleArrayContainsFunction;
import org.hibernate.dialect.function.array.OracleArrayContainsNullFunction;
import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -2589,17 +2590,24 @@ public class CommonFunctionFactory {
functionRegistry.register( "array", new ArrayConstructorFunction( true ) ); functionRegistry.register( "array", new ArrayConstructorFunction( true ) );
} }
/**
* H2, HSQL array() constructor function
*/
public void array_hsql() {
functionRegistry.register( "array", new HSQLArrayConstructorFunction() );
}
/** /**
* CockroachDB and PostgreSQL array() constructor function * CockroachDB and PostgreSQL array() constructor function
*/ */
public void array_casting() { public void array_postgresql() {
functionRegistry.register( "array", new CastingArrayConstructorFunction() ); functionRegistry.register( "array", new PostgreSQLArrayConstructorFunction() );
} }
/** /**
* Google Spanner array() constructor function * Google Spanner array() constructor function
*/ */
public void array_withoutKeyword() { public void array_spanner() {
functionRegistry.register( "array", new ArrayConstructorFunction( false ) ); functionRegistry.register( "array", new ArrayConstructorFunction( false ) );
} }
@ -2627,153 +2635,58 @@ public class CommonFunctionFactory {
/** /**
* H2 array_contains() function * H2 array_contains() function
*/ */
public void arrayContains() { public void arrayContains_h2(int maximumArraySize) {
functionRegistry.namedDescriptorBuilder( "array_contains" ) functionRegistry.register(
.setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( booleanType ) ) "array_contains",
.setArgumentsValidator( new H2ArrayContainsFunction( false, maximumArraySize, typeConfiguration )
StandardArgumentsValidators.composite( );
StandardArgumentsValidators.exactly( 2 ), functionRegistry.register(
ArrayAndElementArgumentValidator.DEFAULT_INSTANCE "array_contains_nullable",
) new H2ArrayContainsFunction( true, maximumArraySize, typeConfiguration )
) );
.setArgumentTypeResolver( ArrayAndElementArgumentTypeResolver.DEFAULT_INSTANCE )
.setArgumentListSignature( "(ARRAY array, OBJECT element)" )
.register();
} }
/** /**
* HSQL array_contains() function * HSQL array_contains() function
*/ */
public void arrayContains_hsql() { public void arrayContains_hsql() {
functionRegistry.patternDescriptorBuilder( "array_contains", "position_array(?2 in ?1)>0" ) functionRegistry.register(
.setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( booleanType ) ) "array_contains",
.setArgumentsValidator( new ArrayContainsUnnestFunction( false, typeConfiguration )
StandardArgumentsValidators.composite( );
StandardArgumentsValidators.exactly( 2 ), functionRegistry.register(
ArrayAndElementArgumentValidator.DEFAULT_INSTANCE "array_contains_nullable",
) new ArrayContainsUnnestFunction( true, typeConfiguration )
) );
.setArgumentTypeResolver( ArrayAndElementArgumentTypeResolver.DEFAULT_INSTANCE )
.setArgumentListSignature( "(ARRAY array, OBJECT element)" )
.register();
} }
/** /**
* CockroachDB and PostgreSQL array contains operator * CockroachDB and PostgreSQL array contains operator
*/ */
public void arrayContains_operator() { public void arrayContains_postgresql() {
functionRegistry.register( "array_contains", new ArrayContainsOperatorFunction( typeConfiguration ) ); functionRegistry.register( "array_contains", new ArrayContainsOperatorFunction( false, typeConfiguration ) );
functionRegistry.register( "array_contains_nullable", new ArrayContainsOperatorFunction( true, typeConfiguration ) );
} }
/** /**
* Oracle array_contains() function * Oracle array_contains() function
*/ */
public void arrayContains_oracle() { public void arrayContains_oracle() {
functionRegistry.register( "array_contains", new OracleArrayContainsFunction( typeConfiguration ) ); functionRegistry.register( "array_contains", new OracleArrayContainsFunction( false, typeConfiguration ) );
} functionRegistry.register( "array_contains_nullable", new OracleArrayContainsFunction( true, typeConfiguration ) );
/**
* H2, HSQL array_contains_null() function
*/
public void arrayContainsNull() {
functionRegistry.patternDescriptorBuilder( "array_contains_null", "array_contains(?1,null)" )
.setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( booleanType ) )
.setArgumentsValidator(
StandardArgumentsValidators.composite(
StandardArgumentsValidators.exactly( 1 ),
ArrayArgumentValidator.DEFAULT_INSTANCE
)
)
.setArgumentListSignature( "(ARRAY array)" )
.register();
}
/**
* CockroachDB and PostgreSQL array contains null emulation
*/
public void arrayContainsNull_array_position() {
functionRegistry.patternDescriptorBuilder( "array_contains_null", "array_position(?1,null) is not null" )
.setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( booleanType ) )
.setArgumentsValidator(
StandardArgumentsValidators.composite(
StandardArgumentsValidators.exactly( 1 ),
ArrayArgumentValidator.DEFAULT_INSTANCE
)
)
.setArgumentListSignature( "(ARRAY array)" )
.register();
}
/**
* Oracle array_contains() function
*/
public void arrayContainsNull_oracle() {
functionRegistry.register( "array_contains_null", new OracleArrayContainsNullFunction( typeConfiguration ) );
}
/**
* CockroachDB and PostgreSQL array contains null emulation
*/
public void arrayContainsNull_hsql() {
functionRegistry.patternDescriptorBuilder( "array_contains_null", "exists(select 1 from unnest(?1) t(i) where t.i is null)" )
.setReturnTypeResolver( StandardFunctionReturnTypeResolvers.invariant( booleanType ) )
.setArgumentsValidator(
StandardArgumentsValidators.composite(
StandardArgumentsValidators.exactly( 1 ),
ArrayArgumentValidator.DEFAULT_INSTANCE
)
)
.setArgumentListSignature( "(ARRAY array)" )
.register();
}
/**
* H2 array_contains_all() function
*/
public void arrayContainsAll_h2() {
functionRegistry.register(
"array_contains_all",
new H2ArrayContainsQuantifiedEmulation( typeConfiguration, true, false )
);
}
/**
* HSQL array_contains_all() function
*/
public void arrayContainsAll_hsql() {
functionRegistry.register(
"array_contains_all",
new ArrayContainsQuantifiedUnnestFunction( typeConfiguration, true, false )
);
}
/**
* CockroachDB and PostgreSQL array contains all operator
*/
public void arrayContainsAll_operator() {
functionRegistry.register(
"array_contains_all",
new ArrayContainsQuantifiedOperatorFunction( typeConfiguration, true, false )
);
}
/**
* Oracle array_contains_all() function
*/
public void arrayContainsAll_oracle() {
functionRegistry.register(
"array_contains_all",
new OracleArrayContainsAllFunction( typeConfiguration, false )
);
} }
/** /**
* H2 array_overlaps() function * H2 array_overlaps() function
*/ */
public void arrayOverlaps_h2() { public void arrayOverlaps_h2(int maximumArraySize) {
functionRegistry.register( functionRegistry.register(
"array_overlaps", "array_overlaps",
new H2ArrayContainsQuantifiedEmulation( typeConfiguration, false, false ) new H2ArrayOverlapsFunction( false, maximumArraySize, typeConfiguration )
);
functionRegistry.register(
"array_overlaps_nullable",
new H2ArrayOverlapsFunction( true, maximumArraySize, typeConfiguration )
); );
} }
@ -2783,15 +2696,20 @@ public class CommonFunctionFactory {
public void arrayOverlaps_hsql() { public void arrayOverlaps_hsql() {
functionRegistry.register( functionRegistry.register(
"array_overlaps", "array_overlaps",
new ArrayContainsQuantifiedUnnestFunction( typeConfiguration, false, false ) new ArrayOverlapsUnnestFunction( false, typeConfiguration )
);
functionRegistry.register(
"array_overlaps_nullable",
new ArrayOverlapsUnnestFunction( true, typeConfiguration )
); );
} }
/** /**
* CockroachDB and PostgreSQL array overlaps operator * CockroachDB and PostgreSQL array overlaps operator
*/ */
public void arrayOverlaps_operator() { public void arrayOverlaps_postgresql() {
functionRegistry.register( "array_overlaps", new ArrayContainsQuantifiedOperatorFunction( typeConfiguration, false, false ) ); functionRegistry.register( "array_overlaps", new ArrayOverlapsOperatorFunction( false, typeConfiguration ) );
functionRegistry.register( "array_overlaps_nullable", new ArrayOverlapsOperatorFunction( true, typeConfiguration ) );
} }
/** /**
@ -2802,72 +2720,6 @@ public class CommonFunctionFactory {
"array_overlaps", "array_overlaps",
new OracleArrayOverlapsFunction( typeConfiguration, false ) new OracleArrayOverlapsFunction( typeConfiguration, false )
); );
}
/**
* H2 array_contains_all_nullable() function
*/
public void arrayContainsAllNullable_h2() {
functionRegistry.register(
"array_contains_all_nullable",
new H2ArrayContainsQuantifiedEmulation( typeConfiguration, true, true )
);
}
/**
* HSQL array_contains_all_nullable() function
*/
public void arrayContainsAllNullable_hsql() {
functionRegistry.register(
"array_contains_all_nullable",
new ArrayContainsQuantifiedUnnestFunction( typeConfiguration, true, true )
);
}
/**
* CockroachDB and PostgreSQL array contains all nullable operator
*/
public void arrayContainsAllNullable_operator() {
functionRegistry.register(
"array_contains_all_nullable",
new ArrayContainsQuantifiedOperatorFunction( typeConfiguration, true, true )
);
}
/**
* Oracle array_contains_all_nullable() function
*/
public void arrayContainsAllNullable_oracle() {
functionRegistry.register(
"array_contains_all_nullable",
new OracleArrayContainsAllFunction( typeConfiguration, true )
);
}
/**
* H2 array_overlaps_nullable() function
*/
public void arrayOverlapsNullable_h2() {
functionRegistry.register(
"array_overlaps_nullable",
new H2ArrayContainsQuantifiedEmulation( typeConfiguration, false, true )
);
}
/**
* HSQL, CockroachDB and PostgreSQL array_overlaps_nullable() function
*/
public void arrayOverlapsNullable_unnest() {
functionRegistry.register(
"array_overlaps_nullable",
new ArrayContainsQuantifiedUnnestFunction( typeConfiguration, false, true )
);
}
/**
* Oracle array_overlaps_nullable() function
*/
public void arrayOverlapsNullable_oracle() {
functionRegistry.register( functionRegistry.register(
"array_overlaps_nullable", "array_overlaps_nullable",
new OracleArrayOverlapsFunction( typeConfiguration, true ) new OracleArrayOverlapsFunction( typeConfiguration, true )
@ -3031,8 +2883,8 @@ public class CommonFunctionFactory {
/** /**
* H2 array_set() function * H2 array_set() function
*/ */
public void arraySet_h2() { public void arraySet_h2(int maximumArraySize) {
functionRegistry.register( "array_set", new H2ArraySetFunction() ); functionRegistry.register( "array_set", new H2ArraySetFunction( maximumArraySize ) );
} }
/** /**
@ -3075,8 +2927,8 @@ public class CommonFunctionFactory {
/** /**
* H2 array_remove() function * H2 array_remove() function
*/ */
public void arrayRemove_h2() { public void arrayRemove_h2(int maximumArraySize) {
functionRegistry.register( "array_remove", new H2ArrayRemoveFunction() ); functionRegistry.register( "array_remove", new H2ArrayRemoveFunction( maximumArraySize ) );
} }
/** /**
@ -3096,8 +2948,8 @@ public class CommonFunctionFactory {
/** /**
* H2 array_remove_index() function * H2 array_remove_index() function
*/ */
public void arrayRemoveIndex_h2() { public void arrayRemoveIndex_h2(int maximumArraySize) {
functionRegistry.register( "array_remove_index", new H2ArrayRemoveIndexFunction() ); functionRegistry.register( "array_remove_index", new H2ArrayRemoveIndexFunction( maximumArraySize ) );
} }
/** /**
@ -3175,8 +3027,8 @@ public class CommonFunctionFactory {
/** /**
* H2 array_replace() function * H2 array_replace() function
*/ */
public void arrayReplace_h2() { public void arrayReplace_h2(int maximumArraySize) {
functionRegistry.register( "array_replace", new H2ArrayReplaceFunction() ); functionRegistry.register( "array_replace", new H2ArrayReplaceFunction( maximumArraySize ) );
} }
/** /**

View File

@ -9,6 +9,7 @@ package org.hibernate.dialect.function;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
@ -48,6 +49,7 @@ public class ConcatPipeFunction extends AbstractSqmSelfRenderingFunctionDescript
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
String separator = "("; String separator = "(";
for ( int i = 0; i < sqlAstArguments.size(); i++ ) { for ( int i = 0; i < sqlAstArguments.size(); i++ ) {

View File

@ -13,6 +13,7 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer; import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
@ -133,8 +134,12 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
} }
@Override @Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) { public void render(
render( sqlAppender, sqlAstArguments, null, walker ); SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, returnType, walker );
} }
@Override @Override
@ -142,6 +147,7 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
final boolean caseWrapper = filter != null && !translator.supportsFilterClause(); final boolean caseWrapper = filter != null && !translator.supportsFilterClause();
final SqlAstNode arg = sqlAstArguments.get( 0 ); final SqlAstNode arg = sqlAstArguments.get( 0 );
@ -207,15 +213,15 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
sqlAppender.appendSql( "''" ); sqlAppender.appendSql( "''" );
} }
sqlAppender.appendSql( SqlAppender.COMMA_SEPARATOR_CHAR ); sqlAppender.appendSql( SqlAppender.COMMA_SEPARATOR_CHAR );
chr.render( sqlAppender, chrArguments, translator ); chr.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( "),'')," ); sqlAppender.appendSql( "),'')," );
chr.render( sqlAppender, chrArguments, translator ); chr.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( concatOperator ); sqlAppender.appendSql( concatOperator );
sqlAppender.appendSql( "'" ); sqlAppender.appendSql( "'" );
sqlAppender.appendSql( argumentNumber ); sqlAppender.appendSql( argumentNumber );
sqlAppender.appendSql( "')" ); sqlAppender.appendSql( "')" );
sqlAppender.appendSql( concatOperator ); sqlAppender.appendSql( concatOperator );
chr.render( sqlAppender, chrArguments, translator ); chr.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( concatOperator ); sqlAppender.appendSql( concatOperator );
sqlAppender.appendSql( "coalesce(nullif(coalesce(" ); sqlAppender.appendSql( "coalesce(nullif(coalesce(" );
needsConcat = renderCastedArgument( sqlAppender, translator, expressions.get( i ) ); needsConcat = renderCastedArgument( sqlAppender, translator, expressions.get( i ) );
@ -226,9 +232,9 @@ public class CountFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
sqlAppender.appendSql( "''" ); sqlAppender.appendSql( "''" );
} }
sqlAppender.appendSql( SqlAppender.COMMA_SEPARATOR_CHAR ); sqlAppender.appendSql( SqlAppender.COMMA_SEPARATOR_CHAR );
chr.render( sqlAppender, chrArguments, translator ); chr.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( "),'')," ); sqlAppender.appendSql( "),'')," );
chr.render( sqlAppender, chrArguments, translator ); chr.render( sqlAppender, chrArguments, returnType, translator );
sqlAppender.appendSql( concatOperator ); sqlAppender.appendSql( concatOperator );
sqlAppender.appendSql( "'" ); sqlAppender.appendSql( "'" );
sqlAppender.appendSql( argumentNumber ); sqlAppender.appendSql( argumentNumber );

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.dialect.function; package org.hibernate.dialect.function;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
@ -41,6 +42,7 @@ public class CurrentFunction
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
sqlAppender.appendSql( sql ); sqlAppender.appendSql( sql );
} }

View File

@ -8,20 +8,11 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.function.FunctionRenderingSupport;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.Format;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.TemporalType; import jakarta.persistence.TemporalType;
@ -49,6 +40,7 @@ public class DB2FormatEmulation extends FormatFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression datetime = (Expression) arguments.get( 0 ); final Expression datetime = (Expression) arguments.get( 0 );
sqlAppender.appendSql( "varchar_format(" ); sqlAppender.appendSql( "varchar_format(" );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -41,6 +42,7 @@ public class DB2PositionFunction extends AbstractSqmSelfRenderingFunctionDescrip
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final int argumentCount = arguments.size(); final int argumentCount = arguments.size();
sqlAppender.appendSql( "position(" ); sqlAppender.appendSql( "position(" );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.FunctionParameterType;
@ -43,6 +44,7 @@ public class DB2SubstringFunction extends AbstractSqmSelfRenderingFunctionDescri
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final int argumentCount = arguments.size(); final int argumentCount = arguments.size();
sqlAppender.appendSql( "substring(" ); sqlAppender.appendSql( "substring(" );

View File

@ -13,7 +13,7 @@ import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionRenderingSupport; import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -39,7 +39,7 @@ import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEM
* *
* @author Marco Belladelli * @author Marco Belladelli
*/ */
public class DateTruncEmulation extends AbstractSqmFunctionDescriptor implements FunctionRenderingSupport { public class DateTruncEmulation extends AbstractSqmFunctionDescriptor implements FunctionRenderer {
protected final String toDateFunction; protected final String toDateFunction;
private final SqmFormat sqmFormat; private final SqmFormat sqmFormat;
@ -58,6 +58,7 @@ public class DateTruncEmulation extends AbstractSqmFunctionDescriptor implements
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
sqlAppender.appendSql( toDateFunction ); sqlAppender.appendSql( toDateFunction );
sqlAppender.append( '(' ); sqlAppender.append( '(' );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -46,6 +47,7 @@ public class DerbyLpadEmulation
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final SqlAstNode string = arguments.get( 0 ); final SqlAstNode string = arguments.get( 0 );
final SqlAstNode length = arguments.get( 1 ); final SqlAstNode length = arguments.get( 1 );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -46,6 +47,7 @@ public class DerbyRpadEmulation
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final SqlAstNode string = arguments.get( 0 ); final SqlAstNode string = arguments.get( 0 );
final SqlAstNode length = arguments.get( 1 ); final SqlAstNode length = arguments.get( 1 );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
@ -70,6 +71,7 @@ public class EveryAnyEmulation extends AbstractSqmSelfRenderingFunctionDescripto
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
if ( trueLiteral != null ) { if ( trueLiteral != null ) {
sqlAppender.appendSql( "case when " ); sqlAppender.appendSql( "case when " );
@ -108,7 +110,9 @@ public class EveryAnyEmulation extends AbstractSqmSelfRenderingFunctionDescripto
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) { SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments,
this.render( sqlAppender, sqlAstArguments, null, walker ); ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
this.render( sqlAppender, sqlAstArguments, null, returnType, walker );
} }
} }

View File

@ -13,7 +13,7 @@ import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionRenderingSupport; import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -48,8 +48,7 @@ import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEM
* *
* @author Gavin King * @author Gavin King
*/ */
public class ExtractFunction public class ExtractFunction extends AbstractSqmFunctionDescriptor implements FunctionRenderer {
extends AbstractSqmFunctionDescriptor implements FunctionRenderingSupport {
private final Dialect dialect; private final Dialect dialect;
@ -70,6 +69,7 @@ public class ExtractFunction
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final ExtractUnit field = (ExtractUnit) sqlAstArguments.get( 0 ); final ExtractUnit field = (ExtractUnit) sqlAstArguments.get( 0 );
final TemporalUnit unit = field.getUnit(); final TemporalUnit unit = field.getUnit();
@ -100,7 +100,7 @@ public class ExtractFunction
); );
return new SelfRenderingSqmFunction<>( return new SelfRenderingSqmFunction<>(
this, this,
(sqlAppender, sqlAstArguments, walker) -> sqlAstArguments.get( 0 ).accept( walker ), (sqlAppender, sqlAstArguments, returnType, walker) -> sqlAstArguments.get( 0 ).accept( walker ),
Collections.singletonList( offsetPath ), Collections.singletonList( offsetPath ),
null, null,
null, null,

View File

@ -20,6 +20,7 @@ import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.FunctionRenderingSupport; import org.hibernate.query.sqm.function.FunctionRenderingSupport;
import org.hibernate.query.sqm.function.MultipatternSqmFunctionDescriptor; import org.hibernate.query.sqm.function.MultipatternSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression; import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
@ -61,7 +62,7 @@ import static org.hibernate.query.sqm.produce.function.FunctionParameterType.TEM
* *
* @author Christian Beikov * @author Christian Beikov
*/ */
public class FormatFunction extends AbstractSqmFunctionDescriptor implements FunctionRenderingSupport { public class FormatFunction extends AbstractSqmFunctionDescriptor implements FunctionRenderer {
private final String nativeFunctionName; private final String nativeFunctionName;
private final boolean reversedArguments; private final boolean reversedArguments;
@ -103,6 +104,7 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
sqlAppender.appendSql( nativeFunctionName ); sqlAppender.appendSql( nativeFunctionName );
sqlAppender.append( '(' ); sqlAppender.append( '(' );
@ -171,6 +173,10 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
private final boolean supportsPatternLiterals; private final boolean supportsPatternLiterals;
private final TypeConfiguration typeConfiguration; private final TypeConfiguration typeConfiguration;
/**
* @deprecated Use {@link #FormatSqmFunction(SqmFunctionDescriptor, FunctionRenderer, List, ReturnableType, ArgumentsValidator, FunctionReturnTypeResolver, boolean, QueryEngine)} instead
*/
@Deprecated(forRemoval = true)
public FormatSqmFunction( public FormatSqmFunction(
SqmFunctionDescriptor descriptor, SqmFunctionDescriptor descriptor,
FunctionRenderingSupport renderingSupport, FunctionRenderingSupport renderingSupport,
@ -194,6 +200,29 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
this.typeConfiguration = queryEngine.getTypeConfiguration(); this.typeConfiguration = queryEngine.getTypeConfiguration();
} }
public FormatSqmFunction(
SqmFunctionDescriptor descriptor,
FunctionRenderer renderer,
List<? extends SqmTypedNode<?>> arguments,
ReturnableType<T> impliedResultType,
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver,
boolean supportsPatternLiterals,
QueryEngine queryEngine) {
super(
descriptor,
renderer,
arguments,
impliedResultType,
argumentsValidator,
returnTypeResolver,
queryEngine.getCriteriaBuilder(),
"format"
);
this.supportsPatternLiterals = supportsPatternLiterals;
this.typeConfiguration = queryEngine.getTypeConfiguration();
}
@Override @Override
public Expression convertToSqlAst(SqmToSqlAstConverter walker) { public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker ); final List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
@ -293,7 +322,7 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
formatExpression, formatExpression,
new SelfRenderingFunctionSqlAstExpression( new SelfRenderingFunctionSqlAstExpression(
getFunctionName(), getFunctionName(),
getRenderingSupport(), getFunctionRenderer(),
List.of( List.of(
arguments.get( 0 ), arguments.get( 0 ),
new QueryLiteral<>( formatPart, stringType ) new QueryLiteral<>( formatPart, stringType )
@ -419,7 +448,7 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
formatExpression, formatExpression,
new SelfRenderingFunctionSqlAstExpression( new SelfRenderingFunctionSqlAstExpression(
getFunctionName(), getFunctionName(),
getRenderingSupport(), getFunctionRenderer(),
List.of( arguments.get( 0 ), new Format( chunks[i] ) ), List.of( arguments.get( 0 ), new Format( chunks[i] ) ),
resultType, resultType,
mappingModelExpressible mappingModelExpressible
@ -440,7 +469,7 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
} }
return new SelfRenderingFunctionSqlAstExpression( return new SelfRenderingFunctionSqlAstExpression(
getFunctionName(), getFunctionName(),
getRenderingSupport(), getFunctionRenderer(),
arguments, arguments,
resultType, resultType,
mappingModelExpressible mappingModelExpressible

View File

@ -9,6 +9,7 @@ package org.hibernate.dialect.function;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
@ -42,8 +43,9 @@ public class HypotheticalSetFunction extends AbstractSqmSelfRenderingFunctionDes
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -51,8 +53,9 @@ public class HypotheticalSetFunction extends AbstractSqmSelfRenderingFunctionDes
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -61,6 +64,7 @@ public class HypotheticalSetFunction extends AbstractSqmSelfRenderingFunctionDes
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
List<SortSpecification> withinGroup, List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
if ( filter != null && !translator.supportsFilterClause() ) { if ( filter != null && !translator.supportsFilterClause() ) {
throw new IllegalArgumentException( "Can't emulate filter clause for inverse distribution function [" + getName() + "]" ); throw new IllegalArgumentException( "Can't emulate filter clause for inverse distribution function [" + getName() + "]" );

View File

@ -101,7 +101,7 @@ public class HypotheticalSetWindowEmulation extends HypotheticalSetFunction {
} }
final SelfRenderingFunctionSqlAstExpression function = new SelfRenderingOrderedSetAggregateFunctionSqlAstExpression( final SelfRenderingFunctionSqlAstExpression function = new SelfRenderingOrderedSetAggregateFunctionSqlAstExpression(
getFunctionName(), getFunctionName(),
getRenderingSupport(), getFunctionRenderer(),
Collections.emptyList(), Collections.emptyList(),
getFilter() == null ? null : (Predicate) getFilter().accept( walker ), getFilter() == null ? null : (Predicate) getFilter().accept( walker ),
Collections.emptyList(), Collections.emptyList(),

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.BinaryArithmeticOperator; import org.hibernate.query.sqm.BinaryArithmeticOperator;
import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression; import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
@ -53,6 +54,7 @@ public class IntegralTimestampaddFunction
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final DurationUnit field = (DurationUnit) arguments.get( 0 ); final DurationUnit field = (DurationUnit) arguments.get( 0 );
@ -64,7 +66,7 @@ public class IntegralTimestampaddFunction
renderWithUnitConversion( sqlAppender, magnitude, to, walker, field, unit ); renderWithUnitConversion( sqlAppender, magnitude, to, walker, field, unit );
} }
else { else {
super.render( sqlAppender, arguments, walker ); super.render( sqlAppender, arguments, returnType, walker );
} }
} }

View File

@ -75,8 +75,9 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -84,8 +85,9 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -94,6 +96,7 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
List<SortSpecification> withinGroup, List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
if ( filter != null && !translator.supportsFilterClause() ) { if ( filter != null && !translator.supportsFilterClause() ) {
throw new IllegalArgumentException( "Can't emulate filter clause for inverse distribution function [" + getName() + "]" ); throw new IllegalArgumentException( "Can't emulate filter clause for inverse distribution function [" + getName() + "]" );

View File

@ -96,7 +96,7 @@ public class InverseDistributionWindowEmulation extends InverseDistributionFunct
} }
final SelfRenderingFunctionSqlAstExpression function = new SelfRenderingOrderedSetAggregateFunctionSqlAstExpression( final SelfRenderingFunctionSqlAstExpression function = new SelfRenderingOrderedSetAggregateFunctionSqlAstExpression(
getFunctionName(), getFunctionName(),
getRenderingSupport(), getFunctionRenderer(),
arguments, arguments,
getFilter() == null ? null : (Predicate) getFilter().accept( walker ), getFilter() == null ? null : (Predicate) getFilter().accept( walker ),
withinGroup, withinGroup,

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.FunctionParameterType; import org.hibernate.query.sqm.produce.function.FunctionParameterType;
@ -54,6 +55,7 @@ public class LengthFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression expression = (Expression) sqlAstArguments.get( 0 ); final Expression expression = (Expression) sqlAstArguments.get( 0 );
final JdbcType jdbcType = expression.getExpressionType().getSingleJdbcMapping().getJdbcType(); final JdbcType jdbcType = expression.getExpressionType().getSingleJdbcMapping().getJdbcType();

View File

@ -9,6 +9,7 @@ package org.hibernate.dialect.function;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
@ -52,8 +53,9 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -61,8 +63,9 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -71,6 +74,7 @@ public class ListaggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
List<SortSpecification> withinGroup, List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
final boolean caseWrapper = filter != null && !translator.supportsFilterClause(); final boolean caseWrapper = filter != null && !translator.supportsFilterClause();
sqlAppender.appendSql( "listagg(" ); sqlAppender.appendSql( "listagg(" );

View File

@ -9,6 +9,7 @@ package org.hibernate.dialect.function;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
@ -52,8 +53,9 @@ public class ListaggGroupConcatEmulation extends AbstractSqmSelfRenderingFunctio
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -61,8 +63,9 @@ public class ListaggGroupConcatEmulation extends AbstractSqmSelfRenderingFunctio
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -71,6 +74,7 @@ public class ListaggGroupConcatEmulation extends AbstractSqmSelfRenderingFunctio
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
List<SortSpecification> withinGroup, List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
final boolean caseWrapper = filter != null && !translator.supportsFilterClause(); final boolean caseWrapper = filter != null && !translator.supportsFilterClause();
sqlAppender.appendSql( "group_concat(" ); sqlAppender.appendSql( "group_concat(" );

View File

@ -10,6 +10,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
@ -65,8 +66,9 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -74,8 +76,9 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -84,6 +87,7 @@ public class ListaggStringAggEmulation extends AbstractSqmSelfRenderingFunctionD
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
List<SortSpecification> withinGroup, List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
final boolean caseWrapper = filter != null && !translator.supportsFilterClause(); final boolean caseWrapper = filter != null && !translator.supportsFilterClause();
sqlAppender.appendSql( functionName ); sqlAppender.appendSql( functionName );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
@ -54,6 +55,7 @@ public class MinMaxCaseEveryAnyEmulation extends AbstractSqmSelfRenderingFunctio
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
if ( every ) { if ( every ) {
sqlAppender.appendSql( "min(case when " ); sqlAppender.appendSql( "min(case when " );
@ -77,7 +79,10 @@ public class MinMaxCaseEveryAnyEmulation extends AbstractSqmSelfRenderingFunctio
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) { SqlAppender sqlAppender,
this.render( sqlAppender, sqlAstArguments, null, walker ); List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
this.render( sqlAppender, sqlAstArguments, null, returnType, walker );
} }
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
@ -37,6 +38,7 @@ public class ModeStatsModeEmulation extends InverseDistributionFunction {
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
List<SortSpecification> withinGroup, List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
final boolean caseWrapper = filter != null && !translator.supportsFilterClause(); final boolean caseWrapper = filter != null && !translator.supportsFilterClause();
sqlAppender.appendSql( "stats_mode(" ); sqlAppender.appendSql( "stats_mode(" );

View File

@ -12,6 +12,7 @@ import java.util.List;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.FunctionRenderingSupport; import org.hibernate.query.sqm.function.FunctionRenderingSupport;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
@ -45,11 +46,11 @@ public class OracleTruncFunction extends TruncFunction {
ReturnableType<T> impliedResultType, ReturnableType<T> impliedResultType,
QueryEngine queryEngine) { QueryEngine queryEngine) {
final List<SqmTypedNode<?>> args = new ArrayList<>( arguments ); final List<SqmTypedNode<?>> args = new ArrayList<>( arguments );
final FunctionRenderingSupport renderingSupport; final FunctionRenderer renderer;
final ArgumentsValidator argumentsValidator; final ArgumentsValidator argumentsValidator;
if ( arguments.size() == 2 && arguments.get( 1 ) instanceof SqmExtractUnit ) { if ( arguments.size() == 2 && arguments.get( 1 ) instanceof SqmExtractUnit ) {
// datetime truncation // datetime truncation
renderingSupport = datetimeRenderingSupport; renderer = datetimeRenderingSupport;
argumentsValidator = TruncArgumentsValidator.DATETIME_VALIDATOR; argumentsValidator = TruncArgumentsValidator.DATETIME_VALIDATOR;
// the trunc() function requires translating the temporal_unit to a format string // the trunc() function requires translating the temporal_unit to a format string
final TemporalUnit temporalUnit = ( (SqmExtractUnit<?>) arguments.get( 1 ) ).getUnit(); final TemporalUnit temporalUnit = ( (SqmExtractUnit<?>) arguments.get( 1 ) ).getUnit();
@ -92,13 +93,13 @@ public class OracleTruncFunction extends TruncFunction {
} }
else { else {
// numeric truncation // numeric truncation
renderingSupport = numericRenderingSupport; renderer = numericRenderingSupport;
argumentsValidator = TruncArgumentsValidator.NUMERIC_VALIDATOR; argumentsValidator = TruncArgumentsValidator.NUMERIC_VALIDATOR;
} }
return new SelfRenderingSqmFunction<>( return new SelfRenderingSqmFunction<>(
this, this,
renderingSupport, renderer,
args, args,
impliedResultType, impliedResultType,
argumentsValidator, argumentsValidator,

View File

@ -9,6 +9,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
@ -46,8 +47,12 @@ public class PostgreSQLMinMaxFunction extends AbstractSqmSelfRenderingFunctionDe
} }
@Override @Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) { public void render(
render( sqlAppender, sqlAstArguments, null, walker ); SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, returnType, walker );
} }
@Override @Override
@ -55,6 +60,7 @@ public class PostgreSQLMinMaxFunction extends AbstractSqmSelfRenderingFunctionDe
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
final boolean caseWrapper = filter != null && !translator.supportsFilterClause(); final boolean caseWrapper = filter != null && !translator.supportsFilterClause();
sqlAppender.appendSql( getName() ); sqlAppender.appendSql( getName() );

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.FunctionRenderingSupport; import org.hibernate.query.sqm.function.FunctionRenderingSupport;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
@ -46,7 +47,7 @@ import static org.hibernate.query.sqm.produce.function.FunctionParameterType.NUM
* @author Marco Belladelli * @author Marco Belladelli
* @see <a href="https://www.postgresql.org/docs/current/functions-math.html">PostgreSQL documentation</a> * @see <a href="https://www.postgresql.org/docs/current/functions-math.html">PostgreSQL documentation</a>
*/ */
public class PostgreSQLTruncRoundFunction extends AbstractSqmFunctionDescriptor implements FunctionRenderingSupport { public class PostgreSQLTruncRoundFunction extends AbstractSqmFunctionDescriptor implements FunctionRenderer {
private final boolean supportsTwoArguments; private final boolean supportsTwoArguments;
public PostgreSQLTruncRoundFunction(String name, boolean supportsTwoArguments) { public PostgreSQLTruncRoundFunction(String name, boolean supportsTwoArguments) {
@ -60,7 +61,11 @@ public class PostgreSQLTruncRoundFunction extends AbstractSqmFunctionDescriptor
} }
@Override @Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> arguments, SqlAstTranslator<?> walker) { public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final int numberOfArguments = arguments.size(); final int numberOfArguments = arguments.size();
final Expression firstArg = (Expression) arguments.get( 0 ); final Expression firstArg = (Expression) arguments.get( 0 );
final JdbcType jdbcType = firstArg.getExpressionType().getSingleJdbcMapping().getJdbcType(); final JdbcType jdbcType = firstArg.getExpressionType().getSingleJdbcMapping().getJdbcType();

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -43,6 +44,7 @@ public class QuantifiedLeastGreatestEmulation
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final int numberOfArguments = arguments.size(); final int numberOfArguments = arguments.size();
if ( numberOfArguments > 1 ) { if ( numberOfArguments > 1 ) {

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
@ -56,6 +57,7 @@ public class SQLServerEveryAnyEmulation extends AbstractSqmSelfRenderingFunction
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
if ( every ) { if ( every ) {
sqlAppender.appendSql( "min(iif(" ); sqlAppender.appendSql( "min(iif(" );
@ -79,7 +81,10 @@ public class SQLServerEveryAnyEmulation extends AbstractSqmSelfRenderingFunction
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) { SqlAppender sqlAppender,
this.render( sqlAppender, sqlAstArguments, null, walker ); List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
this.render( sqlAppender, sqlAstArguments, null, (ReturnableType<?>) null, walker );
} }
} }

View File

@ -9,6 +9,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import jakarta.persistence.TemporalType; import jakarta.persistence.TemporalType;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -31,6 +32,7 @@ public class SQLServerFormatEmulation extends FormatFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression datetime = (Expression) arguments.get(0); final Expression datetime = (Expression) arguments.get(0);

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
@ -38,6 +39,7 @@ public class SqlFunction
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final QueryLiteral<String> sqlFragmentLiteral = (QueryLiteral<String>) arguments.get( 0 ); final QueryLiteral<String> sqlFragmentLiteral = (QueryLiteral<String>) arguments.get( 0 );
final String sqlFragment = sqlFragmentLiteral.getLiteralValue(); final String sqlFragment = sqlFragmentLiteral.getLiteralValue();

View File

@ -79,6 +79,7 @@ public class SqlServerConvertTruncFunction extends TruncFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
sqlAppender.appendSql( toDateFunction ); sqlAppender.appendSql( toDateFunction );
sqlAppender.append( '(' ); sqlAppender.append( '(' );

View File

@ -87,6 +87,7 @@ public class SybaseTruncFunction extends TruncFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
sqlAppender.appendSql( toDateFunction ); sqlAppender.appendSql( toDateFunction );
sqlAppender.append( '(' ); sqlAppender.append( '(' );

View File

@ -65,6 +65,7 @@ public class TimestampaddFunction
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final DurationUnit field = (DurationUnit) arguments.get( 0 ); final DurationUnit field = (DurationUnit) arguments.get( 0 );

View File

@ -74,6 +74,7 @@ public class TimestampdiffFunction
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments, List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final DurationUnit field = (DurationUnit) arguments.get( 0 ); final DurationUnit field = (DurationUnit) arguments.get( 0 );

View File

@ -10,6 +10,7 @@ import java.util.List;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.FunctionRenderingSupport; import org.hibernate.query.sqm.function.FunctionRenderingSupport;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -28,7 +29,7 @@ import org.hibernate.type.spi.TypeConfiguration;
* *
* @author Christian Beikov * @author Christian Beikov
*/ */
public class TransactSQLStrFunction extends CastStrEmulation implements FunctionRenderingSupport { public class TransactSQLStrFunction extends CastStrEmulation implements FunctionRenderer {
public TransactSQLStrFunction(TypeConfiguration typeConfiguration) { public TransactSQLStrFunction(TypeConfiguration typeConfiguration) {
super( super(
@ -66,7 +67,11 @@ public class TransactSQLStrFunction extends CastStrEmulation implements Function
} }
@Override @Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> arguments, SqlAstTranslator<?> walker) { public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
sqlAppender.appendSql( "str(" ); sqlAppender.appendSql( "str(" );
arguments.get( 0 ).accept( walker ); arguments.get( 0 ).accept( walker );
for ( int i = 1; i < arguments.size(); i++ ) { for ( int i = 1; i < arguments.size(); i++ ) {

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect.function; package org.hibernate.dialect.function;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.TrimSpec; import org.hibernate.query.sqm.TrimSpec;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
@ -58,7 +59,11 @@ public class TrimFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
} }
@Override @Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) { public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final TrimSpec specification = ( (TrimSpecification) sqlAstArguments.get( 0 ) ).getSpecification(); final TrimSpec specification = ( (TrimSpecification) sqlAstArguments.get( 0 ) ).getSpecification();
final Object trimCharacter = ( (Literal) sqlAstArguments.get( 1 ) ).getLiteralValue(); final Object trimCharacter = ( (Literal) sqlAstArguments.get( 1 ) ).getLiteralValue();
final Expression sourceExpr = (Expression) sqlAstArguments.get( 2 ); final Expression sourceExpr = (Expression) sqlAstArguments.get( 2 );

View File

@ -14,7 +14,7 @@ import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionRenderingSupport; import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
@ -100,7 +100,7 @@ public class TruncFunction extends AbstractSqmFunctionDescriptor {
QueryEngine queryEngine) { QueryEngine queryEngine) {
final NodeBuilder nodeBuilder = queryEngine.getCriteriaBuilder(); final NodeBuilder nodeBuilder = queryEngine.getCriteriaBuilder();
final List<SqmTypedNode<?>> args = new ArrayList<>( arguments ); final List<SqmTypedNode<?>> args = new ArrayList<>( arguments );
final FunctionRenderingSupport renderingSupport; final FunctionRenderer renderingSupport;
final ArgumentsValidator argumentsValidator; final ArgumentsValidator argumentsValidator;
if ( arguments.size() == 2 && arguments.get( 1 ) instanceof SqmExtractUnit ) { if ( arguments.size() == 2 && arguments.get( 1 ) instanceof SqmExtractUnit ) {
// datetime truncation // datetime truncation
@ -171,7 +171,7 @@ public class TruncFunction extends AbstractSqmFunctionDescriptor {
); );
} }
private static class TruncRenderingSupport implements FunctionRenderingSupport { protected static class TruncRenderingSupport implements FunctionRenderer {
private final PatternRenderer truncPattern; private final PatternRenderer truncPattern;
private final PatternRenderer twoArgTruncPattern; private final PatternRenderer twoArgTruncPattern;
@ -184,6 +184,7 @@ public class TruncFunction extends AbstractSqmFunctionDescriptor {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final PatternRenderer pattern; final PatternRenderer pattern;
if ( twoArgTruncPattern != null && sqlAstArguments.size() == 2 ) { if ( twoArgTruncPattern != null && sqlAstArguments.size() == 2 ) {

View File

@ -0,0 +1,39 @@
/*
* 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.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.type.spi.TypeConfiguration;
/**
* Encapsulates the validator, return type and argument type resolvers for the array_contains function.
* Subclasses only have to implement the rendering.
*/
public abstract class AbstractArrayContainsFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
protected final boolean nullable;
public AbstractArrayContainsFunction(boolean nullable, TypeConfiguration typeConfiguration) {
super(
"array_contains" + ( nullable ? "_nullable" : "" ),
StandardArgumentsValidators.composite(
StandardArgumentsValidators.exactly( 2 ),
ArrayContainsArgumentValidator.INSTANCE
),
StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.standardBasicTypeForJavaType( Boolean.class ) ),
ArrayContainsArgumentTypeResolver.INSTANCE
);
this.nullable = nullable;
}
@Override
public String getArgumentListSignature() {
return "(ARRAY haystackArray, OBJECT needleElementOrArray)";
}
}

View File

@ -13,25 +13,31 @@ import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolv
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
/** /**
* Encapsulates the validator, return type and argument type resolvers for the quantified array_contains functions. * Encapsulates the validator, return type and argument type resolvers for the array_overlaps function.
* Subclasses only have to implement the rendering. * Subclasses only have to implement the rendering.
*/ */
public abstract class AbstractArrayContainsQuantifiedFunction extends AbstractSqmSelfRenderingFunctionDescriptor { public abstract class AbstractArrayOverlapsFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
public AbstractArrayContainsQuantifiedFunction(String functionName, TypeConfiguration typeConfiguration) { protected final boolean nullable;
public AbstractArrayOverlapsFunction(boolean nullable, TypeConfiguration typeConfiguration) {
super( super(
functionName, "array_overlaps" + ( nullable ? "_nullable" : "" ),
StandardArgumentsValidators.composite( StandardArgumentsValidators.composite(
StandardArgumentsValidators.exactly( 2 ), StandardArgumentsValidators.exactly( 2 ),
ArraysOfSameTypeArgumentValidator.INSTANCE ArraysOfSameTypeArgumentValidator.INSTANCE
), ),
StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.standardBasicTypeForJavaType( Boolean.class ) ), StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.standardBasicTypeForJavaType( Boolean.class ) ),
StandardFunctionArgumentTypeResolvers.ARGUMENT_OR_IMPLIED_RESULT_TYPE StandardFunctionArgumentTypeResolvers.byArgument(
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 1 ),
StandardFunctionArgumentTypeResolvers.argumentsOrImplied( 0 )
)
); );
this.nullable = nullable;
} }
@Override @Override
public String getArgumentListSignature() { public String getArgumentListSignature() {
return "(ARRAY haystackArray, ARRAY needleArray)"; return "(ARRAY array0, OBJECT array1)";
} }
} }

View File

@ -9,6 +9,7 @@ package org.hibernate.dialect.function.array;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -50,8 +51,9 @@ public class ArrayAggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -59,8 +61,9 @@ public class ArrayAggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -69,6 +72,7 @@ public class ArrayAggFunction extends AbstractSqmSelfRenderingFunctionDescriptor
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
List<SortSpecification> withinGroup, List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
final boolean caseWrapper = filter != null && ( !supportsFilter || !translator.supportsFilterClause() ); final boolean caseWrapper = filter != null && ( !supportsFilter || !translator.supportsFilterClause() );
sqlAppender.appendSql( functionName ); sqlAppender.appendSql( functionName );

View File

@ -9,11 +9,10 @@ package org.hibernate.dialect.function.array;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.mapping.MappingModelExpressible; import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver; import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmFunction; import org.hibernate.query.sqm.tree.expression.SqmFunction;
import org.hibernate.type.BasicPluralType; import org.hibernate.type.BasicPluralType;
@ -40,21 +39,27 @@ public class ArrayAndElementArgumentTypeResolver implements FunctionArgumentType
SqmToSqlAstConverter converter) { SqmToSqlAstConverter converter) {
if ( argumentIndex == arrayIndex ) { if ( argumentIndex == arrayIndex ) {
for ( int elementIndex : elementIndexes ) { for ( int elementIndex : elementIndexes ) {
final SqmTypedNode<?> argument = function.getArguments().get( elementIndex ); final SqmTypedNode<?> node = function.getArguments().get( elementIndex );
final DomainType<?> sqmType = argument.getExpressible().getSqmType(); if ( node instanceof SqmExpression<?> ) {
if ( sqmType instanceof ReturnableType<?> ) { final MappingModelExpressible<?> expressible = converter.determineValueMapping( (SqmExpression<?>) node );
return DdlTypeHelper.resolveArrayType( if ( expressible != null ) {
sqmType, return DdlTypeHelper.resolveArrayType(
converter.getCreationContext().getSessionFactory().getTypeConfiguration() (DomainType<?>) expressible.getSingleJdbcMapping(),
); converter.getCreationContext().getSessionFactory().getTypeConfiguration()
);
}
} }
} }
} }
else if ( ArrayHelper.contains( elementIndexes, argumentIndex ) ) { else if ( ArrayHelper.contains( elementIndexes, argumentIndex ) ) {
final SqmTypedNode<?> argument = function.getArguments().get( arrayIndex ); final SqmTypedNode<?> node = function.getArguments().get( arrayIndex );
final SqmExpressible<?> sqmType = argument.getNodeType(); if ( node instanceof SqmExpression<?> ) {
if ( sqmType instanceof BasicPluralType<?, ?> ) { final MappingModelExpressible<?> expressible = converter.determineValueMapping( (SqmExpression<?>) node );
return ( (BasicPluralType<?, ?>) sqmType ).getElementType(); if ( expressible != null ) {
if ( expressible.getSingleJdbcMapping() instanceof BasicPluralType<?, ?> ) {
return ( (BasicPluralType<?, ?>) expressible.getSingleJdbcMapping() ).getElementType();
}
}
} }
} }
return null; return null;

View File

@ -44,7 +44,7 @@ public class ArrayArgumentValidator implements ArgumentsValidator {
return getElementType( arrayIndex, arguments, functionName, typeConfiguration ); return getElementType( arrayIndex, arguments, functionName, typeConfiguration );
} }
protected BasicType<?> getElementType( protected BasicPluralType<?, ?> getPluralType(
int arrayIndex, int arrayIndex,
List<? extends SqmTypedNode<?>> arguments, List<? extends SqmTypedNode<?>> arguments,
String functionName, String functionName,
@ -64,6 +64,14 @@ public class ArrayArgumentValidator implements ArgumentsValidator {
) )
); );
} }
return ( (BasicPluralType<?, ?>) arrayType ).getElementType(); return (BasicPluralType<?, ?>) arrayType;
}
protected BasicType<?> getElementType(
int arrayIndex,
List<? extends SqmTypedNode<?>> arguments,
String functionName,
TypeConfiguration typeConfiguration) {
return getPluralType( arrayIndex, arguments, functionName, typeConfiguration ).getElementType();
} }
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
@ -47,6 +48,7 @@ public class ArrayConcatElementFunction extends AbstractSqmSelfRenderingFunction
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final SqlAstNode firstArgument = sqlAstArguments.get( 0 ); final SqlAstNode firstArgument = sqlAstArguments.get( 0 );
final SqlAstNode secondArgument = sqlAstArguments.get( 1 ); final SqlAstNode secondArgument = sqlAstArguments.get( 1 );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
@ -44,6 +45,7 @@ public class ArrayConcatFunction extends AbstractSqmSelfRenderingFunctionDescrip
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
sqlAppender.append( prefix ); sqlAppender.append( prefix );
sqlAstArguments.get( 0 ).accept( walker ); sqlAstArguments.get( 0 ).accept( walker );

View File

@ -10,6 +10,7 @@ import java.util.List;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.JdbcMappingContainer; import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.internal.TypecheckUtil; import org.hibernate.query.sqm.internal.TypecheckUtil;
@ -39,7 +40,11 @@ public class ArrayConstructorFunction extends AbstractSqmSelfRenderingFunctionDe
} }
@Override @Override
public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> arguments, SqlAstTranslator<?> walker) { public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
if ( withKeyword ) { if ( withKeyword ) {
sqlAppender.append( "array" ); sqlAppender.append( "array" );
} }

View File

@ -0,0 +1,60 @@
/*
* 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.metamodel.mapping.MappingModelExpressible;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.produce.function.FunctionArgumentTypeResolver;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmFunction;
import org.hibernate.type.BasicPluralType;
/**
* A {@link FunctionArgumentTypeResolver} that resolves the argument types for the {@code array_contains} function.
*/
public class ArrayContainsArgumentTypeResolver implements FunctionArgumentTypeResolver {
public static final FunctionArgumentTypeResolver INSTANCE = new ArrayContainsArgumentTypeResolver();
@Override
public MappingModelExpressible<?> resolveFunctionArgumentType(
SqmFunction<?> function,
int argumentIndex,
SqmToSqlAstConverter converter) {
if ( argumentIndex == 0 ) {
final SqmTypedNode<?> node = function.getArguments().get( 1 );
if ( node instanceof SqmExpression<?> ) {
final MappingModelExpressible<?> expressible = converter.determineValueMapping( (SqmExpression<?>) node );
if ( expressible != null ) {
if ( expressible.getSingleJdbcMapping() instanceof BasicPluralType<?, ?> ) {
return expressible;
}
else {
return DdlTypeHelper.resolveArrayType(
(DomainType<?>) expressible.getSingleJdbcMapping(),
converter.getCreationContext().getSessionFactory().getTypeConfiguration()
);
}
}
}
}
else if ( argumentIndex == 1 ) {
final SqmTypedNode<?> node = function.getArguments().get( 0 );
if ( node instanceof SqmExpression<?> ) {
final MappingModelExpressible<?> expressible = converter.determineValueMapping( (SqmExpression<?>) node );
if ( expressible != null ) {
return expressible;
}
}
}
return null;
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.sqm.SqmExpressible;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionArgumentException;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.type.BasicPluralType;
import org.hibernate.type.spi.TypeConfiguration;
/**
* A {@link ArgumentsValidator} that validates the arguments for the {@code array_contains} function.
*/
public class ArrayContainsArgumentValidator extends ArrayArgumentValidator {
public static final ArgumentsValidator INSTANCE = new ArrayContainsArgumentValidator();
protected ArrayContainsArgumentValidator() {
super( 0 );
}
@Override
public void validate(
List<? extends SqmTypedNode<?>> arguments,
String functionName,
TypeConfiguration typeConfiguration) {
final BasicPluralType<?, ?> haystackType = getPluralType( 0, arguments, functionName, typeConfiguration );
final SqmExpressible<?> expressible = arguments.get( 1 ).getExpressible();
final SqmExpressible<?> needleType = expressible == null ? null : expressible.getSqmType();
if ( needleType != null && !haystackType.equals( needleType ) && !haystackType.getElementType().equals( needleType ) ) {
throw new FunctionArgumentException(
String.format(
"Parameter 1 of function '%s()' has type %s, but argument is of type '%s'",
functionName,
haystackType.getJavaTypeDescriptor().getTypeName(),
needleType.getTypeName()
)
);
}
}
}

View File

@ -8,53 +8,73 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.BasicPluralType;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
/** /**
* Special array contains function that also applies a cast to the element argument. PostgreSQL needs this, * Special array contains function that also applies a cast to the element argument. PostgreSQL needs this,
* because by default it assumes a {@code text[]}, which is not compatible with {@code varchar[]}. * because by default it assumes a {@code text[]}, which is not compatible with {@code varchar[]}.
*/ */
public class ArrayContainsOperatorFunction extends AbstractSqmSelfRenderingFunctionDescriptor { public class ArrayContainsOperatorFunction extends ArrayContainsUnnestFunction {
public ArrayContainsOperatorFunction(TypeConfiguration typeConfiguration) { public ArrayContainsOperatorFunction(boolean nullable, TypeConfiguration typeConfiguration) {
super( super( nullable, typeConfiguration );
"array_contains",
StandardArgumentsValidators.composite(
StandardArgumentsValidators.exactly( 2 ),
ArrayAndElementArgumentValidator.DEFAULT_INSTANCE
),
StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.standardBasicTypeForJavaType( Boolean.class ) ),
ArrayAndElementArgumentTypeResolver.DEFAULT_INSTANCE
);
} }
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final Expression elementExpression = (Expression) sqlAstArguments.get( 1 ); final Expression needleExpression = (Expression) sqlAstArguments.get( 1 );
arrayExpression.accept( walker ); final JdbcMappingContainer needleTypeContainer = needleExpression.getExpressionType();
sqlAppender.append( "@>" ); final JdbcMapping needleType = needleTypeContainer == null ? null : needleTypeContainer.getSingleJdbcMapping();
if ( needsArrayCasting( elementExpression ) ) { if ( needleType == null || needleType instanceof BasicPluralType<?, ?> ) {
sqlAppender.append( "cast(array[" ); if ( nullable ) {
elementExpression.accept( walker ); super.render( sqlAppender, sqlAstArguments, returnType, walker );
sqlAppender.append( "] as " ); }
sqlAppender.append( DdlTypeHelper.getCastTypeName( arrayExpression.getExpressionType(), walker ) ); else {
sqlAppender.append( ')' ); haystackExpression.accept( walker );
sqlAppender.append( "@>" );
needleExpression.accept( walker );
}
} }
else { else {
sqlAppender.append( "array[" ); if ( nullable ) {
elementExpression.accept( walker ); sqlAppender.append( "array_position(" );
sqlAppender.append( ']' ); haystackExpression.accept( walker );
sqlAppender.append( ',' );
needleExpression.accept( walker );
sqlAppender.append( ") is not null" );
}
else {
haystackExpression.accept( walker );
sqlAppender.append( "@>" );
if ( needsArrayCasting( needleExpression ) ) {
sqlAppender.append( "cast(array[" );
needleExpression.accept( walker );
sqlAppender.append( "] as " );
sqlAppender.append( DdlTypeHelper.getCastTypeName(
haystackExpression.getExpressionType(),
walker
) );
sqlAppender.append( ')' );
}
else {
sqlAppender.append( "array[" );
needleExpression.accept( walker );
sqlAppender.append( ']' );
}
}
} }
} }
@ -62,9 +82,4 @@ public class ArrayContainsOperatorFunction extends AbstractSqmSelfRenderingFunct
// PostgreSQL doesn't do implicit conversion between text[] and varchar[], so we need casting // PostgreSQL doesn't do implicit conversion between text[] and varchar[], so we need casting
return elementExpression.getExpressionType().getSingleJdbcMapping().getJdbcType().isString(); return elementExpression.getExpressionType().getSingleJdbcMapping().getJdbcType().isString();
} }
@Override
public String getArgumentListSignature() {
return "(ARRAY array, OBJECT element)";
}
} }

View File

@ -0,0 +1,77 @@
/*
* 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.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
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;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.BasicPluralType;
import org.hibernate.type.spi.TypeConfiguration;
/**
* Implement the array contains function by using {@code unnest}.
*/
public class ArrayContainsUnnestFunction extends AbstractArrayContainsFunction {
public ArrayContainsUnnestFunction(boolean nullable, TypeConfiguration typeConfiguration) {
super( nullable, typeConfiguration );
}
@Override
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final Expression needleExpression = (Expression) sqlAstArguments.get( 1 );
final JdbcMappingContainer needleTypeContainer = needleExpression.getExpressionType();
final JdbcMapping needleType = needleTypeContainer == null ? null : needleTypeContainer.getSingleJdbcMapping();
if ( needleType == null || needleType instanceof BasicPluralType<?, ?> ) {
sqlAppender.append( '(' );
if ( ArrayHelper.isNullable( haystackExpression ) ) {
walker.render( haystackExpression, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.append( " is not null and " );
}
if ( ArrayHelper.isNullable( needleExpression ) ) {
walker.render( needleExpression, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.append( " is not null and " );
}
if ( !nullable ) {
sqlAppender.append( "not exists(select 1 from unnest(" );
walker.render( needleExpression, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.append( ") t(i) where t.i is null) and " );
}
sqlAppender.append( "not exists(select * from unnest(" );
walker.render( needleExpression, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.append( ") except select * from unnest(" );
walker.render( haystackExpression, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.append( ")))" );
}
else {
sqlAppender.append( "exists(select 1 from unnest(" );
walker.render( haystackExpression, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.append( ") t(i) where t.i" );
if ( nullable ) {
sqlAppender.append( " is not distinct from " );
}
else {
sqlAppender.append( '=' );
}
walker.render( needleExpression, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.append( ")" );
}
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -41,6 +42,7 @@ public class ArrayGetUnnestFunction extends AbstractSqmSelfRenderingFunctionDesc
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression indexExpression = (Expression) sqlAstArguments.get( 1 ); final Expression indexExpression = (Expression) sqlAstArguments.get( 1 );

View File

@ -0,0 +1,21 @@
/*
* 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.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.FunctionExpression;
public class ArrayHelper {
public static boolean isNullable(Expression expression) {
if ( expression instanceof FunctionExpression ) {
final FunctionExpression functionExpression = (FunctionExpression) expression;
// An array function literal is never null
return !"array".equals( functionExpression.getFunctionName() );
}
return true;
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -15,32 +16,27 @@ import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
/** /**
* Array contains all function that uses the PostgreSQL {@code @>} operator. * Array overlaps function that uses the PostgreSQL {@code &&} operator.
*/ */
public class ArrayContainsQuantifiedOperatorFunction extends ArrayContainsQuantifiedUnnestFunction { public class ArrayOverlapsOperatorFunction extends ArrayOverlapsUnnestFunction {
public ArrayContainsQuantifiedOperatorFunction(TypeConfiguration typeConfiguration, boolean all, boolean nullable) { public ArrayOverlapsOperatorFunction(boolean nullable, TypeConfiguration typeConfiguration) {
super( typeConfiguration, all, nullable ); super( nullable, typeConfiguration );
} }
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
SqlAstTranslator<?> walker) { ReturnableType<?> returnType, SqlAstTranslator<?> walker) {
if ( nullable ) { if ( nullable ) {
super.render( sqlAppender, sqlAstArguments, walker ); super.render( sqlAppender, sqlAstArguments, returnType, walker );
} }
else { else {
final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 ); final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final Expression needleExpression = (Expression) sqlAstArguments.get( 1 ); final Expression needleExpression = (Expression) sqlAstArguments.get( 1 );
haystackExpression.accept( walker ); haystackExpression.accept( walker );
if ( all ) { sqlAppender.append( "&&" );
sqlAppender.append( "@>" );
}
else {
sqlAppender.append( "&&" );
}
needleExpression.accept( walker ); needleExpression.accept( walker );
} }
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -15,48 +16,40 @@ import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
/** /**
* Implement the contains all function by using {@code unnest}. * Implement the overlaps function by using {@code unnest}.
*/ */
public class ArrayContainsQuantifiedUnnestFunction extends AbstractArrayContainsQuantifiedFunction { public class ArrayOverlapsUnnestFunction extends AbstractArrayOverlapsFunction {
protected final boolean all; public ArrayOverlapsUnnestFunction(boolean nullable, TypeConfiguration typeConfiguration) {
protected final boolean nullable; super( nullable, typeConfiguration );
public ArrayContainsQuantifiedUnnestFunction(TypeConfiguration typeConfiguration, boolean all, boolean nullable) {
super( "array_contains_" + ( all ? "all" : "any" ), typeConfiguration );
this.all = all;
this.nullable = nullable;
} }
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 ); final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final Expression needleExpression = (Expression) sqlAstArguments.get( 1 ); final Expression needleExpression = (Expression) sqlAstArguments.get( 1 );
sqlAppender.append( '(' ); sqlAppender.append( '(' );
haystackExpression.accept( walker ); if ( ArrayHelper.isNullable( haystackExpression ) ) {
sqlAppender.append( " is not null and " ); haystackExpression.accept( walker );
needleExpression.accept( walker ); sqlAppender.append( " is not null and " );
sqlAppender.append( " is not null and " ); }
if ( ArrayHelper.isNullable( needleExpression ) ) {
needleExpression.accept( walker );
sqlAppender.append( " is not null and " );
}
if ( !nullable ) { if ( !nullable ) {
sqlAppender.append( "not exists(select 1 from unnest(" ); sqlAppender.append( "not exists(select 1 from unnest(" );
needleExpression.accept( walker ); needleExpression.accept( walker );
sqlAppender.append( ") t(i) where t.i is null) and " ); sqlAppender.append( ") t(i) where t.i is null) and " );
} }
if ( all ) {
sqlAppender.append( "not " );
}
sqlAppender.append( "exists(select * from unnest(" ); sqlAppender.append( "exists(select * from unnest(" );
needleExpression.accept( walker ); needleExpression.accept( walker );
sqlAppender.append( ")" ); sqlAppender.append( ")" );
if ( all ) { sqlAppender.append( " intersect " );
sqlAppender.append( " except " );
}
else {
sqlAppender.append( " intersect " );
}
sqlAppender.append( "select * from unnest(" ); sqlAppender.append( "select * from unnest(" );
haystackExpression.accept( walker ); haystackExpression.accept( walker );
sqlAppender.append( ")))" ); sqlAppender.append( ")))" );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -47,6 +48,7 @@ public class ArrayRemoveIndexUnnestFunction extends AbstractSqmSelfRenderingFunc
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression indexExpression = (Expression) sqlAstArguments.get( 1 ); final Expression indexExpression = (Expression) sqlAstArguments.get( 1 );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
@ -36,6 +37,7 @@ public class ArrayReplaceUnnestFunction extends AbstractSqmSelfRenderingFunction
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression oldExpression = (Expression) sqlAstArguments.get( 1 ); final Expression oldExpression = (Expression) sqlAstArguments.get( 1 );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -45,6 +46,7 @@ public class ArraySetUnnestFunction extends AbstractSqmSelfRenderingFunctionDesc
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression indexExpression = (Expression) sqlAstArguments.get( 1 ); final Expression indexExpression = (Expression) sqlAstArguments.get( 1 );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator; import org.hibernate.query.sqm.produce.function.ArgumentTypesValidator;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -47,6 +48,7 @@ public class ArraySliceUnnestFunction extends AbstractSqmSelfRenderingFunctionDe
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression startIndexExpression = (Expression) sqlAstArguments.get( 1 ); final Expression startIndexExpression = (Expression) sqlAstArguments.get( 1 );

View File

@ -1,128 +0,0 @@
/*
* 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.engine.jdbc.Size;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.function.FunctionRenderingSupport;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmTypedNode;
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.type.BasicPluralType;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.sql.DdlType;
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration;
/**
* Special array constructor function that also applies a cast to the array literal,
* based on the inferred result type. PostgreSQL needs this,
* because by default it assumes a {@code text[]}, which is not compatible with {@code varchar[]}.
*/
public class CastingArrayConstructorFunction extends ArrayConstructorFunction {
public CastingArrayConstructorFunction() {
super( true );
}
@Override
protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
List<? extends SqmTypedNode<?>> arguments,
ReturnableType<T> impliedResultType,
QueryEngine queryEngine) {
return new ArrayConstructorSqmFunction<>(
this,
this,
arguments,
impliedResultType,
getArgumentsValidator(),
getReturnTypeResolver(),
queryEngine.getCriteriaBuilder(),
getName()
);
}
protected static class ArrayConstructorSqmFunction<T> extends SelfRenderingSqmFunction<T> {
public ArrayConstructorSqmFunction(
CastingArrayConstructorFunction descriptor,
FunctionRenderingSupport renderingSupport,
List<? extends SqmTypedNode<?>> arguments,
ReturnableType<T> impliedResultType,
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver,
NodeBuilder nodeBuilder,
String name) {
super(
descriptor,
renderingSupport,
arguments,
impliedResultType,
argumentsValidator,
returnTypeResolver,
nodeBuilder,
name
);
}
@Override
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final ReturnableType<?> resultType = resolveResultType( walker );
List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
if ( getArgumentsValidator() != null ) {
getArgumentsValidator().validateSqlTypes( arguments, getFunctionName() );
}
return new SelfRenderingFunctionSqlAstExpression(
getFunctionName(),
getRenderingSupport(),
arguments,
resultType,
resultType == null ? null : getMappingModelExpressible( walker, resultType, arguments )
) {
@Override
public void renderToSql(
SqlAppender sqlAppender,
SqlAstTranslator<?> walker,
SessionFactoryImplementor sessionFactory) {
String arrayTypeName = null;
if ( resultType != null ) {
final DomainType<?> type = resultType.getSqmType();
if ( type instanceof BasicPluralType<?, ?> ) {
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) type;
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry();
final DdlType ddlType = ddlTypeRegistry.getDescriptor(
pluralType.getJdbcType().getDdlTypeCode()
);
arrayTypeName = ddlType.getCastTypeName( Size.nil(), pluralType, ddlTypeRegistry );
sqlAppender.append( "cast(" );
}
}
super.renderToSql( sqlAppender, walker, sessionFactory );
if ( arrayTypeName != null ) {
sqlAppender.appendSql( " as " );
sqlAppender.appendSql( arrayTypeName );
sqlAppender.appendSql( ')' );
}
}
};
}
}
}

View File

@ -13,6 +13,7 @@ import org.hibernate.engine.jdbc.Size;
import org.hibernate.metamodel.mapping.JdbcMappingContainer; import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.SqlTypedMapping; import org.hibernate.metamodel.mapping.SqlTypedMapping;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.query.ReturnableType;
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.AbstractSqlAstTranslator;
import org.hibernate.type.BasicPluralType; import org.hibernate.type.BasicPluralType;
@ -59,13 +60,13 @@ public class DdlTypeHelper {
return AbstractSqlAstTranslator.getCastTypeName( (SqlTypedMapping) type, walker.getSessionFactory() ); return AbstractSqlAstTranslator.getCastTypeName( (SqlTypedMapping) type, walker.getSessionFactory() );
} }
else { else {
final BasicType<?> jdbcMapping = (BasicType<?>) type.getSingleJdbcMapping(); final BasicType<?> basicType = (BasicType<?>) type.getSingleJdbcMapping();
final TypeConfiguration typeConfiguration = walker.getSessionFactory().getTypeConfiguration(); final TypeConfiguration typeConfiguration = walker.getSessionFactory().getTypeConfiguration();
final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry(); final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry();
final DdlType ddlType = ddlTypeRegistry.getDescriptor( final DdlType ddlType = ddlTypeRegistry.getDescriptor(
jdbcMapping.getJdbcType().getDdlTypeCode() basicType.getJdbcType().getDdlTypeCode()
); );
return ddlType.getCastTypeName( Size.nil(), jdbcMapping, ddlTypeRegistry ); return ddlType.getCastTypeName( Size.nil(), basicType, ddlTypeRegistry );
} }
} }

View File

@ -0,0 +1,87 @@
/*
* 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.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
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;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.BasicPluralType;
import org.hibernate.type.spi.TypeConfiguration;
/**
* H2 requires a very special emulation, because {@code unnest} is pretty much useless,
* due to https://github.com/h2database/h2database/issues/1815.
* This emulation uses {@code array_get}, {@code array_length} and {@code system_range} functions to roughly achieve the same.
*/
public class H2ArrayContainsFunction extends AbstractArrayContainsFunction {
private final int maximumArraySize;
public H2ArrayContainsFunction(boolean nullable, int maximumArraySize, TypeConfiguration typeConfiguration) {
super( nullable, typeConfiguration );
this.maximumArraySize = maximumArraySize;
}
@Override
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final Expression needleExpression = (Expression) sqlAstArguments.get( 1 );
final JdbcMappingContainer needleTypeContainer = needleExpression.getExpressionType();
final JdbcMapping needleType = needleTypeContainer == null ? null : needleTypeContainer.getSingleJdbcMapping();
if ( needleType == null || needleType instanceof BasicPluralType<?, ?> ) {
sqlAppender.append( '(' );
if ( ArrayHelper.isNullable( haystackExpression ) ) {
haystackExpression.accept( walker );
sqlAppender.append( " is not null and " );
}
if ( ArrayHelper.isNullable( needleExpression ) ) {
needleExpression.accept( walker );
sqlAppender.append( " is not null and " );
}
if ( !nullable ) {
sqlAppender.append( "not array_contains(" );
needleExpression.accept( walker );
sqlAppender.append( ",null) and " );
}
sqlAppender.append( "not " );
sqlAppender.append( "exists(select array_get(" );
walker.render( needleExpression, SqlAstNodeRenderingMode.NO_PLAIN_PARAMETER );
sqlAppender.append( ",t.i) from system_range(1," );
sqlAppender.append( Integer.toString( maximumArraySize ) );
sqlAppender.append( ") t(i) where array_length(" );
needleExpression.accept( walker );
sqlAppender.append( ")>=t.i" );
sqlAppender.append( " except " );
sqlAppender.append( "select array_get(" );
haystackExpression.accept( walker );
sqlAppender.append( ",t.i) from system_range(1," );
sqlAppender.append( Integer.toString( maximumArraySize ) );
sqlAppender.append( ") t(i) where array_length(" );
haystackExpression.accept( walker );
sqlAppender.append( ")>=t.i))" );
}
else {
sqlAppender.append( "array_contains(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
needleExpression.accept( walker );
sqlAppender.append( ')' );
}
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -19,61 +20,52 @@ import org.hibernate.type.spi.TypeConfiguration;
* due to https://github.com/h2database/h2database/issues/1815. * due to https://github.com/h2database/h2database/issues/1815.
* This emulation uses {@code array_get}, {@code array_length} and {@code system_range} functions to roughly achieve the same. * This emulation uses {@code array_get}, {@code array_length} and {@code system_range} functions to roughly achieve the same.
*/ */
public class H2ArrayContainsQuantifiedEmulation extends AbstractArrayContainsQuantifiedFunction { public class H2ArrayOverlapsFunction extends AbstractArrayOverlapsFunction {
private final boolean all; private final int maximumArraySize;
private final boolean nullable;
public H2ArrayContainsQuantifiedEmulation(TypeConfiguration typeConfiguration, boolean all, boolean nullable) { public H2ArrayOverlapsFunction(boolean nullable, int maximumArraySize, TypeConfiguration typeConfiguration) {
super( "array_contains_" + ( all ? "all" : "any" ), typeConfiguration ); super( nullable, typeConfiguration );
this.all = all; this.maximumArraySize = maximumArraySize;
this.nullable = nullable;
} }
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 ); final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final Expression needleExpression = (Expression) sqlAstArguments.get( 1 ); final Expression needleExpression = (Expression) sqlAstArguments.get( 1 );
sqlAppender.append( '(' ); sqlAppender.append( '(' );
haystackExpression.accept( walker ); if ( ArrayHelper.isNullable( haystackExpression ) ) {
sqlAppender.append( " is not null and " ); haystackExpression.accept( walker );
needleExpression.accept( walker ); sqlAppender.append( " is not null and " );
sqlAppender.append( " is not null and " ); }
if ( ArrayHelper.isNullable( needleExpression ) ) {
needleExpression.accept( walker );
sqlAppender.append( " is not null and " );
}
if ( !nullable ) { if ( !nullable ) {
sqlAppender.append( "not array_contains(" ); sqlAppender.append( "not array_contains(" );
needleExpression.accept( walker ); needleExpression.accept( walker );
sqlAppender.append( ",null) and " ); sqlAppender.append( ",null) and " );
} }
if ( all ) {
sqlAppender.append( "not " );
}
sqlAppender.append( "exists(select array_get(" ); sqlAppender.append( "exists(select array_get(" );
needleExpression.accept( walker ); needleExpression.accept( walker );
sqlAppender.append( ",t.i) from system_range(1," ); sqlAppender.append( ",t.i) from system_range(1," );
sqlAppender.append( Integer.toString( getMaximumArraySize() ) ); sqlAppender.append( Integer.toString( maximumArraySize ) );
sqlAppender.append( ") t(i) where array_length(" ); sqlAppender.append( ") t(i) where array_length(" );
needleExpression.accept( walker ); needleExpression.accept( walker );
sqlAppender.append( ")>=t.i" ); sqlAppender.append( ")>=t.i" );
if ( all ) { sqlAppender.append( " intersect " );
sqlAppender.append( " except " );
}
else {
sqlAppender.append( " intersect " );
}
sqlAppender.append( "select array_get(" ); sqlAppender.append( "select array_get(" );
haystackExpression.accept( walker ); haystackExpression.accept( walker );
sqlAppender.append( ",t.i) from system_range(1," ); sqlAppender.append( ",t.i) from system_range(1," );
sqlAppender.append( Integer.toString( getMaximumArraySize() ) ); sqlAppender.append( Integer.toString( maximumArraySize ) );
sqlAppender.append( ") t(i) where array_length(" ); sqlAppender.append( ") t(i) where array_length(" );
haystackExpression.accept( walker ); haystackExpression.accept( walker );
sqlAppender.append( ")>=t.i))" ); sqlAppender.append( ")>=t.i))" );
} }
protected int getMaximumArraySize() {
return 1000;
}
} }

View File

@ -8,23 +8,30 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
/** /**
* H2 array_remove function. * H2 requires a very special emulation, because {@code unnest} is pretty much useless,
* due to https://github.com/h2database/h2database/issues/1815.
* This emulation uses {@code array_get}, {@code array_length} and {@code system_range} functions to roughly achieve the same.
*/ */
public class H2ArrayRemoveFunction extends AbstractArrayRemoveFunction { public class H2ArrayRemoveFunction extends AbstractArrayRemoveFunction {
public H2ArrayRemoveFunction() { private final int maximumArraySize;
public H2ArrayRemoveFunction(int maximumArraySize) {
this.maximumArraySize = maximumArraySize;
} }
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression elementExpression = (Expression) sqlAstArguments.get( 1 ); final Expression elementExpression = (Expression) sqlAstArguments.get( 1 );
@ -33,7 +40,7 @@ public class H2ArrayRemoveFunction extends AbstractArrayRemoveFunction {
sqlAppender.append( " is null then null else coalesce((select array_agg(array_get("); sqlAppender.append( " is null then null else coalesce((select array_agg(array_get(");
arrayExpression.accept( walker ); arrayExpression.accept( walker );
sqlAppender.append(",i.idx)) from system_range(1," ); sqlAppender.append(",i.idx)) from system_range(1," );
sqlAppender.append( Integer.toString( getMaximumArraySize() ) ); sqlAppender.append( Integer.toString( maximumArraySize ) );
sqlAppender.append( ") i(idx) where i.idx<=coalesce(cardinality("); sqlAppender.append( ") i(idx) where i.idx<=coalesce(cardinality(");
arrayExpression.accept( walker ); arrayExpression.accept( walker );
sqlAppender.append("),0) and array_get("); sqlAppender.append("),0) and array_get(");
@ -42,8 +49,4 @@ public class H2ArrayRemoveFunction extends AbstractArrayRemoveFunction {
elementExpression.accept( walker ); elementExpression.accept( walker );
sqlAppender.append( "),array[]) end" ); sqlAppender.append( "),array[]) end" );
} }
protected int getMaximumArraySize() {
return 1000;
}
} }

View File

@ -8,24 +8,31 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
/** /**
* H2 array_remove_index function. * H2 requires a very special emulation, because {@code unnest} is pretty much useless,
* due to https://github.com/h2database/h2database/issues/1815.
* This emulation uses {@code array_get}, {@code array_length} and {@code system_range} functions to roughly achieve the same.
*/ */
public class H2ArrayRemoveIndexFunction extends ArrayRemoveIndexUnnestFunction { public class H2ArrayRemoveIndexFunction extends ArrayRemoveIndexUnnestFunction {
public H2ArrayRemoveIndexFunction() { private final int maximumArraySize;
public H2ArrayRemoveIndexFunction(int maximumArraySize) {
super( false ); super( false );
this.maximumArraySize = maximumArraySize;
} }
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression indexExpression = (Expression) sqlAstArguments.get( 1 ); final Expression indexExpression = (Expression) sqlAstArguments.get( 1 );
@ -34,15 +41,11 @@ public class H2ArrayRemoveIndexFunction extends ArrayRemoveIndexUnnestFunction {
sqlAppender.append( " is null then null else coalesce((select array_agg(array_get("); sqlAppender.append( " is null then null else coalesce((select array_agg(array_get(");
arrayExpression.accept( walker ); arrayExpression.accept( walker );
sqlAppender.append(",i.idx)) from system_range(1," ); sqlAppender.append(",i.idx)) from system_range(1," );
sqlAppender.append( Integer.toString( getMaximumArraySize() ) ); sqlAppender.append( Integer.toString( maximumArraySize ) );
sqlAppender.append( ") i(idx) where i.idx<=coalesce(cardinality("); sqlAppender.append( ") i(idx) where i.idx<=coalesce(cardinality(");
arrayExpression.accept( walker ); arrayExpression.accept( walker );
sqlAppender.append("),0) and i.idx is distinct from " ); sqlAppender.append("),0) and i.idx is distinct from " );
indexExpression.accept( walker ); indexExpression.accept( walker );
sqlAppender.append( "),array[]) end" ); sqlAppender.append( "),array[]) end" );
} }
protected int getMaximumArraySize() {
return 1000;
}
} }

View File

@ -8,20 +8,30 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
/** /**
* H2 array_replace function. * H2 requires a very special emulation, because {@code unnest} is pretty much useless,
* due to https://github.com/h2database/h2database/issues/1815.
* This emulation uses {@code array_get}, {@code array_length} and {@code system_range} functions to roughly achieve the same.
*/ */
public class H2ArrayReplaceFunction extends ArrayReplaceUnnestFunction { public class H2ArrayReplaceFunction extends ArrayReplaceUnnestFunction {
private final int maximumArraySize;
public H2ArrayReplaceFunction(int maximumArraySize) {
this.maximumArraySize = maximumArraySize;
}
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression oldExpression = (Expression) sqlAstArguments.get( 1 ); final Expression oldExpression = (Expression) sqlAstArguments.get( 1 );
@ -37,13 +47,9 @@ public class H2ArrayReplaceFunction extends ArrayReplaceUnnestFunction {
sqlAppender.append( " else array_get(" ); sqlAppender.append( " else array_get(" );
arrayExpression.accept( walker ); arrayExpression.accept( walker );
sqlAppender.append(",i.idx) end) from system_range(1," ); sqlAppender.append(",i.idx) end) from system_range(1," );
sqlAppender.append( Integer.toString( getMaximumArraySize() ) ); sqlAppender.append( Integer.toString( maximumArraySize ) );
sqlAppender.append( ") i(idx) where i.idx<=coalesce(cardinality("); sqlAppender.append( ") i(idx) where i.idx<=coalesce(cardinality(");
arrayExpression.accept( walker ); arrayExpression.accept( walker );
sqlAppender.append("),0)),array[]) end" ); sqlAppender.append("),0)),array[]) end" );
} }
protected int getMaximumArraySize() {
return 1000;
}
} }

View File

@ -8,24 +8,30 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.metamodel.mapping.JdbcMappingContainer; import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
/** /**
* H2 array_set function. * H2 requires a very special emulation, because {@code unnest} is pretty much useless,
* due to https://github.com/h2database/h2database/issues/1815.
* This emulation uses {@code array_get}, {@code array_length} and {@code system_range} functions to roughly achieve the same.
*/ */
public class H2ArraySetFunction extends ArraySetUnnestFunction { public class H2ArraySetFunction extends ArraySetUnnestFunction {
public H2ArraySetFunction() { private final int maximumArraySize;
public H2ArraySetFunction(int maximumArraySize) {
this.maximumArraySize = maximumArraySize;
} }
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression indexExpression = (Expression) sqlAstArguments.get( 1 ); final Expression indexExpression = (Expression) sqlAstArguments.get( 1 );
@ -41,7 +47,7 @@ public class H2ArraySetFunction extends ArraySetUnnestFunction {
sqlAppender.append(") then array_get("); sqlAppender.append(") then array_get(");
arrayExpression.accept( walker ); arrayExpression.accept( walker );
sqlAppender.append(",i.idx) end) from system_range(1," ); sqlAppender.append(",i.idx) end) from system_range(1," );
sqlAppender.append( Integer.toString( getMaximumArraySize() ) ); sqlAppender.append( Integer.toString( maximumArraySize ) );
sqlAppender.append( ") i(idx) where i.idx<=greatest(case when "); sqlAppender.append( ") i(idx) where i.idx<=greatest(case when ");
arrayExpression.accept( walker ); arrayExpression.accept( walker );
sqlAppender.append(" is not null then cardinality(" ); sqlAppender.append(" is not null then cardinality(" );
@ -50,8 +56,4 @@ public class H2ArraySetFunction extends ArraySetUnnestFunction {
indexExpression.accept( walker ); indexExpression.accept( walker );
sqlAppender.append( "))" ); sqlAppender.append( "))" );
} }
protected int getMaximumArraySize() {
return 1000;
}
} }

View File

@ -0,0 +1,77 @@
/*
* 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.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.SqlTypedMapping;
import org.hibernate.query.ReturnableType;
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.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.BottomType;
public class HSQLArrayConstructorFunction extends ArrayConstructorFunction {
public HSQLArrayConstructorFunction() {
super( true );
}
@Override
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final String castTypeName;
if ( returnType != null && hasOnlyBottomArguments( arguments ) ) {
if ( returnType instanceof SqlTypedMapping ) {
castTypeName = AbstractSqlAstTranslator.getCastTypeName( (SqlTypedMapping) returnType, walker.getSessionFactory() );
}
else {
castTypeName = DdlTypeHelper.getCastTypeName( (JdbcMappingContainer) returnType, walker );
}
sqlAppender.append( "cast(" );
}
else {
castTypeName = null;
}
sqlAppender.append( "array" );
final int size = arguments.size();
if ( size == 0 ) {
sqlAppender.append( '[' );
}
else {
char separator = '[';
for ( int i = 0; i < size; i++ ) {
SqlAstNode argument = arguments.get( i );
sqlAppender.append( separator );
argument.accept( walker );
separator = ',';
}
}
sqlAppender.append( ']' );
if ( castTypeName != null ) {
sqlAppender.append( " as " );
sqlAppender.append( castTypeName );
sqlAppender.append( ')' );
}
}
private boolean hasOnlyBottomArguments(List<? extends SqlAstNode> arguments) {
for ( int i = 0; i < arguments.size(); i++ ) {
final Expression argument = (Expression) arguments.get( i );
if ( !( argument.getExpressionType().getSingleJdbcMapping() instanceof BottomType ) ) {
return false;
}
}
return !arguments.isEmpty();
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -27,6 +28,7 @@ public class HSQLArrayPositionFunction extends AbstractArrayPositionFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression elementExpression = (Expression) sqlAstArguments.get( 1 ); final Expression elementExpression = (Expression) sqlAstArguments.get( 1 );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -25,6 +26,7 @@ public class HSQLArrayRemoveFunction extends AbstractArrayRemoveFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression elementExpression = (Expression) sqlAstArguments.get( 1 ); final Expression elementExpression = (Expression) sqlAstArguments.get( 1 );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -25,6 +26,7 @@ public class HSQLArraySetFunction extends ArraySetUnnestFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final Expression indexExpression = (Expression) sqlAstArguments.get( 1 ); final Expression indexExpression = (Expression) sqlAstArguments.get( 1 );
@ -41,8 +43,4 @@ public class HSQLArraySetFunction extends ArraySetUnnestFunction {
arrayExpression.accept( walker ); arrayExpression.accept( walker );
sqlAppender.append( ") with ordinality t(val, idx) on i.idx=t.idx)" ); sqlAppender.append( ") with ordinality t(val, idx) on i.idx=t.idx)" );
} }
protected int getMaximumArraySize() {
return 1000;
}
} }

View File

@ -18,10 +18,9 @@ import org.hibernate.query.ReturnableType;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionKind; import org.hibernate.query.sqm.function.FunctionKind;
import org.hibernate.query.sqm.function.FunctionRenderingSupport; import org.hibernate.query.sqm.function.FunctionRenderer;
import org.hibernate.query.sqm.function.SelfRenderingOrderedSetAggregateFunctionSqlAstExpression; import org.hibernate.query.sqm.function.SelfRenderingOrderedSetAggregateFunctionSqlAstExpression;
import org.hibernate.query.sqm.function.SelfRenderingSqmOrderedSetAggregateFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmOrderedSetAggregateFunction;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
@ -38,7 +37,6 @@ import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.cte.CteContainer; import org.hibernate.sql.ast.tree.cte.CteContainer;
import org.hibernate.sql.ast.tree.cte.CteStatement;
import org.hibernate.sql.ast.tree.cte.SelfRenderingCteObject; import org.hibernate.sql.ast.tree.cte.SelfRenderingCteObject;
import org.hibernate.sql.ast.tree.expression.Distinct; import org.hibernate.sql.ast.tree.expression.Distinct;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
@ -73,8 +71,9 @@ public class OracleArrayAggEmulation extends AbstractSqmSelfRenderingFunctionDes
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, null, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -82,8 +81,9 @@ public class OracleArrayAggEmulation extends AbstractSqmSelfRenderingFunctionDes
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), walker ); render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), returnType, walker );
} }
@Override @Override
@ -92,6 +92,7 @@ public class OracleArrayAggEmulation extends AbstractSqmSelfRenderingFunctionDes
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
List<SortSpecification> withinGroup, List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) { SqlAstTranslator<?> translator) {
sqlAppender.appendSql( "json_arrayagg" ); sqlAppender.appendSql( "json_arrayagg" );
sqlAppender.appendSql( '(' ); sqlAppender.appendSql( '(' );
@ -154,7 +155,7 @@ public class OracleArrayAggEmulation extends AbstractSqmSelfRenderingFunctionDes
protected static class OracleArrayAggSqmFunction<T> extends SelfRenderingSqmOrderedSetAggregateFunction<T> { protected static class OracleArrayAggSqmFunction<T> extends SelfRenderingSqmOrderedSetAggregateFunction<T> {
public OracleArrayAggSqmFunction( public OracleArrayAggSqmFunction(
OracleArrayAggEmulation descriptor, OracleArrayAggEmulation descriptor,
FunctionRenderingSupport renderingSupport, FunctionRenderer renderingSupport,
List<? extends SqmTypedNode<?>> arguments, List<? extends SqmTypedNode<?>> arguments,
SqmPredicate filter, SqmPredicate filter,
SqmOrderByClause withinGroupClause, SqmOrderByClause withinGroupClause,
@ -241,7 +242,7 @@ public class OracleArrayAggEmulation extends AbstractSqmSelfRenderingFunctionDes
} }
final OracleArrayAggEmulationSqlAstExpression expression = new OracleArrayAggEmulationSqlAstExpression( final OracleArrayAggEmulationSqlAstExpression expression = new OracleArrayAggEmulationSqlAstExpression(
getFunctionName(), getFunctionName(),
getRenderingSupport(), getFunctionRenderer(),
arguments, arguments,
getFilter() == null ? null : walker.visitNestedTopLevelPredicate( getFilter() ), getFilter() == null ? null : walker.visitNestedTopLevelPredicate( getFilter() ),
withinGroup, withinGroup,
@ -261,7 +262,7 @@ public class OracleArrayAggEmulation extends AbstractSqmSelfRenderingFunctionDes
public OracleArrayAggEmulationSqlAstExpression( public OracleArrayAggEmulationSqlAstExpression(
String functionName, String functionName,
FunctionRenderingSupport renderer, FunctionRenderer renderer,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
Predicate filter, Predicate filter,
List<SortSpecification> withinGroup, List<SortSpecification> withinGroup,

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -26,6 +27,7 @@ public class OracleArrayConcatElementFunction extends ArrayConcatElementFunction
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression firstArgument = (Expression) sqlAstArguments.get( 0 ); final Expression firstArgument = (Expression) sqlAstArguments.get( 0 );
final Expression secondArgument = (Expression) sqlAstArguments.get( 1 ); final Expression secondArgument = (Expression) sqlAstArguments.get( 1 );

View File

@ -9,10 +9,10 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.metamodel.mapping.JdbcMappingContainer; import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
/** /**
* Oracle concatenation function for arrays. * Oracle concatenation function for arrays.
@ -27,18 +27,11 @@ public class OracleArrayConcatFunction extends ArrayConcatFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
JdbcMappingContainer expressionType = null; final String arrayTypeName = DdlTypeHelper.getTypeName( (JdbcMappingContainer) returnType, walker );
for ( SqlAstNode sqlAstArgument : sqlAstArguments ) {
expressionType = ( (Expression) sqlAstArgument ).getExpressionType();
if ( expressionType != null ) {
break;
}
}
final String arrayTypeName = DdlTypeHelper.getTypeName( expressionType, walker );
sqlAppender.append( arrayTypeName ); sqlAppender.append( arrayTypeName );
sqlAppender.append( "_concat" ); sqlAppender.append( "_concat" );
super.render( sqlAppender, sqlAstArguments, walker ); super.render( sqlAppender, sqlAstArguments, returnType, walker );
} }
} }

View File

@ -8,28 +8,13 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.function.FunctionRenderingSupport;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.BasicPluralType; import org.hibernate.type.BasicPluralType;
import org.hibernate.type.descriptor.sql.DdlType;
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration;
public class OracleArrayConstructorFunction extends ArrayConstructorFunction { public class OracleArrayConstructorFunction extends ArrayConstructorFunction {
@ -38,100 +23,38 @@ public class OracleArrayConstructorFunction extends ArrayConstructorFunction {
} }
@Override @Override
protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression( public void render(
List<? extends SqmTypedNode<?>> arguments, SqlAppender sqlAppender,
ReturnableType<T> impliedResultType, List<? extends SqlAstNode> sqlAstArguments,
QueryEngine queryEngine) { ReturnableType<?> returnType,
return new ArrayConstructorSqmFunction<>( SqlAstTranslator<?> walker) {
this, if ( returnType == null ) {
this, throw new SemanticException(
arguments, "Oracle array constructor emulation requires knowledge about the return type, but resolved return type could not be determined"
impliedResultType,
getArgumentsValidator(),
getReturnTypeResolver(),
queryEngine.getCriteriaBuilder(),
getName()
);
}
protected static class ArrayConstructorSqmFunction<T> extends SelfRenderingSqmFunction<T> {
public ArrayConstructorSqmFunction(
OracleArrayConstructorFunction descriptor,
FunctionRenderingSupport renderingSupport,
List<? extends SqmTypedNode<?>> arguments,
ReturnableType<T> impliedResultType,
ArgumentsValidator argumentsValidator,
FunctionReturnTypeResolver returnTypeResolver,
NodeBuilder nodeBuilder,
String name) {
super(
descriptor,
renderingSupport,
arguments,
impliedResultType,
argumentsValidator,
returnTypeResolver,
nodeBuilder,
name
); );
} }
final DomainType<?> type = returnType.getSqmType();
@Override if ( !( type instanceof BasicPluralType<?, ?> ) ) {
public Expression convertToSqlAst(SqmToSqlAstConverter walker) { throw new SemanticException(
final ReturnableType<?> resultType = resolveResultType( walker ); "Oracle array constructor emulation requires a basic plural return type, but resolved return type was: " + type
List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
if ( getArgumentsValidator() != null ) {
getArgumentsValidator().validateSqlTypes( arguments, getFunctionName() );
}
if ( resultType == null ) {
throw new SemanticException(
"Oracle array constructor emulation requires knowledge about the return type, but resolved return type could not be determined"
);
}
final DomainType<?> type = resultType.getSqmType();
if ( !( type instanceof BasicPluralType<?, ?> ) ) {
throw new SemanticException(
"Oracle array constructor emulation requires a basic plural return type, but resolved return type was: " + type
);
}
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) type;
final TypeConfiguration typeConfiguration = walker.getCreationContext().getSessionFactory().getTypeConfiguration();
final DdlTypeRegistry ddlTypeRegistry = typeConfiguration.getDdlTypeRegistry();
final DdlType ddlType = ddlTypeRegistry.getDescriptor(
pluralType.getJdbcType().getDdlTypeCode()
); );
final String arrayTypeName = ddlType.getCastTypeName( Size.nil(), pluralType, ddlTypeRegistry );
return new SelfRenderingFunctionSqlAstExpression(
getFunctionName(),
getRenderingSupport(),
arguments,
resultType,
getMappingModelExpressible( walker, resultType, arguments )
) {
@Override
public void renderToSql(
SqlAppender sqlAppender,
SqlAstTranslator<?> walker,
SessionFactoryImplementor sessionFactory) {
sqlAppender.appendSql( arrayTypeName );
final List<? extends SqlAstNode> arguments = getArguments();
final int size = arguments.size();
if ( size == 0 ) {
sqlAppender.append( '(' );
}
else {
char separator = '(';
for ( int i = 0; i < size; i++ ) {
SqlAstNode argument = arguments.get( i );
sqlAppender.append( separator );
argument.accept( walker );
separator = ',';
}
}
sqlAppender.append( ')' );
}
};
} }
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) type;
final String arrayTypeName = DdlTypeHelper.getCastTypeName( pluralType, walker );
sqlAppender.appendSql( arrayTypeName );
final int size = sqlAstArguments.size();
if ( size == 0 ) {
sqlAppender.append( '(' );
}
else {
char separator = '(';
for ( int i = 0; i < size; i++ ) {
SqlAstNode argument = sqlAstArguments.get( i );
sqlAppender.append( separator );
argument.accept( walker );
separator = ',';
}
}
sqlAppender.append( ')' );
} }
} }

View File

@ -1,43 +0,0 @@
/*
* 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.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.type.spi.TypeConfiguration;
public class OracleArrayContainsAllFunction extends AbstractArrayContainsQuantifiedFunction {
private final boolean nullable;
public OracleArrayContainsAllFunction(TypeConfiguration typeConfiguration, boolean nullable) {
super( "array_contains_all", typeConfiguration );
this.nullable = nullable;
}
@Override
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
SqlAstTranslator<?> walker) {
final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final String arrayTypeName = DdlTypeHelper.getTypeName( haystackExpression.getExpressionType(), walker );
sqlAppender.appendSql( arrayTypeName );
sqlAppender.append( "_contains_all(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ',' );
sqlAppender.append( nullable ? "1" : "0" );
sqlAppender.append( ")>0" );
}
}

View File

@ -8,46 +8,49 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.BasicPluralType;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
public class OracleArrayContainsFunction extends AbstractSqmSelfRenderingFunctionDescriptor { public class OracleArrayContainsFunction extends AbstractArrayContainsFunction {
public OracleArrayContainsFunction(TypeConfiguration typeConfiguration) { public OracleArrayContainsFunction(boolean nullable, TypeConfiguration typeConfiguration) {
super( super( nullable, typeConfiguration );
"array_contains",
StandardArgumentsValidators.composite(
StandardArgumentsValidators.exactly( 2 ),
ArrayAndElementArgumentValidator.DEFAULT_INSTANCE
),
StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.standardBasicTypeForJavaType( Boolean.class ) ),
ArrayAndElementArgumentTypeResolver.DEFAULT_INSTANCE
);
} }
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final String arrayTypeName = DdlTypeHelper.getTypeName( arrayExpression.getExpressionType(), walker ); 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 );
sqlAppender.appendSql( arrayTypeName ); sqlAppender.appendSql( arrayTypeName );
sqlAppender.append( "_position(" ); if ( needleType == null || needleType instanceof BasicPluralType<?, ?> ) {
arrayExpression.accept( walker ); sqlAppender.append( "_contains(" );
sqlAppender.append( ',' ); haystackExpression.accept( walker );
sqlAstArguments.get( 1 ).accept( walker ); sqlAppender.append( ',' );
sqlAppender.append( ")>0" ); sqlAstArguments.get( 1 ).accept( walker );
} sqlAppender.append( ',' );
sqlAppender.append( nullable ? "1" : "0" );
@Override sqlAppender.append( ")>0" );
public String getArgumentListSignature() { }
return "(ARRAY array, OBJECT element)"; else {
sqlAppender.append( "_position(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
needleExpression.accept( walker );
sqlAppender.append( ")>0" );
}
} }
} }

View File

@ -1,51 +0,0 @@
/*
* 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.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
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.type.spi.TypeConfiguration;
public class OracleArrayContainsNullFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
public OracleArrayContainsNullFunction(TypeConfiguration typeConfiguration) {
super(
"array_contains_null",
StandardArgumentsValidators.composite(
StandardArgumentsValidators.exactly( 1 ),
ArrayArgumentValidator.DEFAULT_INSTANCE
),
StandardFunctionReturnTypeResolvers.invariant( typeConfiguration.standardBasicTypeForJavaType( Boolean.class ) ),
null
);
}
@Override
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final String arrayTypeName = DdlTypeHelper.getTypeName( arrayExpression.getExpressionType(), walker );
sqlAppender.appendSql( arrayTypeName );
sqlAppender.append( "_position(" );
arrayExpression.accept( walker );
sqlAppender.append( ",null)>0" );
}
@Override
public String getArgumentListSignature() {
return "(ARRAY array)";
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -25,6 +26,7 @@ public class OracleArrayGetFunction extends ArrayGetUnnestFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final String arrayTypeName = DdlTypeHelper.getTypeName( final String arrayTypeName = DdlTypeHelper.getTypeName(
( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(), ( (Expression) sqlAstArguments.get( 0 ) ).getExpressionType(),

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators; import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers; import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
@ -35,6 +36,7 @@ public class OracleArrayLengthFunction extends AbstractSqmSelfRenderingFunctionD
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final String arrayTypeName = DdlTypeHelper.getTypeName( arrayExpression.getExpressionType(), walker ); final String arrayTypeName = DdlTypeHelper.getTypeName( arrayExpression.getExpressionType(), walker );

View File

@ -8,25 +8,24 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
public class OracleArrayOverlapsFunction extends AbstractArrayContainsQuantifiedFunction { public class OracleArrayOverlapsFunction extends AbstractArrayOverlapsFunction {
private final boolean nullable;
public OracleArrayOverlapsFunction(TypeConfiguration typeConfiguration, boolean nullable) { public OracleArrayOverlapsFunction(TypeConfiguration typeConfiguration, boolean nullable) {
super( "array_overlaps", typeConfiguration ); super( nullable, typeConfiguration );
this.nullable = nullable;
} }
@Override @Override
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 ); final Expression haystackExpression = (Expression) sqlAstArguments.get( 0 );
final String arrayTypeName = DdlTypeHelper.getTypeName( haystackExpression.getExpressionType(), walker ); final String arrayTypeName = DdlTypeHelper.getTypeName( haystackExpression.getExpressionType(), walker );

View File

@ -8,6 +8,7 @@ package org.hibernate.dialect.function.array;
import java.util.List; import java.util.List;
import org.hibernate.query.ReturnableType;
import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender; import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -24,6 +25,7 @@ public class OracleArrayPositionFunction extends AbstractArrayPositionFunction {
public void render( public void render(
SqlAppender sqlAppender, SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments, List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) { SqlAstTranslator<?> walker) {
final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 ); final Expression arrayExpression = (Expression) sqlAstArguments.get( 0 );
final String arrayTypeName = DdlTypeHelper.getTypeName( arrayExpression.getExpressionType(), walker ); final String arrayTypeName = DdlTypeHelper.getTypeName( arrayExpression.getExpressionType(), walker );

Some files were not shown because too many files have changed in this diff Show More