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);