calcite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jcama...@apache.org
Subject calcite git commit: [CALCITE-1618] SortProjectTransposeRule should check for monotonicity preserving CAST
Date Wed, 08 Feb 2017 13:33:03 GMT
Repository: calcite
Updated Branches:
  refs/heads/master a07c7420b -> 2c9fddfe7


[CALCITE-1618] SortProjectTransposeRule should check for monotonicity preserving CAST

Close apache/calcite#369


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/2c9fddfe
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/2c9fddfe
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/2c9fddfe

Branch: refs/heads/master
Commit: 2c9fddfe7db9c0c7c55b8a8b2fe1b00948cd94b2
Parents: a07c742
Author: Jesus Camacho Rodriguez <jcamacho@apache.org>
Authored: Fri Feb 3 14:11:34 2017 +0000
Committer: Jesus Camacho Rodriguez <jcamacho@apache.org>
Committed: Wed Feb 8 13:32:24 2017 +0000

----------------------------------------------------------------------
 .../org/apache/calcite/plan/RelOptUtil.java     | 36 ++++++++++--
 .../rel/rules/SortProjectTransposeRule.java     | 18 +++++-
 .../org/apache/calcite/rex/RexCallBinding.java  |  2 +-
 .../apache/calcite/test/RelOptRulesTest.java    | 36 ++++++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml | 60 ++++++++++++++++++++
 5 files changed, 144 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/2c9fddfe/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index 37bb54a..c0073ea 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -388,10 +388,10 @@ public abstract class RelOptUtil {
   /**
    * Returns a permutation describing where output fields come from. In
    * the returned map, value of {@code map.getTargetOpt(i)} is {@code n} if
-   * field {@code i} projects input field {@code n}, -1 if it is an
-   * expression.
+   * field {@code i} projects input field {@code n} or applies a cast on
+   * {@code n}, -1 if it is another expression.
    */
-  public static Mappings.TargetMapping permutation(
+  public static Mappings.TargetMapping permutationIgnoreCast(
       List<RexNode> nodes,
       RelDataType inputRowType) {
     final Mappings.TargetMapping mapping =
@@ -405,17 +405,41 @@ public abstract class RelOptUtil {
             node.i,
             ((RexInputRef) node.e).getIndex());
       } else if (node.e.isA(SqlKind.CAST)) {
-        RexNode operand = ((RexCall) node.e).getOperands().get(0);
+        final RexNode operand = ((RexCall) node.e).getOperands().get(0);
         if (operand instanceof RexInputRef) {
           mapping.set(
-              node.i,
-              ((RexInputRef) operand).getIndex());
+            node.i,
+            ((RexInputRef) operand).getIndex());
         }
       }
     }
     return mapping;
   }
 
