You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2016/01/15 00:16:41 UTC

[1/4] calcite git commit: [CALCITE-1058] Add method RelBuilder.empty, and rewrite LIMIT 0 to it

Repository: calcite
Updated Branches:
  refs/heads/master 3cba70550 -> af77ec861


[CALCITE-1058] Add method RelBuilder.empty, and rewrite LIMIT 0 to it


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

Branch: refs/heads/master
Commit: ee283cadf17d8add8e8ea2bf1f8dd5735f05dc1d
Parents: 3cba705
Author: Julian Hyde <jh...@apache.org>
Authored: Wed Jan 13 21:37:27 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jan 14 13:51:44 2016 -0800

----------------------------------------------------------------------
 .../org/apache/calcite/tools/RelBuilder.java    | 21 +++++++++++++
 .../org/apache/calcite/test/RelBuilderTest.java | 33 ++++++++++++++++++++
 2 files changed, 54 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/ee283cad/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
index 00ce6d1..cf9fcb6 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -1155,6 +1155,24 @@ public class RelBuilder {
     return true;
   }
 
+  /** Creates a relational expression that reads from an input and throws
+   * all of the rows away.
+   *
+   * <p>Note that this method always pops one relational expression from the
+   * stack. {@code values}, in contrast, does not pop any relational
+   * expressions, and always produces a leaf.
+   *
+   * <p>The default implementation creates a {@link Values} with the same
+   * specified row type as the input, and ignores the input entirely.
+   * But schema-on-query systems such as Drill might override this method to
+   * create a relation expression that retains the input, just to read its
+   * schema.
+   */
+  public RelBuilder empty() {
+    final Frame frame = Stacks.pop(stack);
+    return values(frame.rel.getRowType());
+  }
+
   /** Creates a {@link Values} with a specified row type.
    *
    * <p>This method can handle cases that {@link #values(String[], Object...)}
@@ -1274,6 +1292,9 @@ public class RelBuilder {
     }
     final RexNode offsetNode = offset <= 0 ? null : literal(offset);
     final RexNode fetchNode = fetch < 0 ? null : literal(fetch);
+    if (offsetNode == null && fetch == 0) {
+      return empty();
+    }
     if (offsetNode == null && fetchNode == null && fieldCollations.isEmpty()) {
       return this; // sort is trivial
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/ee283cad/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
index 0b232f4..db13a02 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -873,6 +873,25 @@ public class RelBuilderTest {
     assertThat(str(root), is(expected));
   }
 
+  @Test public void testEmpty() {
+    // Equivalent SQL:
+    //   SELECT deptno, true FROM dept LIMIT 0
+    // optimized to
+    //   VALUES
+    final RelBuilder builder = RelBuilder.create(config().build());
+    RelNode root =
+        builder.scan("DEPT")
+            .project(builder.field(0), builder.literal(false))
+            .empty()
+            .build();
+    final String expected =
+        "LogicalValues(tuples=[[]])\n";
+    assertThat(str(root), is(expected));
+    final String expectedType =
+        "RecordType(TINYINT NOT NULL DEPTNO, BOOLEAN NOT NULL $f1) NOT NULL";
+    assertThat(root.getRowType().getFullTypeString(), is(expectedType));
+  }
+
   @Test public void testValues() {
     // Equivalent SQL:
     //   VALUES (true, 1), (false, -50) AS t(a, b)
@@ -1071,6 +1090,20 @@ public class RelBuilderTest {
     assertThat(str(root), is(expected));
   }
 
+  @Test public void testSortLimit0() {
+    // Equivalent SQL:
+    //   SELECT *
+    //   FROM emp
+    //   ORDER BY deptno DESC FETCH 0
+    final RelBuilder builder = RelBuilder.create(config().build());
+    final RelNode root =
+        builder.scan("EMP")
+            .sortLimit(-1, 0, builder.desc(builder.field("DEPTNO")))
+            .build();
+    final String expected = "LogicalValues(tuples=[[]])\n";
+    assertThat(str(root), is(expected));
+  }
+
   /** Tests that a sort on a field followed by a limit gives the same
    * effect as calling sortLimit.
    *


[2/4] calcite git commit: [CALCITE-978] Enable customizing constant folding rule behavior when a Filter simplifies to false (Jason Altekruse)

Posted by jh...@apache.org.
[CALCITE-978] Enable customizing constant folding rule behavior when a Filter simplifies to false (Jason Altekruse)

For static schema systems, a Filter that is always false or null can be
replaced by a Values operator that produces no rows, as the schema
information can just be taken from the input Rel. In dynamic schema
environments, the filter might have an unknown input type, in these cases
they must define a system specific alternative to a Values operator, such
as inserting a Limit 0 instead of a Filter on top of the original input.

This change enables this behavior to be customized by a subclass of the
constant reduction rules.

Close apache/calcite#183


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

Branch: refs/heads/master
Commit: 898fdfc2720770ec4752fb702ce0aae1521aa07d
Parents: ee283ca
Author: Jason Altekruse <al...@gmail.com>
Authored: Fri Apr 10 15:39:54 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jan 14 13:52:01 2016 -0800

----------------------------------------------------------------------
 .../rel/rules/ReduceExpressionsRule.java        | 51 ++++++++++++++++++--
 1 file changed, 48 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/898fdfc2/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index 3fce8a6..1036ea4 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -55,6 +55,7 @@ import org.apache.calcite.sql.SqlOperator;
 import org.apache.calcite.sql.fun.SqlRowOperator;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.tools.RelBuilder;
 import org.apache.calcite.tools.RelBuilderFactory;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Stacks;
@@ -160,7 +161,7 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
             filter.getInput());
       } else if (newConditionExp instanceof RexLiteral
           || RexUtil.isNullLiteral(newConditionExp, true)) {
-        call.transformTo(call.builder().values(filter.getRowType()).build());
+        call.transformTo(createEmptyRelOrEquivalent(call, filter));
       } else if (reduced) {
         call.transformTo(call.builder().
             push(filter.getInput()).filter(expList.get(0)).build());
@@ -182,6 +183,28 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
       call.getPlanner().setImportance(filter, 0.0);
     }
 
+    /**
+     * For static schema systems, a filter that is always false or null can be
+     * replaced by a values operator that produces no rows, as the schema
+     * information can just be taken from the input Rel. In dynamic schema
+     * environments, the filter might have an unknown input type, in these cases
+     * they must define a system specific alternative to a Values operator, such
+     * as inserting a limit 0 instead of a filter on top of the original input.
+     *
+     * <p>The default implementation of this method is to call
+     * {@link RelBuilder#empty}, which for the static schema will be optimized
+     * to an empty
+     * {@link org.apache.calcite.rel.core.Values}.
+     *
+     * @param input rel to replace, assumes caller has already determined
+     *              equivalence to Values operation for 0 records or a
+     *              false filter.
+     * @return equivalent but less expensive replacement rel
+     */
+    protected RelNode createEmptyRelOrEquivalent(RelOptRuleCall call, Filter input) {
+      return call.builder().push(input).empty().build();
+    }
+
     private void reduceNotNullableFilter(
         RelOptRuleCall call,
         Filter filter,
@@ -212,7 +235,7 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
           if (alwaysTrue) {
             call.transformTo(filter.getInput());
           } else {
-            call.transformTo(call.builder().values(filter.getRowType()).build());
+            call.transformTo(createEmptyRelOrEquivalent(call, filter));
           }
         }
       }
