This is an automated email from the ASF dual-hosted git repository.
rubenql pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new 3c70ca4 [CALCITE-3820] EnumerableDefaults#orderBy should be lazily
computed + support enumerator re-initialization
3c70ca4 is described below
commit 3c70ca47272053a7c1f1f41079b88713da06f29c
Author: rubenada <[email protected]>
AuthorDate: Tue Feb 25 16:54:40 2020 +0100
[CALCITE-3820] EnumerableDefaults#orderBy should be lazily computed +
support enumerator re-initialization
---
.../test/enumerable/EnumerableJoinTest.java | 80 ++++++++++++++++++++++
.../apache/calcite/linq4j/EnumerableDefaults.java | 18 +++--
2 files changed, 91 insertions(+), 7 deletions(-)
diff --git
a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableJoinTest.java
b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableJoinTest.java
index 18d0215..aa500ab 100644
---
a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableJoinTest.java
+++
b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableJoinTest.java
@@ -21,11 +21,13 @@ import
org.apache.calcite.adapter.enumerable.EnumerableRules;
import org.apache.calcite.adapter.java.ReflectiveSchema;
import org.apache.calcite.config.CalciteConnectionProperty;
import org.apache.calcite.config.Lex;
+import org.apache.calcite.interpreter.Bindables;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.runtime.Hook;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.test.HierarchySchema;
import org.apache.calcite.test.JdbcTest;
import org.junit.jupiter.api.Test;
@@ -218,6 +220,84 @@ public class EnumerableJoinTest {
+ "empid=150; name=Sebastian; dept_name=Sales; e_deptno=10;
d_deptno=10");
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-3820">[CALCITE-3820]
+ * EnumerableDefaults#orderBy should be lazily computed + support enumerator
+ * re-initialization</a>. */
+ @Test public void testRepeatUnionWithMergeJoin() {
+ tester(false, new HierarchySchema())
+ .query("?")
+ .withHook(Hook.PLANNER, (Consumer<RelOptPlanner>) planner -> {
+ planner.addRule(Bindables.BINDABLE_TABLE_SCAN_RULE);
+ planner.addRule(EnumerableRules.ENUMERABLE_MERGE_JOIN_RULE);
+ planner.removeRule(EnumerableRules.ENUMERABLE_JOIN_RULE);
+ })
+ // Note: explicit sort is used so EnumerableMergeJoin can actually work
+ .withRel(builder -> builder
+ // WITH RECURSIVE delta(empid, name) as (
+ // SELECT empid, name FROM emps WHERE empid = 2
+ // UNION ALL
+ // SELECT e.empid, e.name FROM delta d
+ // JOIN hierarchies h ON d.empid =
h.managerid
+ // JOIN emps e ON
h.subordinateid = e.empid
+ // )
+ // SELECT empid, name FROM delta
+ .scan("s", "emps")
+ .filter(
+ builder.equals(
+ builder.field("empid"),
+ builder.literal(2)))
+ .project(
+ builder.field("emps", "empid"),
+ builder.field("emps", "name"))
+
+ .transientScan("#DELTA#")
+ .sort(builder.field("empid"))
+ .scan("s", "hierarchies")
+ .sort(builder.field("managerid"))
+ .join(
+ JoinRelType.INNER,
+ builder.equals(
+ builder.field(2, "#DELTA#", "empid"),
+ builder.field(2, "hierarchies", "managerid")))
+ .sort(builder.field("subordinateid"))
+
+ .scan("s", "emps")
+ .sort(builder.field("empid"))
+ .join(
+ JoinRelType.INNER,
+ builder.equals(
+ builder.field(2, "hierarchies", "subordinateid"),
+ builder.field(2, "emps", "empid")))
+ .project(
+ builder.field("emps", "empid"),
+ builder.field("emps", "name"))
+ .repeatUnion("#DELTA#", true)
+ .build()
+ )
+ .explainHookMatches("" // It is important to have MergeJoin +
EnumerableSort in the plan
+ + "EnumerableRepeatUnion(all=[true])\n"
+ + " EnumerableTableSpool(readType=[LAZY], writeType=[LAZY],
table=[[#DELTA#]])\n"
+ + " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[2],
expr#6=[=($t0, $t5)], empid=[$t0], name=[$t2], $condition=[$t6])\n"
+ + " EnumerableTableScan(table=[[s, emps]])\n"
+ + " EnumerableTableSpool(readType=[LAZY], writeType=[LAZY],
table=[[#DELTA#]])\n"
+ + " EnumerableCalc(expr#0..8=[{inputs}], empid=[$t0],
name=[$t2])\n"
+ + " EnumerableMergeJoin(condition=[=($0, $8)],
joinType=[inner])\n"
+ + " EnumerableSort(sort0=[$0], dir0=[ASC])\n"
+ + " EnumerableTableScan(table=[[s, emps]])\n"
+ + " EnumerableSort(sort0=[$3], dir0=[ASC])\n"
+ + " EnumerableMergeJoin(condition=[=($0, $2)],
joinType=[inner])\n"
+ + " EnumerableSort(sort0=[$0], dir0=[ASC])\n"
+ + " EnumerableInterpreter\n"
+ + " BindableTableScan(table=[[#DELTA#]])\n"
+ + " EnumerableSort(sort0=[$0], dir0=[ASC])\n"
+ + " EnumerableTableScan(table=[[s, hierarchies]])\n")
+ .returnsUnordered(""
+ + "empid=2; name=Emp2\n"
+ + "empid=3; name=Emp3\n"
+ + "empid=5; name=Emp5");
+ }
+
private CalciteAssert.AssertThat tester(boolean forceDecorrelate,
Object schema) {
return CalciteAssert.that()
diff --git
a/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
b/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
index 57531d1..a20f5fa 100644
--- a/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
+++ b/linq4j/src/main/java/org/apache/calcite/linq4j/EnumerableDefaults.java
@@ -2407,13 +2407,17 @@ public abstract class EnumerableDefaults {
public static <TSource, TKey> Enumerable<TSource> orderBy(
Enumerable<TSource> source, Function1<TSource, TKey> keySelector,
Comparator<TKey> comparator) {
- // NOTE: TreeMap allows null comparator. But the caller of this method
- // must supply a comparator if the key does not extend Comparable.
- // Otherwise there will be a ClassCastException while retrieving.
- final Map<TKey, List<TSource>> map = new TreeMap<>(comparator);
- LookupImpl<TKey, TSource> lookup = toLookup_(map, source, keySelector,
- Functions.identitySelector());
- return lookup.valuesEnumerable();
+ return new AbstractEnumerable<TSource>() {
+ @Override public Enumerator<TSource> enumerator() {
+ // NOTE: TreeMap allows null comparator. But the caller of this method
+ // must supply a comparator if the key does not extend Comparable.
+ // Otherwise there will be a ClassCastException while retrieving.
+ final Map<TKey, List<TSource>> map = new TreeMap<>(comparator);
+ final LookupImpl<TKey, TSource> lookup = toLookup_(map, source,
keySelector,
+ Functions.identitySelector());
+ return lookup.valuesEnumerable().enumerator();
+ }
+ };
}
/**