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

jcamacho 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 16c9c36  [CALCITE-3908] JoinCommuteRule should update all input 
references in join condition
16c9c36 is described below

commit 16c9c36f319b06ebcf1338f0e40e9de2ee912adf
Author: Jesus Camacho Rodriguez <[email protected]>
AuthorDate: Thu Apr 9 10:52:27 2020 -0700

    [CALCITE-3908] JoinCommuteRule should update all input references in join 
condition
    
    Close apache/calcite#1906
---
 .../apache/calcite/rel/rules/JoinCommuteRule.java  | 55 ++++++++--------------
 .../org/apache/calcite/test/RelOptRulesTest.java   | 17 +++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 21 +++++++++
 3 files changed, 58 insertions(+), 35 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/JoinCommuteRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/JoinCommuteRule.java
index 560a3fb..dfc74fb 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/JoinCommuteRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/JoinCommuteRule.java
@@ -29,14 +29,12 @@ import org.apache.calcite.rel.logical.LogicalJoin;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexShuttle;
 import org.apache.calcite.tools.RelBuilder;
 import org.apache.calcite.tools.RelBuilderFactory;
 
-import com.google.common.collect.ImmutableList;
-
 import java.util.List;
 import java.util.function.Predicate;
 
@@ -130,7 +128,7 @@ public class JoinCommuteRule extends RelOptRule {
     final VariableReplacer variableReplacer =
         new VariableReplacer(rexBuilder, leftRowType, rightRowType);
     final RexNode oldCondition = join.getCondition();
-    RexNode condition = variableReplacer.go(oldCondition);
+    RexNode condition = variableReplacer.apply(oldCondition);
 
     // NOTE jvs 14-Mar-2006: We preserve attribute semiJoinDone after the
     // swap.  This way, we will generate one semijoin for the original
@@ -189,7 +187,7 @@ public class JoinCommuteRule extends RelOptRule {
    * greater than leftFieldCount, it must be from the right, so we subtract
    * leftFieldCount from it.</p>
    */
-  private static class VariableReplacer {
+  private static class VariableReplacer extends RexShuttle {
     private final RexBuilder rexBuilder;
     private final List<RelDataTypeField> leftFields;
     private final List<RelDataTypeField> rightFields;
@@ -203,37 +201,24 @@ public class JoinCommuteRule extends RelOptRule {
       this.rightFields = rightType.getFieldList();
     }
 
-    public RexNode go(RexNode rex) {
-      if (rex instanceof RexCall) {
-        ImmutableList.Builder<RexNode> builder =
-            ImmutableList.builder();
-        final RexCall call = (RexCall) rex;
-        for (RexNode operand : call.operands) {
-          builder.add(go(operand));
-        }
-        return call.clone(call.getType(), builder.build());
-      } else if (rex instanceof RexInputRef) {
-        RexInputRef var = (RexInputRef) rex;
-        int index = var.getIndex();
-        if (index < leftFields.size()) {
-          // Field came from left side of join. Move it to the right.
-          return rexBuilder.makeInputRef(
-              leftFields.get(index).getType(),
-              rightFields.size() + index);
-        }
-        index -= leftFields.size();
-        if (index < rightFields.size()) {
-          // Field came from right side of join. Move it to the left.
-          return rexBuilder.makeInputRef(
-              rightFields.get(index).getType(),
-              index);
-        }
-        throw new AssertionError("Bad field offset: index=" + var.getIndex()
-            + ", leftFieldCount=" + leftFields.size()
-            + ", rightFieldCount=" + rightFields.size());
-      } else {
-        return rex;
+    @Override public RexNode visitInputRef(RexInputRef inputRef) {
+      int index = inputRef.getIndex();
+      if (index < leftFields.size()) {
+        // Field came from left side of join. Move it to the right.
+        return rexBuilder.makeInputRef(
+            leftFields.get(index).getType(),
+            rightFields.size() + index);
+      }
+      index -= leftFields.size();
+      if (index < rightFields.size()) {
+        // Field came from right side of join. Move it to the left.
+        return rexBuilder.makeInputRef(
+            rightFields.get(index).getType(),
+            index);
       }
+      throw new AssertionError("Bad field offset: index=" + inputRef.getIndex()
+          + ", leftFieldCount=" + leftFields.size()
+          + ", rightFieldCount=" + rightFields.size());
     }
   }
 }
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 c1c5635..5197126 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -1689,6 +1689,23 @@ class RelOptRulesTest extends RelOptTestBase {
     sql(sql).withRule(customPCTrans).check();
   }
 
+  @Test void testSwapOuterJoinFieldAccess() {
+    HepProgram preProgram = new HepProgramBuilder()
+        .addMatchLimit(1)
+        .addRuleInstance(JoinProjectTransposeRule.LEFT_PROJECT_INCLUDE_OUTER)
+        .addRuleInstance(ProjectMergeRule.INSTANCE)
+        .build();
+    final HepProgram program = new HepProgramBuilder()
+        .addMatchLimit(1)
+        .addRuleInstance(JoinCommuteRule.SWAP_OUTER)
+        .addRuleInstance(ProjectMergeRule.INSTANCE)
+        .build();
+    final String sql = "select t1.name, e.ename\n"
+        + "from DEPT_NESTED as t1 left outer join sales.emp e\n"
+        + " on t1.skill.type = e.job";
+    sql(sql).withPre(preProgram).with(program).check();
+  }
+
   @Test void testProjectCorrelateTranspose() {
     ProjectCorrelateTransposeRule customPCTrans =
         new ProjectCorrelateTransposeRule(expr -> true,
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 7cb8505..a99eaf2 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -12460,4 +12460,25 @@ LogicalProject(**=[$1])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testSwapOuterJoinFieldAccess">
+        <Resource name="sql">
+            <![CDATA[select t1.name, e.ename from DEPT_NESTED as t1 left outer 
join sales.emp e on t1.skill.type = e.job]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(NAME=[$1], ENAME=[$5])
+  LogicalJoin(condition=[=($2.TYPE, $6)], joinType=[left])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT_NESTED]])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(NAME=[$10], ENAME=[$1])
+  LogicalJoin(condition=[=($11.TYPE, $2)], joinType=[right])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT_NESTED]])
+]]>
+        </Resource>
+    </TestCase>
 </Root>

Reply via email to