@@ -343,7 +366,7 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
               || RexUtil.isNullLiteral(newConditionExp, true)) {
             // condition is always NULL or FALSE - replace calc
             // with empty
-            call.transformTo(call.builder().values(calc.getRowType()).build());
+            call.transformTo(createEmptyRelOrEquivalent(call, calc));
             return;
           } else {
             builder.addCondition(list.get(conditionIndex));
@@ -363,6 +386,28 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
         call.getPlanner().setImportance(calc, 0.0);
       }
     }
+
+    /**
+     * For static schema systems, a filter that is always false or null can be
+     * replaced by a values operator that produces no rows, as the schema
+     * information can just be taken from the input Rel. In dynamic schema
+     * environments, the filter might have an unknown input type, in these cases
+     * they must define a system specific alternative to a Values operator, such
+     * as inserting a limit 0 instead of a filter on top of the original input.
+     *
+     * <p>The default implementation of this method is to call
+     * {@link RelBuilder#empty}, which for the static schema will be optimized
+     * to an empty
+     * {@link org.apache.calcite.rel.core.Values}.
+     *
+     * @param input rel to replace, assumes caller has already determined
+     *              equivalence to Values operation for 0 records or a
+     *              false filter.
+     * @return equivalent but less expensive replacement rel
+     */
+    protected RelNode createEmptyRelOrEquivalent(RelOptRuleCall call, Calc input) {
+      return call.builder().push(input).empty().build();
+    }
   }
 
   //~ Constructors -----------------------------------------------------------


