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/10/07 11:47:47 UTC

[groovy] branch GROOVY-8258 updated: GROOVY-8258: support referencing column by name

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

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


The following commit(s) were added to refs/heads/GROOVY-8258 by this push:
     new 7b769f8  GROOVY-8258: support referencing column by name
7b769f8 is described below

commit 7b769f87c8520036a8551eb62b3901b43dce9718
Author: Daniel Sun <su...@apache.org>
AuthorDate: Wed Oct 7 19:45:35 2020 +0800

    GROOVY-8258: support referencing column by name
---
 .../linq/provider/collection/GinqAstWalker.groovy  |  9 +++-
 .../linq/provider/collection/NamedList.groovy      | 61 ++++++++++++++++++++++
 .../groovy/org/apache/groovy/linq/GinqTest.groovy  | 41 ++++++++++++++-
 3 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/collection/GinqAstWalker.groovy b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/collection/GinqAstWalker.groovy
index e0453c1..ff102fe 100644
--- a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/collection/GinqAstWalker.groovy
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/collection/GinqAstWalker.groovy
@@ -36,6 +36,7 @@ import org.apache.groovy.linq.dsl.expression.WhereExpression
 import org.codehaus.groovy.ast.ClassHelper
 import org.codehaus.groovy.ast.expr.ArgumentListExpression
 import org.codehaus.groovy.ast.expr.ClassExpression
+import org.codehaus.groovy.ast.expr.ConstantExpression
 import org.codehaus.groovy.ast.expr.Expression
 import org.codehaus.groovy.ast.expr.ExpressionTransformer
 import org.codehaus.groovy.ast.expr.ListExpression
@@ -44,7 +45,11 @@ import org.codehaus.groovy.ast.expr.TupleExpression
 import org.codehaus.groovy.ast.expr.VariableExpression
 import org.codehaus.groovy.control.SourceUnit
 
+import java.util.stream.Collectors
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX
 import static org.codehaus.groovy.ast.tools.GeneralUtils.lambdaX
 import static org.codehaus.groovy.ast.tools.GeneralUtils.param
 import static org.codehaus.groovy.ast.tools.GeneralUtils.params
@@ -206,7 +211,9 @@ class GinqAstWalker implements GinqVisitor<Object>, SyntaxErrorReportable {
         List<Expression> expressionList = ((TupleExpression) projectionExpr).getExpressions()
         Expression lambdaCode
         if (expressionList.size() > 1) {
-            lambdaCode = new ListExpression(expressionList)
+            List<Expression> nameExpressionList = expressionList.stream().map(e -> new ConstantExpression(e.text)).collect(Collectors.toList())
+            ListExpression nameListExpression = new ListExpression(nameExpressionList)
+            lambdaCode = ctorX(ClassHelper.make(NamedList.class), args(new ListExpression(expressionList), nameListExpression))
         } else {
             lambdaCode = expressionList.get(0)
         }
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/collection/NamedList.groovy b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/collection/NamedList.groovy
new file mode 100644
index 0000000..6fbd45c
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/collection/NamedList.groovy
@@ -0,0 +1,61 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.groovy.linq.provider.collection
+
+import groovy.transform.CompileStatic
+
+/**
+ * Immutable named list to represent list result of GINQ
+ *
+ * @since 4.0.0
+ */
+@CompileStatic
+class NamedList<E> extends AbstractList<E> {
+    private final List<E> elementList
+    private final List<String> nameList
+
+    private NamedList(List<E> elementList, List<String> nameList) {
+        this.elementList = elementList
+        this.nameList = nameList
+    }
+
+    E getAt(String name) {
+        final int index = nameList.indexOf(name)
+
+        if (-1 == index) {
+            throw new IndexOutOfBoundsException("Failed to find element with name: $name")
+        }
+
+        return get(index)
+    }
+
+    E get(String name) {
+        return getAt(name)
+    }
+
+    @Override
+    E get(int index) {
+        return elementList.get(index)
+    }
+
+    @Override
+    int size() {
+        return elementList.size()
+    }
+}
diff --git a/subprojects/groovy-linq/src/test/groovy/org/apache/groovy/linq/GinqTest.groovy b/subprojects/groovy-linq/src/test/groovy/org/apache/groovy/linq/GinqTest.groovy
index f34bc3f..f394f25 100644
--- a/subprojects/groovy-linq/src/test/groovy/org/apache/groovy/linq/GinqTest.groovy
+++ b/subprojects/groovy-linq/src/test/groovy/org/apache/groovy/linq/GinqTest.groovy
@@ -459,9 +459,48 @@ class GinqTest {
                     where n1 > 1 && n2 <= 5
                     select n1, n2
                 )
-                where v[0] >= 3 && v[1] in [3, 5] // v[0] references column 1, and v[1] references column 2
+                where v.n1 >= 3 && v.n2 in [3, 5]
                 select v
             }.toList()
         '''
     }
+
+    @Test
+    void "testGinq - nested from - 5"() {
+        assertScript '''
+            def nums1 = [1, 2, 3, 4, 5]
+            def nums2 = [1, 2, 3, 4, 5]
+            assert [[3, 3], [5, 5]] == GINQ {
+                from v in (
+                    from n1 in nums1
+                    innerJoin n2 in nums2
+                    on n1 == n2
+                    where n1 > 1 && n2 <= 5
+                    select n1, n2
+                )
+                where v['n1'] >= 3 && v['n2'] in [3, 5]
+                select v
+            }.toList()
+        '''
+    }
+
+    @Test
+    void "testGinq - nested from - 6"() {
+        assertScript '''
+            def nums1 = [1, 2, 3, 4, 5]
+            def nums2 = [1, 2, 3, 4, 5]
+            assert [[3, 3], [5, 5]] == GINQ {
+                from v in (
+                    from n1 in nums1
+                    innerJoin n2 in nums2
+                    on n1 == n2
+                    where n1 > 1 && n2 <= 5
+                    select n1, n2
+                )
+                where v[0] >= 3 && v[1] in [3, 5] // v[0] references column1 n1, and v[1] references column2 n2
+                select v
+            }.toList()
+        '''
+    }
+
 }