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>