You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by ma...@apache.org on 2017/02/09 20:23:33 UTC

calcite git commit: [CALCITE-1628] Add an alternative match pattern for SemiJoinRule

Repository: calcite
Updated Branches:
  refs/heads/master a269a2b78 -> 824d7e7a5


[CALCITE-1628] Add an alternative match pattern for SemiJoinRule


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

Branch: refs/heads/master
Commit: 824d7e7a5943891ed39052c4e6e737646e52721c
Parents: a269a2b
Author: maryannxue <ma...@gmail.com>
Authored: Thu Feb 9 12:23:20 2017 -0800
Committer: maryannxue <ma...@gmail.com>
Committed: Thu Feb 9 12:23:20 2017 -0800

----------------------------------------------------------------------
 .../calcite/plan/volcano/VolcanoPlanner.java    |  3 +-
 .../apache/calcite/rel/rules/SemiJoinRule.java  | 99 ++++++++++++++++----
 .../java/org/apache/calcite/tools/Programs.java |  3 +-
 .../apache/calcite/test/RelOptRulesTest.java    | 16 ++--
 4 files changed, 92 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/824d7e7a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
index e415944..1e73adf 100644
--- a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
+++ b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
@@ -920,7 +920,8 @@ public class VolcanoPlanner extends AbstractRelOptPlanner {
     addRule(FilterJoinRule.JOIN);
     addRule(AbstractConverter.ExpandConversionRule.INSTANCE);
     addRule(JoinCommuteRule.INSTANCE);
-    addRule(SemiJoinRule.INSTANCE);
+    addRule(SemiJoinRule.PROJECT);
+    addRule(SemiJoinRule.JOIN);
     if (CalcitePrepareImpl.COMMUTE) {
       addRule(JoinAssociateRule.INSTANCE);
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/824d7e7a/core/src/main/java/org/apache/calcite/rel/rules/SemiJoinRule.java
----------------------------------------------------------------------
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 d8d56b4..2d899c3 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
@@ -44,7 +44,7 @@ import java.util.List;
  * {@link org.apache.calcite.rel.core.Join} on top of a
  * {@link org.apache.calcite.rel.logical.LogicalAggregate}.
  */
-public class SemiJoinRule extends RelOptRule {
+public abstract class SemiJoinRule extends RelOptRule {
   private static final Predicate<Join> IS_LEFT_OR_INNER =
       new PredicateImpl<Join>() {
         public boolean test(Join input) {
@@ -58,12 +58,23 @@ public class SemiJoinRule extends RelOptRule {
         }
       };
 
-  public static final SemiJoinRule INSTANCE =
-      new SemiJoinRule(Project.class, Join.class, Aggregate.class,
-          RelFactories.LOGICAL_BUILDER, "SemiJoinRule");
+  /* Tests if an Aggregate always produces 1 row and 0 columns. */
+  private static final Predicate<Aggregate> IS_EMPTY_AGGREGATE =
+      new Predicate<Aggregate>() {
+        public boolean apply(Aggregate input) {
+          return input.getRowType().getFieldCount() == 0;
+        }
+      };
+
+  public static final SemiJoinRule PROJECT =
+      new ProjectToSemiJoinRule(Project.class, Join.class, Aggregate.class,
+          RelFactories.LOGICAL_BUILDER, "SemiJoinRule:project");
+
+  public static final SemiJoinRule JOIN =
+      new JoinToSemiJoinRule(Join.class, Aggregate.class,
+          RelFactories.LOGICAL_BUILDER, "SemiJoinRule:join");
 
-  /** Creates a SemiJoinRule. */
-  public SemiJoinRule(Class<Project> projectClass, Class<Join> joinClass,
+  protected SemiJoinRule(Class<Project> projectClass, Class<Join> joinClass,
       Class<Aggregate> aggregateClass, RelBuilderFactory relBuilderFactory,
       String description) {
     super(
@@ -75,20 +86,28 @@ public class SemiJoinRule extends RelOptRule {
         relBuilderFactory, description);
   }
 
-  @Override public void onMatch(RelOptRuleCall call) {
-    final Project project = call.rel(0);
-    final Join join = call.rel(1);
-    final RelNode left = call.rel(2);
-    final Aggregate aggregate = call.rel(3);
+  protected SemiJoinRule(Class<Join> joinClass, Class<Aggregate> aggregateClass,
+      RelBuilderFactory relBuilderFactory, String description) {
+    super(
+        operand(joinClass, null, IS_LEFT_OR_INNER,
+            some(operand(RelNode.class, any()),
+                operand(aggregateClass, null, IS_EMPTY_AGGREGATE, any()))),
+        relBuilderFactory, description);
+  }
+
+  protected void perform(RelOptRuleCall call, Project project,
+      Join join, RelNode left, Aggregate aggregate) {
     final RelOptCluster cluster = join.getCluster();
     final RexBuilder rexBuilder = cluster.getRexBuilder();
-    final ImmutableBitSet bits =
-        RelOptUtil.InputFinder.bits(project.getProjects(), null);
-    final ImmutableBitSet rightBits =
-        ImmutableBitSet.range(left.getRowType().getFieldCount(),
-            join.getRowType().getFieldCount());
-    if (bits.intersects(rightBits)) {
-      return;
+    if (project != null) {
+      final ImmutableBitSet bits =
+          RelOptUtil.InputFinder.bits(project.getProjects(), null);
+      final ImmutableBitSet rightBits =
+          ImmutableBitSet.range(left.getRowType().getFieldCount(),
+              join.getRowType().getFieldCount());
+      if (bits.intersects(rightBits)) {
+        return;
+      }
     }
     final JoinInfo joinInfo = join.analyzeCondition();
     if (!joinInfo.rightSet().equals(
@@ -127,9 +146,51 @@ public class SemiJoinRule extends RelOptRule {
     default:
       throw new AssertionError(join.getJoinType());
     }
-    relBuilder.project(project.getProjects(), project.getRowType().getFieldNames());
+    if (project != null) {
+      relBuilder.project(project.getProjects(), project.getRowType().getFieldNames());
+    }
     call.transformTo(relBuilder.build());
   }
+
+  /** SemiJoinRule that matches a Project on top of a Join with an Aggregate
+   * as its right child. */
+  public static class ProjectToSemiJoinRule extends SemiJoinRule {
+
+    /** Creates a ProjectToSemiJoinRule. */
+    public ProjectToSemiJoinRule(Class<Project> projectClass,
+        Class<Join> joinClass, Class<Aggregate> aggregateClass,
+        RelBuilderFactory relBuilderFactory, String description) {
+      super(projectClass, joinClass, aggregateClass,
+          relBuilderFactory, description);
+    }
+
+    @Override public void onMatch(RelOptRuleCall call) {
+      final Project project = call.rel(0);
+      final Join join = call.rel(1);
+      final RelNode left = call.rel(2);
+      final Aggregate aggregate = call.rel(3);
+      perform(call, project, join, left, aggregate);
+    }
+  }
+
+  /** SemiJoinRule that matches a Join with an empty Aggregate as its right
+   * child. */
+  public static class JoinToSemiJoinRule extends SemiJoinRule {
+
+    /** Creates a JoinToSemiJoinRule. */
+    public JoinToSemiJoinRule(
+        Class<Join> joinClass, Class<Aggregate> aggregateClass,
+        RelBuilderFactory relBuilderFactory, String description) {
+      super(joinClass, aggregateClass, relBuilderFactory, description);
+    }
+  }
+
+  @Override public void onMatch(RelOptRuleCall call) {
+    final Join join = call.rel(0);
+    final RelNode left = call.rel(1);
+    final Aggregate aggregate = call.rel(2);
+    perform(call, null, join, left, aggregate);
+  }
 }
 
 // End SemiJoinRule.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/824d7e7a/core/src/main/java/org/apache/calcite/tools/Programs.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/Programs.java b/core/src/main/java/org/apache/calcite/tools/Programs.java
index 4c552af..edf4be5 100644
--- a/core/src/main/java/org/apache/calcite/tools/Programs.java
+++ b/core/src/main/java/org/apache/calcite/tools/Programs.java
@@ -127,7 +127,8 @@ public class Programs {
           EnumerableRules.ENUMERABLE_TABLE_MODIFICATION_RULE,
           EnumerableRules.ENUMERABLE_VALUES_RULE,
           EnumerableRules.ENUMERABLE_WINDOW_RULE,
-          SemiJoinRule.INSTANCE,
+          SemiJoinRule.PROJECT,
+          SemiJoinRule.JOIN,
           TableScanRule.INSTANCE,
           CalcitePrepareImpl.COMMUTE
               ? JoinAssociateRule.INSTANCE

http://git-wip-us.apache.org/repos/asf/calcite/blob/824d7e7a/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 cc65a23..a900339 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -514,7 +514,7 @@ public class RelOptRulesTest extends RelOptTestBase {
             .build();
     final HepProgram program =
         HepProgram.builder()
-            .addRuleInstance(SemiJoinRule.INSTANCE)
+            .addRuleInstance(SemiJoinRule.PROJECT)
             .build();
     final String sql = "select * from dept where exists (\n"
         + "  select * from emp\n"
@@ -537,7 +537,7 @@ public class RelOptRulesTest extends RelOptTestBase {
             .build();
     final HepProgram program =
         HepProgram.builder()
-            .addRuleInstance(SemiJoinRule.INSTANCE)
+            .addRuleInstance(SemiJoinRule.PROJECT)
             .build();
     final String sql = "select dept.* from dept join (\n"
         + "  select distinct deptno from emp\n"
@@ -562,7 +562,7 @@ public class RelOptRulesTest extends RelOptTestBase {
             .build();
     final HepProgram program =
         HepProgram.builder()
-            .addRuleInstance(SemiJoinRule.INSTANCE)
+            .addRuleInstance(SemiJoinRule.PROJECT)
             .build();
     final String sql = "select dept.* from dept right join (\n"
         + "  select distinct deptno from emp\n"
@@ -585,7 +585,7 @@ public class RelOptRulesTest extends RelOptTestBase {
             .build();
     final HepProgram program =
         HepProgram.builder()
-            .addRuleInstance(SemiJoinRule.INSTANCE)
+            .addRuleInstance(SemiJoinRule.PROJECT)
             .build();
     final String sql = "select dept.* from dept full join (\n"
         + "  select distinct deptno from emp\n"
@@ -608,7 +608,7 @@ public class RelOptRulesTest extends RelOptTestBase {
             .build();
     final HepProgram program =
         HepProgram.builder()
-            .addRuleInstance(SemiJoinRule.INSTANCE)
+            .addRuleInstance(SemiJoinRule.PROJECT)
             .build();
     final String sql = "select name from dept left join (\n"
         + "  select distinct deptno from emp\n"
@@ -627,7 +627,7 @@ public class RelOptRulesTest extends RelOptTestBase {
   @Test public void testPushFilterThroughSemiJoin() {
     final HepProgram preProgram =
         HepProgram.builder()
-            .addRuleInstance(SemiJoinRule.INSTANCE)
+            .addRuleInstance(SemiJoinRule.PROJECT)
             .build();
 
     final HepProgram program =
@@ -654,7 +654,7 @@ public class RelOptRulesTest extends RelOptTestBase {
    * condition</a>. */
   @Test public void testSemiJoinReduceConstants() {
     final HepProgram preProgram = HepProgram.builder()
-        .addRuleInstance(SemiJoinRule.INSTANCE)
+        .addRuleInstance(SemiJoinRule.PROJECT)
         .build();
     final HepProgram program = HepProgram.builder()
         .addRuleInstance(ReduceExpressionsRule.JOIN_INSTANCE)
@@ -700,7 +700,7 @@ public class RelOptRulesTest extends RelOptTestBase {
             .addRuleInstance(FilterProjectTransposeRule.INSTANCE)
             .addRuleInstance(FilterJoinRule.FILTER_ON_JOIN)
             .addRuleInstance(ProjectMergeRule.INSTANCE)
-            .addRuleInstance(SemiJoinRule.INSTANCE)
+            .addRuleInstance(SemiJoinRule.PROJECT)
             .build();
 
     HepPlanner planner = new HepPlanner(program);