[CALCITE-816] Represent sub-query as a RexNode Reduce 3-value logic to 1- or 2-value logic.
Optimize certain IN and EXISTS to an inner join. Represent correlation variables using CorrelationId wherever possible. In Join, replace field "ImmutableSet<String> variablesStopped" with "ImmutableSet<CorrelationId> variablesSet". RelNode.getVariablesSet is now preferred to RelNode.getVariablesStopped. Make Join.joinType final. Verify in builder that there are no correlation variables where there shouldn't be. Refactor decorrelator. Logged [CALCITE-1045] for remaining work. Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/505a9064 Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/505a9064 Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/505a9064 Branch: refs/heads/master Commit: 505a9064b96a6c8399735fc2fa4d0ac9d5f3ed87 Parents: cd92b77 Author: Julian Hyde <[email protected]> Authored: Sat Jul 25 14:44:20 2015 -0700 Committer: Julian Hyde <[email protected]> Committed: Sun Jan 10 00:51:25 2016 -0800 ---------------------------------------------------------------------- .../adapter/enumerable/EnumerableJoin.java | 42 +- .../adapter/enumerable/EnumerableJoinRule.java | 9 +- .../adapter/enumerable/EnumerableMergeJoin.java | 22 +- .../enumerable/EnumerableMergeJoinRule.java | 4 +- .../adapter/enumerable/EnumerableThetaJoin.java | 16 +- .../calcite/adapter/enumerable/RexImpTable.java | 14 +- .../apache/calcite/adapter/jdbc/JdbcRules.java | 20 +- .../apache/calcite/interpreter/Bindables.java | 17 +- .../org/apache/calcite/materialize/Lattice.java | 3 +- .../org/apache/calcite/plan/RelOptCluster.java | 5 +- .../org/apache/calcite/plan/RelOptQuery.java | 3 +- .../org/apache/calcite/plan/RelOptUtil.java | 127 +- .../calcite/plan/SubstitutionVisitor.java | 19 +- .../org/apache/calcite/plan/volcano/RelSet.java | 24 +- .../apache/calcite/plan/volcano/RelSubset.java | 29 +- .../calcite/plan/volcano/VolcanoPlanner.java | 2 +- .../org/apache/calcite/prepare/Prepare.java | 10 +- .../org/apache/calcite/rel/AbstractRelNode.java | 16 +- .../java/org/apache/calcite/rel/RelNode.java | 31 +- .../org/apache/calcite/rel/core/Correlate.java | 15 +- .../apache/calcite/rel/core/CorrelationId.java | 54 +- .../org/apache/calcite/rel/core/EquiJoin.java | 15 +- .../java/org/apache/calcite/rel/core/Join.java | 53 +- .../apache/calcite/rel/core/RelFactories.java | 63 +- .../org/apache/calcite/rel/core/SemiJoin.java | 4 +- .../apache/calcite/rel/externalize/RelJson.java | 2 +- .../apache/calcite/rel/logical/LogicalCalc.java | 5 +- .../calcite/rel/logical/LogicalCorrelate.java | 3 + .../calcite/rel/logical/LogicalFilter.java | 46 +- .../apache/calcite/rel/logical/LogicalJoin.java | 73 +- .../calcite/rel/metadata/RelMdUniqueKeys.java | 11 +- .../org/apache/calcite/rel/rules/EquiJoin.java | 3 +- .../calcite/rel/rules/JoinToCorrelateRule.java | 5 +- .../rel/rules/JoinUnionTransposeRule.java | 2 +- .../calcite/rel/rules/SubQueryRemoveRule.java | 365 ++++ .../apache/calcite/rel/stream/StreamRules.java | 10 +- .../org/apache/calcite/rex/LogicVisitor.java | 158 ++ .../org/apache/calcite/rex/RexBiVisitor.java | 52 + .../java/org/apache/calcite/rex/RexBuilder.java | 7 +- .../java/org/apache/calcite/rex/RexCall.java | 8 +- .../apache/calcite/rex/RexCorrelVariable.java | 12 +- .../org/apache/calcite/rex/RexDynamicParam.java | 4 + .../org/apache/calcite/rex/RexFieldAccess.java | 4 + .../org/apache/calcite/rex/RexInputRef.java | 4 + .../java/org/apache/calcite/rex/RexLiteral.java | 10 +- .../org/apache/calcite/rex/RexLocalRef.java | 4 + .../java/org/apache/calcite/rex/RexNode.java | 6 + .../java/org/apache/calcite/rex/RexOver.java | 4 + .../java/org/apache/calcite/rex/RexProgram.java | 4 + .../org/apache/calcite/rex/RexRangeRef.java | 4 + .../java/org/apache/calcite/rex/RexShuttle.java | 12 +- .../org/apache/calcite/rex/RexSubQuery.java | 115 ++ .../java/org/apache/calcite/rex/RexUtil.java | 103 +- .../java/org/apache/calcite/rex/RexVisitor.java | 2 + .../org/apache/calcite/rex/RexVisitorImpl.java | 12 + .../org/apache/calcite/schema/SchemaPlus.java | 2 +- .../java/org/apache/calcite/sql/SqlKind.java | 8 +- .../calcite/sql/validate/SqlValidatorImpl.java | 1 + .../sql2rel/DeduplicateCorrelateVariables.java | 65 +- .../apache/calcite/sql2rel/RelDecorrelator.java | 1646 ++++++++---------- .../apache/calcite/sql2rel/RelFieldTrimmer.java | 12 +- .../sql2rel/RelStructuredTypeFlattener.java | 7 +- .../calcite/sql2rel/SqlToRelConverter.java | 390 +++-- .../java/org/apache/calcite/tools/Programs.java | 54 +- .../org/apache/calcite/tools/RelBuilder.java | 47 +- .../main/java/org/apache/calcite/util/Bug.java | 5 + .../org/apache/calcite/test/CalciteAssert.java | 10 +- .../apache/calcite/test/JdbcAdapterTest.java | 122 +- .../java/org/apache/calcite/test/JdbcTest.java | 214 ++- .../org/apache/calcite/test/LatticeTest.java | 47 +- .../calcite/test/ReflectiveSchemaTest.java | 21 +- .../org/apache/calcite/test/RelBuilderTest.java | 22 + .../apache/calcite/test/RelMetadataTest.java | 3 +- .../apache/calcite/test/RelOptRulesTest.java | 159 +- .../org/apache/calcite/test/RelOptTestBase.java | 30 + .../apache/calcite/test/RexTransformerTest.java | 210 +-- .../calcite/test/SqlToRelConverterTest.java | 421 ++++- .../apache/calcite/test/SqlToRelTestBase.java | 36 +- .../apache/calcite/test/SqlValidatorTest.java | 37 + .../enumerable/EnumerableCorrelateTest.java | 29 +- .../org/apache/calcite/test/RelOptRulesTest.xml | 706 ++++++++ .../calcite/test/SqlToRelConverterTest.xml | 582 ++++++- core/src/test/resources/sql/join.iq | 18 +- core/src/test/resources/sql/misc.iq | 121 +- core/src/test/resources/sql/subquery.iq | 70 +- site/_docs/reference.md | 17 +- 86 files changed, 5027 insertions(+), 1752 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoin.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoin.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoin.java index 14fcf3b..0b86771 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoin.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoin.java @@ -26,6 +26,7 @@ import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.InvalidRelException; 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.JoinInfo; import org.apache.calcite.rel.core.JoinRelType; @@ -53,8 +54,8 @@ public class EnumerableJoin extends EquiJoin implements EnumerableRel { RexNode condition, ImmutableIntList leftKeys, ImmutableIntList rightKeys, - JoinRelType joinType, - Set<String> variablesStopped) + Set<CorrelationId> variablesSet, + JoinRelType joinType) throws InvalidRelException { super( cluster, @@ -64,8 +65,17 @@ public class EnumerableJoin extends EquiJoin implements EnumerableRel { condition, leftKeys, rightKeys, - joinType, - variablesStopped); + variablesSet, + joinType); + } + + @Deprecated // to be removed before 2.0 + protected EnumerableJoin(RelOptCluster cluster, RelTraitSet traits, + RelNode left, RelNode right, RexNode condition, ImmutableIntList leftKeys, + ImmutableIntList rightKeys, JoinRelType joinType, + Set<String> variablesStopped) throws InvalidRelException { + this(cluster, traits, left, right, condition, leftKeys, rightKeys, + CorrelationId.setOf(variablesStopped), joinType); } /** Creates an EnumerableJoin. */ @@ -75,14 +85,28 @@ public class EnumerableJoin extends EquiJoin implements EnumerableRel { RexNode condition, ImmutableIntList leftKeys, ImmutableIntList rightKeys, - JoinRelType joinType, - Set<String> variablesStopped) + Set<CorrelationId> variablesSet, + JoinRelType joinType) throws InvalidRelException { final RelOptCluster cluster = left.getCluster(); final RelTraitSet traitSet = cluster.traitSetOf(EnumerableConvention.INSTANCE); return new EnumerableJoin(cluster, traitSet, left, right, condition, - leftKeys, rightKeys, joinType, variablesStopped); + leftKeys, rightKeys, variablesSet, joinType); + } + + @Deprecated // to be removed before 2.0 + public static EnumerableJoin create( + RelNode left, + RelNode right, + RexNode condition, + ImmutableIntList leftKeys, + ImmutableIntList rightKeys, + JoinRelType joinType, + Set<String> variablesStopped) + throws InvalidRelException { + return create(left, right, condition, leftKeys, rightKeys, + CorrelationId.setOf(variablesStopped), joinType); } @Override public EnumerableJoin copy(RelTraitSet traitSet, RexNode condition, @@ -92,8 +116,8 @@ public class EnumerableJoin extends EquiJoin implements EnumerableRel { assert joinInfo.isEqui(); try { return new EnumerableJoin(getCluster(), traitSet, left, right, - condition, joinInfo.leftKeys, joinInfo.rightKeys, joinType, - variablesStopped); + condition, joinInfo.leftKeys, joinInfo.rightKeys, variablesSet, + joinType); } catch (InvalidRelException e) { // Semantic error not possible. Must be a bug. Convert to // internal error. http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableJoinRule.java ---------------------------------------------------------------------- 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 6ffc912..88655ba 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 @@ -43,7 +43,7 @@ class EnumerableJoinRule extends ConverterRule { @Override public RelNode convert(RelNode rel) { LogicalJoin join = (LogicalJoin) rel; - List<RelNode> newInputs = new ArrayList<RelNode>(); + List<RelNode> newInputs = new ArrayList<>(); for (RelNode input : join.getInputs()) { if (!(input.getConvention() instanceof EnumerableConvention)) { input = @@ -65,8 +65,7 @@ class EnumerableJoinRule extends ConverterRule { // if it is an inner join. try { return new EnumerableThetaJoin(cluster, traitSet, left, right, - join.getCondition(), join.getJoinType(), - join.getVariablesStopped()); + join.getCondition(), join.getVariablesSet(), join.getJoinType()); } catch (InvalidRelException e) { EnumerableRules.LOGGER.fine(e.toString()); return null; @@ -82,8 +81,8 @@ class EnumerableJoinRule extends ConverterRule { info.getEquiCondition(left, right, cluster.getRexBuilder()), info.leftKeys, info.rightKeys, - join.getJoinType(), - join.getVariablesStopped()); + join.getVariablesSet(), + join.getJoinType()); } catch (InvalidRelException e) { EnumerableRules.LOGGER.fine(e.toString()); return null; http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoin.java ---------------------------------------------------------------------- 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 be0d821..18419e3 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 @@ -28,6 +28,7 @@ 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.JoinInfo; import org.apache.calcite.rel.core.JoinRelType; @@ -56,16 +57,25 @@ public class EnumerableMergeJoin extends EquiJoin implements EnumerableRel { RexNode condition, ImmutableIntList leftKeys, ImmutableIntList rightKeys, - JoinRelType joinType, - Set<String> variablesStopped) + Set<CorrelationId> variablesSet, + JoinRelType joinType) throws InvalidRelException { super(cluster, traits, left, right, condition, leftKeys, rightKeys, - joinType, variablesStopped); + variablesSet, joinType); final List<RelCollation> collations = traits.getTraits(RelCollationTraitDef.INSTANCE); assert collations == null || RelCollations.contains(collations, leftKeys); } + @Deprecated // to be removed before 2.0 + EnumerableMergeJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, + RelNode right, RexNode condition, ImmutableIntList leftKeys, + ImmutableIntList rightKeys, JoinRelType joinType, + Set<String> variablesStopped) throws InvalidRelException { + 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) @@ -78,7 +88,7 @@ public class EnumerableMergeJoin extends EquiJoin implements EnumerableRel { traitSet = traitSet.replace(collations); } return new EnumerableMergeJoin(cluster, traitSet, left, right, condition, - leftKeys, rightKeys, joinType, ImmutableSet.<String>of()); + leftKeys, rightKeys, ImmutableSet.<CorrelationId>of(), joinType); } @Override public EnumerableMergeJoin copy(RelTraitSet traitSet, @@ -88,8 +98,8 @@ public class EnumerableMergeJoin extends EquiJoin implements EnumerableRel { assert joinInfo.isEqui(); try { return new EnumerableMergeJoin(getCluster(), traitSet, left, right, - condition, joinInfo.leftKeys, joinInfo.rightKeys, joinType, - variablesStopped); + condition, joinInfo.leftKeys, joinInfo.rightKeys, variablesSet, + joinType); } catch (InvalidRelException e) { // Semantic error not possible. Must be a bug. Convert to // internal error. http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableMergeJoinRule.java ---------------------------------------------------------------------- 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 51f09f4..9dd0ce1 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 @@ -99,8 +99,8 @@ class EnumerableMergeJoinRule extends ConverterRule { info.getEquiCondition(left, right, cluster.getRexBuilder()), info.leftKeys, info.rightKeys, - join.getJoinType(), - join.getVariablesStopped()); + join.getVariablesSet(), + join.getJoinType()); } catch (InvalidRelException e) { EnumerableRules.LOGGER.fine(e.toString()); return null; http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableThetaJoin.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableThetaJoin.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableThetaJoin.java index bf4516a..e28ddfc 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableThetaJoin.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableThetaJoin.java @@ -27,6 +27,7 @@ import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.InvalidRelException; import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.core.Join; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.metadata.RelMetadataQuery; @@ -43,11 +44,20 @@ import java.util.Set; * {@link org.apache.calcite.adapter.enumerable.EnumerableConvention enumerable calling convention} * that allows conditions that are not just {@code =} (equals). */ public class EnumerableThetaJoin extends Join implements EnumerableRel { + /** Creates an EnumerableThetaJoin. */ + protected EnumerableThetaJoin(RelOptCluster cluster, RelTraitSet traits, + RelNode left, RelNode right, RexNode condition, + Set<CorrelationId> variablesSet, JoinRelType joinType) + throws InvalidRelException { + super(cluster, traits, left, right, condition, variablesSet, joinType); + } + + @Deprecated // to be removed before 2.0 protected EnumerableThetaJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition, JoinRelType joinType, Set<String> variablesStopped) throws InvalidRelException { - super(cluster, traits, left, right, condition, joinType, - variablesStopped); + this(cluster, traits, left, right, condition, + CorrelationId.setOf(variablesStopped), joinType); } @Override public EnumerableThetaJoin copy(RelTraitSet traitSet, @@ -55,7 +65,7 @@ public class EnumerableThetaJoin extends Join implements EnumerableRel { boolean semiJoinDone) { try { return new EnumerableThetaJoin(getCluster(), traitSet, left, right, - condition, joinType, variablesStopped); + condition, variablesSet, joinType); } catch (InvalidRelException e) { // Semantic error not possible. Must be a bug. Convert to // internal error. http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java index 511584b..2633490 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java @@ -359,10 +359,8 @@ public class RexImpTable { public T get() { try { return constructor.newInstance(); - } catch (InstantiationException e) { - throw new IllegalStateException( - "Unable to instantiate aggregate implementor " + constructor, e); - } catch (IllegalAccessException | InvocationTargetException e) { + } catch (InstantiationException | IllegalAccessException + | InvocationTargetException e) { throw new IllegalStateException( "Error while creating aggregate implementor " + constructor, e); } @@ -1883,11 +1881,9 @@ public class RexImpTable { return translator.translate(operands.get(0), negate ? NullAs.IS_NOT_NULL : NullAs.IS_NULL); } else { - return maybeNegate( - negate == seek, - translator.translate( - operands.get(0), - negate == seek ? NullAs.TRUE : NullAs.FALSE)); + return maybeNegate(negate == seek, + translator.translate(operands.get(0), + seek ? NullAs.FALSE : NullAs.TRUE)); } } } http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java index 5fbb08f..ca80d29 100644 --- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java +++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java @@ -35,6 +35,7 @@ import org.apache.calcite.rel.SingleRel; import org.apache.calcite.rel.convert.ConverterRule; import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.AggregateCall; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.core.Intersect; import org.apache.calcite.rel.core.Join; @@ -159,8 +160,8 @@ public class JdbcRules { newInputs.get(0), newInputs.get(1), join.getCondition(), - join.getJoinType(), - join.getVariablesStopped()); + join.getVariablesSet(), + join.getJoinType()); } catch (InvalidRelException e) { LOGGER.fine(e.toString()); return null; @@ -211,6 +212,15 @@ public class JdbcRules { /** Join operator implemented in JDBC convention. */ public static class JdbcJoin extends Join implements JdbcRel { + /** Creates a JdbcJoin. */ + protected JdbcJoin(RelOptCluster cluster, RelTraitSet traitSet, + RelNode left, RelNode right, RexNode condition, + Set<CorrelationId> variablesSet, JoinRelType joinType) + throws InvalidRelException { + super(cluster, traitSet, left, right, condition, variablesSet, joinType); + } + + @Deprecated // to be removed before 2.0 protected JdbcJoin( RelOptCluster cluster, RelTraitSet traitSet, @@ -220,8 +230,8 @@ public class JdbcRules { JoinRelType joinType, Set<String> variablesStopped) throws InvalidRelException { - super(cluster, traitSet, left, right, condition, - joinType, variablesStopped); + this(cluster, traitSet, left, right, condition, + CorrelationId.setOf(variablesStopped), joinType); } @Override public JdbcJoin copy(RelTraitSet traitSet, RexNode condition, @@ -229,7 +239,7 @@ public class JdbcRules { boolean semiJoinDone) { try { return new JdbcJoin(getCluster(), traitSet, left, right, - condition, joinType, variablesStopped); + condition, variablesSet, joinType); } catch (InvalidRelException e) { // Semantic error not possible. Must be a bug. Convert to // internal error. http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/interpreter/Bindables.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/interpreter/Bindables.java b/core/src/main/java/org/apache/calcite/interpreter/Bindables.java index a4474b4..9d4b250 100644 --- a/core/src/main/java/org/apache/calcite/interpreter/Bindables.java +++ b/core/src/main/java/org/apache/calcite/interpreter/Bindables.java @@ -37,6 +37,7 @@ import org.apache.calcite.rel.RelWriter; import org.apache.calcite.rel.convert.ConverterRule; import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.AggregateCall; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.core.Join; import org.apache.calcite.rel.core.JoinRelType; @@ -417,25 +418,33 @@ public class Bindables { convert(join.getRight(), join.getRight().getTraitSet() .replace(BindableConvention.INSTANCE)), - join.getCondition(), join.getJoinType(), join.getVariablesStopped()); + join.getCondition(), join.getVariablesSet(), join.getJoinType()); } } /** Implementation of {@link org.apache.calcite.rel.core.Join} in * bindable calling convention. */ public static class BindableJoin extends Join implements BindableRel { + /** Creates a BindableJoin. */ + protected BindableJoin(RelOptCluster cluster, RelTraitSet traitSet, + RelNode left, RelNode right, RexNode condition, + Set<CorrelationId> variablesSet, JoinRelType joinType) { + super(cluster, traitSet, left, right, condition, variablesSet, joinType); + } + + @Deprecated // to be removed before 2.0 protected BindableJoin(RelOptCluster cluster, RelTraitSet traitSet, RelNode left, RelNode right, RexNode condition, JoinRelType joinType, Set<String> variablesStopped) { - super(cluster, traitSet, left, right, condition, joinType, - variablesStopped); + this(cluster, traitSet, left, right, condition, + CorrelationId.setOf(variablesStopped), joinType); } public BindableJoin copy(RelTraitSet traitSet, RexNode conditionExpr, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) { return new BindableJoin(getCluster(), traitSet, left, right, - conditionExpr, joinType, variablesStopped); + conditionExpr, variablesSet, joinType); } public Class<Object[]> getElementType() { http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/materialize/Lattice.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/materialize/Lattice.java b/core/src/main/java/org/apache/calcite/materialize/Lattice.java index 62ab07f..244a245 100644 --- a/core/src/main/java/org/apache/calcite/materialize/Lattice.java +++ b/core/src/main/java/org/apache/calcite/materialize/Lattice.java @@ -44,7 +44,6 @@ import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.SqlUtil; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.validate.SqlValidatorUtil; -import org.apache.calcite.util.BitSets; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.graph.DefaultDirectedGraph; import org.apache.calcite.util.graph.DefaultEdge; @@ -260,7 +259,7 @@ public class Lattice { final StringBuilder groupBuf = new StringBuilder("\nGROUP BY "); int k = 0; final Set<String> columnNames = Sets.newHashSet(); - for (int i : BitSets.toIter(groupSet)) { + for (int i : groupSet) { if (k++ > 0) { buf.append(", "); groupBuf.append(", "); http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java b/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java index c4592db..241f4e0 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptCluster.java @@ -17,6 +17,7 @@ package org.apache.calcite.plan; import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider; import org.apache.calcite.rel.metadata.MetadataFactory; import org.apache.calcite.rel.metadata.MetadataFactoryImpl; @@ -143,8 +144,8 @@ public class RelOptCluster { * Constructs a new id for a correlating variable. It is unique within the * whole query. */ - public int createCorrel() { - return nextCorrel.getAndIncrement(); + public CorrelationId createCorrel() { + return new CorrelationId(nextCorrel.getAndIncrement()); } /** Returns the default trait set for this cluster. */ http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/plan/RelOptQuery.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptQuery.java b/core/src/main/java/org/apache/calcite/plan/RelOptQuery.java index 2c2703d..34f5c5f 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptQuery.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptQuery.java @@ -17,6 +17,7 @@ package org.apache.calcite.plan; import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rex.RexBuilder; @@ -35,7 +36,7 @@ public class RelOptQuery { /** * Prefix to the name of correlating variables. */ - public static final String CORREL_PREFIX = "$cor"; + public static final String CORREL_PREFIX = CorrelationId.CORREL_PREFIX; //~ Instance fields -------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java ---------------------------------------------------------------------- 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 b932cef..eeaea21 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java @@ -26,6 +26,7 @@ import org.apache.calcite.rel.RelVisitor; import org.apache.calcite.rel.RelWriter; 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.Filter; import org.apache.calcite.rel.core.Join; import org.apache.calcite.rel.core.JoinRelType; @@ -60,6 +61,7 @@ import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexOver; import org.apache.calcite.rex.RexProgram; import org.apache.calcite.rex.RexShuttle; +import org.apache.calcite.rex.RexSubQuery; import org.apache.calcite.rex.RexUtil; import org.apache.calcite.rex.RexVisitorImpl; import org.apache.calcite.sql.SqlExplainLevel; @@ -83,7 +85,9 @@ import org.apache.calcite.util.mapping.Mappings; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; +import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; import java.io.PrintWriter; import java.io.StringWriter; @@ -155,7 +159,7 @@ public abstract class RelOptUtil { * Returns a list of variables set by a relational expression or its * descendants. */ - public static Set<String> getVariablesSet(RelNode rel) { + public static Set<CorrelationId> getVariablesSet(RelNode rel) { VariableSetVisitor visitor = new VariableSetVisitor(); go(visitor, rel); return visitor.variables; @@ -165,19 +169,18 @@ public abstract class RelOptUtil { * Returns a set of distinct variables set by <code>rel0</code> and used by * <code>rel1</code>. */ - public static List<String> getVariablesSetAndUsed( - RelNode rel0, + public static List<CorrelationId> getVariablesSetAndUsed(RelNode rel0, RelNode rel1) { - Set<String> set = getVariablesSet(rel0); + Set<CorrelationId> set = getVariablesSet(rel0); if (set.size() == 0) { return ImmutableList.of(); } - Set<String> used = getVariablesUsed(rel1); + Set<CorrelationId> used = getVariablesUsed(rel1); if (used.size() == 0) { return ImmutableList.of(); } - final List<String> result = new ArrayList<>(); - for (String s : set) { + final List<CorrelationId> result = new ArrayList<>(); + for (CorrelationId s : set) { if (used.contains(s) && !result.contains(s)) { result.add(s); } @@ -187,24 +190,45 @@ public abstract class RelOptUtil { /** * Returns a set of variables used by a relational expression or its - * descendants. The set may contain duplicates. The item type is the same as - * {@link org.apache.calcite.rex.RexVariable#getName} - */ - public static Set<String> getVariablesUsed(RelNode rel) { - final VariableUsedVisitor vuv = new VariableUsedVisitor(); - RelShuttle visitor = new RelHomogeneousShuttle() { - @Override public RelNode visit(RelNode other) { - other.collectVariablesUsed(vuv.variables); - other.accept(vuv); - RelNode result = super.visit(other); - // Important! Remove stopped variables AFTER we visit - // children. (which what super.visit() does) - vuv.variables.removeAll(other.getVariablesStopped()); - return result; - } - }; + * descendants. + * + * <p>The set may contain "duplicates" (variables with different ids that, + * when resolved, will reference the same source relational expression). + * + * <p>The item type is the same as + * {@link org.apache.calcite.rex.RexCorrelVariable#id}. + */ + public static Set<CorrelationId> getVariablesUsed(RelNode rel) { + CorrelationCollector visitor = new CorrelationCollector(); rel.accept(visitor); - return vuv.variables; + return visitor.vuv.variables; + } + + /** Finds which columns of a correlation variable are used within a + * relational expression. */ + public static ImmutableBitSet correlationColumns(CorrelationId id, + RelNode rel) { + final CorrelationCollector collector = new CorrelationCollector(); + rel.accept(collector); + final ImmutableBitSet.Builder builder = ImmutableBitSet.builder(); + for (int field : collector.vuv.variableFields.get(id)) { + if (field >= 0) { + builder.set(field); + } + } + return builder.build(); + } + + /** Returns true, and calls {@link Litmus#succeed()} if a given relational + * expression does not contain a given correlation. */ + public static boolean notContainsCorrelation(RelNode r, + CorrelationId correlationId, Litmus litmus) { + final Set<CorrelationId> set = getVariablesUsed(r); + if (!set.contains(correlationId)) { + return litmus.succeed(); + } else { + return litmus.fail("contains " + correlationId); + } } /** @@ -2946,6 +2970,7 @@ public abstract class RelOptUtil { public Logic negate() { switch (this) { case UNKNOWN_AS_FALSE: + case TRUE: return UNKNOWN_AS_TRUE; case UNKNOWN_AS_TRUE: return UNKNOWN_AS_FALSE; @@ -2982,7 +3007,8 @@ public abstract class RelOptUtil { // Pushing sub-queries is OK in principle (if they don't reference both // sides of the join via correlating variables) but we'd rather not do it // yet. - if (!containsGet(joinCond)) { + if (!containsGet(joinCond) + && RexUtil.SubQueryFinder.find(joinCond) == null) { joinCond = pushDownEqualJoinConditions( joinCond, leftCount, rightCount, extraLeftExprs, extraRightExprs); } @@ -3177,7 +3203,7 @@ public abstract class RelOptUtil { /** Visitor that finds all variables used but not stopped in an expression. */ private static class VariableSetVisitor extends RelVisitor { - final Set<String> variables = new HashSet<>(); + final Set<CorrelationId> variables = new HashSet<>(); // implement RelVisitor public void visit( @@ -3189,18 +3215,42 @@ public abstract class RelOptUtil { // Important! Remove stopped variables AFTER we visit children // (which what super.visit() does) - variables.removeAll(p.getVariablesStopped()); + variables.removeAll(p.getVariablesSet()); } } /** Visitor that finds all variables used in an expression. */ public static class VariableUsedVisitor extends RexShuttle { - public final Set<String> variables = new LinkedHashSet<>(); + public final Set<CorrelationId> variables = new LinkedHashSet<>(); + public final Multimap<CorrelationId, Integer> variableFields = + LinkedHashMultimap.create(); + private final RelShuttle relShuttle; + + public VariableUsedVisitor(RelShuttle relShuttle) { + this.relShuttle = relShuttle; + } - public RexNode visitCorrelVariable(RexCorrelVariable p) { - variables.add(p.getName()); + @Override public RexNode visitCorrelVariable(RexCorrelVariable p) { + variables.add(p.id); + variableFields.put(p.id, -1); return p; } + + @Override public RexNode visitFieldAccess(RexFieldAccess fieldAccess) { + if (fieldAccess.getReferenceExpr() instanceof RexCorrelVariable) { + final RexCorrelVariable v = + (RexCorrelVariable) fieldAccess.getReferenceExpr(); + variableFields.put(v.id, fieldAccess.getField().getIndex()); + } + return super.visitFieldAccess(fieldAccess); + } + + @Override public RexNode visitSubQuery(RexSubQuery subQuery) { + if (relShuttle != null) { + subQuery.rel.accept(relShuttle); // look inside sub-queries + } + return super.visitSubQuery(subQuery); + } } /** Shuttle that finds the set of inputs that are used. */ @@ -3462,6 +3512,23 @@ public abstract class RelOptUtil { return BOTH; } } + + /** Shuttle that finds correlation variables inside a given relational + * expression, including those that are inside + * {@link RexSubQuery sub-queries}. */ + private static class CorrelationCollector extends RelHomogeneousShuttle { + private final VariableUsedVisitor vuv = new VariableUsedVisitor(this); + + @Override public RelNode visit(RelNode other) { + other.collectVariablesUsed(vuv.variables); + other.accept(vuv); + RelNode result = super.visit(other); + // Important! Remove stopped variables AFTER we visit + // children. (which what super.visit() does) + vuv.variables.removeAll(other.getVariablesSet()); + return result; + } + } } // End RelOptUtil.java http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java index 8dd0d01..ccbe2c2 100644 --- a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java +++ b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java @@ -24,6 +24,7 @@ import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.SingleRel; import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.AggregateCall; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.core.Join; import org.apache.calcite.rel.core.JoinRelType; @@ -249,7 +250,7 @@ public class SubstitutionVisitor { final MutableRel left = toMutable(join.getLeft()); final MutableRel right = toMutable(join.getRight()); return MutableJoin.of(join.getCluster(), left, right, - join.getCondition(), join.getJoinType(), join.getVariablesStopped()); + join.getCondition(), join.getJoinType(), join.getVariablesSet()); } if (rel instanceof Sort) { final Sort sort = (Sort) rel; @@ -646,7 +647,7 @@ public class SubstitutionVisitor { case JOIN: final MutableJoin join = (MutableJoin) node; return LogicalJoin.create(fromMutable(join.getLeft()), fromMutable(join.getRight()), - join.getCondition(), join.getJoinType(), join.getVariablesStopped()); + join.getCondition(), join.getVariablesSet(), join.getJoinType()); default: throw new AssertionError(node.deep()); } @@ -690,7 +691,7 @@ public class SubstitutionVisitor { final MutableJoin join = (MutableJoin) node; return MutableJoin.of(join.cluster, copyMutable(join.getLeft()), copyMutable(join.getRight()), join.getCondition(), join.getJoinType(), - join.getVariablesStopped()); + join.getVariablesSet()); default: throw new AssertionError(node.deep()); } @@ -1980,7 +1981,7 @@ public class SubstitutionVisitor { //~ Instance fields -------------------------------------------------------- protected final RexNode condition; - protected final ImmutableSet<String> variablesStopped; + protected final ImmutableSet<CorrelationId> variablesSet; /** * Values must be of enumeration {@link JoinRelType}, except that @@ -1994,10 +1995,10 @@ public class SubstitutionVisitor { MutableRel right, RexNode condition, JoinRelType joinType, - Set<String> variablesStopped) { + Set<CorrelationId> variablesSet) { super(MutableRelType.JOIN, left.cluster, rowType, left, right); this.condition = Preconditions.checkNotNull(condition); - this.variablesStopped = ImmutableSet.copyOf(variablesStopped); + this.variablesSet = ImmutableSet.copyOf(variablesSet); this.joinType = Preconditions.checkNotNull(joinType); } @@ -2009,13 +2010,13 @@ public class SubstitutionVisitor { return joinType; } - public ImmutableSet getVariablesStopped() { - return variablesStopped; + public ImmutableSet<CorrelationId> getVariablesSet() { + return variablesSet; } static MutableJoin of(RelOptCluster cluster, MutableRel left, MutableRel right, RexNode condition, JoinRelType joinType, - Set<String> variablesStopped) { + Set<CorrelationId> variablesStopped) { List<RelDataTypeField> fieldList = Collections.emptyList(); RelDataType rowType = Join.deriveJoinRowType(left.getRowType(), right.getRowType(), http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/plan/volcano/RelSet.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/plan/volcano/RelSet.java b/core/src/main/java/org/apache/calcite/plan/volcano/RelSet.java index 93d8509..cf78dff 100644 --- a/core/src/main/java/org/apache/calcite/plan/volcano/RelSet.java +++ b/core/src/main/java/org/apache/calcite/plan/volcano/RelSet.java @@ -22,6 +22,7 @@ import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.plan.RelTrait; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.util.trace.CalciteTrace; import com.google.common.collect.ImmutableList; @@ -47,21 +48,20 @@ class RelSet { //~ Instance fields -------------------------------------------------------- - final List<RelNode> rels = new ArrayList<RelNode>(); + final List<RelNode> rels = new ArrayList<>(); /** * Relational expressions that have a subset in this set as a child. This * is a multi-set. If multiple relational expressions in this set have the * same parent, there will be multiple entries. */ - final List<RelNode> parents = new ArrayList<RelNode>(); - final List<RelSubset> subsets = new ArrayList<RelSubset>(); + final List<RelNode> parents = new ArrayList<>(); + final List<RelSubset> subsets = new ArrayList<>(); /** * List of {@link AbstractConverter} objects which have not yet been * satisfied. */ - final List<AbstractConverter> abstractConverters = - new ArrayList<AbstractConverter>(); + final List<AbstractConverter> abstractConverters = new ArrayList<>(); /** * Set to the superseding set when this is found to be equivalent to another @@ -71,15 +71,15 @@ class RelSet { RelNode rel; /** - * Names of variables which are set by relational expressions in this set + * Variables that are set by relational expressions in this set * and available for use by parent and child expressions. */ - final Set<String> variablesPropagated; + final Set<CorrelationId> variablesPropagated; /** - * Names of variables which are used by relational expressions in this set. + * Variables that are used by relational expressions in this set. */ - final Set<String> variablesUsed; + final Set<CorrelationId> variablesUsed; final int id; /** @@ -91,8 +91,8 @@ class RelSet { RelSet( int id, - Set<String> variablesPropagated, - Set<String> variablesUsed) { + Set<CorrelationId> variablesPropagated, + Set<CorrelationId> variablesUsed) { this.id = id; this.variablesPropagated = variablesPropagated; this.variablesUsed = variablesUsed; @@ -275,7 +275,7 @@ class RelSet { } // Make sure the cost changes as a result of merging are propagated. - Set<RelSubset> activeSet = new HashSet<RelSubset>(); + Set<RelSubset> activeSet = new HashSet<>(); for (RelNode parentRel : getParentRels()) { final RelSubset parentSubset = planner.getSubset(parentRel); parentSubset.propagateCostImprovements( http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/plan/volcano/RelSubset.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/plan/volcano/RelSubset.java b/core/src/main/java/org/apache/calcite/plan/volcano/RelSubset.java index bb42218..3fede02 100644 --- a/core/src/main/java/org/apache/calcite/plan/volcano/RelSubset.java +++ b/core/src/main/java/org/apache/calcite/plan/volcano/RelSubset.java @@ -28,6 +28,7 @@ import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.AbstractRelNode; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelWriter; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.metadata.RelMetadataQuery; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.util.Litmus; @@ -136,14 +137,6 @@ public class RelSubset extends AbstractRelNode { } } - public Set<String> getVariablesSet() { - return set.variablesPropagated; - } - - public Set<String> getVariablesUsed() { - return set.variablesUsed; - } - public RelNode getBest() { return best; } @@ -164,7 +157,7 @@ public class RelSubset extends AbstractRelNode { } } - public void explain(RelWriter pw) { + @Override public void explain(RelWriter pw) { // Not a typical implementation of "explain". We don't gather terms & // values to be printed later. We actually do the work. String s = getDescription(); @@ -178,7 +171,7 @@ public class RelSubset extends AbstractRelNode { pw.done(input); } - protected String computeDigest() { + @Override protected String computeDigest() { StringBuilder digest = new StringBuilder("Subset#"); digest.append(set.id); for (RelTrait trait : traitSet) { @@ -276,13 +269,13 @@ public class RelSubset extends AbstractRelNode { "rowtype of set", getRowType(), Litmus.THROW); } set.addInternal(rel); - Set<String> variablesSet = RelOptUtil.getVariablesSet(rel); - Set<String> variablesStopped = rel.getVariablesStopped(); + Set<CorrelationId> variablesSet = RelOptUtil.getVariablesSet(rel); + Set<CorrelationId> variablesStopped = rel.getVariablesSet(); if (false) { - Set<String> variablesPropagated = + Set<CorrelationId> variablesPropagated = Util.minus(variablesSet, variablesStopped); assert set.variablesPropagated.containsAll(variablesPropagated); - Set<String> variablesUsed = RelOptUtil.getVariablesUsed(rel); + Set<CorrelationId> variablesUsed = RelOptUtil.getVariablesUsed(rel); assert set.variablesUsed.containsAll(variablesUsed); } } @@ -375,12 +368,12 @@ public class RelSubset extends AbstractRelNode { } } - public void collectVariablesUsed(Set<String> variableSet) { - variableSet.addAll(getVariablesUsed()); + @Override public void collectVariablesUsed(Set<CorrelationId> variableSet) { + variableSet.addAll(set.variablesUsed); } - public void collectVariablesSet(Set<String> variableSet) { - variableSet.addAll(getVariablesSet()); + @Override public void collectVariablesSet(Set<CorrelationId> variableSet) { + variableSet.addAll(set.variablesPropagated); } /** http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/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 4186232..425ebec 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 @@ -1759,7 +1759,7 @@ public class VolcanoPlanner extends AbstractRelOptPlanner { nextSetId++, Util.minus( RelOptUtil.getVariablesSet(rel), - rel.getVariablesStopped()), + rel.getVariablesSet()), RelOptUtil.getVariablesUsed(rel)); this.allSets.add(set); } http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/prepare/Prepare.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/prepare/Prepare.java b/core/src/main/java/org/apache/calcite/prepare/Prepare.java index 3530e93..e624d1d 100644 --- a/core/src/main/java/org/apache/calcite/prepare/Prepare.java +++ b/core/src/main/java/org/apache/calcite/prepare/Prepare.java @@ -87,9 +87,13 @@ public abstract class Prepare { public static final TryThreadLocal<Boolean> THREAD_TRIM = TryThreadLocal.of(false); - /** Temporary, while CALCITE-816 is under development. + /** Temporary, until + * <a href="https://issues.apache.org/jira/browse/CALCITE-1045">[CALCITE-1045] + * Decorrelate sub-queries in Project and Join</a> is fixed. * - * @see org.apache.calcite.util.Util#deprecated(Object, boolean) */ + * <p>The default is false, meaning do not expand queries during sql-to-rel, + * but a few tests override and set it to true. After CALCITE-1045 + * is fixed, remove those overrides and use false everywhere. */ public static final TryThreadLocal<Boolean> THREAD_EXPAND = TryThreadLocal.of(false); @@ -209,6 +213,7 @@ public abstract class Prepare { SqlToRelConverter sqlToRelConverter = getSqlToRelConverter(validator, catalogReader); + sqlToRelConverter.setExpand(THREAD_EXPAND.get()); SqlExplain sqlExplain = null; if (sqlQuery.getKind() == SqlKind.EXPLAIN) { @@ -344,6 +349,7 @@ public abstract class Prepare { getSqlToRelConverter( getSqlValidator(), catalogReader); converter.setTrimUnusedFields(shouldTrim(root.rel)); + converter.setExpand(THREAD_EXPAND.get()); final boolean ordered = !root.collation.getFieldCollations().isEmpty(); final boolean dml = SqlKind.DML.contains(root.kind); return root.withRel(converter.trimUnusedFields(dml || ordered, root.rel)); http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java b/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java index 1938447..75a546c 100644 --- a/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java +++ b/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java @@ -26,6 +26,7 @@ import org.apache.calcite.plan.RelOptTable; import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.plan.RelTrait; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.externalize.RelWriterImpl; import org.apache.calcite.rel.metadata.Metadata; import org.apache.calcite.rel.metadata.RelMetadataQuery; @@ -40,6 +41,7 @@ import org.apache.calcite.util.Util; import org.apache.calcite.util.trace.CalciteTrace; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import java.io.PrintWriter; import java.io.StringWriter; @@ -237,15 +239,19 @@ public abstract class AbstractRelNode implements RelNode { return 1.0; } - public Set<String> getVariablesStopped() { - return Collections.emptySet(); + public final Set<String> getVariablesStopped() { + return CorrelationId.names(getVariablesSet()); } - public void collectVariablesUsed(Set<String> variableSet) { + public Set<CorrelationId> getVariablesSet() { + return ImmutableSet.of(); + } + + public void collectVariablesUsed(Set<CorrelationId> variableSet) { // for default case, nothing to do } - public void collectVariablesSet(Set<String> variableSet) { + public void collectVariablesSet(Set<CorrelationId> variableSet) { } public void childrenAccept(RelVisitor visitor) { @@ -305,7 +311,7 @@ public abstract class AbstractRelNode implements RelNode { public RelNode onRegister(RelOptPlanner planner) { List<RelNode> oldInputs = getInputs(); - List<RelNode> inputs = new ArrayList<RelNode>(oldInputs.size()); + List<RelNode> inputs = new ArrayList<>(oldInputs.size()); for (final RelNode input : oldInputs) { RelNode e = planner.ensureRegistered(input, null); if (e != input) { http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/RelNode.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/RelNode.java b/core/src/main/java/org/apache/calcite/rel/RelNode.java index 29dc023..973bc98 100644 --- a/core/src/main/java/org/apache/calcite/rel/RelNode.java +++ b/core/src/main/java/org/apache/calcite/rel/RelNode.java @@ -23,6 +23,7 @@ import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelOptQuery; import org.apache.calcite.plan.RelOptTable; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.metadata.Metadata; import org.apache.calcite.rel.metadata.RelMetadataQuery; import org.apache.calcite.rel.type.RelDataType; @@ -175,18 +176,40 @@ public interface RelNode extends RelOptNode, Cloneable { double getRows(); /** - * Returns the names of variables which are set in this relational + * Returns the names of variables that are set in this relational * expression but also used and therefore not available to parents of this * relational expression. + * * <p>Note: only {@link org.apache.calcite.rel.core.Correlate} should set - * variables</p> + * variables. + * + * <p>Note: {@link #getVariablesSet()} is equivalent but returns + * {@link CorrelationId} rather than their names. It is preferable except for + * calling old methods that require a set of strings. * * @return Names of variables which are set in this relational * expression + * + * @deprecated Use {@link #getVariablesSet()} + * and {@link CorrelationId#names(Set)} */ + @Deprecated // to be removed before 2.0 Set<String> getVariablesStopped(); /** + * Returns the variables that are set in this relational + * expression but also used and therefore not available to parents of this + * relational expression. + * + * <p>Note: only {@link org.apache.calcite.rel.core.Correlate} should set + * variables. + * + * @return Names of variables which are set in this relational + * expression + */ + Set<CorrelationId> getVariablesSet(); + + /** * Collects variables known to be used by this expression or its * descendants. By default, no such information is available and must be * derived by analyzing sub-expressions, but some optimizer implementations @@ -194,7 +217,7 @@ public interface RelNode extends RelOptNode, Cloneable { * * @param variableSet receives variables used */ - void collectVariablesUsed(Set<String> variableSet); + void collectVariablesUsed(Set<CorrelationId> variableSet); /** * Collects variables set by this expression. @@ -202,7 +225,7 @@ public interface RelNode extends RelOptNode, Cloneable { * * @param variableSet receives variables known to be set by */ - void collectVariablesSet(Set<String> variableSet); + void collectVariablesSet(Set<CorrelationId> variableSet); /** * Interacts with the {@link RelVisitor} in a http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/core/Correlate.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/core/Correlate.java b/core/src/main/java/org/apache/calcite/rel/core/Correlate.java index b1c0e04..982a762 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/Correlate.java +++ b/core/src/main/java/org/apache/calcite/rel/core/Correlate.java @@ -19,6 +19,7 @@ package org.apache.calcite.rel.core; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptPlanner; +import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.BiRel; import org.apache.calcite.rel.RelInput; @@ -29,6 +30,7 @@ import org.apache.calcite.rel.metadata.RelMetadataQuery; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.sql.SemiJoinType; import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.Litmus; import com.google.common.collect.ImmutableSet; @@ -109,6 +111,11 @@ public abstract class Correlate extends BiRel { //~ Methods ---------------------------------------------------------------- + @Override public boolean isValid(Litmus litmus) { + return super.isValid(litmus) + && RelOptUtil.notContainsCorrelation(left, correlationId, litmus); + } + @Override public Correlate copy(RelTraitSet traitSet, List<RelNode> inputs) { assert inputs.size() == 2; return copy(traitSet, @@ -133,8 +140,8 @@ public abstract class Correlate extends BiRel { case INNER: // LogicalJoin is used to share the code of column names deduplication final LogicalJoin join = LogicalJoin.create(left, right, - getCluster().getRexBuilder().makeLiteral(true), joinType.toJoinType(), - ImmutableSet.<String>of()); + getCluster().getRexBuilder().makeLiteral(true), + ImmutableSet.<CorrelationId>of(), joinType.toJoinType()); return join.deriveRowType(); case ANTI: case SEMI: @@ -174,8 +181,8 @@ public abstract class Correlate extends BiRel { return requiredColumns; } - @Override public Set<String> getVariablesStopped() { - return ImmutableSet.of(correlationId.getName()); + @Override public Set<CorrelationId> getVariablesSet() { + return ImmutableSet.of(correlationId); } @Override public RelOptCost computeSelfCost(RelOptPlanner planner) { http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/core/CorrelationId.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/core/CorrelationId.java b/core/src/main/java/org/apache/calcite/rel/core/CorrelationId.java index 2b2558c..d5d74c9 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/CorrelationId.java +++ b/core/src/main/java/org/apache/calcite/rel/core/CorrelationId.java @@ -16,39 +16,51 @@ */ package org.apache.calcite.rel.core; +import com.google.common.collect.ImmutableSet; + +import java.util.Set; + /** * Describes the necessary parameters for an implementation in order to * identify and set dynamic variables */ public class CorrelationId implements Cloneable, Comparable<CorrelationId> { - private static final String CORREL_PREFIX = "$cor"; + /** + * Prefix to the name of correlating variables. + */ + public static final String CORREL_PREFIX = "$cor"; private final int id; private final String name; /** * Creates a correlation identifier. + */ + private CorrelationId(int id, String name) { + this.id = id; + this.name = name; + } + + /** + * Creates a correlation identifier. * This is a type-safe wrapper over int. * * @param id Identifier */ public CorrelationId(int id) { - this.id = id; - this.name = CORREL_PREFIX + id; + this(id, CORREL_PREFIX + id); } /** - * Creates a correlation identifier. - * This is a type-safe wrapper over int. + * Creates a correlation identifier from a name. * * @param name variable name */ public CorrelationId(String name) { - assert name != null && name.startsWith(CORREL_PREFIX) + this(Integer.parseInt(name.substring(CORREL_PREFIX.length())), name); + assert name.startsWith(CORREL_PREFIX) : "Correlation name should start with " + CORREL_PREFIX + " actual name is " + name; - this.id = Integer.parseInt(name.substring(CORREL_PREFIX.length())); - this.name = name; } /** @@ -61,7 +73,7 @@ public class CorrelationId implements Cloneable, Comparable<CorrelationId> { } /** - * Returns the preffered name of the variable. + * Returns the preferred name of the variable. * * @return name */ @@ -86,6 +98,30 @@ public class CorrelationId implements Cloneable, Comparable<CorrelationId> { || obj instanceof CorrelationId && this.id == ((CorrelationId) obj).id; } + + /** Converts a set of correlation ids to a set of names. */ + public static ImmutableSet<CorrelationId> setOf(Set<String> set) { + if (set.isEmpty()) { + return ImmutableSet.of(); + } + final ImmutableSet.Builder<CorrelationId> builder = ImmutableSet.builder(); + for (String s : set) { + builder.add(new CorrelationId(s)); + } + return builder.build(); + } + + /** Converts a set of names to a set of correlation ids. */ + public static Set<String> names(Set<CorrelationId> set) { + if (set.isEmpty()) { + return ImmutableSet.of(); + } + final ImmutableSet.Builder<String> builder = ImmutableSet.builder(); + for (CorrelationId s : set) { + builder.add(s.name); + } + return builder.build(); + } } // End CorrelationId.java http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/core/EquiJoin.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 3a06c86..a45a854 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 @@ -36,13 +36,22 @@ public abstract class EquiJoin extends Join { /** Creates an EquiJoin. */ public EquiJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition, ImmutableIntList leftKeys, - ImmutableIntList rightKeys, JoinRelType joinType, - Set<String> variablesStopped) { - super(cluster, traits, left, right, condition, joinType, variablesStopped); + ImmutableIntList rightKeys, Set<CorrelationId> variablesSet, + JoinRelType joinType) { + super(cluster, traits, left, right, condition, variablesSet, joinType); this.leftKeys = Preconditions.checkNotNull(leftKeys); this.rightKeys = Preconditions.checkNotNull(rightKeys); } + @Deprecated // to be removed before 2.0 + public EquiJoin(RelOptCluster cluster, RelTraitSet traits, RelNode left, + RelNode right, RexNode condition, ImmutableIntList leftKeys, + ImmutableIntList rightKeys, JoinRelType joinType, + Set<String> variablesStopped) { + this(cluster, traits, left, right, condition, leftKeys, rightKeys, + CorrelationId.setOf(variablesStopped), joinType); + } + public ImmutableIntList getLeftKeys() { return leftKeys; } http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/core/Join.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/core/Join.java b/core/src/main/java/org/apache/calcite/rel/core/Join.java index bb460ff..3ac32d2 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/Join.java +++ b/core/src/main/java/org/apache/calcite/rel/core/Join.java @@ -35,6 +35,7 @@ import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.Litmus; import org.apache.calcite.util.Util; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -56,43 +57,67 @@ public abstract class Join extends BiRel { //~ Instance fields -------------------------------------------------------- protected final RexNode condition; - protected final ImmutableSet<String> variablesStopped; + protected final ImmutableSet<CorrelationId> variablesSet; /** * Values must be of enumeration {@link JoinRelType}, except that * {@link JoinRelType#RIGHT} is disallowed. */ - protected JoinRelType joinType; + protected final JoinRelType joinType; //~ Constructors ----------------------------------------------------------- + // Next time we need to change the constructor of Join, let's change the + // "Set<String> variablesStopped" parameter to + // "Set<CorrelationId> variablesSet". At that point we would deprecate + // RelNode.getVariablesStopped(). + /** * Creates a Join. * + * <p>Note: We plan to change the {@code variablesStopped} parameter to + * {@code Set<CorrelationId> variablesSet} + * {@link org.apache.calcite.util.Bug#upgrade(String) before version 2.0}, + * because {@link #getVariablesSet()} + * is preferred over {@link #getVariablesStopped()}. + * This constructor is not deprecated, for now, because maintaining overloaded + * constructors in multiple sub-classes would be onerous. + * * @param cluster Cluster - * @param traits Traits + * @param traitSet Trait set * @param left Left input * @param right Right input * @param condition Join condition * @param joinType Join type - * @param variablesStopped Set of names of variables which are set by the + * @param variablesSet Set variables that are set by the * LHS and used by the RHS and are not available to - * nodes above this LogicalJoin in the tree + * nodes above this Join in the tree */ protected Join( RelOptCluster cluster, - RelTraitSet traits, + RelTraitSet traitSet, + RelNode left, + RelNode right, + RexNode condition, + Set<CorrelationId> variablesSet, + JoinRelType joinType) { + super(cluster, traitSet, left, right); + this.condition = Preconditions.checkNotNull(condition); + this.variablesSet = ImmutableSet.copyOf(variablesSet); + this.joinType = Preconditions.checkNotNull(joinType); + } + + @Deprecated // to be removed before 2.0 + protected Join( + RelOptCluster cluster, + RelTraitSet traitSet, RelNode left, RelNode right, RexNode condition, JoinRelType joinType, Set<String> variablesStopped) { - super(cluster, traits, left, right); - this.condition = condition; - this.variablesStopped = ImmutableSet.copyOf(variablesStopped); - assert joinType != null; - assert condition != null; - this.joinType = joinType; + this(cluster, traitSet, left, right, condition, + CorrelationId.setOf(variablesStopped), joinType); } //~ Methods ---------------------------------------------------------------- @@ -172,8 +197,8 @@ public abstract class Join extends BiRel { return Util.first(RelMdUtil.getJoinRowCount(this, condition), 1D); } - @Override public Set<String> getVariablesStopped() { - return variablesStopped; + @Override public Set<CorrelationId> getVariablesSet() { + return variablesSet; } @Override public RelWriter explainTerms(RelWriter pw) { http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java b/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java index d58150b..6c410b9 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java +++ b/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java @@ -24,6 +24,7 @@ import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.logical.LogicalAggregate; +import org.apache.calcite.rel.logical.LogicalCorrelate; import org.apache.calcite.rel.logical.LogicalFilter; import org.apache.calcite.rel.logical.LogicalIntersect; import org.apache.calcite.rel.logical.LogicalJoin; @@ -37,6 +38,7 @@ import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeField; import org.apache.calcite.rex.RexLiteral; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.SemiJoinType; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.tools.RelBuilderFactory; @@ -60,6 +62,9 @@ public class RelFactories { public static final JoinFactory DEFAULT_JOIN_FACTORY = new JoinFactoryImpl(); + public static final CorrelateFactory DEFAULT_CORRELATE_FACTORY = + new CorrelateFactoryImpl(); + public static final SemiJoinFactory DEFAULT_SEMI_JOIN_FACTORY = new SemiJoinFactoryImpl(); @@ -234,14 +239,19 @@ public class RelFactories { * @param left Left input * @param right Right input * @param condition Join condition - * @param joinType Join type - * @param variablesStopped Set of names of variables which are set by the + * @param variablesSet Set of variables that are set by the * LHS and used by the RHS and are not available to * nodes above this LogicalJoin in the tree + * @param joinType Join type * @param semiJoinDone Whether this join has been translated to a * semi-join */ RelNode createJoin(RelNode left, RelNode right, RexNode condition, + Set<CorrelationId> variablesSet, JoinRelType joinType, + boolean semiJoinDone); + + @Deprecated // to be removed before 2.0 + RelNode createJoin(RelNode left, RelNode right, RexNode condition, JoinRelType joinType, Set<String> variablesStopped, boolean semiJoinDone); } @@ -252,10 +262,51 @@ public class RelFactories { */ private static class JoinFactoryImpl implements JoinFactory { public RelNode createJoin(RelNode left, RelNode right, - RexNode condition, JoinRelType joinType, - Set<String> variablesStopped, boolean semiJoinDone) { - return LogicalJoin.create(left, right, condition, joinType, - variablesStopped, semiJoinDone, ImmutableList.<RelDataTypeField>of()); + RexNode condition, Set<CorrelationId> variablesSet, + JoinRelType joinType, boolean semiJoinDone) { + return LogicalJoin.create(left, right, condition, variablesSet, joinType, + semiJoinDone, ImmutableList.<RelDataTypeField>of()); + } + + public RelNode createJoin(RelNode left, RelNode right, RexNode condition, + JoinRelType joinType, Set<String> variablesStopped, + boolean semiJoinDone) { + return createJoin(left, right, condition, + CorrelationId.setOf(variablesStopped), joinType, semiJoinDone); + } + } + + /** + * Can create a correlate of the appropriate type for a rule's calling + * convention. + * + * <p>The result is typically a {@link Correlate}. + */ + public interface CorrelateFactory { + /** + * Creates a correlate. + * + * @param left Left input + * @param right Right input + * @param correlationId Variable name for the row of left input + * @param requiredColumns Required columns + * @param joinType Join type + */ + RelNode createCorrelate(RelNode left, RelNode right, + CorrelationId correlationId, ImmutableBitSet requiredColumns, + SemiJoinType joinType); + } + + /** + * Implementation of {@link CorrelateFactory} that returns a vanilla + * {@link org.apache.calcite.rel.logical.LogicalCorrelate}. + */ + private static class CorrelateFactoryImpl implements CorrelateFactory { + public RelNode createCorrelate(RelNode left, RelNode right, + CorrelationId correlationId, ImmutableBitSet requiredColumns, + SemiJoinType joinType) { + return LogicalCorrelate.create(left, right, correlationId, + requiredColumns, joinType); } } http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java b/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java index 4570919..6db45f1 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java +++ b/core/src/main/java/org/apache/calcite/rel/core/SemiJoin.java @@ -71,8 +71,8 @@ public class SemiJoin extends EquiJoin { condition, leftKeys, rightKeys, - JoinRelType.INNER, - ImmutableSet.<String>of()); + ImmutableSet.<CorrelationId>of(), + JoinRelType.INNER); } /** Creates a SemiJoin. */ http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java b/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java index a4da2d4..92324ba 100644 --- a/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java +++ b/core/src/main/java/org/apache/calcite/rel/externalize/RelJson.java @@ -397,7 +397,7 @@ public class RelJson { if (correl != null) { final Object jsonType = map.get("type"); RelDataType type = toType(cluster.getTypeFactory(), jsonType); - return rexBuilder.makeCorrel(type, correl); + return rexBuilder.makeCorrel(type, new CorrelationId(correl)); } if (map.containsKey("literal")) { final Object literal = map.get("literal"); http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java index 3fb2123..3ca1645 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalCalc.java @@ -26,6 +26,7 @@ import org.apache.calcite.rel.RelDistribution; import org.apache.calcite.rel.RelDistributionTraitDef; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.Calc; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.metadata.RelMdCollation; import org.apache.calcite.rel.metadata.RelMdDistribution; import org.apache.calcite.rel.rules.FilterToCalcRule; @@ -113,9 +114,9 @@ public final class LogicalCalc extends Calc { return new LogicalCalc(getCluster(), traitSet, child, program); } - @Override public void collectVariablesUsed(Set<String> variableSet) { + @Override public void collectVariablesUsed(Set<CorrelationId> variableSet) { final RelOptUtil.VariableUsedVisitor vuv = - new RelOptUtil.VariableUsedVisitor(); + new RelOptUtil.VariableUsedVisitor(null); for (RexNode expr : program.getExprList()) { expr.accept(vuv); } http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java index fd403e0..c0c69d4 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java @@ -19,6 +19,7 @@ package org.apache.calcite.rel.logical; import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.prepare.CalcitePrepareImpl; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; @@ -26,6 +27,7 @@ import org.apache.calcite.rel.core.Correlate; import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.sql.SemiJoinType; import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.Litmus; /** * A relational operator that performs nested-loop joins. @@ -69,6 +71,7 @@ public final class LogicalCorrelate extends Correlate { correlationId, requiredColumns, joinType); + assert !CalcitePrepareImpl.DEBUG || isValid(Litmus.THROW); } @Deprecated // to be removed before 2.0 http://git-wip-us.apache.org/repos/asf/calcite/blob/505a9064/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java index 79b0b1d..d25874e 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java @@ -26,20 +26,27 @@ import org.apache.calcite.rel.RelDistributionTraitDef; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; +import org.apache.calcite.rel.RelWriter; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.metadata.RelMdCollation; import org.apache.calcite.rel.metadata.RelMdDistribution; import org.apache.calcite.rex.RexNode; +import com.google.common.base.Preconditions; import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableSet; import java.util.List; +import java.util.Set; /** * Sub-class of {@link org.apache.calcite.rel.core.Filter} * not targeted at any particular engine or calling convention. */ public final class LogicalFilter extends Filter { + private final ImmutableSet<CorrelationId> variablesSet; + //~ Constructors ----------------------------------------------------------- /** @@ -51,21 +58,35 @@ public final class LogicalFilter extends Filter { * @param child Input relational expression * @param condition Boolean expression which determines whether a row is * allowed to pass + * @param variablesSet Correlation variables set by this relational expression + * to be used by nested expressions */ public LogicalFilter( RelOptCluster cluster, RelTraitSet traitSet, RelNode child, - RexNode condition) { + RexNode condition, + ImmutableSet<CorrelationId> variablesSet) { super(cluster, traitSet, child, condition); + this.variablesSet = Preconditions.checkNotNull(variablesSet); } @Deprecated // to be removed before 2.0 public LogicalFilter( RelOptCluster cluster, + RelTraitSet traitSet, RelNode child, RexNode condition) { - this(cluster, cluster.traitSetOf(Convention.NONE), child, condition); + this(cluster, traitSet, child, condition, ImmutableSet.<CorrelationId>of()); + } + + @Deprecated // to be removed before 2.0 + public LogicalFilter( + RelOptCluster cluster, + RelNode child, + RexNode condition) { + this(cluster, cluster.traitSetOf(Convention.NONE), child, condition, + ImmutableSet.<CorrelationId>of()); } /** @@ -73,10 +94,17 @@ public final class LogicalFilter extends Filter { */ public LogicalFilter(RelInput input) { super(input); + this.variablesSet = ImmutableSet.of(); } /** Creates a LogicalFilter. */ public static LogicalFilter create(final RelNode input, RexNode condition) { + return create(input, condition, ImmutableSet.<CorrelationId>of()); + } + + /** Creates a LogicalFilter. */ + public static LogicalFilter create(final RelNode input, RexNode condition, + ImmutableSet<CorrelationId> variablesSet) { final RelOptCluster cluster = input.getCluster(); final RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE) .replaceIfs(RelCollationTraitDef.INSTANCE, @@ -91,20 +119,30 @@ public final class LogicalFilter extends Filter { return RelMdDistribution.filter(input); } }); - return new LogicalFilter(cluster, traitSet, input, condition); + return new LogicalFilter(cluster, traitSet, input, condition, variablesSet); } //~ Methods ---------------------------------------------------------------- + @Override public Set<CorrelationId> getVariablesSet() { + return variablesSet; + } + public LogicalFilter copy(RelTraitSet traitSet, RelNode input, RexNode condition) { assert traitSet.containsIfApplicable(Convention.NONE); - return new LogicalFilter(getCluster(), traitSet, input, condition); + return new LogicalFilter(getCluster(), traitSet, input, condition, + variablesSet); } @Override public RelNode accept(RelShuttle shuttle) { return shuttle.visit(this); } + + @Override public RelWriter explainTerms(RelWriter pw) { + return super.explainTerms(pw) + .itemIf("variablesSet", variablesSet, !variablesSet.isEmpty()); + } } // End LogicalFilter.java
