From f2e6ad67412d1868dca243cf77f7b937d4017cf2 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 27 Oct 2023 12:10:47 +0200 Subject: [PATCH] HHH-17355 Add array_agg documentation and add it to NodeBuilder --- .../chapters/query/hql/QueryLanguage.adoc | 13 ++++++ .../org/hibernate/query/sqm/NodeBuilder.java | 41 +++++++++++++++++++ .../sqm/internal/SqmCriteriaNodeBuilder.java | 24 +++++++++++ .../function/array/ArrayAggregateTest.java | 2 + 4 files changed, 80 insertions(+) diff --git a/documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc b/documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc index aeb792d83d..04f6e89621 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc @@ -1118,6 +1118,7 @@ The following functions deal with SQL array types, which are not supported on ev | Function | Purpose | `array()` | Creates an array based on the passed arguments +| `array_agg()` | Aggregates row values into an array | `array_position()` | Determines the position of an element in an array | `array_length()` | Determines the length of an array | `array_concat()` | Concatenates array with each other in order @@ -1147,6 +1148,18 @@ include::{array-example-dir-hql}/ArrayConstructorTest.java[tags=hql-array-exampl ---- ==== +===== `array_agg()` + +An <> that aggregates values to an array. + +[[hql-array-agg-example]] +==== +[source, JAVA, indent=0] +---- +include::{array-example-dir-hql}/ArrayAggregateTest.java[tags=hql-array-agg-example] +---- +==== + [[hql-array-position-functions]] ===== `array_position()` diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/NodeBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/NodeBuilder.java index eb0177bb39..1221a63702 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/NodeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/NodeBuilder.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.hibernate.Incubating; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.query.NullPrecedence; @@ -25,10 +26,13 @@ import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaCoalesce; import org.hibernate.query.criteria.JpaCompoundSelection; import org.hibernate.query.criteria.JpaExpression; +import org.hibernate.query.criteria.JpaOrder; import org.hibernate.query.criteria.JpaParameterExpression; +import org.hibernate.query.criteria.JpaPredicate; import org.hibernate.query.criteria.JpaSearchedCase; import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.criteria.JpaSimpleCase; +import org.hibernate.query.criteria.JpaWindow; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; import org.hibernate.query.sqm.tree.domain.SqmBagJoin; @@ -100,6 +104,43 @@ public interface NodeBuilder extends HibernateCriteriaBuilder { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Array functions for array types + /** + * @see #arrayAgg(JpaOrder, JpaPredicate, JpaWindow, Expression) + * @since 6.4 + */ + JpaExpression arrayAgg(JpaOrder order, Expression argument); + + /** + * @see #arrayAgg(JpaOrder, JpaPredicate, JpaWindow, Expression) + * @since 6.4 + */ + JpaExpression arrayAgg(JpaOrder order, JpaPredicate filter, Expression argument); + + /** + * @see #arrayAgg(JpaOrder, JpaPredicate, JpaWindow, Expression) + * @since 6.4 + */ + JpaExpression arrayAgg(JpaOrder order, JpaWindow window, Expression argument); + + /** + * Create a {@code array_agg} ordered set-aggregate function expression. + * + * @param order order by clause used in within group + * @param filter optional filter clause + * @param window optional window over which to apply the function + * @param argument values to aggregate + * + * @return ordered set-aggregate expression + * + * @see #functionWithinGroup(String, Class, JpaOrder, JpaPredicate, JpaWindow, Expression...) + * @since 6.4 + */ + JpaExpression arrayAgg( + JpaOrder order, + JpaPredicate filter, + JpaWindow window, + Expression argument); + /** * Creates an array literal with the {@code array} constructor function. * diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java index 5bf64d266c..182c4fbed4 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java @@ -3632,6 +3632,30 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, return functionWithinGroup( "percent_rank", Double.class, order, filter, window, arguments ); } + @Override + public JpaExpression arrayAgg(JpaOrder order, Expression argument) { + return arrayAgg( order, null, null, argument ); + } + + @Override + public JpaExpression arrayAgg(JpaOrder order, JpaPredicate filter, Expression argument) { + return arrayAgg( order, filter, null, argument ); + } + + @Override + public JpaExpression arrayAgg(JpaOrder order, JpaWindow window, Expression argument) { + return arrayAgg( order, null, window, argument ); + } + + @Override + public JpaExpression arrayAgg( + JpaOrder order, + JpaPredicate filter, + JpaWindow window, + Expression argument) { + return functionWithinGroup( "array_agg", null, order, filter, window, argument ); + } + @Override public SqmExpression arrayLiteral(T... elements) { return getFunctionDescriptor( "array" ).generateSqmExpression( diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayAggregateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayAggregateTest.java index cc6aec90cf..3ea1bbbea5 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayAggregateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/function/array/ArrayAggregateTest.java @@ -109,8 +109,10 @@ public class ArrayAggregateTest { @Test public void testEmpty(SessionFactoryScope scope) { scope.inSession( em -> { + //tag::hql-array-agg-example[] List results = em.createQuery( "select array_agg(e.data) within group (order by e.id) from BasicEntity e", String[].class ) .getResultList(); + //end::hql-array-agg-example[] assertEquals( 1, results.size() ); assertNull( results.get( 0 ) ); } );