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/23 00:09:05 UTC
[groovy] branch master updated: Tweak validation for window
function and add more test cases
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 544ef57 Tweak validation for window function and add more test cases
544ef57 is described below
commit 544ef57dea9bc698381749b25780793c08cb1279
Author: Daniel Sun <su...@apache.org>
AuthorDate: Wed Dec 23 08:08:01 2020 +0800
Tweak validation for window function and add more test cases
---
.../ginq/provider/collection/GinqAstWalker.groovy | 74 +++++++++++++---------
.../test/org/apache/groovy/ginq/GinqTest.groovy | 21 ++++++
.../org/apache/groovy/ginq/GinqErrorTest.groovy | 12 ++++
3 files changed, 76 insertions(+), 31 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 017ed64..5b1cd1d 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
@@ -666,41 +666,53 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
VariableExpression currentRecordVar = varX(lambdaParamName)
currentGinqExpression.putNodeMetaData(__VISITING_WINDOW_FUNCTION, true)
- def windowDefinitionFactoryMethodCallExpression = constructWindowDefinitionFactoryMethodCallExpression(expression, dataSourceExpression)
- Expression newObjectExpression = callX(wqVar, 'over', args(
- currentRecordVar,
- windowDefinitionFactoryMethodCallExpression
- ))
-
def windowFunctionMethodCallExpression = (MethodCallExpression) expression.objectExpression
- def windowFunctionLambdaCode = ((ArgumentListExpression) windowFunctionMethodCallExpression.arguments).getExpression(0)
- def windowFunctionLambdaName = findRootObjectExpression(windowFunctionLambdaCode).text
- def newWindowFunctionLambdaName = '__wfp'
-
- windowFunctionLambdaCode = ((ListExpression) (new ListExpression(Collections.singletonList(windowFunctionLambdaCode)).transformExpression(new ExpressionTransformer() {
- @Override
- Expression transform(Expression expr) {
- if (expr instanceof VariableExpression) {
- if (windowFunctionLambdaName == expr.text) {
- if (dataSourceExpression instanceof JoinExpression) {
- return correctVars(dataSourceExpression, newWindowFunctionLambdaName=getLambdaParamName(dataSourceExpression, expr), expr)
- } else {
- return new VariableExpression(newWindowFunctionLambdaName)
+
+ Expression result = null
+ if (windowFunctionMethodCallExpression.methodAsString in ['lead', 'lag']) {
+ def windowFunctionLambdaCode = ((ArgumentListExpression) windowFunctionMethodCallExpression.arguments).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)
-
- def result = callX(
- newObjectExpression,
- windowFunctionMethodCallExpression.methodAsString,
- lambdaX(
- params(param(ClassHelper.DYNAMIC_TYPE, newWindowFunctionLambdaName)),
- block(stmt(windowFunctionLambdaCode))
- )
- )
+ }))).getExpression(0)
+
+ def argumentExpressionList = []
+ argumentExpressionList << lambdaX(
+ params(param(ClassHelper.DYNAMIC_TYPE, windowFunctionLambdaName)),
+ block(stmt(windowFunctionLambdaCode))
+ )
+
+ def windowDefinitionFactoryMethodCallExpression = constructWindowDefinitionFactoryMethodCallExpression(expression, dataSourceExpression)
+ Expression newObjectExpression = callX(wqVar, 'over', args(
+ currentRecordVar,
+ windowDefinitionFactoryMethodCallExpression
+ ))
+ result = callX(
+ newObjectExpression,
+ windowFunctionMethodCallExpression.methodAsString,
+ args(argumentExpressionList)
+ )
+ } else {
+ GinqAstWalker.this.collectSyntaxError(new GinqSyntaxError(
+ "Unsupported window function: `${windowFunctionMethodCallExpression.methodAsString}`",
+ windowFunctionMethodCallExpression.getLineNumber(), windowFunctionMethodCallExpression.getColumnNumber()
+ ))
+ }
+
currentGinqExpression.putNodeMetaData(__VISITING_WINDOW_FUNCTION, false)
return result
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 6d2b48d..f0251fa 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
@@ -4669,6 +4669,27 @@ class GinqTest {
'''
}
+ @Test
+ void "testGinq - window - 2"() {
+ assertGinqScript '''
+ assert [[2, 3], [1, 2], [3, null]] == GQ {
+ from n in [2, 1, 3]
+ select n, (lead(n) over(orderby n))
+ }.toList()
+ '''
+ }
+
+ @Test
+ void "testGinq - window - 3"() {
+ assertGinqScript '''
+ assert [[2, 3], [1, 2], [3, null]] == GQ {
+ from n in [2, 1, 3]
+ join m in [2, 1, 3] on m == n
+ select n, (lead(n) over(orderby n))
+ }.toList()
+ '''
+ }
+
private static void assertGinqScript(String script) {
String deoptimizedScript = script.replaceAll(/\bGQ\s*[{]/, 'GQ(optimize:false) {')
List<String> scriptList = [deoptimizedScript, script]
diff --git a/subprojects/groovy-ginq/src/test/groovy/org/apache/groovy/ginq/GinqErrorTest.groovy b/subprojects/groovy-ginq/src/test/groovy/org/apache/groovy/ginq/GinqErrorTest.groovy
index cd365f0..8bf9087 100644
--- a/subprojects/groovy-ginq/src/test/groovy/org/apache/groovy/ginq/GinqErrorTest.groovy
+++ b/subprojects/groovy-ginq/src/test/groovy/org/apache/groovy/ginq/GinqErrorTest.groovy
@@ -430,4 +430,16 @@ class GinqErrorTest {
assert err.toString().contains('Only binary expressions(`==`, `&&`) are allowed in `on` clause of hash join @ line 3, column 49.')
}
+
+ @Test
+ void "testGinq - window - 0"() {
+ def err = shouldFail '''\
+ GQ {
+ from n in [2, 1, 3]
+ select n, (xxx(n) over(orderby n))
+ }.toList()
+ '''
+
+ assert err.toString().contains('Unsupported window function: `xxx` @ line 3, column 28.')
+ }
}