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 2015/09/03 00:16:23 UTC

[35/50] incubator-calcite git commit: [CALCITE-811] Extend JoinProjectTransposeRule with option to support outer joins

[CALCITE-811] Extend JoinProjectTransposeRule with option to support outer joins

Close apache/incubator-calcite#109


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

Branch: refs/heads/branch-release
Commit: 2376ae4a876b421ee19c2b2a05a6bd1d306e442b
Parents: 5cb95e6
Author: Jesus Camacho Rodriguez <jc...@apache.org>
Authored: Mon Jul 27 19:41:36 2015 +0100
Committer: Jesus Camacho Rodriguez <jc...@apache.org>
Committed: Mon Jul 27 19:48:48 2015 +0100

----------------------------------------------------------------------
 .../rel/rules/JoinProjectTransposeRule.java     | 61 +++++++++++++++++---
 .../apache/calcite/test/RelOptRulesTest.java    | 24 ++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml | 31 ++++++++++
 3 files changed, 107 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2376ae4a/core/src/main/java/org/apache/calcite/rel/rules/JoinProjectTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/JoinProjectTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/JoinProjectTransposeRule.java
index 2f41648..afcea6b 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/JoinProjectTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/JoinProjectTransposeRule.java
@@ -75,20 +75,52 @@ public class JoinProjectTransposeRule extends RelOptRule {
               operand(LogicalProject.class, any())),
           "JoinProjectTransposeRule(Other-Project)");
 
+  public static final JoinProjectTransposeRule BOTH_PROJECT_INCLUDE_OUTER =
+      new JoinProjectTransposeRule(
+          operand(LogicalJoin.class,
+              operand(LogicalProject.class, any()),
+              operand(LogicalProject.class, any())),
+          "Join(IncludingOuter)ProjectTransposeRule(Project-Project)",
+          true, RelFactories.DEFAULT_PROJECT_FACTORY);
+
+  public static final JoinProjectTransposeRule LEFT_PROJECT_INCLUDE_OUTER =
+      new JoinProjectTransposeRule(
+          operand(LogicalJoin.class,
+              some(operand(LogicalProject.class, any()))),
+          "Join(IncludingOuter)ProjectTransposeRule(Project-Other)",
+          true, RelFactories.DEFAULT_PROJECT_FACTORY);
+
+  public static final JoinProjectTransposeRule RIGHT_PROJECT_INCLUDE_OUTER =
+      new JoinProjectTransposeRule(
+          operand(
+              LogicalJoin.class,
+              operand(RelNode.class, any()),
+              operand(LogicalProject.class, any())),
+          "Join(IncludingOuter)ProjectTransposeRule(Other-Project)",
+          true, RelFactories.DEFAULT_PROJECT_FACTORY);
+
+  private final boolean includeOuter;
   private final ProjectFactory projectFactory;
 
   //~ Constructors -----------------------------------------------------------
   public JoinProjectTransposeRule(
       RelOptRuleOperand operand,
       String description) {
-    this(operand, description, RelFactories.DEFAULT_PROJECT_FACTORY);
+    this(operand, description, false, RelFactories.DEFAULT_PROJECT_FACTORY);
   }
 
