You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/07/20 04:48:29 UTC

[groovy] branch master updated: Add `agg` window function for GINQ

This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new b3e522d  Add `agg` window function for GINQ
b3e522d is described below

commit b3e522d38ae678b364b0e71d877bd8a71bb83e9d
Author: Daniel Sun <su...@apache.org>
AuthorDate: Tue Jul 20 12:48:10 2021 +0800

    Add `agg` window function for GINQ
---
 .../ginq/provider/collection/GinqAstWalker.groovy  | 22 ++++++++++---
 .../groovy-ginq/src/spec/doc/ginq-userguide.adoc   | 12 ++++++-
 .../test/org/apache/groovy/ginq/GinqTest.groovy    | 38 +++++++++++++++++++++-
 3 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
index 3333790..6f33278 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
@@ -769,12 +769,24 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
                                         @Override
                                         Expression transform(Expression expr) {
                                             if (expr instanceof VariableExpression) {
+                                                def isJoin = dataSourceExpression instanceof JoinExpression
                                                 if (rootObjectExpression.text == expr.text) {
-                                                    if (dataSourceExpression instanceof JoinExpression) {
-                                                        return correctVars(dataSourceExpression, windowFunctionLambdaName=getLambdaParamName(dataSourceExpression, expr), expr)
-                                                    } else {
-                                                        return new VariableExpression(windowFunctionLambdaName)
+                                                    if (isJoin) {
+                                                        windowFunctionLambdaName = getLambdaParamName(dataSourceExpression, expr)
+                                                        return correctVars(dataSourceExpression, windowFunctionLambdaName, expr)
                                                     }
+
+                                                    return new VariableExpression(windowFunctionLambdaName)
+                                                } else if (FUNCTION_AGG == windowFunctionMethodCallExpression.methodAsString && _G == expr.text) {
+                                                    if (isJoin) {
+                                                        windowFunctionLambdaName = getLambdaParamName(dataSourceExpression, expr)
+                                                    }
+
+                                                    return callX(
+                                                            classX(QUERYABLE_HELPER_TYPE),
+                                                            "navigate",
+                                                            args(new VariableExpression(windowFunctionLambdaName), getMetaDataMethodCall(MD_ALIAS_NAME_LIST))
+                                                    )
                                                 }
                                             }
                                             return expr.transformExpression(this)
@@ -1575,7 +1587,7 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
     private static final String FUNCTION_PERCENT_RANK = 'percentRank'
     private static final String FUNCTION_CUME_DIST = 'cumeDist'
     private static final String FUNCTION_NTILE = 'ntile'
-    private static final List<String> WINDOW_FUNCTION_LIST = [FUNCTION_COUNT, FUNCTION_MIN, FUNCTION_MAX, FUNCTION_SUM, FUNCTION_AVG, FUNCTION_MEDIAN, FUNCTION_STDEV, FUNCTION_STDEVP, FUNCTION_VAR, FUNCTION_VARP,
+    private static final List<String> WINDOW_FUNCTION_LIST = [FUNCTION_COUNT, FUNCTION_MIN, FUNCTION_MAX, FUNCTION_SUM, FUNCTION_AVG, FUNCTION_MEDIAN, FUNCTION_STDEV, FUNCTION_STDEVP, FUNCTION_VAR, FUNCTION_VARP, FUNCTION_AGG,
                                                               FUNCTION_ROW_NUMBER, FUNCTION_LEAD, FUNCTION_LAG, FUNCTION_FIRST_VALUE, FUNCTION_LAST_VALUE, FUNCTION_NTH_VALUE, FUNCTION_RANK, FUNCTION_DENSE_RANK, FUNCTION_PERCENT_RANK, FUNCTION_CUME_DIST, FUNCTION_NTILE]
 
     private static final String NAMEDRECORD_CLASS_NAME = NamedRecord.class.name
diff --git a/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc b/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
index a0368ff..dc386b8 100644
--- a/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
+++ b/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
@@ -660,6 +660,11 @@ Also, GINQ provides some built-in window functions:
 |java.math.BigDecimal
 |the statistical variance for the population for all non-null values
 
+|agg(_expression_)
+|any
+|any
+|customizes the aggregation logic in _expression_ and returns single value
+
 |===
 
 
@@ -805,7 +810,7 @@ include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_11
 include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_40,indent=0]
 ----
 
-===== `min`, `max`, `count`, `sum`, `avg`, `median`, `stdev`, `stdevp`, `var` and `varp`
+===== `min`, `max`, `count`, `sum`, `avg`, `median`, `stdev`, `stdevp`, `var` ,`varp` and `agg`
 [source, groovy]
 ----
 include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_22,indent=0]
@@ -876,6 +881,11 @@ include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_37
 include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_38,indent=0]
 ----
 
+[source, groovy]
+----
+include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_42,indent=0]
+----
+
 === GINQ Tips
 ==== Row Number
 `_rn` is the implicit variable representing row number for each record in the result set. It starts with `0`
diff --git a/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy b/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy
index 228fc08..756f2fc 100644
--- a/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy
+++ b/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy
@@ -5429,7 +5429,7 @@ class GinqTest {
                 from n in [1, 1, 2, 2, 3, 3]
                 select n, (count() over(partitionby n)),
                           (count(n) over(partitionby n)),
-                          (sum(n) over(partitionby n)), 
+                          (sum(n) over(partitionby n)),
                           (avg(n) over(partitionby n)),
                           (median(n) over(partitionby n))
             }.toList()
@@ -6007,6 +6007,42 @@ class GinqTest {
     }
 
     @Test
+    void "testGinq - window - 88"() {
+        assertGinqScript '''
+            assert [[1, 3], [2, 3]] == GQ {
+                from n in [1, 2]
+                select n,
+                    (agg(_g.stream().map(r -> r.n).reduce(BigDecimal.ZERO, BigDecimal::add)) over())
+            }.toList()
+        '''
+    }
+
+    @Test
+    void "testGinq - window - 89"() {
+        assertGinqScript '''
+// tag::ginq_winfunction_42[]
+            assert [[1, 4], [2, 2], [3, 4]] == GQ {
+                from n in [1, 2, 3]
+                select n,
+                       (agg(_g.stream().map(r -> r.n).reduce(BigDecimal.ZERO, BigDecimal::add)) over(partitionby n % 2))
+            }.toList()
+// end::ginq_winfunction_42[]
+        '''
+    }
+
+    @Test
+    void "testGinq - window - 90"() {
+        assertGinqScript'''
+            assert [[1, 4], [2, 2], [3, 4]] == GQ {
+                from n in [1, 2, 3]
+                join m in [1, 2, 3] on m == n
+                select n,
+                       (agg(_g.stream().map(r -> r.n).reduce(BigDecimal.ZERO, BigDecimal::add)) over(partitionby n % 2))
+            }.toList()
+        '''
+    }
+
+    @Test
     void "testGinq - switch - 1"() {
         assertGinqScript '''
 // tag::ginq_tips_13[]