[3/4] calcite git commit: [CALCITE-1055] SubQueryRemoveRule should create Correlate, not Join, for correlated sub-queries

Posted by jh...@apache.org.
[CALCITE-1055] SubQueryRemoveRule should create Correlate, not Join, for correlated sub-queries


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

Branch: refs/heads/master
Commit: cecef9d3209cbd092a6e9b578bc063a52007b99f
Parents: 898fdfc
Author: maryannxue <ma...@gmail.com>
Authored: Thu Jan 14 13:46:07 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jan 14 14:05:17 2016 -0800

----------------------------------------------------------------------
 .../calcite/rel/rules/SubQueryRemoveRule.java   |  4 +-
 .../apache/calcite/test/RelOptRulesTest.java    |  8 ++++
 .../org/apache/calcite/test/RelOptRulesTest.xml | 39 ++++++++++++++++++--
 3 files changed, 46 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/cecef9d3/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java b/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java
index 56b362d..6eec2fc 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java
@@ -156,7 +156,7 @@ public abstract class SubQueryRemoveRule extends RelOptRule {
             builder.aggregateCall(SqlStdOperatorTable.SINGLE_VALUE, false, null,
                 null, builder.field(0)));
       }
-      builder.join(JoinRelType.LEFT);
+      builder.join(JoinRelType.LEFT, builder.literal(true), variablesSet);
       return field(builder, inputCount, offset);
 
     case IN:
@@ -247,7 +247,7 @@ public abstract class SubQueryRemoveRule extends RelOptRule {
             builder.aggregateCall(SqlStdOperatorTable.COUNT, false, null, "ck",
                 builder.fields()));
         builder.as("ct");
-        builder.join(JoinRelType.INNER);
+        builder.join(JoinRelType.INNER, builder.literal(true), variablesSet);
         offset += 2;
         builder.push(e.rel);
         break;

http://git-wip-us.apache.org/repos/asf/calcite/blob/cecef9d3/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 6300579..f59b9e7 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -2216,6 +2216,14 @@ public class RelOptRulesTest extends RelOptTestBase {
     checkSubQuery(sql).check();
   }
 
+  @Test public void testExpandWhereComparisonCorrelated() throws Exception {
+    final String sql = "select empno\n"
+        + "from sales.emp as e\n"
+        + "where sal = (\n"
+        + "  select max(sal) from sales.emp e2 where e2.empno = e.empno)";
+    checkSubQuery(sql).check();
+  }
+
 }
 
 // End RelOptRulesTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/cecef9d3/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 e45b82c..45ea111 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -1064,6 +1064,39 @@ LogicalValues(tuples=[[]])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testExpandWhereComparisonCorrelated">
+        <Resource name="sql">
+            <![CDATA[select empno
+from sales.emp as e
+where sal = (
+  select max(sal) from sales.emp e2 where e2.empno = e.empno)]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(EMPNO=[$0])
+  LogicalFilter(condition=[=($5, $SCALAR_QUERY({
+LogicalAggregate(group=[{}], EXPR$0=[MAX($0)])
+  LogicalProject(SAL=[$5])
+    LogicalFilter(condition=[=($0, $cor0.EMPNO)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+}))], variablesSet=[[$cor0]])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(EMPNO=[$0])
+  LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
+    LogicalFilter(condition=[=($5, $9)])
+      LogicalCorrelate(correlation=[$cor0], joinType=[LEFT], requiredColumns=[{0}])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+        LogicalAggregate(group=[{}], EXPR$0=[MAX($0)])
+          LogicalProject(SAL=[$5])
+            LogicalFilter(condition=[=($0, $cor0.EMPNO)])
+              LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testPushSumConstantThroughUnion">
         <Resource name="sql">
             <![CDATA[select ename, sum(u) from
@@ -4944,9 +4977,9 @@ LogicalFilter(condition=[<($0, 20)])
 })])
     LogicalTableScan(table=[[CATALOG, SALES, EMP]])
 ]]>
