You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by hy...@apache.org on 2020/06/10 15:28:39 UTC

[calcite] branch master updated: [CALCITE-4018] Support trait propagation for EnumerableValues

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

hyuan 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 7c5c7e3  [CALCITE-4018] Support trait propagation for EnumerableValues
7c5c7e3 is described below

commit 7c5c7e3b77b6a7606e1295dd7c47815cbbe10871
Author: Haisheng Yuan <h....@alibaba-inc.com>
AuthorDate: Tue Jun 9 19:20:50 2020 -0500

    [CALCITE-4018] Support trait propagation for EnumerableValues
    
    In addition, add code snippet to demonstrate how to generate IndexScan on
    demand by passing required collation through TableScan.
---
 .../adapter/enumerable/EnumerableTableScan.java    | 22 +++++++++++++
 .../adapter/enumerable/EnumerableValues.java       | 37 ++++++++++++++++++++++
 .../calcite/rel/metadata/RelMdCollation.java       |  2 +-
 .../org/apache/calcite/test/TopDownOptTest.java    | 12 +++++++
 .../org/apache/calcite/test/TopDownOptTest.xml     | 37 ++++++++++++++++++++++
 5 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableScan.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableScan.java
index fe10098..1381463 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableScan.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableScan.java
@@ -29,6 +29,7 @@ import org.apache.calcite.linq4j.tree.MethodCallExpression;
 import org.apache.calcite.linq4j.tree.ParameterExpression;
 import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.linq4j.tree.Types;
+import org.apache.calcite.plan.DeriveMode;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelOptUtil;
@@ -73,6 +74,27 @@ public class EnumerableTableScan
         : "EnumerableTableScan can't implement " + table + ", see EnumerableTableScan#canHandle";
   }
 