+  /**
+   * Returns a permutation describing where output fields come from. In
+   * the returned map, value of {@code map.getTargetOpt(i)} is {@code n} if
+   * field {@code i} projects input field {@code n}, -1 if it is an
+   * expression.
+   */
+  public static Mappings.TargetMapping permutation(
+      List<RexNode> nodes,
+      RelDataType inputRowType) {
+    final Mappings.TargetMapping mapping =
+        Mappings.create(
+            MappingType.PARTIAL_FUNCTION,
+            nodes.size(),
+            inputRowType.getFieldCount());
+    for (Ord<RexNode> node : Ord.zip(nodes)) {
+      if (node.e instanceof RexInputRef) {
+        mapping.set(
+            node.i,
+            ((RexInputRef) node.e).getIndex());
+      }
+    }
+    return mapping;
+  }
+
   @Deprecated // to be removed before 2.0
   public static RelNode createExistsPlan(
       RelOptCluster cluster,

http://git-wip-us.apache.org/repos/asf/calcite/blob/2c9fddfe/core/src/main/java/org/apache/calcite/rel/rules/SortProjectTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SortProjectTransposeRule.java
b/core/src/main/java/org/apache/calcite/rel/rules/SortProjectTransposeRule.java
index 29d66cf..e7b4467 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/SortProjectTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/SortProjectTransposeRule.java
@@ -28,7 +28,12 @@ import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Project;
 import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexCallBinding;
+import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexUtil;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.util.mapping.Mappings;
 
 import com.google.common.collect.ImmutableList;
@@ -85,12 +90,23 @@ public class SortProjectTransposeRule extends RelOptRule {
     // Determine mapping between project input and output fields. If sort
     // relies on non-trivial expressions, we can't push.
     final Mappings.TargetMapping map =
-        RelOptUtil.permutation(
+        RelOptUtil.permutationIgnoreCast(
             project.getProjects(), project.getInput().getRowType());
     for (RelFieldCollation fc : sort.getCollation().getFieldCollations()) {
       if (map.getTargetOpt(fc.getFieldIndex()) < 0) {
         return;
       }
+      final RexNode node = project.getProjects().get(fc.getFieldIndex());
+      if (node.isA(SqlKind.CAST)) {
+        // Check whether it is a monotonic preserving cast, otherwise we cannot push
+        final RexCall cast = (RexCall) node;
+        final RexCallBinding binding =
+            RexCallBinding.create(cluster.getTypeFactory(), cast,
+                ImmutableList.of(RexUtil.apply(map, sort.getCollation())));
+        if (cast.getOperator().getMonotonicity(binding) == SqlMonotonicity.NOT_MONOTONIC)
{
+          return;
+        }
+      }
     }
     final RelCollation newCollation =
         cluster.traitSet().canonize(

http://git-wip-us.apache.org/repos/asf/calcite/blob/2c9fddfe/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java b/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
index 4b21ec4..427b550 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
@@ -104,7 +104,7 @@ public class RexCallBinding extends SqlOperatorBinding {
     } else if (operand instanceof RexCall) {
       final RexCallBinding binding =
           RexCallBinding.create(typeFactory, (RexCall) operand, inputCollations);
-      ((RexCall) operand).getOperator().getMonotonicity(binding);
+      return ((RexCall) operand).getOperator().getMonotonicity(binding);
     }
 
     return SqlMonotonicity.NOT_MONOTONIC;

http://git-wip-us.apache.org/repos/asf/calcite/blob/2c9fddfe/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 88ca598..cc65a23 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -2750,6 +2750,42 @@ public class RelOptRulesTest extends RelOptTestBase {
         .checkUnchanged();
   }
 
+  @Test public void testSortProjectTranspose1() {
+    final HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(SortProjectTransposeRule.INSTANCE)
+        .build();
+    // This one can be pushed down
+    final String sql = "select d.deptno from sales.dept d\n"
+        + "order by cast(d.deptno as integer) offset 1";
+    sql(sql)
+        .with(program)
+        .check();
+  }
+
+  @Test public void testSortProjectTranspose2() {
+    final HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(SortProjectTransposeRule.INSTANCE)
+        .build();
+    // This one can be pushed down
+    final String sql = "select d.deptno from sales.dept d\n"
+        + "order by cast(d.deptno as double) offset 1";
+    sql(sql)
+        .with(program)
+        .check();
+  }
+
+  @Test public void testSortProjectTranspose3() {
+    final HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(SortProjectTransposeRule.INSTANCE)
+        .build();
+    // This one cannot be pushed down
+    final String sql = "select d.deptno from sales.dept d\n"
+        + "order by cast(d.deptno as varchar(10)) offset 1";
+    sql(sql)
+        .with(program)
+        .checkUnchanged();
+  }
+
   /** Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-1023">[CALCITE-1023]
    * Planner rule that removes Aggregate keys that are constant</a>. */

http://git-wip-us.apache.org/repos/asf/calcite/blob/2c9fddfe/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index 2f74e37..66c634b 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -5772,6 +5772,66 @@ LogicalProject(DEPTNO=[$0], EMPNO=[$2])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testSortProjectTranspose1">
+        <Resource name="sql">
+            <![CDATA[select d.deptno from sales.dept d
+order by cast(d.deptno as integer) offset 1]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalSort(sort0=[$1], dir0=[ASC], offset=[1])
+  LogicalProject(DEPTNO=[$0], EXPR$1=[CAST($0):INTEGER NOT NULL])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(DEPTNO=[$0], EXPR$1=[CAST($0):INTEGER NOT NULL])
+  LogicalSort(sort0=[$0], dir0=[ASC], offset=[1])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testSortProjectTranspose2">
+        <Resource name="sql">
+            <![CDATA[select d.deptno from sales.dept d
+order by cast(d.deptno as double) offset 1]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalSort(sort0=[$1], dir0=[ASC], offset=[1])
+  LogicalProject(DEPTNO=[$0], EXPR$1=[CAST($0):DOUBLE NOT NULL])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(DEPTNO=[$0], EXPR$1=[CAST($0):DOUBLE NOT NULL])
+  LogicalSort(sort0=[$0], dir0=[ASC], offset=[1])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testSortProjectTranspose3">
+        <Resource name="sql">
+            <![CDATA[select d.deptno from sales.dept d
+order by cast(d.deptno as varchar(10)) offset 1]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalSort(sort0=[$1], dir0=[ASC], offset=[1])
+  LogicalProject(DEPTNO=[$0], EXPR$1=[CAST($0):VARCHAR(10) CHARACTER SET "ISO-8859-1" COLLATE
"ISO-8859-1$en_US$primary" NOT NULL])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalSort(sort0=[$1], dir0=[ASC], offset=[1])
+  LogicalProject(DEPTNO=[$0], EXPR$1=[CAST($0):VARCHAR(10) CHARACTER SET "ISO-8859-1" COLLATE
"ISO-8859-1$en_US$primary" NOT NULL])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testSortUnionTranspose">
         <Resource name="sql">
             <![CDATA[select a.name from dept a


Mime
View raw message