-    </Resource>
-    <Resource name="planAfter">
-      <![CDATA[
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
 LogicalProject(EMPNO=[$0])
   LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
     LogicalJoin(condition=[true], joinType=[inner])


[4/4] calcite git commit: [CALCITE-1057] Add RelMetadataProvider parameter to standard planner Programs

Posted by jh...@apache.org.
[CALCITE-1057] Add RelMetadataProvider parameter to standard planner Programs


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

Branch: refs/heads/master
Commit: af77ec861989c50229c55be1889efcb0031cfd32
Parents: cecef9d
Author: maryannxue <we...@intel.com>
Authored: Thu Jan 14 14:17:18 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jan 14 14:17:18 2016 -0800

----------------------------------------------------------------------
 .../java/org/apache/calcite/tools/Programs.java | 27 +++++++++++++++-----
 1 file changed, 20 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/af77ec86/core/src/main/java/org/apache/calcite/tools/Programs.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/Programs.java b/core/src/main/java/org/apache/calcite/tools/Programs.java
index 472563e..a52387d 100644
--- a/core/src/main/java/org/apache/calcite/tools/Programs.java
+++ b/core/src/main/java/org/apache/calcite/tools/Programs.java
@@ -102,14 +102,11 @@ public class Programs {
 
   /** Program that converts filters and projects to {@link Calc}s. */
   public static final Program CALC_PROGRAM =
-      hep(CALC_RULES, true, new DefaultRelMetadataProvider());
+      calc(new DefaultRelMetadataProvider());
 
   /** Program that expands sub-queries. */
   public static final Program SUB_QUERY_PROGRAM =
-      hep(
-          ImmutableList.of((RelOptRule) SubQueryRemoveRule.FILTER,
-              SubQueryRemoveRule.PROJECT,
-              SubQueryRemoveRule.JOIN), true, new DefaultRelMetadataProvider());
+      subquery(new DefaultRelMetadataProvider());
 
   public static final ImmutableSet<RelOptRule> RULE_SET =
       ImmutableSet.of(
@@ -260,6 +257,17 @@ public class Programs {
     };
   }
 
+  public static Program calc(RelMetadataProvider metadataProvider) {
+    return hep(CALC_RULES, true, metadataProvider);
+  }
+
+  public static Program subquery(RelMetadataProvider metadataProvider) {
+    return hep(
+        ImmutableList.of((RelOptRule) SubQueryRemoveRule.FILTER,
+            SubQueryRemoveRule.PROJECT,
+            SubQueryRemoveRule.JOIN), true, metadataProvider);
+  }
+
   public static Program getProgram() {
     return new Program() {
       public RelNode run(RelOptPlanner planner, RelNode rel,
@@ -271,6 +279,11 @@ public class Programs {
 
   /** Returns the standard program used by Prepare. */
   public static Program standard() {
+    return standard(new DefaultRelMetadataProvider());
+  }
+
+  /** Returns the standard program with user metadata provider. */
+  public static Program standard(RelMetadataProvider metadataProvider) {
 
     final Program program1 =
         new Program() {
@@ -290,14 +303,14 @@ public class Programs {
           }
         };
 
-    return sequence(SUB_QUERY_PROGRAM,
+    return sequence(subquery(metadataProvider),
         new DecorrelateProgram(),
         new TrimFieldsProgram(),
         program1,
 
         // Second planner pass to do physical "tweaks". This the first time that
         // EnumerableCalcRel is introduced.
-        CALC_PROGRAM);
+        calc(metadataProvider));
   }
 
   /** Program backed by a {@link RuleSet}. */