This is an automated email from the ASF dual-hosted git repository. jhyde pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
commit 36e3109fb524c13ca0a08e3ad585785aa5abc18b Author: Haisheng Yuan <[email protected]> AuthorDate: Thu May 30 23:53:37 2019 -0500 [CALCITE-3089] Deprecate EquiJoin Close apache/calcite#1247 --- .../adapter/enumerable/EnumerableHashJoin.java | 23 ++----- .../adapter/enumerable/EnumerableJoinRule.java | 45 ++++++------- .../adapter/enumerable/EnumerableMergeJoin.java | 25 +++---- .../enumerable/EnumerableMergeJoinRule.java | 38 +++++------ .../enumerable/EnumerableNestedLoopJoin.java | 18 ++--- .../java/org/apache/calcite/plan/RelOptUtil.java | 28 +++++--- .../java/org/apache/calcite/rel/core/EquiJoin.java | 6 ++ .../java/org/apache/calcite/rel/core/JoinInfo.java | 78 +++++++--------------- .../apache/calcite/rel/rules/FilterJoinRule.java | 27 ++++---- .../calcite/rel/rules/ReduceExpressionsRule.java | 10 --- .../org/apache/calcite/test/RelMetadataTest.java | 10 +-- .../org/apache/calcite/test/RelOptRulesTest.java | 2 +- .../org/apache/calcite/test/RelOptRulesTest.xml | 2 +- .../calcite/test/PigRelBuilderStyleTest.java | 6 +- 14 files changed, 126 insertions(+), 192 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableHashJoin.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableHashJoin.java index ec0264a..679d7fb 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableHashJoin.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableHashJoin.java @@ -23,12 +23,11 @@ import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelTraitSet; -import org.apache.calcite.rel.InvalidRelException; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelNodes; import org.apache.calcite.rel.core.CorrelationId; -import org.apache.calcite.rel.core.EquiJoin; +import org.apache.calcite.rel.core.Join; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.metadata.RelMdCollation; import org.apache.calcite.rel.metadata.RelMdUtil; @@ -45,7 +44,7 @@ import java.util.Set; /** Implementation of {@link org.apache.calcite.rel.core.Join} in * {@link org.apache.calcite.adapter.enumerable.EnumerableConvention enumerable calling convention}. */ -public class EnumerableHashJoin extends EquiJoin implements EnumerableRel { +public class EnumerableHashJoin extends Join implements EnumerableRel { /** Creates an EnumerableHashJoin. * * <p>Use {@link #create} unless you know what you're doing. */ @@ -56,8 +55,7 @@ public class EnumerableHashJoin extends EquiJoin implements EnumerableRel { RelNode right, RexNode condition, Set<CorrelationId> variablesSet, - JoinRelType joinType) - throws InvalidRelException { + JoinRelType joinType) { super( cluster, traits, @@ -72,7 +70,7 @@ public class EnumerableHashJoin extends EquiJoin implements EnumerableRel { protected EnumerableHashJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition, ImmutableIntList leftKeys, ImmutableIntList rightKeys, JoinRelType joinType, - Set<String> variablesStopped) throws InvalidRelException { + Set<String> variablesStopped) { this(cluster, traits, left, right, condition, CorrelationId.setOf(variablesStopped), joinType); } @@ -82,8 +80,7 @@ public class EnumerableHashJoin extends EquiJoin implements EnumerableRel { RelNode right, RexNode condition, Set<CorrelationId> variablesSet, - JoinRelType joinType) - throws InvalidRelException { + JoinRelType joinType) { final RelOptCluster cluster = left.getCluster(); final RelMetadataQuery mq = cluster.getMetadataQuery(); final RelTraitSet traitSet = @@ -97,14 +94,8 @@ public class EnumerableHashJoin extends EquiJoin implements EnumerableRel { @Override public EnumerableHashJoin copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) { - try { - return new EnumerableHashJoin(getCluster(), traitSet, left, right, - condition, variablesSet, joinType); - } catch (InvalidRelException e) { - // Semantic error not possible. Must be a bug. Convert to - // internal error. - throw new AssertionError(e); - } + return new EnumerableHashJoin(getCluster(), traitSet, left, right, + condition, variablesSet, joinType); } @Override public RelOptCost computeSelfCost(RelOptPlanner planner, diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoinRule.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoinRule.java index 76f9831..4bade2d 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoinRule.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoinRule.java @@ -18,12 +18,13 @@ package org.apache.calcite.adapter.enumerable; import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; -import org.apache.calcite.rel.InvalidRelException; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.convert.ConverterRule; import org.apache.calcite.rel.core.JoinInfo; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.logical.LogicalJoin; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexUtil; import java.util.ArrayList; import java.util.List; @@ -56,37 +57,29 @@ class EnumerableJoinRule extends ConverterRule { final RelOptCluster cluster = join.getCluster(); final RelNode left = newInputs.get(0); final RelNode right = newInputs.get(1); - final JoinInfo info = JoinInfo.of(left, right, join.getCondition()); + final JoinInfo info = join.analyzeCondition(); if (!info.isEqui() && join.getJoinType() != JoinRelType.INNER) { - // EnumerableJoinRel only supports equi-join. We can put a filter on top + // EnumerableHashJoin only supports equi-join. We can put a filter on top // if it is an inner join. - try { - return EnumerableNestedLoopJoin.create( - left, - right, - join.getCondition(), - join.getVariablesSet(), - join.getJoinType()); - } catch (InvalidRelException e) { - EnumerableRules.LOGGER.debug(e.toString()); - return null; - } + return EnumerableNestedLoopJoin.create( + left, + right, + join.getCondition(), + join.getVariablesSet(), + join.getJoinType()); } else { RelNode newRel; - try { - newRel = EnumerableHashJoin.create( - left, - right, - info.getEquiCondition(left, right, cluster.getRexBuilder()), - join.getVariablesSet(), - join.getJoinType()); - } catch (InvalidRelException e) { - EnumerableRules.LOGGER.debug(e.toString()); - return null; - } + newRel = EnumerableHashJoin.create( + left, + right, + info.getEquiCondition(left, right, cluster.getRexBuilder()), + join.getVariablesSet(), + join.getJoinType()); if (!info.isEqui()) { + RexNode nonEqui = RexUtil.composeConjunction(cluster.getRexBuilder(), + info.nonEquiConditions); newRel = new EnumerableFilter(cluster, newRel.getTraitSet(), - newRel, info.getRemaining(cluster.getRexBuilder())); + newRel, nonEqui); } return newRel; } diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoin.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoin.java index 2ff7b50..d17184b 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoin.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoin.java @@ -26,13 +26,12 @@ import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelTraitSet; -import org.apache.calcite.rel.InvalidRelException; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelCollations; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.CorrelationId; -import org.apache.calcite.rel.core.EquiJoin; +import org.apache.calcite.rel.core.Join; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.metadata.RelMdCollation; import org.apache.calcite.rel.metadata.RelMetadataQuery; @@ -54,7 +53,7 @@ import java.util.Set; /** Implementation of {@link org.apache.calcite.rel.core.Join} in * {@link EnumerableConvention enumerable calling convention} using * a merge algorithm. */ -public class EnumerableMergeJoin extends EquiJoin implements EnumerableRel { +public class EnumerableMergeJoin extends Join implements EnumerableRel { EnumerableMergeJoin( RelOptCluster cluster, RelTraitSet traits, @@ -62,8 +61,7 @@ public class EnumerableMergeJoin extends EquiJoin implements EnumerableRel { RelNode right, RexNode condition, Set<CorrelationId> variablesSet, - JoinRelType joinType) - throws InvalidRelException { + JoinRelType joinType) { super(cluster, traits, left, right, condition, variablesSet, joinType); final List<RelCollation> collations = traits.getTraits(RelCollationTraitDef.INSTANCE); @@ -74,7 +72,7 @@ public class EnumerableMergeJoin extends EquiJoin implements EnumerableRel { EnumerableMergeJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition, ImmutableIntList leftKeys, ImmutableIntList rightKeys, Set<CorrelationId> variablesSet, - JoinRelType joinType) throws InvalidRelException { + JoinRelType joinType) { this(cluster, traits, left, right, condition, variablesSet, joinType); } @@ -82,15 +80,14 @@ public class EnumerableMergeJoin extends EquiJoin implements EnumerableRel { EnumerableMergeJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition, ImmutableIntList leftKeys, ImmutableIntList rightKeys, JoinRelType joinType, - Set<String> variablesStopped) throws InvalidRelException { + Set<String> variablesStopped) { this(cluster, traits, left, right, condition, leftKeys, rightKeys, CorrelationId.setOf(variablesStopped), joinType); } public static EnumerableMergeJoin create(RelNode left, RelNode right, RexLiteral condition, ImmutableIntList leftKeys, - ImmutableIntList rightKeys, JoinRelType joinType) - throws InvalidRelException { + ImmutableIntList rightKeys, JoinRelType joinType) { final RelOptCluster cluster = right.getCluster(); RelTraitSet traitSet = cluster.traitSet(); if (traitSet.isEnabled(RelCollationTraitDef.INSTANCE)) { @@ -106,14 +103,8 @@ public class EnumerableMergeJoin extends EquiJoin implements EnumerableRel { @Override public EnumerableMergeJoin copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) { - try { - return new EnumerableMergeJoin(getCluster(), traitSet, left, right, - condition, variablesSet, joinType); - } catch (InvalidRelException e) { - // Semantic error not possible. Must be a bug. Convert to - // internal error. - throw new AssertionError(e); - } + return new EnumerableMergeJoin(getCluster(), traitSet, left, right, + condition, variablesSet, joinType); } @Override public RelOptCost computeSelfCost(RelOptPlanner planner, diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoinRule.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoinRule.java index 44e4798..b993d94 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoinRule.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoinRule.java @@ -20,7 +20,6 @@ import org.apache.calcite.linq4j.Ord; import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; -import org.apache.calcite.rel.InvalidRelException; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelCollations; import org.apache.calcite.rel.RelFieldCollation; @@ -29,6 +28,8 @@ import org.apache.calcite.rel.convert.ConverterRule; import org.apache.calcite.rel.core.JoinInfo; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.logical.LogicalJoin; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexUtil; import java.util.ArrayList; import java.util.List; @@ -49,8 +50,7 @@ class EnumerableMergeJoinRule extends ConverterRule { @Override public RelNode convert(RelNode rel) { LogicalJoin join = (LogicalJoin) rel; - final JoinInfo info = - JoinInfo.of(join.getLeft(), join.getRight(), join.getCondition()); + final JoinInfo info = join.analyzeCondition(); if (join.getJoinType() != JoinRelType.INNER) { // EnumerableMergeJoin only supports inner join. // (It supports non-equi join, using a post-filter; see below.) @@ -84,26 +84,24 @@ class EnumerableMergeJoinRule extends ConverterRule { final RelNode right = newInputs.get(1); final RelOptCluster cluster = join.getCluster(); RelNode newRel; - try { - RelTraitSet traitSet = join.getTraitSet() - .replace(EnumerableConvention.INSTANCE); - if (!collations.isEmpty()) { - traitSet = traitSet.replace(collations); - } - newRel = new EnumerableMergeJoin(cluster, - traitSet, - left, - right, - info.getEquiCondition(left, right, cluster.getRexBuilder()), - join.getVariablesSet(), - join.getJoinType()); - } catch (InvalidRelException e) { - EnumerableRules.LOGGER.debug(e.toString()); - return null; + + RelTraitSet traitSet = join.getTraitSet() + .replace(EnumerableConvention.INSTANCE); + if (!collations.isEmpty()) { + traitSet = traitSet.replace(collations); } + newRel = new EnumerableMergeJoin(cluster, + traitSet, + left, + right, + info.getEquiCondition(left, right, cluster.getRexBuilder()), + join.getVariablesSet(), + join.getJoinType()); if (!info.isEqui()) { + RexNode nonEqui = RexUtil.composeConjunction(cluster.getRexBuilder(), + info.nonEquiConditions); newRel = new EnumerableFilter(cluster, newRel.getTraitSet(), - newRel, info.getRemaining(cluster.getRexBuilder())); + newRel, nonEqui); } return newRel; } diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableNestedLoopJoin.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableNestedLoopJoin.java index 99fac65..a4e7b81 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableNestedLoopJoin.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableNestedLoopJoin.java @@ -25,7 +25,6 @@ import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelTraitSet; -import org.apache.calcite.rel.InvalidRelException; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.CorrelationId; @@ -50,15 +49,14 @@ public class EnumerableNestedLoopJoin extends Join implements EnumerableRel { /** Creates an EnumerableNestedLoopJoin. */ protected EnumerableNestedLoopJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition, - Set<CorrelationId> variablesSet, JoinRelType joinType) - throws InvalidRelException { + Set<CorrelationId> variablesSet, JoinRelType joinType) { super(cluster, traits, left, right, condition, variablesSet, joinType); } @Deprecated // to be removed before 2.0 protected EnumerableNestedLoopJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition, JoinRelType joinType, - Set<String> variablesStopped) throws InvalidRelException { + Set<String> variablesStopped) { this(cluster, traits, left, right, condition, CorrelationId.setOf(variablesStopped), joinType); } @@ -66,14 +64,8 @@ public class EnumerableNestedLoopJoin extends Join implements EnumerableRel { @Override public EnumerableNestedLoopJoin copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) { - try { - return new EnumerableNestedLoopJoin(getCluster(), traitSet, left, right, - condition, variablesSet, joinType); - } catch (InvalidRelException e) { - // Semantic error not possible. Must be a bug. Convert to - // internal error. - throw new AssertionError(e); - } + return new EnumerableNestedLoopJoin(getCluster(), traitSet, left, right, + condition, variablesSet, joinType); } /** Creates an EnumerableNestedLoopJoin. */ @@ -82,7 +74,7 @@ public class EnumerableNestedLoopJoin extends Join implements EnumerableRel { RelNode right, RexNode condition, Set<CorrelationId> variablesSet, - JoinRelType joinType) throws InvalidRelException { + JoinRelType joinType) { final RelOptCluster cluster = left.getCluster(); final RelMetadataQuery mq = cluster.getMetadataQuery(); final RelTraitSet traitSet = diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java index d29eebf..4645e9c 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java @@ -34,7 +34,6 @@ import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.AggregateCall; import org.apache.calcite.rel.core.Calc; import org.apache.calcite.rel.core.CorrelationId; -import org.apache.calcite.rel.core.EquiJoin; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.core.Join; import org.apache.calcite.rel.core.JoinRelType; @@ -862,6 +861,24 @@ public abstract class RelOptUtil { List<Boolean> filterNulls) { final List<RexNode> nonEquiList = new ArrayList<>(); + splitJoinCondition(left, right, condition, leftKeys, rightKeys, + filterNulls, nonEquiList); + + return RexUtil.composeConjunction( + left.getCluster().getRexBuilder(), nonEquiList); + } + + /** As + * {@link #splitJoinCondition(RelNode, RelNode, RexNode, List, List, List)}, + * but writes non-equi conditions to a conjunctive list. */ + public static void splitJoinCondition( + RelNode left, + RelNode right, + RexNode condition, + List<Integer> leftKeys, + List<Integer> rightKeys, + List<Boolean> filterNulls, + List<RexNode> nonEquiList) { splitJoinCondition( left.getCluster().getRexBuilder(), left.getRowType().getFieldCount(), @@ -870,9 +887,6 @@ public abstract class RelOptUtil { rightKeys, filterNulls, nonEquiList); - - return RexUtil.composeConjunction( - left.getCluster().getRexBuilder(), nonEquiList); } @Deprecated // to be removed before 2.0 @@ -3921,12 +3935,6 @@ public abstract class RelOptUtil { this.outerJoin = outerJoin; } } - - /** Check if it is the join whose condition is based on column equality, - * this mostly depends on the physical implementation of the join. */ - public static boolean forceEquiJoin(Join join) { - return join.isSemiJoin() || join instanceof EquiJoin; - } } // End RelOptUtil.java diff --git a/core/src/main/java/org/apache/calcite/rel/core/EquiJoin.java b/core/src/main/java/org/apache/calcite/rel/core/EquiJoin.java index f2c496f..3821c6d 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/EquiJoin.java +++ b/core/src/main/java/org/apache/calcite/rel/core/EquiJoin.java @@ -37,7 +37,13 @@ import java.util.Set; * eliminate some optimize logic for {@code EquiJoin} in some planning rules. * e.g. {@link org.apache.calcite.rel.rules.FilterJoinRule} would not push non-equi * join conditions of the above filter into the join underneath if it is an {@code EquiJoin}. + * + * @deprecated This class is no longer needed; if you are writing a sub-class of + * Join that only accepts equi conditions, it is sufficient that it extends + * {@link Join}. It will be evident that it is an equi-join when its + * {@link JoinInfo#nonEquiConditions} is an empty list. */ +@Deprecated // to be removed before 2.0 public abstract class EquiJoin extends Join { public final ImmutableIntList leftKeys; public final ImmutableIntList rightKeys; diff --git a/core/src/main/java/org/apache/calcite/rel/core/JoinInfo.java b/core/src/main/java/org/apache/calcite/rel/core/JoinInfo.java index 6588ffa..468cb97 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/JoinInfo.java +++ b/core/src/main/java/org/apache/calcite/rel/core/JoinInfo.java @@ -20,34 +20,39 @@ import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rex.RexBuilder; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexUtil; import org.apache.calcite.runtime.FlatLists; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.ImmutableIntList; import org.apache.calcite.util.mapping.IntPair; +import com.google.common.collect.ImmutableList; + import java.util.ArrayList; import java.util.List; import java.util.Objects; /** An analyzed join condition. * - * <p>It is useful for the many algorithms that care whether a join is an - * equi-join. + * <p>It is useful for the many algorithms that care whether a join has an + * equi-join condition. * * <p>You can create one using {@link #of}, or call * {@link Join#analyzeCondition()}; many kinds of join cache their - * join info, especially those that are equi-joins and sub-class - * {@link org.apache.calcite.rel.core.EquiJoin}.</p> + * join info, especially those that are equi-joins.</p> * * @see Join#analyzeCondition() */ -public abstract class JoinInfo { +public class JoinInfo { public final ImmutableIntList leftKeys; public final ImmutableIntList rightKeys; + public final ImmutableList<RexNode> nonEquiConditions; /** Creates a JoinInfo. */ - protected JoinInfo(ImmutableIntList leftKeys, ImmutableIntList rightKeys) { + protected JoinInfo(ImmutableIntList leftKeys, ImmutableIntList rightKeys, + ImmutableList<RexNode> nonEquiConditions) { this.leftKeys = Objects.requireNonNull(leftKeys); this.rightKeys = Objects.requireNonNull(rightKeys); + this.nonEquiConditions = Objects.requireNonNull(nonEquiConditions); assert leftKeys.size() == rightKeys.size(); } @@ -56,26 +61,23 @@ public abstract class JoinInfo { final List<Integer> leftKeys = new ArrayList<>(); final List<Integer> rightKeys = new ArrayList<>(); final List<Boolean> filterNulls = new ArrayList<>(); - RexNode remaining = - RelOptUtil.splitJoinCondition(left, right, condition, leftKeys, - rightKeys, filterNulls); - if (remaining.isAlwaysTrue()) { - return new EquiJoinInfo(ImmutableIntList.copyOf(leftKeys), - ImmutableIntList.copyOf(rightKeys)); - } else { - return new NonEquiJoinInfo(ImmutableIntList.copyOf(leftKeys), - ImmutableIntList.copyOf(rightKeys), remaining); - } + final List<RexNode> nonEquiList = new ArrayList<>(); + RelOptUtil.splitJoinCondition(left, right, condition, leftKeys, rightKeys, + filterNulls, nonEquiList); + return new JoinInfo(ImmutableIntList.copyOf(leftKeys), + ImmutableIntList.copyOf(rightKeys), ImmutableList.copyOf(nonEquiList)); } /** Creates an equi-join. */ public static JoinInfo of(ImmutableIntList leftKeys, ImmutableIntList rightKeys) { - return new EquiJoinInfo(leftKeys, rightKeys); + return new JoinInfo(leftKeys, rightKeys, ImmutableList.of()); } /** Returns whether this is an equi-join. */ - public abstract boolean isEqui(); + public boolean isEqui() { + return nonEquiConditions.isEmpty(); + } /** Returns a list of (left, right) key ordinals. */ public List<IntPair> pairs() { @@ -90,7 +92,10 @@ public abstract class JoinInfo { return ImmutableBitSet.of(rightKeys); } - public abstract RexNode getRemaining(RexBuilder rexBuilder); + @Deprecated // to be removed before 2.0 + public RexNode getRemaining(RexBuilder rexBuilder) { + return RexUtil.composeConjunction(rexBuilder, nonEquiConditions); + } public RexNode getEquiCondition(RelNode left, RelNode right, RexBuilder rexBuilder) { @@ -102,41 +107,6 @@ public abstract class JoinInfo { return FlatLists.of(leftKeys, rightKeys); } - /** JoinInfo that represents an equi-join. */ - private static class EquiJoinInfo extends JoinInfo { - protected EquiJoinInfo(ImmutableIntList leftKeys, - ImmutableIntList rightKeys) { - super(leftKeys, rightKeys); - } - - @Override public boolean isEqui() { - return true; - } - - @Override public RexNode getRemaining(RexBuilder rexBuilder) { - return rexBuilder.makeLiteral(true); - } - } - - /** JoinInfo that represents a non equi-join. */ - private static class NonEquiJoinInfo extends JoinInfo { - public final RexNode remaining; - - protected NonEquiJoinInfo(ImmutableIntList leftKeys, - ImmutableIntList rightKeys, RexNode remaining) { - super(leftKeys, rightKeys); - this.remaining = Objects.requireNonNull(remaining); - assert !remaining.isAlwaysTrue(); - } - - @Override public boolean isEqui() { - return false; - } - - @Override public RexNode getRemaining(RexBuilder rexBuilder) { - return remaining; - } - } } // End JoinInfo.java diff --git a/core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java b/core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java index 144af2c..a0b15ea 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java @@ -16,6 +16,7 @@ */ package org.apache.calcite.rel.rules; +import org.apache.calcite.adapter.enumerable.EnumerableConvention; import org.apache.calcite.plan.RelOptRule; import org.apache.calcite.plan.RelOptRuleCall; import org.apache.calcite.plan.RelOptRuleOperand; @@ -52,21 +53,28 @@ public abstract class FilterJoinRule extends RelOptRule { * will be pushed into the ON clause. */ public static final Predicate TRUE_PREDICATE = (join, joinType, exp) -> true; + /** Predicate that returns true if the join is not Enumerable convention, + * will be replaced by {@link #TRUE_PREDICATE} once enumerable join supports + * non-equi join. */ + // to be removed before 1.22.0 + private static final Predicate NOT_ENUMERABLE = (join, joinType, exp) -> + join.getConvention() != EnumerableConvention.INSTANCE; + /** Rule that pushes predicates from a Filter into the Join below them. */ public static final FilterJoinRule FILTER_ON_JOIN = new FilterIntoJoinRule(true, RelFactories.LOGICAL_BUILDER, - TRUE_PREDICATE); + NOT_ENUMERABLE); /** Dumber version of {@link #FILTER_ON_JOIN}. Not intended for production * use, but keeps some tests working for which {@code FILTER_ON_JOIN} is too * smart. */ public static final FilterJoinRule DUMB_FILTER_ON_JOIN = new FilterIntoJoinRule(false, RelFactories.LOGICAL_BUILDER, - TRUE_PREDICATE); + NOT_ENUMERABLE); /** Rule that pushes predicates in a Join into the inputs to the join. */ public static final FilterJoinRule JOIN = - new JoinConditionPushRule(RelFactories.LOGICAL_BUILDER, TRUE_PREDICATE); + new JoinConditionPushRule(RelFactories.LOGICAL_BUILDER, NOT_ENUMERABLE); /** Whether to try to strengthen join-type. */ private final boolean smart; @@ -98,7 +106,7 @@ public abstract class FilterJoinRule extends RelOptRule { boolean smart, RelFactories.FilterFactory filterFactory, RelFactories.ProjectFactory projectFactory) { this(operand, id, smart, RelBuilder.proto(filterFactory, projectFactory), - TRUE_PREDICATE); + NOT_ENUMERABLE); } /** @@ -116,15 +124,6 @@ public abstract class FilterJoinRule extends RelOptRule { //~ Methods ---------------------------------------------------------------- - /** Returns if it is needed to push the filter condition above join - * into the join condition. - */ - private boolean needsPushInto(Join join) { - // If the join force the join info to be based on column equality, - // or it is a non-correlated semijoin, returns false. - return !RelOptUtil.forceEquiJoin(join); - } - protected void perform(RelOptRuleCall call, Filter filter, Join join) { final List<RexNode> joinFilters = @@ -171,7 +170,7 @@ public abstract class FilterJoinRule extends RelOptRule { join, aboveFilters, joinType, - needsPushInto(join), + true, !joinType.generatesNullsOnLeft(), !joinType.generatesNullsOnRight(), joinFilters, diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java index 467827d..e91dc88 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java @@ -28,7 +28,6 @@ import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.Calc; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.core.Join; -import org.apache.calcite.rel.core.JoinInfo; import org.apache.calcite.rel.core.Project; import org.apache.calcite.rel.core.RelFactories; import org.apache.calcite.rel.core.Window; @@ -346,15 +345,6 @@ public abstract class ReduceExpressionsRule extends RelOptRule { matchNullability)) { return; } - if (RelOptUtil.forceEquiJoin(join)) { - final JoinInfo joinInfo = - JoinInfo.of(join.getLeft(), join.getRight(), expList.get(0)); - if (!joinInfo.isEqui()) { - // This kind of join must be an equi-join, and the condition is - // no longer an equi-join. SemiJoin is an example of this. - return; - } - } call.transformTo( join.copy( join.getTraitSet(), diff --git a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java index 8964c1a..d0719d1 100644 --- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java @@ -24,7 +24,6 @@ import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelOptPredicateList; import org.apache.calcite.plan.RelOptTable; import org.apache.calcite.plan.RelTraitSet; -import org.apache.calcite.rel.InvalidRelException; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelCollations; @@ -90,7 +89,6 @@ import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.util.BuiltInMethod; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.ImmutableIntList; -import org.apache.calcite.util.TestUtil; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -1130,12 +1128,8 @@ public class RelMetadataTest extends SqlToRelTestBase { final ImmutableIntList leftKeys = ImmutableIntList.of(2); final ImmutableIntList rightKeys = ImmutableIntList.of(0); final EnumerableMergeJoin join; - try { - join = EnumerableMergeJoin.create(project, deptSort, - rexBuilder.makeLiteral(true), leftKeys, rightKeys, JoinRelType.INNER); - } catch (InvalidRelException e) { - throw TestUtil.rethrow(e); - } + join = EnumerableMergeJoin.create(project, deptSort, + rexBuilder.makeLiteral(true), leftKeys, rightKeys, JoinRelType.INNER); collations = RelMdCollation.mergeJoin(mq, project, deptSort, leftKeys, rightKeys); 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 915f626..eb0effd 100644 --- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java @@ -1097,7 +1097,7 @@ public class RelOptRulesTest extends RelOptTestBase { .withTrim(true) .withPre(preProgram) .with(program) - .checkUnchanged(); + .check(); } @Test public void testSemiJoinTrim() throws Exception { 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 896215e..c987c22 100644 --- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml @@ -1260,7 +1260,7 @@ LogicalProject(SAL=[$0]) <Resource name="planAfter"> <![CDATA[ LogicalProject(SAL=[$0]) - LogicalJoin(condition=[=($1, $2)], joinType=[semi]) + LogicalJoin(condition=[=(200, $2)], joinType=[semi]) LogicalFilter(condition=[=($1, 200)]) LogicalProject(SAL=[$5], DEPTNO=[$7]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) diff --git a/pig/src/test/java/org/apache/calcite/test/PigRelBuilderStyleTest.java b/pig/src/test/java/org/apache/calcite/test/PigRelBuilderStyleTest.java index fd1f9ea..8bc1a32 100644 --- a/pig/src/test/java/org/apache/calcite/test/PigRelBuilderStyleTest.java +++ b/pig/src/test/java/org/apache/calcite/test/PigRelBuilderStyleTest.java @@ -253,8 +253,10 @@ public class PigRelBuilderStyleTest extends AbstractPigTest { planner.removeRule(FilterAggregateTransposeRule.INSTANCE); planner.removeRule(FilterJoinRule.FILTER_ON_JOIN); planner.addRule( - new FilterAggregateTransposeRule(PigFilter.class, builderFactory, PigAggregate.class)); - planner.addRule(new FilterIntoJoinRule(true, builderFactory, TRUE_PREDICATE)); + new FilterAggregateTransposeRule(PigFilter.class, builderFactory, + PigAggregate.class)); + planner.addRule( + new FilterIntoJoinRule(true, builderFactory, TRUE_PREDICATE)); planner.setRoot(root); return planner; }
