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 cac28e9  [CALCITE-4621] SemiJoinRule throws AssertionError on ANTI join
cac28e9 is described below

commit cac28e95762532538cd3d0dce9e933ef9e4d5228
Author: rubenada <rube...@gmail.com>
AuthorDate: Tue May 25 13:51:45 2021 +0100

    [CALCITE-4621] SemiJoinRule throws AssertionError on ANTI join
---
 .../org/apache/calcite/rel/rules/SemiJoinRule.java | 10 +++---
 .../org/apache/calcite/test/RelOptRulesTest.java   | 39 ++++++++++++++++++++++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinRule.java
index 16422d3..60c9f7a 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinRule.java
@@ -24,6 +24,7 @@ import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Aggregate;
 import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.JoinInfo;
+import org.apache.calcite.rel.core.JoinRelType;
 import org.apache.calcite.rel.core.Project;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexNode;
@@ -45,8 +46,9 @@ import java.util.List;
 public abstract class SemiJoinRule
     extends RelRule<SemiJoinRule.Config>
     implements TransformationRule {
-  private static boolean notGenerateNullsOnLeft(Join join) {
-    return !join.getJoinType().generatesNullsOnLeft();
+  private static boolean isJoinTypeSupported(Join join) {
+    final JoinRelType type = join.getJoinType();
+    return type == JoinRelType.INNER || type == JoinRelType.SEMI || type == 
JoinRelType.LEFT;
   }
 
   /**
@@ -170,7 +172,7 @@ public abstract class SemiJoinRule
         return withOperandSupplier(b ->
             b.operand(projectClass).oneInput(b2 ->
                 b2.operand(joinClass)
-                    .predicate(SemiJoinRule::notGenerateNullsOnLeft).inputs(
+                    .predicate(SemiJoinRule::isJoinTypeSupported).inputs(
                         b3 -> b3.operand(RelNode.class).anyInputs(),
                         b4 -> b4.operand(aggregateClass).anyInputs())))
             .as(Config.class);
@@ -219,7 +221,7 @@ public abstract class SemiJoinRule
       default Config withOperandFor(Class<Join> joinClass,
           Class<Aggregate> aggregateClass) {
         return withOperandSupplier(b ->
-            
b.operand(joinClass).predicate(SemiJoinRule::notGenerateNullsOnLeft).inputs(
+            
b.operand(joinClass).predicate(SemiJoinRule::isJoinTypeSupported).inputs(
                 b2 -> b2.operand(RelNode.class).anyInputs(),
                 b3 -> b3.operand(aggregateClass).anyInputs()))
             .as(Config.class);
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 e23e86f..d988d72 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -5513,6 +5513,45 @@ class RelOptRulesTest extends RelOptTestBase {
     assertEquals(planBefore, planAfter);
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-4621";>[CALCITE-4621]
+   * SemiJoinRule throws AssertionError on ANTI join</a>. */
+  @Test void testJoinToSemiJoinRuleOnAntiJoin() {
+    testSemiJoinRuleOnAntiJoin(CoreRules.JOIN_TO_SEMI_JOIN);
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-4621";>[CALCITE-4621]
+   * SemiJoinRule throws AssertionError on ANTI join</a>. */
+  @Test void testProjectToSemiJoinRuleOnAntiJoin() {
+    testSemiJoinRuleOnAntiJoin(CoreRules.PROJECT_TO_SEMI_JOIN);
+  }
+
+  private void testSemiJoinRuleOnAntiJoin(RelOptRule rule) {
+    final RelBuilder relBuilder = 
RelBuilder.create(RelBuilderTest.config().build());
+    final RelNode input = relBuilder
+        .scan("DEPT")
+        .scan("EMP")
+        .project(relBuilder.field("DEPTNO"))
+        .distinct()
+        .antiJoin(relBuilder
+            .equals(
+                relBuilder.field(2, 0, "DEPTNO"),
+                relBuilder.field(2, 1, "DEPTNO")))
+        .project(relBuilder.field("DNAME"))
+        .build();
+
+    final HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(rule)
+        .build();
+    final HepPlanner hepPlanner = new HepPlanner(program);
+    hepPlanner.setRoot(input);
+    final RelNode output = hepPlanner.findBestExp();
+    final String planBefore = RelOptUtil.toString(input);
+    final String planAfter = RelOptUtil.toString(output);
+    assertEquals(planBefore, planAfter);
+  }
+
   @Test void testPushJoinCondDownToProject() {
     final String sql = "select d.deptno, e.deptno from sales.dept d, sales.emp 
e\n"
         + " where d.deptno + 10 = e.deptno * 2";

Reply via email to