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/25 17:20:59 UTC
[groovy] 02/02: Tweak `orderby` for window function
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
commit 89db644b8ad79aa910686e6b059cc9be8cd1ac7c
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat Dec 26 01:20:34 2020 +0800
Tweak `orderby` for window function
---
.../ginq/provider/collection/GinqAstWalker.groovy | 4 ++--
.../provider/collection/runtime/Queryable.java | 1 +
.../collection/runtime/WindowDefinition.java | 23 ++++++++++++++++++----
.../collection/runtime/WindowDefinitionImpl.java | 15 +++++++-------
.../provider/collection/runtime/WindowImpl.java | 8 ++++----
.../test/org/apache/groovy/ginq/GinqTest.groovy | 20 +++++++++++++++++++
6 files changed, 54 insertions(+), 17 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 5ad13c2..a82357a 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
@@ -760,8 +760,8 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
}
if (orderExpr) {
- def orderCtorCallExpression = constructOrderCtorCallExpressions(orderExpr, dataSourceExpression).get(0)
- argumentExpressionList << orderCtorCallExpression
+ def orderCtorCallExpressions = constructOrderCtorCallExpressions(orderExpr, dataSourceExpression)
+ argumentExpressionList << new ListExpression(orderCtorCallExpressions)
}
callX(
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java
index cfc422d..8021955 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java
@@ -462,6 +462,7 @@ public interface Queryable<T> {
class Order<T, U extends Comparable<? super U>> {
private final Function<? super T, ? extends U> keyExtractor;
private final boolean asc;
+ public static final Order[] EMPTY_ARRAY = new Order[0];
public Order(Function<? super T, ? extends U> keyExtractor, boolean asc) {
this.keyExtractor = keyExtractor;
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinition.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinition.java
index 5567507..88e72f6 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinition.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinition.java
@@ -18,6 +18,8 @@
*/
package org.apache.groovy.ginq.provider.collection.runtime;
+import java.util.Collections;
+import java.util.List;
import java.util.function.Function;
/**
@@ -52,6 +54,19 @@ public interface WindowDefinition<T, U extends Comparable<? super U>> {
* @since 4.0.0
*/
static <T, U extends Comparable<? super U>> WindowDefinition<T, U> of(Queryable.Order<? super T, ? extends U> orderBy) {
+ return new WindowDefinitionImpl<T, U>(Collections.singletonList(orderBy));
+ }
+
+ /**
+ * Factory method to create {@link WindowDefinition} instance
+ *
+ * @param orderBy order definition
+ * @param <T> the type of {@link Queryable} element
+ * @param <U> the type of field to sort
+ * @return the {@link WindowDefinition} instance
+ * @since 4.0.0
+ */
+ static <T, U extends Comparable<? super U>> WindowDefinition<T, U> of(List<Queryable.Order<? super T, ? extends U>> orderBy) {
return new WindowDefinitionImpl<>(orderBy);
}
@@ -65,7 +80,7 @@ public interface WindowDefinition<T, U extends Comparable<? super U>> {
* @return the {@link WindowDefinition} instance
* @since 4.0.0
*/
- static <T, U extends Comparable<? super U>> WindowDefinition<T, U> of(Function<? super T, ?> partitionBy, Queryable.Order<? super T, ? extends U> orderBy) {
+ static <T, U extends Comparable<? super U>> WindowDefinition<T, U> of(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy) {
return new WindowDefinitionImpl<>(partitionBy, orderBy);
}
@@ -80,7 +95,7 @@ public interface WindowDefinition<T, U extends Comparable<? super U>> {
* @return the {@link WindowDefinition} instance
* @since 4.0.0
*/
- static <T, U extends Comparable<? super U>> WindowDefinition<T, U> of(Function<? super T, ?> partitionBy, Queryable.Order<? super T, ? extends U> orderBy, RowBound rows) {
+ static <T, U extends Comparable<? super U>> WindowDefinition<T, U> of(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy, RowBound rows) {
return new WindowDefinitionImpl<>(partitionBy, orderBy, rows);
}
@@ -95,7 +110,7 @@ public interface WindowDefinition<T, U extends Comparable<? super U>> {
* @return the {@link WindowDefinition} instance
* @since 4.0.0
*/
- static <T, U extends Comparable<? super U>> WindowDefinition<T, U> of(Function<? super T, ?> partitionBy, Queryable.Order<? super T, ? extends U> orderBy, ValueBound<? extends U, ? extends U> range) {
+ static <T, U extends Comparable<? super U>> WindowDefinition<T, U> of(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy, ValueBound<? extends U, ? extends U> range) {
return new WindowDefinitionImpl<>(partitionBy, orderBy, range);
}
@@ -114,7 +129,7 @@ public interface WindowDefinition<T, U extends Comparable<? super U>> {
* @return order definition
* @since 4.0.0
*/
- Queryable.Order<? super T, ? extends U> orderBy();
+ List<Queryable.Order<? super T, ? extends U>> orderBy();
/**
* Define the window bounds by offsets, similar to MySQL's {@code rows between 1 preceding and 1 following } of window definition
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinitionImpl.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinitionImpl.java
index efd946b..39c350a 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinitionImpl.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinitionImpl.java
@@ -18,6 +18,7 @@
*/
package org.apache.groovy.ginq.provider.collection.runtime;
+import java.util.List;
import java.util.Objects;
import java.util.function.Function;
@@ -30,11 +31,11 @@ import java.util.function.Function;
*/
class WindowDefinitionImpl<T, U extends Comparable<? super U>> implements WindowDefinition<T, U> {
private final Function<? super T, ?> partitionBy;
- private final Queryable.Order<? super T, ? extends U> orderBy;
+ private final List<Queryable.Order<? super T, ? extends U>> orderBy;
private final RowBound rows;
private final ValueBound<? extends U, ? extends U> range;
- public WindowDefinitionImpl(Function<? super T, ?> partitionBy, Queryable.Order<? super T, ? extends U> orderBy,
+ public WindowDefinitionImpl(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy,
RowBound rows, ValueBound<? extends U, ? extends U> range) {
this.partitionBy = partitionBy;
this.orderBy = orderBy;
@@ -46,20 +47,20 @@ class WindowDefinitionImpl<T, U extends Comparable<? super U>> implements Window
this(partitionBy, null, RowBound.DEFAULT, null);
}
- public WindowDefinitionImpl(Queryable.Order<? super T, ? extends U> orderBy) {
+ public WindowDefinitionImpl(List<Queryable.Order<? super T, ? extends U>> orderBy) {
this((T t) -> Queryable.NULL, orderBy, RowBound.DEFAULT, null);
}
- public WindowDefinitionImpl(Function<? super T, ?> partitionBy, Queryable.Order<? super T, ? extends U> orderBy) {
+ public WindowDefinitionImpl(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy) {
this(partitionBy, orderBy, RowBound.DEFAULT, null);
}
- public WindowDefinitionImpl(Function<? super T, ?> partitionBy, Queryable.Order<? super T, ? extends U> orderBy,
+ public WindowDefinitionImpl(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy,
RowBound rows) {
this(partitionBy, orderBy, rows, null);
}
- public WindowDefinitionImpl(Function<? super T, ?> partitionBy, Queryable.Order<? super T, ? extends U> orderBy,
+ public WindowDefinitionImpl(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy,
ValueBound<? extends U, ? extends U> range) {
this(partitionBy, orderBy, RowBound.DEFAULT, range);
}
@@ -70,7 +71,7 @@ class WindowDefinitionImpl<T, U extends Comparable<? super U>> implements Window
}
@Override
- public Queryable.Order<? super T, ? extends U> orderBy() {
+ public List<Queryable.Order<? super T, ? extends U>> orderBy() {
return orderBy;
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java
index 61dad4b..c6a654b 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java
@@ -36,14 +36,14 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
private final WindowDefinition<T, U> windowDefinition;
WindowImpl(T currentRecord, Queryable<T> partition, WindowDefinition<T, U> windowDefinition) {
- super(partition.orderBy(windowDefinition.orderBy()).toList());
+ super(partition.orderBy(windowDefinition.orderBy().toArray(Order.EMPTY_ARRAY)).toList());
this.currentRecord = currentRecord;
this.windowDefinition = windowDefinition;
List<T> sortedList = this.toList();
- final Order<? super T, ? extends U> order = windowDefinition.orderBy();
- if (null != order) {
- this.value = order.getKeyExtractor().apply(currentRecord);
+ final List<Order<? super T, ? extends U>> order = windowDefinition.orderBy();
+ if (null != order && 1 == order.size()) {
+ this.value = order.get(0).getKeyExtractor().apply(currentRecord);
} else {
this.value = null;
}
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 cfccb5a..83b6d8c 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
@@ -4905,6 +4905,26 @@ class GinqTest {
'''
}
+ @Test
+ void "testGinq - window - 24"() {
+ assertGinqScript '''
+ assert [['a', 'bc'], ['ab', null], ['b', 'a'], ['bc', 'ab']] == GQ {
+ from s in ['a', 'ab', 'b', 'bc']
+ select s, (lead(s) over(orderby s.length(), s in desc))
+ }.toList()
+ '''
+ }
+
+ @Test
+ void "testGinq - window - 25"() {
+ assertGinqScript '''
+ assert [['a', null], ['ab', null], ['b', 'a'], ['bc', 'ab']] == GQ {
+ from s in ['a', 'ab', 'b', 'bc']
+ select s, (lead(s) over(partitionby s.length() orderby s.length(), s in desc))
+ }.toList()
+ '''
+ }
+
private static void assertGinqScript(String script) {
String deoptimizedScript = script.replaceAll(/\bGQ\s*[{]/, 'GQ(optimize:false) {')
List<String> scriptList = [deoptimizedScript, script]