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[]