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 2020/12/26 16:52:29 UTC
[groovy] branch master updated: Support window function `rowNumber`
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 865fa04 Support window function `rowNumber`
865fa04 is described below
commit 865fa043da4473ed010ffff19656eb31aca340f5
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Dec 27 00:52:01 2020 +0800
Support window function `rowNumber`
---
.../ginq/provider/collection/GinqAstWalker.groovy | 55 ++++++++++++----------
.../groovy-ginq/src/spec/doc/ginq-userguide.adoc | 12 +++--
.../test/org/apache/groovy/ginq/GinqTest.groovy | 12 +++++
3 files changed, 50 insertions(+), 29 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 fce78b0..30347b5 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
@@ -677,36 +677,38 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
Expression result = null
if (windowFunctionMethodCallExpression.methodAsString in WINDOW_FUNCTION_LIST) {
def argumentListExpression = (ArgumentListExpression) windowFunctionMethodCallExpression.arguments
- def windowFunctionLambdaCode = argumentListExpression.getExpression(0)
- def windowFunctionLambdaName = '__wfp'
- def rootObjectExpression = findRootObjectExpression(windowFunctionLambdaCode)
-
- windowFunctionLambdaCode = ((ListExpression) (new ListExpression(Collections.singletonList(windowFunctionLambdaCode)).transformExpression(new ExpressionTransformer() {
- @Override
- Expression transform(Expression expr) {
- if (expr instanceof VariableExpression) {
- if (rootObjectExpression.text == expr.text) {
- if (dataSourceExpression instanceof JoinExpression) {
- return correctVars(dataSourceExpression, windowFunctionLambdaName=getLambdaParamName(dataSourceExpression, expr), expr)
- } else {
- return new VariableExpression(windowFunctionLambdaName)
+ List<Expression> argumentExpressionList = []
+ if (windowFunctionMethodCallExpression.methodAsString !in [FUNCTION_ROW_NUMBER]) {
+ def windowFunctionLambdaCode = argumentListExpression.getExpression(0)
+ def windowFunctionLambdaName = '__wfp'
+ def rootObjectExpression = findRootObjectExpression(windowFunctionLambdaCode)
+
+ windowFunctionLambdaCode = ((ListExpression) (new ListExpression(Collections.singletonList(windowFunctionLambdaCode)).transformExpression(new ExpressionTransformer() {
+ @Override
+ Expression transform(Expression expr) {
+ if (expr instanceof VariableExpression) {
+ if (rootObjectExpression.text == expr.text) {
+ if (dataSourceExpression instanceof JoinExpression) {
+ return correctVars(dataSourceExpression, windowFunctionLambdaName=getLambdaParamName(dataSourceExpression, expr), expr)
+ } else {
+ return new VariableExpression(windowFunctionLambdaName)
+ }
}
}
+ return expr.transformExpression(this)
}
- return expr.transformExpression(this)
- }
- }))).getExpression(0)
+ }))).getExpression(0)
- def argumentExpressionList = []
- argumentExpressionList << lambdaX(
- params(param(ClassHelper.DYNAMIC_TYPE, windowFunctionLambdaName)),
- block(stmt(windowFunctionLambdaCode))
- )
+ argumentExpressionList << lambdaX(
+ params(param(ClassHelper.DYNAMIC_TYPE, windowFunctionLambdaName)),
+ block(stmt(windowFunctionLambdaCode))
+ )
- if (windowFunctionMethodCallExpression.methodAsString in [FUNCTION_LEAD, FUNCTION_LAG]) {
- List<Expression> exprList = argumentListExpression.getExpressions()
- if (exprList.size() > 1) {
- argumentExpressionList.addAll(exprList.subList(1, exprList.size()))
+ if (windowFunctionMethodCallExpression.methodAsString in [FUNCTION_LEAD, FUNCTION_LAG]) {
+ List<Expression> exprList = argumentListExpression.getExpressions()
+ if (exprList.size() > 1) {
+ argumentExpressionList.addAll(exprList.subList(1, exprList.size()))
+ }
}
}
@@ -1342,12 +1344,13 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
private static final String FUNCTION_AGG = 'agg'
private static final List<String> AGG_FUNCTION_NAME_LIST = [FUNCTION_COUNT, FUNCTION_MIN, FUNCTION_MAX, FUNCTION_SUM, FUNCTION_AVG, FUNCTION_MEDIAN, FUNCTION_AGG]
+ private static final String FUNCTION_ROW_NUMBER = 'rowNumber'
private static final String FUNCTION_LEAD = 'lead'
private static final String FUNCTION_LAG = 'lag'
private static final String FUNCTION_FIRST_VALUE = 'firstValue'
private static final String FUNCTION_LAST_VALUE = 'lastValue'
private static final List<String> WINDOW_FUNCTION_LIST = [FUNCTION_COUNT, FUNCTION_MIN, FUNCTION_MAX, FUNCTION_SUM, FUNCTION_AVG, FUNCTION_MEDIAN,
- FUNCTION_LEAD, FUNCTION_LAG, FUNCTION_FIRST_VALUE, FUNCTION_LAST_VALUE]
+ FUNCTION_ROW_NUMBER, FUNCTION_LEAD, FUNCTION_LAG, FUNCTION_FIRST_VALUE, FUNCTION_LAST_VALUE]
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 95f9c37..46631cf 100644
--- a/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
+++ b/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
@@ -411,16 +411,22 @@ include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_nested_04,inde
==== Window Functions
GINQ supports some built-in window functions, e.g.
-`lead`, `lag`, `firstValue`, `lastValue`, `min`, `max`, `count`, `sum`, `avg`, `median`, etc.
+`rowNumber`, `lead`, `lag`, `firstValue`, `lastValue`, `min`, `max`, `count`, `sum`, `avg`, `median`, etc.
-===== `lead` and `lag`
+===== `rowNumber`
[source, groovy]
----
-include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_02,indent=0]
+include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_24,indent=0]
----
[NOTE]
The parentheses around the window function is required.
+===== `lead` and `lag`
+[source, groovy]
+----
+include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_02,indent=0]
+----
+
[source, groovy]
----
include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_04,indent=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 afb84c6..3e6f7f98 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
@@ -5147,6 +5147,18 @@ class GinqTest {
'''
}
+ @Test
+ void "testGinq - window - 43"() {
+ assertGinqScript '''
+// tag::ginq_winfunction_24[]
+ assert [[2, 1], [1, 0], [3, 2]] == GQ {
+ from n in [2, 1, 3]
+ select n, (rowNumber() over(orderby n))
+ }.toList()
+// end::ginq_winfunction_24[]
+ '''
+ }
+
private static void assertGinqScript(String script) {
String deoptimizedScript = script.replaceAll(/\bGQ\s*[{]/, 'GQ(optimize:false) {')
List<String> scriptList = [deoptimizedScript, script]