+  /**
+   * Code snippet to demonstrate how to generate IndexScan on demand
+   * by passing required collation through TableScan.
+   *
+   * @return IndexScan if there is index available on collation keys
+   */
+  @Override public RelNode passThrough(final RelTraitSet required) {
+/*
+    keys = required.getCollation().getKeys();
+    if (table has index on keys) {
+      direction = forward or backward;
+      return new IndexScan(table, indexInfo, direction);
+    }
+*/
+    return null;
+  }
+
+  @Override public DeriveMode getDeriveMode() {
+    return DeriveMode.PROHIBITED;
+  }
+
   /** Creates an EnumerableTableScan. */
   public static EnumerableTableScan create(RelOptCluster cluster,
       RelOptTable relOptTable) {
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableValues.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableValues.java
index 97b6554..8c6fa5c 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableValues.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableValues.java
@@ -21,10 +21,13 @@ import org.apache.calcite.linq4j.tree.BlockBuilder;
 import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.Expressions;
 import org.apache.calcite.linq4j.tree.Primitive;
+import org.apache.calcite.plan.DeriveMode;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.RelCollationTraitDef;
 import org.apache.calcite.rel.RelDistributionTraitDef;
+import org.apache.calcite.rel.RelFieldCollation;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Values;
 import org.apache.calcite.rel.metadata.RelMdCollation;
@@ -37,6 +40,7 @@ import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Pair;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Ordering;
 
 import java.lang.reflect.Type;
 import java.util.ArrayList;
@@ -70,6 +74,39 @@ public class EnumerableValues extends Values implements EnumerableRel {
     return new EnumerableValues(getCluster(), rowType, tuples, traitSet);
   }
 
+  @Override public RelNode passThrough(final RelTraitSet required) {
+    RelCollation collation = required.getCollation();
+    if (collation == null || collation.isDefault()) {
+      return null;
+    }
+
+    // A Values with 0 or 1 rows can be ordered by any collation.
+    if (tuples.size() > 1) {
+      Ordering<List<RexLiteral>> ordering = null;
+      // Generate ordering comparator according to the required collations.
+      for (RelFieldCollation fc : collation.getFieldCollations()) {
+        Ordering<List<RexLiteral>> comparator = RelMdCollation.comparator(fc);
+        if (ordering == null) {
+          ordering = comparator;
+        } else {
+          ordering = ordering.compound(comparator);
+        }
+      }
+      // Check whether the tuples are sorted by required collations.
+      if (!ordering.isOrdered(tuples)) {
+        return null;
+      }
+    }
+
+    // The tuples order satisfies the collation, we just create a new
+    // relnode with required collation info.
+    return copy(traitSet.replace(collation), ImmutableList.of());
+  }
+
+  @Override public DeriveMode getDeriveMode() {
+    return DeriveMode.PROHIBITED;
+  }
+
   public Result implement(EnumerableRelImplementor implementor, Prefer pref) {
 /*
           return Linq4j.asEnumerable(
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
index 1a5b42b..4923bfc 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
@@ -405,7 +405,7 @@ public class RelMdCollation
     return list;
   }
 
-  private static Ordering<List<RexLiteral>> comparator(
+  public static Ordering<List<RexLiteral>> comparator(
       RelFieldCollation fieldCollation) {
     final int nullComparison = fieldCollation.nullDirection.nullComparison;
     final int x = fieldCollation.getFieldIndex();
diff --git a/core/src/test/java/org/apache/calcite/test/TopDownOptTest.java b/core/src/test/java/org/apache/calcite/test/TopDownOptTest.java
index 6b6ceb6..28950fd 100644
--- a/core/src/test/java/org/apache/calcite/test/TopDownOptTest.java
+++ b/core/src/test/java/org/apache/calcite/test/TopDownOptTest.java
@@ -73,6 +73,18 @@ import java.util.List;
  * </ol>
  */
 class TopDownOptTest extends RelOptTestBase {
+  @Test void testValuesTraitRequest() {
+    final String sql = "SELECT * from (values (1, 1), (2, 1), (1, 2), (2, 2))\n"
+        + "as t(a, b) order by b, a";
+    Query.create(sql).check();
+  }
+
+  @Test void testValuesTraitRequestNeg() {
+    final String sql = "SELECT * from (values (1, 1), (2, 1), (3, 2), (2, 2))\n"
+        + "as t(a, b) order by b, a";
+    Query.create(sql).check();
+  }
+
   @Test void testSortAgg() {
     final String sql = "select mgr, count(*) from sales.emp\n"
         + "group by mgr order by mgr desc nulls last limit 5";
diff --git a/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml b/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml
index 8dc333c..eb266ba 100644
--- a/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml
@@ -1192,4 +1192,41 @@ EnumerableCorrelate(correlation=[$cor2], joinType=[semi], requiredColumns=[{0}])
 ]]>
     </Resource>
   </TestCase>
+  <TestCase name="testValuesTraitRequest">
+    <Resource name="sql">
+      <![CDATA[SELECT * from (values (1, 1), (2, 1), (1, 2), (2, 2))
+as t(a, b) order by b, a]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[ASC])
+  LogicalProject(A=[$0], B=[$1])
+    LogicalValues(tuples=[[{ 1, 1 }, { 2, 1 }, { 1, 2 }, { 2, 2 }]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+EnumerableValues(tuples=[[{ 1, 1 }, { 2, 1 }, { 1, 2 }, { 2, 2 }]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testValuesTraitRequestNeg">
+    <Resource name="sql">
+      <![CDATA[SELECT * from (values (1, 1), (2, 1), (3, 2), (2, 2))
+as t(a, b) order by b, a]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[ASC])
+  LogicalProject(A=[$0], B=[$1])
+    LogicalValues(tuples=[[{ 1, 1 }, { 2, 1 }, { 3, 2 }, { 2, 2 }]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+EnumerableSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[ASC])
+  EnumerableValues(tuples=[[{ 1, 1 }, { 2, 1 }, { 3, 2 }, { 2, 2 }]])
+]]>
+    </Resource>
+  </TestCase>
 </Root>