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

rubenql 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 f82353c  [CALCITE-3225] JoinToMultiJoinRule should not match SEMI/ANTI 
LogicalJoin
f82353c is described below

commit f82353c80223143673fc78561a05c79d6fd4f364
Author: godfreyhe <[email protected]>
AuthorDate: Fri Aug 2 13:42:49 2019 +0800

    [CALCITE-3225] JoinToMultiJoinRule should not match SEMI/ANTI LogicalJoin
---
 .../calcite/rel/rules/JoinToMultiJoinRule.java     |  6 ++
 .../org/apache/calcite/test/RelOptRulesTest.java   | 81 +++++++++++++++++++++-
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 32 +++++++++
 3 files changed, 118 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/JoinToMultiJoinRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/JoinToMultiJoinRule.java
index 0576ff7..42fbb89 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/JoinToMultiJoinRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/JoinToMultiJoinRule.java
@@ -127,6 +127,12 @@ public class JoinToMultiJoinRule extends RelOptRule {
 
   //~ Methods ----------------------------------------------------------------
 
+
+  @Override public boolean matches(RelOptRuleCall call) {
+    final Join origJoin = call.rel(0);
+    return origJoin.getJoinType().projectsRight();
+  }
+
   public void onMatch(RelOptRuleCall call) {
     final Join origJoin = call.rel(0);
     final RelNode left = call.rel(1);
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 d95cbb7..60d0475 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -549,7 +549,6 @@ public class RelOptRulesTest extends RelOptTestBase {
             + " where e.sal > 100");
   }
 
-
   @Test public void testRightOuterJoinSimplificationToInner() {
     checkPlanning(FilterJoinRule.FILTER_ON_JOIN,
         "select 1 from sales.dept d right outer join sales.emp e"
@@ -557,6 +556,86 @@ public class RelOptRulesTest extends RelOptTestBase {
             + " where d.name = 'Charlie'");
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-3225";>[CALCITE-3225]
+   * JoinToMultiJoinRule should not match SEMI/ANTI LogicalJoin</a>. */
+  @Test public void testJoinToMultiJoinDoesNotMatchSemiJoin() {
+    final RelBuilder relBuilder = 
RelBuilder.create(RelBuilderTest.config().build());
+    // build a rel equivalent to sql:
+    // select * from
+    // (select * from emp join dept ON emp.deptno = emp.deptno) t
+    // where emp.job in (select job from bonus)
+    RelNode left = relBuilder.scan("EMP").build();
+    RelNode right = relBuilder.scan("DEPT").build();
+    RelNode semiRight = relBuilder.scan("BONUS").build();
+    RelNode relNode = relBuilder.push(left)
+                                .push(right)
+                                .join(
+                                    JoinRelType.INNER,
+                                    relBuilder.call(SqlStdOperatorTable.EQUALS,
+                                                    relBuilder.field(2, 0, 
"DEPTNO"),
+                                                    relBuilder.field(2, 1, 
"DEPTNO")))
+                                .push(semiRight)
+                                .semiJoin(
+                                    relBuilder.call(SqlStdOperatorTable.EQUALS,
+                                                    relBuilder.field(2, 0, 
"JOB"),
+                                                    relBuilder.field(2, 1, 
"JOB")))
+                                .build();
+
+    HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(JoinToMultiJoinRule.INSTANCE)
+        .build();
+
+    HepPlanner hepPlanner = new HepPlanner(program);
+    hepPlanner.setRoot(relNode);
+    RelNode output = hepPlanner.findBestExp();
+
+    final String planAfter = NL + RelOptUtil.toString(output);
+    final DiffRepository diffRepos = getDiffRepos();
+    diffRepos.assertEquals("planAfter", "${planAfter}", planAfter);
+    SqlToRelTestBase.assertValid(output);
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-3225";>[CALCITE-3225]
+   * JoinToMultiJoinRule should not match SEMI/ANTI LogicalJoin</a>. */
+  @Test public void testJoinToMultiJoinDoesNotMatchAntiJoin() {
+    final RelBuilder relBuilder = 
RelBuilder.create(RelBuilderTest.config().build());
+    // build a rel equivalent to sql:
+    // select * from
+    // (select * from emp join dept ON emp.deptno = emp.deptno) t
+    // where not exists (select job from bonus where emp.job = bonus.job)
+    RelNode left = relBuilder.scan("EMP").build();
+    RelNode right = relBuilder.scan("DEPT").build();
+    RelNode antiRight = relBuilder.scan("BONUS").build();
+    RelNode relNode = relBuilder.push(left)
+                                .push(right)
+                                .join(
+                                    JoinRelType.INNER,
+                                    relBuilder.call(SqlStdOperatorTable.EQUALS,
+                                                    relBuilder.field(2, 0, 
"DEPTNO"),
+                                                    relBuilder.field(2, 1, 
"DEPTNO")))
+                                .push(antiRight)
+                                .antiJoin(
+                                    relBuilder.call(SqlStdOperatorTable.EQUALS,
+                                                    relBuilder.field(2, 0, 
"JOB"),
+                                                    relBuilder.field(2, 1, 
"JOB")))
+                                .build();
+
+    HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(JoinToMultiJoinRule.INSTANCE)
+        .build();
+
+    HepPlanner hepPlanner = new HepPlanner(program);
+    hepPlanner.setRoot(relNode);
+    RelNode output = hepPlanner.findBestExp();
+
+    final String planAfter = NL + RelOptUtil.toString(output);
+    final DiffRepository diffRepos = getDiffRepos();
+    diffRepos.assertEquals("planAfter", "${planAfter}", planAfter);
+    SqlToRelTestBase.assertValid(output);
+  }
+
   @Test public void testPushFilterPastAgg() {
     checkPlanning(FilterAggregateTransposeRule.INSTANCE,
         "select dname, c from"
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 73e0ea6..cb07e35 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -11273,4 +11273,36 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], 
MGR=[$3], HIREDATE=[$4], SAL=[$
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testJoinToMultiJoinDoesNotMatchSemiJoin">
+        <Resource name="sql">
+            <![CDATA[select * from
+(select * from emp join dept ON emp.deptno = emp.deptno) t
+where emp.job in (select job from bonus))]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalJoin(condition=[=($2, $12)], joinType=[semi])
+  MultiJoin(joinFilter=[=($7, $8)], isFullOuterJoin=[false], 
joinTypes=[[INNER, INNER]], outerJoinConditions=[[NULL, NULL]], 
projFields=[[ALL, ALL]])
+    LogicalTableScan(table=[[scott, EMP]])
+    LogicalTableScan(table=[[scott, DEPT]])
+  LogicalTableScan(table=[[scott, BONUS]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJoinToMultiJoinDoesNotMatchAntiJoin">
+        <Resource name="sql">
+            <![CDATA[select * from
+(select * from emp join dept ON emp.deptno = emp.deptno) t
+where not exists (select job from bonus where emp.job = bonus.job)]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalJoin(condition=[=($2, $12)], joinType=[anti])
+  MultiJoin(joinFilter=[=($7, $8)], isFullOuterJoin=[false], 
joinTypes=[[INNER, INNER]], outerJoinConditions=[[NULL, NULL]], 
projFields=[[ALL, ALL]])
+    LogicalTableScan(table=[[scott, EMP]])
+    LogicalTableScan(table=[[scott, DEPT]])
+  LogicalTableScan(table=[[scott, BONUS]])
+]]>
+        </Resource>
+    </TestCase>
 </Root>

Reply via email to