Skip to content

Commit d9ffbf2

Browse files
committed
HHH-17355 Test array functions with NodeBuilder
1 parent d8773f3 commit d9ffbf2

40 files changed

+3543
-2420
lines changed

documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,7 @@ The following functions deal with SQL array types, which are not supported on ev
11181118
| Function | Purpose
11191119
11201120
| `array()` | Creates an array based on the passed arguments
1121+
| `array_list()` | Like `array`, but returns the result as `List<?>`
11211122
| `array_agg()` | Aggregates row values into an array
11221123
| `array_position()` | Determines the position of an element in an array
11231124
| `array_positions()` | Determines all positions of an element in an array
@@ -1138,12 +1139,15 @@ The following functions deal with SQL array types, which are not supported on ev
11381139
| `array_replace()` | Creates array copy replacing a given element with another
11391140
| `array_trim()` | Creates array copy trimming the last _N_ elements
11401141
| `array_fill()` | Creates array filled with the same element _N_ times
1142+
| `array_fill_list()` | Like `array_fill`, but returns the result as `List<?>`
11411143
| `array_to_string()` | String representation of non-null array elements
11421144
|===
11431145
1144-
===== `array()`
1146+
[[hql-array-constructor-functions]]
1147+
===== `array()` and `array_list()`
11451148
11461149
Creates an array based on the passed arguments, and infers the array type from the context if possible.
1150+
To retrieve the result as `List<?>`, use the `array_list()` function.
11471151
11481152
[[hql-array-constructor-example]]
11491153
====
@@ -1153,6 +1157,7 @@ include::{array-example-dir-hql}/ArrayConstructorTest.java[tags=hql-array-exampl
11531157
----
11541158
====
11551159
1160+
[[hql-array-aggregate-functions]]
11561161
===== `array_agg()`
11571162
11581163
An <<hql-aggregate-functions-orderedset,ordered set aggregate function>> that aggregates values to an array.
@@ -1404,6 +1409,7 @@ include::{array-example-dir-hql}/ArrayReplaceTest.java[tags=hql-array-replace-ex
14041409
----
14051410
====
14061411
1412+
[[hql-array-trim-functions]]
14071413
===== `array_trim()`
14081414
14091415
Returns an array copy without the last _N_ elements, specified by the second argument.
@@ -1417,10 +1423,12 @@ include::{array-example-dir-hql}/ArrayTrimTest.java[tags=hql-array-trim-example]
14171423
----
14181424
====
14191425
1420-
===== `array_fill()`
1426+
[[hql-array-fill-functions]]
1427+
===== `array_fill()` and `array_fill_list()`
14211428
14221429
Creates an array filled with the same element _N_ times as specified by the arguments.
14231430
It is an error to supply an array length smaller than 0.
1431+
To retrieve the result as `List<?>`, use the `array_fill_list()` function.
14241432
14251433
[[hql-array-fill-example]]
14261434
====
@@ -1430,6 +1438,7 @@ include::{array-example-dir-hql}/ArrayFillTest.java[tags=hql-array-fill-example]
14301438
----
14311439
====
14321440
1441+
[[hql-array-to-string-functions]]
14331442
===== `array_to_string()`
14341443
14351444
Concatenates the non-null array elements with a separator, as specified by the arguments.

hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
*/
77
package org.hibernate.dialect.function;
88

9-
import java.lang.reflect.Type;
109
import java.util.Date;
1110
import java.util.Arrays;
12-
import java.util.List;
1311

14-
import org.hibernate.annotations.common.reflection.java.generics.ParameterizedTypeImpl;
1512
import org.hibernate.boot.model.FunctionContributions;
1613
import org.hibernate.dialect.Dialect;
1714

@@ -2604,35 +2601,40 @@ public void dateTrunc_datetrunc() {
26042601
* H2, HSQL array() constructor function
26052602
*/
26062603
public void array() {
2607-
functionRegistry.register( "array", new ArrayConstructorFunction( true ) );
2604+
functionRegistry.register( "array", new ArrayConstructorFunction( false, true ) );
2605+
functionRegistry.register( "array_list", new ArrayConstructorFunction( true, true ) );
26082606
}
26092607

26102608
/**
26112609
* H2, HSQL array() constructor function
26122610
*/
26132611
public void array_hsql() {
2614-
functionRegistry.register( "array", new HSQLArrayConstructorFunction() );
2612+
functionRegistry.register( "array", new HSQLArrayConstructorFunction( false ) );
2613+
functionRegistry.register( "array_list", new HSQLArrayConstructorFunction( true ) );
26152614
}
26162615

26172616
/**
26182617
* CockroachDB and PostgreSQL array() constructor function
26192618
*/
26202619
public void array_postgresql() {
2621-
functionRegistry.register( "array", new PostgreSQLArrayConstructorFunction() );
2620+
functionRegistry.register( "array", new PostgreSQLArrayConstructorFunction( false ) );
2621+
functionRegistry.register( "array_list", new PostgreSQLArrayConstructorFunction( true ) );
26222622
}
26232623

26242624
/**
26252625
* Google Spanner array() constructor function
26262626
*/
26272627
public void array_spanner() {
2628-
functionRegistry.register( "array", new ArrayConstructorFunction( false ) );
2628+
functionRegistry.register( "array", new ArrayConstructorFunction( false, false ) );
2629+
functionRegistry.register( "array_list", new ArrayConstructorFunction( true, false ) );
26292630
}
26302631

26312632
/**
26322633
* Oracle array() constructor function
26332634
*/
26342635
public void array_oracle() {
2635-
functionRegistry.register( "array", new OracleArrayConstructorFunction() );
2636+
functionRegistry.register( "array", new OracleArrayConstructorFunction( false ) );
2637+
functionRegistry.register( "array_list", new OracleArrayConstructorFunction( true ) );
26362638
}
26372639

26382640
/**
@@ -3175,28 +3177,32 @@ public void arrayTrim_oracle() {
31753177
* H2 array_fill() function
31763178
*/
31773179
public void arrayFill_h2() {
3178-
functionRegistry.register( "array_fill", new H2ArrayFillFunction() );
3180+
functionRegistry.register( "array_fill", new H2ArrayFillFunction( false ) );
3181+
functionRegistry.register( "array_fill_list", new H2ArrayFillFunction( true ) );
31793182
}
31803183

31813184
/**
31823185
* HSQLDB array_fill() function
31833186
*/
31843187
public void arrayFill_hsql() {
3185-
functionRegistry.register( "array_fill", new HSQLArrayFillFunction() );
3188+
functionRegistry.register( "array_fill", new HSQLArrayFillFunction( false ) );
3189+
functionRegistry.register( "array_fill_list", new HSQLArrayFillFunction( true ) );
31863190
}
31873191

31883192
/**
31893193
* PostgreSQL array_fill() function
31903194
*/
31913195
public void arrayFill_postgresql() {
3192-
functionRegistry.register( "array_fill", new PostgreSQLArrayFillFunction() );
3196+
functionRegistry.register( "array_fill", new PostgreSQLArrayFillFunction( false ) );
3197+
functionRegistry.register( "array_fill_list", new PostgreSQLArrayFillFunction( true ) );
31933198
}
31943199

31953200
/**
31963201
* Oracle array_fill() function
31973202
*/
31983203
public void arrayFill_oracle() {
3199-
functionRegistry.register( "array_fill", new OracleArrayFillFunction() );
3204+
functionRegistry.register( "array_fill", new OracleArrayFillFunction( false ) );
3205+
functionRegistry.register( "array_fill_list", new OracleArrayFillFunction( true ) );
32003206
}
32013207

32023208
/**

hibernate-core/src/main/java/org/hibernate/dialect/function/array/AbstractArrayFillFunction.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121
*/
2222
public abstract class AbstractArrayFillFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
2323

24-
public AbstractArrayFillFunction() {
24+
public AbstractArrayFillFunction(boolean list) {
2525
super(
26-
"array_fill",
26+
"array_fill" + ( list ? "_list" : "" ),
2727
new ArgumentTypesValidator( null, FunctionParameterType.NO_UNTYPED, FunctionParameterType.INTEGER ),
28-
ArrayViaElementArgumentReturnTypeResolver.DEFAULT_INSTANCE,
28+
list
29+
? ArrayViaElementArgumentReturnTypeResolver.VARARGS_LIST_INSTANCE
30+
: ArrayViaElementArgumentReturnTypeResolver.VARARGS_INSTANCE,
2931
ArrayFillArgumentsValidator.INSTANCE
3032
);
3133
}

hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayConstructorFunction.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ public class ArrayConstructorFunction extends AbstractSqmSelfRenderingFunctionDe
2929

3030
private final boolean withKeyword;
3131

32-
public ArrayConstructorFunction(boolean withKeyword) {
32+
public ArrayConstructorFunction(boolean list, boolean withKeyword) {
3333
super(
34-
"array",
34+
"array" + ( list ? "_list" : "" ),
3535
ArrayConstructorArgumentsValidator.INSTANCE,
36-
ArrayViaElementArgumentReturnTypeResolver.VARARGS_INSTANCE,
36+
list
37+
? ArrayViaElementArgumentReturnTypeResolver.VARARGS_LIST_INSTANCE
38+
: ArrayViaElementArgumentReturnTypeResolver.VARARGS_INSTANCE,
3739
StandardFunctionArgumentTypeResolvers.NULL
3840
);
3941
this.withKeyword = withKeyword;

hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayViaElementArgumentReturnTypeResolver.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,17 @@
2424
*/
2525
public class ArrayViaElementArgumentReturnTypeResolver implements FunctionReturnTypeResolver {
2626

27-
public static final FunctionReturnTypeResolver DEFAULT_INSTANCE = new ArrayViaElementArgumentReturnTypeResolver( 0 );
28-
public static final FunctionReturnTypeResolver VARARGS_INSTANCE = new ArrayViaElementArgumentReturnTypeResolver( -1 );
27+
public static final FunctionReturnTypeResolver DEFAULT_INSTANCE = new ArrayViaElementArgumentReturnTypeResolver( false, 0 );
2928

29+
public static final FunctionReturnTypeResolver DEFAULT_LIST_INSTANCE = new ArrayViaElementArgumentReturnTypeResolver( true, 0 );
30+
public static final FunctionReturnTypeResolver VARARGS_INSTANCE = new ArrayViaElementArgumentReturnTypeResolver( false, -1 );
31+
public static final FunctionReturnTypeResolver VARARGS_LIST_INSTANCE = new ArrayViaElementArgumentReturnTypeResolver( true, -1 );
32+
33+
private final boolean list;
3034
private final int elementIndex;
3135

32-
private ArrayViaElementArgumentReturnTypeResolver(int elementIndex) {
36+
private ArrayViaElementArgumentReturnTypeResolver(boolean list, int elementIndex) {
37+
this.list = list;
3338
this.elementIndex = elementIndex;
3439
}
3540

@@ -55,14 +60,18 @@ else if ( inferredType instanceof BasicValuedMapping ) {
5560
for ( SqmTypedNode<?> argument : arguments ) {
5661
final DomainType<?> sqmType = argument.getExpressible().getSqmType();
5762
if ( sqmType instanceof ReturnableType<?> ) {
58-
return DdlTypeHelper.resolveArrayType( sqmType, typeConfiguration );
63+
return list
64+
? DdlTypeHelper.resolveListType( sqmType, typeConfiguration )
65+
: DdlTypeHelper.resolveArrayType( sqmType, typeConfiguration );
5966
}
6067
}
6168
}
6269
else {
6370
final DomainType<?> sqmType = arguments.get( elementIndex ).getExpressible().getSqmType();
6471
if ( sqmType instanceof ReturnableType<?> ) {
65-
return DdlTypeHelper.resolveArrayType( sqmType, typeConfiguration );
72+
return list
73+
? DdlTypeHelper.resolveListType( sqmType, typeConfiguration )
74+
: DdlTypeHelper.resolveArrayType( sqmType, typeConfiguration );
6675
}
6776
}
6877
return null;

hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArraysOfSameTypeArgumentValidator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package org.hibernate.dialect.function.array;
88

99
import java.util.List;
10+
import java.util.Objects;
1011

1112
import org.hibernate.metamodel.model.domain.DomainType;
1213
import org.hibernate.query.sqm.SqmExpressible;
@@ -46,7 +47,7 @@ public void validate(
4647
}
4748
arrayType = (BasicPluralType<?, ?>) sqmType;
4849
}
49-
else if ( !arrayType.equals( sqmType ) ) {
50+
else if ( !isCompatible( arrayType, sqmType ) ) {
5051
throw new FunctionArgumentException(
5152
String.format(
5253
"Parameter %d of function '%s()' requires an array type %s, but argument is of type '%s'",
@@ -61,6 +62,11 @@ else if ( !arrayType.equals( sqmType ) ) {
6162
}
6263
}
6364

65+
private static boolean isCompatible(BasicPluralType<?,?> arrayType, DomainType<?> sqmType) {
66+
return arrayType == sqmType || sqmType instanceof BasicPluralType<?, ?>
67+
&& Objects.equals( arrayType.getElementType(), ( (BasicPluralType<?, ?>) sqmType ).getElementType() );
68+
}
69+
6470
@Override
6571
public String getSignature() {
6672
return "(ARRAY array0, ARRAY array1[, ARRAY array2, ...])";

hibernate-core/src/main/java/org/hibernate/dialect/function/array/DdlTypeHelper.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
package org.hibernate.dialect.function.array;
88

99
import java.lang.reflect.Array;
10+
import java.lang.reflect.Type;
11+
import java.util.List;
1012

13+
import org.hibernate.annotations.common.reflection.java.generics.ParameterizedTypeImpl;
1114
import org.hibernate.dialect.Dialect;
1215
import org.hibernate.engine.jdbc.Size;
1316
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
@@ -16,7 +19,6 @@
1619
import org.hibernate.query.ReturnableType;
1720
import org.hibernate.sql.ast.SqlAstTranslator;
1821
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
19-
import org.hibernate.type.BasicPluralType;
2022
import org.hibernate.type.BasicType;
2123
import org.hibernate.type.descriptor.java.BasicPluralJavaType;
2224
import org.hibernate.type.descriptor.sql.DdlType;
@@ -40,6 +42,24 @@ public static BasicType<?> resolveArrayType(DomainType<?> elementType, TypeConfi
4042
);
4143
}
4244

45+
@SuppressWarnings("unchecked")
46+
public static BasicType<?> resolveListType(DomainType<?> elementType, TypeConfiguration typeConfiguration) {
47+
@SuppressWarnings("unchecked") final BasicPluralJavaType<Object> arrayJavaType = (BasicPluralJavaType<Object>) typeConfiguration.getJavaTypeRegistry()
48+
.getDescriptor( List.class )
49+
.createJavaType(
50+
new ParameterizedTypeImpl( List.class, new Type[]{ elementType.getBindableJavaType() }, null ),
51+
typeConfiguration
52+
);
53+
final Dialect dialect = typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect();
54+
return arrayJavaType.resolveType(
55+
typeConfiguration,
56+
dialect,
57+
(BasicType<Object>) elementType,
58+
null,
59+
typeConfiguration.getCurrentBaseSqlTypeIndicators()
60+
);
61+
}
62+
4363
public static String getTypeName(BasicType<?> type, SqlAstTranslator<?> walker) {
4464
return getTypeName( (JdbcMappingContainer) type, walker );
4565
}

hibernate-core/src/main/java/org/hibernate/dialect/function/array/H2ArrayFillFunction.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
*/
1919
public class H2ArrayFillFunction extends AbstractArrayFillFunction {
2020

21+
public H2ArrayFillFunction(boolean list) {
22+
super( list );
23+
}
24+
2125
@Override
2226
public void render(
2327
SqlAppender sqlAppender,

hibernate-core/src/main/java/org/hibernate/dialect/function/array/HSQLArrayConstructorFunction.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,17 @@
88

99
import java.util.List;
1010

11-
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
12-
import org.hibernate.metamodel.mapping.SqlTypedMapping;
1311
import org.hibernate.query.ReturnableType;
1412
import org.hibernate.sql.ast.SqlAstTranslator;
15-
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
1613
import org.hibernate.sql.ast.spi.SqlAppender;
1714
import org.hibernate.sql.ast.tree.SqlAstNode;
1815
import org.hibernate.sql.ast.tree.expression.Expression;
1916
import org.hibernate.type.BottomType;
2017

2118
public class HSQLArrayConstructorFunction extends ArrayConstructorFunction {
2219

23-
public HSQLArrayConstructorFunction() {
24-
super( true );
20+
public HSQLArrayConstructorFunction(boolean list) {
21+
super( list, true );
2522
}
2623

2724
@Override

hibernate-core/src/main/java/org/hibernate/dialect/function/array/HSQLArrayFillFunction.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
*/
2020
public class HSQLArrayFillFunction extends AbstractArrayFillFunction {
2121

22+
public HSQLArrayFillFunction(boolean list) {
23+
super( list );
24+
}
25+
2226
@Override
2327
public void render(
2428
SqlAppender sqlAppender,

hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayConstructorFunction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
public class OracleArrayConstructorFunction extends ArrayConstructorFunction {
2020

21-
public OracleArrayConstructorFunction() {
22-
super( false );
21+
public OracleArrayConstructorFunction(boolean list) {
22+
super( list, false );
2323
}
2424

2525
@Override

hibernate-core/src/main/java/org/hibernate/dialect/function/array/OracleArrayFillFunction.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
*/
2020
public class OracleArrayFillFunction extends AbstractArrayFillFunction {
2121

22+
public OracleArrayFillFunction(boolean list) {
23+
super( list );
24+
}
25+
2226
@Override
2327
public void render(
2428
SqlAppender sqlAppender,

hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayConstructorFunction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
*/
2424
public class PostgreSQLArrayConstructorFunction extends ArrayConstructorFunction {
2525

26-
public PostgreSQLArrayConstructorFunction() {
27-
super( true );
26+
public PostgreSQLArrayConstructorFunction(boolean list) {
27+
super( list, true );
2828
}
2929

3030
@Override

hibernate-core/src/main/java/org/hibernate/dialect/function/array/PostgreSQLArrayFillFunction.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
*/
2121
public class PostgreSQLArrayFillFunction extends AbstractArrayFillFunction {
2222

23+
public PostgreSQLArrayFillFunction(boolean list) {
24+
super( list );
25+
}
26+
2327
@Override
2428
public void render(
2529
SqlAppender sqlAppender,

0 commit comments

Comments
 (0)