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 );
if ( expressible != null ) {
return DdlTypeHelper.resolveArrayType( return DdlTypeHelper.resolveArrayType(
sqmType, (DomainType<?>) expressible.getSingleJdbcMapping(),
converter.getCreationContext().getSessionFactory().getTypeConfiguration() 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,63 +8,78 @@ 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();
final JdbcMapping needleType = needleTypeContainer == null ? null : needleTypeContainer.getSingleJdbcMapping();
if ( needleType == null || needleType instanceof BasicPluralType<?, ?> ) {
if ( nullable ) {
super.render( sqlAppender, sqlAstArguments, returnType, walker );
}
else {
haystackExpression.accept( walker );
sqlAppender.append( "@>" ); sqlAppender.append( "@>" );
if ( needsArrayCasting( elementExpression ) ) { needleExpression.accept( walker );
}
}
else {
if ( nullable ) {
sqlAppender.append( "array_position(" );
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[" ); sqlAppender.append( "cast(array[" );
elementExpression.accept( walker ); needleExpression.accept( walker );
sqlAppender.append( "] as " ); sqlAppender.append( "] as " );
sqlAppender.append( DdlTypeHelper.getCastTypeName( arrayExpression.getExpressionType(), walker ) ); sqlAppender.append( DdlTypeHelper.getCastTypeName(
haystackExpression.getExpressionType(),
walker
) );
sqlAppender.append( ')' ); sqlAppender.append( ')' );
} }
else { else {
sqlAppender.append( "array[" ); sqlAppender.append( "array[" );
elementExpression.accept( walker ); needleExpression.accept( walker );
sqlAppender.append( ']' ); sqlAppender.append( ']' );
} }
} }
}
}
private static boolean needsArrayCasting(Expression elementExpression) { private static boolean needsArrayCasting(Expression elementExpression) {
// 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( "@>" );
}
else {
sqlAppender.append( "&&" ); 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( '(' );
if ( ArrayHelper.isNullable( haystackExpression ) ) {
haystackExpression.accept( walker ); haystackExpression.accept( walker );
sqlAppender.append( " is not null and " ); sqlAppender.append( " is not null and " );
}
if ( ArrayHelper.isNullable( needleExpression ) ) {
needleExpression.accept( walker ); needleExpression.accept( walker );
sqlAppender.append( " is not null and " ); 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( " except " );
}
else {
sqlAppender.append( " intersect " ); 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( '(' );
if ( ArrayHelper.isNullable( haystackExpression ) ) {
haystackExpression.accept( walker ); haystackExpression.accept( walker );
sqlAppender.append( " is not null and " ); sqlAppender.append( " is not null and " );
}
if ( ArrayHelper.isNullable( needleExpression ) ) {
needleExpression.accept( walker ); needleExpression.accept( walker );
sqlAppender.append( " is not null and " ); 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( " except " );
}
else {
sqlAppender.append( " intersect " ); 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,92 +23,33 @@ 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,
arguments,
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
);
}
@Override
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final ReturnableType<?> resultType = resolveResultType( walker );
List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
if ( getArgumentsValidator() != null ) {
getArgumentsValidator().validateSqlTypes( arguments, getFunctionName() );
}
if ( resultType == null ) {
throw new SemanticException( throw new SemanticException(
"Oracle array constructor emulation requires knowledge about the return type, but resolved return type could not be determined" "Oracle array constructor emulation requires knowledge about the return type, but resolved return type could not be determined"
); );
} }
final DomainType<?> type = resultType.getSqmType(); final DomainType<?> type = returnType.getSqmType();
if ( !( type instanceof BasicPluralType<?, ?> ) ) { if ( !( type instanceof BasicPluralType<?, ?> ) ) {
throw new SemanticException( throw new SemanticException(
"Oracle array constructor emulation requires a basic plural return type, but resolved return type was: " + type "Oracle array constructor emulation requires a basic plural return type, but resolved return type was: " + type
); );
} }
final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) type; final BasicPluralType<?, ?> pluralType = (BasicPluralType<?, ?>) type;
final TypeConfiguration typeConfiguration = walker.getCreationContext().getSessionFactory().getTypeConfiguration(); final String arrayTypeName = DdlTypeHelper.getCastTypeName( pluralType, walker );
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 ); sqlAppender.appendSql( arrayTypeName );
final List<? extends SqlAstNode> arguments = getArguments(); final int size = sqlAstArguments.size();
final int size = arguments.size();
if ( size == 0 ) { if ( size == 0 ) {
sqlAppender.append( '(' ); sqlAppender.append( '(' );
} }
else { else {
char separator = '('; char separator = '(';
for ( int i = 0; i < size; i++ ) { for ( int i = 0; i < size; i++ ) {
SqlAstNode argument = arguments.get( i ); SqlAstNode argument = sqlAstArguments.get( i );
sqlAppender.append( separator ); sqlAppender.append( separator );
argument.accept( walker ); argument.accept( walker );
separator = ','; separator = ',';
@ -131,7 +57,4 @@ public class OracleArrayConstructorFunction extends ArrayConstructorFunction {
} }
sqlAppender.append( ')' ); 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(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' ); sqlAppender.append( ',' );
sqlAstArguments.get( 1 ).accept( walker ); sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.append( ',' );
sqlAppender.append( nullable ? "1" : "0" );
sqlAppender.append( ")>0" );
}
else {
sqlAppender.append( "_position(" );
haystackExpression.accept( walker );
sqlAppender.append( ',' );
needleExpression.accept( walker );
sqlAppender.append( ")>0" ); sqlAppender.append( ")>0" );
} }
@Override
public String getArgumentListSignature() {
return "(ARRAY array, OBJECT element)";
} }
} }

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