-  public JoinProjectTransposeRule(
-      RelOptRuleOperand operand,
-      String description, ProjectFactory pFactory) {
+  @Deprecated
+  public JoinProjectTransposeRule(RelOptRuleOperand operand,
+      String description, ProjectFactory projectFactory) {
+    this(operand, description, false, projectFactory);
+  }
+
+  public JoinProjectTransposeRule(RelOptRuleOperand operand,
+      String description, boolean includeOuter,
+      ProjectFactory projectFactory) {
     super(operand, description);
-    projectFactory = pFactory;
+    this.includeOuter = includeOuter;
+    this.projectFactory = projectFactory;
   }
 
   //~ Methods ----------------------------------------------------------------
@@ -103,15 +135,18 @@ public class JoinProjectTransposeRule extends RelOptRule {
     RelNode leftJoinChild;
     RelNode rightJoinChild;
 
-    // see if at least one input's projection doesn't generate nulls
-    if (hasLeftChild(call) && !joinType.generatesNullsOnLeft()) {
+    // If 1) the rule works on outer joins, or
+    //    2) input's projection doesn't generate nulls
+    if (hasLeftChild(call)
+            && (includeOuter || !joinType.generatesNullsOnLeft())) {
       leftProj = call.rel(1);
       leftJoinChild = getProjectChild(call, leftProj, true);
     } else {
       leftProj = null;
       leftJoinChild = call.rel(1);
     }
-    if (hasRightChild(call) && !joinType.generatesNullsOnRight()) {
+    if (hasRightChild(call)
+            && (includeOuter || !joinType.generatesNullsOnRight())) {
       rightProj = getRightChild(call);
       rightJoinChild = getProjectChild(call, rightProj, false);
     } else {
@@ -235,6 +270,14 @@ public class JoinProjectTransposeRule extends RelOptRule {
     // finally, create the projection on top of the join
     RelNode newProjRel = projectFactory.createProject(newJoinRel, newProjExprs,
         joinRel.getRowType().getFieldNames());
+    // if the join was outer, we might need a cast after the
+    // projection to fix differences wrt nullability of fields
+    if (joinType != JoinRelType.INNER) {
+      RelNode newTopProjRel = RelOptUtil.createCastRel(newProjRel, joinRel.getRowType(),
+          false, projectFactory);
+      call.transformTo(newTopProjRel);
+      return;
+    }
 
     call.transformTo(newProjRel);
   }
@@ -294,7 +337,7 @@ public class JoinProjectTransposeRule extends RelOptRule {
    *                           removed)
    * @param projects           Projection expressions &amp; names to be created
    */
-  private void createProjectExprs(
+  protected void createProjectExprs(
       Project projRel,
       RelNode joinChild,
       int adjustmentAmount,

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2376ae4a/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 1901f89..013405c 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -51,6 +51,7 @@ import org.apache.calcite.rel.rules.FilterToCalcRule;
 import org.apache.calcite.rel.rules.JoinAddRedundantSemiJoinRule;
 import org.apache.calcite.rel.rules.JoinCommuteRule;
 import org.apache.calcite.rel.rules.JoinExtractFilterRule;
+import org.apache.calcite.rel.rules.JoinProjectTransposeRule;
 import org.apache.calcite.rel.rules.JoinPushTransitivePredicatesRule;
 import org.apache.calcite.rel.rules.JoinToMultiJoinRule;
 import org.apache.calcite.rel.rules.JoinUnionTransposeRule;
@@ -296,6 +297,29 @@ public class RelOptRulesTest extends RelOptTestBase {
             + "right join dept c on b.deptno > 10\n");
   }
 
+  @Test public void testJoinProjectTranspose() {
+    final HepProgram preProgram =
+        HepProgram.builder()
+            .addRuleInstance(ProjectJoinTransposeRule.INSTANCE)
+            .addRuleInstance(ProjectMergeRule.INSTANCE)
+            .build();
+    final HepProgram program =
+        HepProgram.builder()
+            .addRuleInstance(JoinProjectTransposeRule.LEFT_PROJECT_INCLUDE_OUTER)
+            .addRuleInstance(ProjectMergeRule.INSTANCE)
+            .addRuleInstance(JoinProjectTransposeRule.RIGHT_PROJECT_INCLUDE_OUTER)
+            .addRuleInstance(JoinProjectTransposeRule.LEFT_PROJECT_INCLUDE_OUTER)
+            .addRuleInstance(ProjectMergeRule.INSTANCE)
+            .build();
+    checkPlanning(tester,
+        preProgram,
+        new HepPlanner(program),
+        "select a.name\n"
+            + "from dept a\n"
+            + "left join dept b on b.deptno > 10\n"
+            + "right join dept c on b.deptno > 10\n");
+  }
+
   @Test public void testSemiJoinRule() {
     final HepProgram preProgram =
         HepProgram.builder()

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2376ae4a/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 04d0fe2..bd650ce 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -3255,6 +3255,37 @@ LogicalProject(NAME=[$1])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testJoinProjectTranspose">
+        <Resource name="sql">
+            <![CDATA[select a.name
+from dept a
+left join dept b on b.deptno > 10
+right join dept c on b.deptno > 10
+]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalJoin(condition=[$4], joinType=[right])
+    LogicalProject(DEPTNO=[$0], NAME=[$1], DEPTNO0=[$2], NAME0=[$3], $f4=[>($2, 10)])
+      LogicalJoin(condition=[$4], joinType=[left])
+        LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+        LogicalProject(DEPTNO=[$0], NAME=[$1], $f2=[>($0, 10)])
+          LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalJoin(condition=[>($2, 10)], joinType=[right])
+    LogicalJoin(condition=[>($2, 10)], joinType=[left])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testMergeFilter">
         <Resource name="sql">
             <![CDATA[select name from (