diff --git a/cassandra/src/test/java/org/apache/calcite/test/CassandraAdapterTest.java b/cassandra/src/test/java/org/apache/calcite/test/CassandraAdapterTest.java index 871b25d00250..8747e07e5bb5 100644 --- a/cassandra/src/test/java/org/apache/calcite/test/CassandraAdapterTest.java +++ b/cassandra/src/test/java/org/apache/calcite/test/CassandraAdapterTest.java @@ -100,8 +100,8 @@ static void load(Session session) { .returns("tweet_id=f3c329de-d05b-11e5-b58b-90e2ba530b12\n" + "tweet_id=f3dbb03a-d05b-11e5-b58b-90e2ba530b12\n") .explainContains("PLAN=CassandraToEnumerableConverter\n" - + " CassandraLimit(fetch=[2])\n" - + " CassandraProject(tweet_id=[$2])\n" + + " CassandraProject(tweet_id=[$2])\n" + + " CassandraLimit(fetch=[2])\n" + " CassandraFilter(condition=[=($0, '!PUBLIC!')])\n"); } diff --git a/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java b/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java index cf350b630c42..cbc6d3366bf4 100644 --- a/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java +++ b/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java @@ -225,6 +225,10 @@ public long getRelMetadataTimestamp(RelNode rel) { @Override public void prune(RelNode rel) { } + @Override public boolean isPruned(RelNode rel) { + return false; + } + public void registerClass(RelNode node) { final Class clazz = node.getClass(); if (classes.add(clazz)) { diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptPlanner.java b/core/src/main/java/org/apache/calcite/plan/RelOptPlanner.java index e2117b528ad8..ef22fef2f21c 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptPlanner.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptPlanner.java @@ -306,6 +306,13 @@ RelNode register( */ void prune(RelNode rel); + /** + * Check whether or not a RelNode is pruned + * @param rel the node to check + * @return true if rel is pruned, false if otherwise + */ + boolean isPruned(RelNode rel); + /** * Registers a class of RelNode. If this class of RelNode has been seen * before, does nothing. 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 09e6f3712d44..f7271d47be1d 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 @@ -23,6 +23,7 @@ import org.apache.calcite.plan.RelTrait; import org.apache.calcite.plan.RelTraitDef; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.PhysicalNode; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.convert.Converter; @@ -73,7 +74,14 @@ class RelSet { * set. */ RelSet equivalentSet; - RelNode rel; + + /** + * The first RelNode added to the set or the RelNode with highest confidence + * level of estimated statistics. + * The logical properties of the RelSet, including row count, uniqueness, etc, + * are determined by this RelNode. + */ + RelNode originalRel; /** * The position indicator of rel node that is to be processed. @@ -211,6 +219,7 @@ public RelSubset add(RelNode rel) { final RelSubset subset = getOrCreateSubset( rel.getCluster(), traitSet, rel.isEnforcer()); subset.add(rel); + checkAndUpdateOriginalRel(rel); return subset; } @@ -350,15 +359,16 @@ void addInternal(RelNode rel) { postEquivalenceEvent(planner, rel); } } - if (this.rel == null) { - this.rel = rel; + if (this.originalRel == null) { + this.originalRel = rel; } else { // Row types must be the same, except for field names. RelOptUtil.verifyTypeEquivalence( - this.rel, + this.originalRel, rel, this); } + checkAndUpdateOriginalRel(rel); } /** @@ -383,7 +393,7 @@ void mergeWith( assert otherSet.equivalentSet == null; LOGGER.trace("Merge set#{} into set#{}", otherSet.id, id); otherSet.equivalentSet = this; - RelOptCluster cluster = rel.getCluster(); + RelOptCluster cluster = originalRel.getCluster(); RelMetadataQuery mq = cluster.getMetadataQuery(); // remove from table @@ -486,4 +496,50 @@ void mergeWith( planner.fireRules(subset); } } + + private void checkAndUpdateOriginalRel(RelNode newRel) { + if (newRel instanceof LogicalNode && this.originalRel instanceof LogicalNode + && ((LogicalNode) newRel).getStatsEstimateConfidence().compareTo( + ((LogicalNode) this.originalRel).getStatsEstimateConfidence()) > 0) { + this.originalRel = newRel; + + // Invalidate parent sets original rel meta cache since child set properties might + // have been changed. + HashSet newParentSets = getParentSets(); + HashSet allParentSets = new HashSet<>(); + while (!newParentSets.isEmpty()) { + allParentSets.addAll(newParentSets); + HashSet validParents = new HashSet<>(); + for (RelSet set : newParentSets) { + HashSet parents = set.getParentSets(); + for (RelSet s : parents) { + // To handle cycle references between sets + if (!allParentSets.contains(s)) { + validParents.add(s); + } + } + } + newParentSets = validParents; + } + for (RelSet set : allParentSets) { + final RelMetadataQuery mq = set.originalRel.getCluster().getMetadataQuery(); + mq.clearCache(set.originalRel); + } + } + } + + private HashSet getParentSets() { + HashSet results = new HashSet<>(); + VolcanoPlanner planner = (VolcanoPlanner) this.originalRel.getCluster().getPlanner(); + assert planner != null; + + for (RelNode rel : getParentRels()) { + RelSet set = planner.getSet(rel); + if (set.id != this.id && !planner.isPruned(rel)) { + results.add(set); + } + } + + return results; + } } 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 8b0a78a82e8e..5e766556ed05 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 @@ -185,7 +185,7 @@ public RelNode getBest() { } public RelNode getOriginal() { - return set.rel; + return set.originalRel; } public RelNode copy(RelTraitSet traitSet, List inputs) { @@ -207,7 +207,7 @@ public double estimateRowCount(RelMetadataQuery mq) { if (best != null) { return mq.getRowCount(best); } else { - return mq.getRowCount(set.rel); + return mq.getRowCount(set.originalRel); } } @@ -234,7 +234,7 @@ public double estimateRowCount(RelMetadataQuery mq) { } @Override protected RelDataType deriveRowType() { - return set.rel.getRowType(); + return set.originalRel.getRowType(); } /** @@ -318,7 +318,7 @@ void add(RelNode rel) { // If this isn't the first rel in the set, it must have compatible // row type. - if (set.rel != null) { + if (set.originalRel != null) { RelOptUtil.equal("rowtype of new rel", rel.getRowType(), "rowtype of set", getRowType(), Litmus.THROW); } 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 8374f1b9fdf2..7f606ec7d8af 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 @@ -848,6 +848,10 @@ RelNode changeTraitsUsingConverters( prunedNodes.add(rel); } + @Override public boolean isPruned(RelNode rel) { + return prunedNodes.contains(rel); + } + /** * Dumps the internal state of this VolcanoPlanner to a writer. * diff --git a/core/src/main/java/org/apache/calcite/rel/LogicalNode.java b/core/src/main/java/org/apache/calcite/rel/LogicalNode.java new file mode 100644 index 000000000000..98e8173b5e27 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/rel/LogicalNode.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.calcite.rel; + +/** + * Represents a logical node in Calcite + */ +public interface LogicalNode extends RelNode { + + /** + * Confidence levels of statistics estimation + */ + enum StatsEstimateConfidenceLevel { + None, + Low, + Medium, + High + } + + /** + * Get confidence level of statistics estimation + * @return Confidence level of statistics estimation + */ + default StatsEstimateConfidenceLevel getStatsEstimateConfidence() { + return StatsEstimateConfidenceLevel.Medium; + } +} diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java index 115e423abdd9..871b5bafb016 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalAggregate.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; @@ -43,7 +44,7 @@ *
  • {@link org.apache.calcite.rel.rules.AggregateReduceFunctionsRule}. * */ -public final class LogicalAggregate extends Aggregate { +public final class LogicalAggregate extends Aggregate implements LogicalNode { //~ Constructors ----------------------------------------------------------- /** 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 8e5d2acd76f3..e396588a8dcf 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 @@ -20,6 +20,7 @@ import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelDistributionTraitDef; @@ -63,7 +64,7 @@ * merges two {@code LogicalCalc}s * */ -public final class LogicalCalc extends Calc { +public final class LogicalCalc extends Calc implements LogicalNode { //~ Static fields/initializers --------------------------------------------- //~ Constructors ----------------------------------------------------------- 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 031de6483f89..0c0cfa0260aa 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 @@ -20,6 +20,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; @@ -41,7 +42,7 @@ * * @see org.apache.calcite.rel.core.CorrelationId */ -public final class LogicalCorrelate extends Correlate { +public final class LogicalCorrelate extends Correlate implements LogicalNode { //~ Instance fields -------------------------------------------------------- //~ Constructors ----------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalExchange.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalExchange.java index 8c8f12aeb519..f492363da874 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalExchange.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalExchange.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelDistribution; import org.apache.calcite.rel.RelDistributionTraitDef; import org.apache.calcite.rel.RelInput; @@ -30,7 +31,7 @@ * Sub-class of {@link Exchange} not * targeted at any particular engine or calling convention. */ -public final class LogicalExchange extends Exchange { +public final class LogicalExchange extends Exchange implements LogicalNode { private LogicalExchange(RelOptCluster cluster, RelTraitSet traitSet, RelNode input, RelDistribution distribution) { super(cluster, traitSet, input, distribution); 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 8995241a9d3b..d67c5b195a19 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 @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelDistributionTraitDef; import org.apache.calcite.rel.RelInput; @@ -42,7 +43,8 @@ * 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 { +public final class LogicalFilter extends Filter implements LogicalNode { + private final ImmutableSet variablesSet; //~ Constructors ----------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalIntersect.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalIntersect.java index 99ecf659df36..5a036750fd29 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalIntersect.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalIntersect.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; @@ -30,7 +31,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.Intersect} * not targeted at any particular engine or calling convention. */ -public final class LogicalIntersect extends Intersect { +public final class LogicalIntersect extends Intersect implements LogicalNode { //~ Constructors ----------------------------------------------------------- /** diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalJoin.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalJoin.java index 4b55785faf3b..d1869dce9c11 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalJoin.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalJoin.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; @@ -54,7 +55,7 @@ * * */ -public final class LogicalJoin extends Join { +public final class LogicalJoin extends Join implements LogicalNode { //~ Instance fields -------------------------------------------------------- // NOTE jvs 14-Mar-2006: Normally we don't use state like this diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalMatch.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalMatch.java index 8f370da29228..e5be70eaa93f 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalMatch.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalMatch.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; @@ -35,7 +36,7 @@ * Sub-class of {@link Match} * not targeted at any particular engine or calling convention. */ -public class LogicalMatch extends Match { +public class LogicalMatch extends Match implements LogicalNode { /** * Creates a LogicalMatch. diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalMinus.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalMinus.java index 357c403510cf..80cd24b2afc4 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalMinus.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalMinus.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; @@ -30,7 +31,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.Minus} * not targeted at any particular engine or calling convention. */ -public final class LogicalMinus extends Minus { +public final class LogicalMinus extends Minus implements LogicalNode { //~ Constructors ----------------------------------------------------------- /** diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java index 2696dba2ab9b..8a81ee77736b 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalProject.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelCollations; import org.apache.calcite.rel.RelInput; @@ -42,7 +43,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.Project} not * targeted at any particular engine or calling convention. */ -public final class LogicalProject extends Project { +public final class LogicalProject extends Project implements LogicalNode { //~ Constructors ----------------------------------------------------------- /** diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalRepeatUnion.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalRepeatUnion.java index 50841767b665..6452820f3a03 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalRepeatUnion.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalRepeatUnion.java @@ -20,6 +20,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.RepeatUnion; @@ -33,7 +34,7 @@ * notice. */ @Experimental -public class LogicalRepeatUnion extends RepeatUnion { +public class LogicalRepeatUnion extends RepeatUnion implements LogicalNode { //~ Constructors ----------------------------------------------------------- private LogicalRepeatUnion(RelOptCluster cluster, RelTraitSet traitSet, diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalSnapshot.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSnapshot.java index 47e9967f6dbf..18f93afa40cc 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalSnapshot.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSnapshot.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelDistributionTraitDef; import org.apache.calcite.rel.RelNode; @@ -32,7 +33,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.Snapshot} * not targeted at any particular engine or calling convention. */ -public class LogicalSnapshot extends Snapshot { +public class LogicalSnapshot extends Snapshot implements LogicalNode { //~ Constructors ----------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java index a53a4605cc69..e26916a318b0 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelInput; @@ -31,7 +32,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.Sort} not * targeted at any particular engine or calling convention. */ -public final class LogicalSort extends Sort { +public final class LogicalSort extends Sort implements LogicalNode { private LogicalSort(RelOptCluster cluster, RelTraitSet traitSet, RelNode input, RelCollation collation, RexNode offset, RexNode fetch) { super(cluster, traitSet, input, collation, offset, fetch); diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalSortExchange.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSortExchange.java index 3870d5b0acac..f42cf2cee4ca 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalSortExchange.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSortExchange.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelDistribution; @@ -31,7 +32,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.SortExchange} not * targeted at any particular engine or calling convention. */ -public class LogicalSortExchange extends SortExchange { +public class LogicalSortExchange extends SortExchange implements LogicalNode { private LogicalSortExchange(RelOptCluster cluster, RelTraitSet traitSet, RelNode input, RelDistribution distribution, RelCollation collation) { super(cluster, traitSet, input, distribution, collation); diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableFunctionScan.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableFunctionScan.java index fbd1869f4524..97ce310c09f6 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableFunctionScan.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableFunctionScan.java @@ -21,6 +21,7 @@ import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.TableFunctionScan; @@ -37,7 +38,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.TableFunctionScan} * not targeted at any particular engine or calling convention. */ -public class LogicalTableFunctionScan extends TableFunctionScan { +public class LogicalTableFunctionScan extends TableFunctionScan implements LogicalNode { //~ Constructors ----------------------------------------------------------- /** diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableModify.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableModify.java index 6a84e235e078..7f61a7fda3b8 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableModify.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableModify.java @@ -21,6 +21,7 @@ import org.apache.calcite.plan.RelOptTable; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.prepare.Prepare; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.TableModify; @@ -32,7 +33,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.TableModify} * not targeted at any particular engine or calling convention. */ -public final class LogicalTableModify extends TableModify { +public final class LogicalTableModify extends TableModify implements LogicalNode { //~ Constructors ----------------------------------------------------------- /** diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableScan.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableScan.java index 07157d01979f..c0fbbb1c97ea 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableScan.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableScan.java @@ -20,6 +20,7 @@ import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptTable; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; @@ -57,7 +58,7 @@ *

    can. It is the optimizer's responsibility to find these ways, by applying * transformation rules.

    */ -public final class LogicalTableScan extends TableScan { +public final class LogicalTableScan extends TableScan implements LogicalNode { //~ Constructors ----------------------------------------------------------- /** @@ -94,6 +95,10 @@ public LogicalTableScan(RelInput input) { return this; } + @Override public LogicalNode.StatsEstimateConfidenceLevel getStatsEstimateConfidence() { + return StatsEstimateConfidenceLevel.High; + } + /** Creates a LogicalTableScan. * * @param cluster Cluster diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableSpool.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableSpool.java index 4aab172fd2ad..9cb0f527895b 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableSpool.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableSpool.java @@ -21,6 +21,7 @@ import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptTable; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelDistributionTraitDef; import org.apache.calcite.rel.RelNode; @@ -36,7 +37,7 @@ * notice. */ @Experimental -public class LogicalTableSpool extends TableSpool { +public class LogicalTableSpool extends TableSpool implements LogicalNode { //~ Constructors ----------------------------------------------------------- public LogicalTableSpool(RelOptCluster cluster, RelTraitSet traitSet, RelNode input, diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalUnion.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalUnion.java index 535ca8193b3e..622058fa8210 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalUnion.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalUnion.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelInput; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; @@ -30,7 +31,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.Union} * not targeted at any particular engine or calling convention. */ -public final class LogicalUnion extends Union { +public final class LogicalUnion extends Union implements LogicalNode { //~ Constructors ----------------------------------------------------------- /** diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java index 32b98505175b..ea50c1d7e10b 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java @@ -19,6 +19,7 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelDistributionTraitDef; import org.apache.calcite.rel.RelInput; @@ -41,7 +42,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.Values} * not targeted at any particular engine or calling convention. */ -public class LogicalValues extends Values { +public class LogicalValues extends Values implements LogicalNode { //~ Constructors ----------------------------------------------------------- /** diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java index 7272a5796b8e..408d162dfdc5 100644 --- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java +++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java @@ -20,6 +20,7 @@ import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.Window; @@ -56,7 +57,7 @@ * Sub-class of {@link org.apache.calcite.rel.core.Window} * not targeted at any particular engine or calling convention. */ -public final class LogicalWindow extends Window { +public final class LogicalWindow extends Window implements LogicalNode { /** * Creates a LogicalWindow. * diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdAllPredicates.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdAllPredicates.java index 7945780c9029..b768d12c5e55 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdAllPredicates.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdAllPredicates.java @@ -41,7 +41,6 @@ import org.apache.calcite.sql.validate.SqlValidatorUtil; import org.apache.calcite.util.BuiltInMethod; import org.apache.calcite.util.ImmutableBitSet; -import org.apache.calcite.util.Util; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; @@ -99,7 +98,7 @@ public RelOptPredicateList getAllPredicates(HepRelVertex rel, RelMetadataQuery m public RelOptPredicateList getAllPredicates(RelSubset rel, RelMetadataQuery mq) { - return mq.getAllPredicates(Util.first(rel.getBest(), rel.getOriginal())); + return mq.getAllPredicates(rel.getOriginal()); } /** diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java index 86b1e82d2d23..92d432c83ed7 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java @@ -391,31 +391,7 @@ public Boolean areColumnsUnique(HepRelVertex rel, RelMetadataQuery mq, public Boolean areColumnsUnique(RelSubset rel, RelMetadataQuery mq, ImmutableBitSet columns, boolean ignoreNulls) { - columns = decorateWithConstantColumnsFromPredicates(columns, rel, mq); - int nullCount = 0; - for (RelNode rel2 : rel.getRels()) { - if (rel2 instanceof Aggregate - || rel2 instanceof Filter - || rel2 instanceof Values - || rel2 instanceof Sort - || rel2 instanceof TableScan - || simplyProjects(rel2, columns)) { - try { - final Boolean unique = mq.areColumnsUnique(rel2, columns, ignoreNulls); - if (unique != null) { - if (unique) { - return true; - } - } else { - ++nullCount; - } - } catch (CyclicMetadataException e) { - // Ignore this relational expression; there will be non-cyclic ones - // in this set. - } - } - } - return nullCount == 0 ? false : null; + return mq.areColumnsUnique(rel.getOriginal(), columns, ignoreNulls); } private boolean simplyProjects(RelNode rel, ImmutableBitSet columns) { diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java index 6a6b8e5882e2..c962d6c80328 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java @@ -31,7 +31,6 @@ import org.apache.calcite.rex.RexBuilder; import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexUtil; -import org.apache.calcite.util.Bug; import org.apache.calcite.util.BuiltInMethod; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.NumberUtil; @@ -264,23 +263,6 @@ public Double getDistinctRowCount(Project rel, RelMetadataQuery mq, public Double getDistinctRowCount(RelSubset rel, RelMetadataQuery mq, ImmutableBitSet groupKey, RexNode predicate) { - final RelNode best = rel.getBest(); - if (best != null) { - return mq.getDistinctRowCount(best, groupKey, predicate); - } - if (!Bug.CALCITE_1048_FIXED) { - return getDistinctRowCount((RelNode) rel, mq, groupKey, predicate); - } - Double d = null; - for (RelNode r2 : rel.getRels()) { - try { - Double d2 = mq.getDistinctRowCount(r2, groupKey, predicate); - d = NumberUtil.min(d, d2); - } catch (CyclicMetadataException e) { - // Ignore this relational expression; there will be non-cyclic ones - // in this set. - } - } - return d; + return mq.getDistinctRowCount(rel.getOriginal(), groupKey, predicate); } } diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExpressionLineage.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExpressionLineage.java index 7f495b1be3f8..90bac848afed 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExpressionLineage.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdExpressionLineage.java @@ -42,7 +42,6 @@ import org.apache.calcite.sql.validate.SqlValidatorUtil; import org.apache.calcite.util.BuiltInMethod; import org.apache.calcite.util.ImmutableBitSet; -import org.apache.calcite.util.Util; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; @@ -105,8 +104,7 @@ public Set getExpressionLineage(HepRelVertex rel, RelMetadataQuery mq, public Set getExpressionLineage(RelSubset rel, RelMetadataQuery mq, RexNode outputExpression) { - return mq.getExpressionLineage(Util.first(rel.getBest(), rel.getOriginal()), - outputExpression); + return mq.getExpressionLineage(rel.getOriginal(), outputExpression); } /** diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java index e6255a31e31b..3b7f3ebb501f 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java @@ -35,9 +35,7 @@ import org.apache.calcite.rel.core.Values; import org.apache.calcite.rex.RexBuilder; import org.apache.calcite.rex.RexLiteral; -import org.apache.calcite.util.Bug; import org.apache.calcite.util.BuiltInMethod; -import org.apache.calcite.util.Util; /** * RelMdMaxRowCount supplies a default implementation of @@ -202,19 +200,7 @@ public Double getMaxRowCount(TableModify rel, RelMetadataQuery mq) { } public Double getMaxRowCount(RelSubset rel, RelMetadataQuery mq) { - // FIXME This is a short-term fix for [CALCITE-1018]. A complete - // solution will come with [CALCITE-1048]. - Util.discard(Bug.CALCITE_1048_FIXED); - for (RelNode node : rel.getRels()) { - if (node instanceof Sort) { - Sort sort = (Sort) node; - if (sort.fetch != null) { - return (double) RexLiteral.intValue(sort.fetch); - } - } - } - - return Double.POSITIVE_INFINITY; + return mq.getMaxRowCount(rel.getOriginal()); } // Catch-all rule when none of the others apply. diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMinRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMinRowCount.java index 069e40ff1125..9eebb4d595db 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMinRowCount.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMinRowCount.java @@ -33,9 +33,7 @@ import org.apache.calcite.rel.core.Union; import org.apache.calcite.rel.core.Values; import org.apache.calcite.rex.RexLiteral; -import org.apache.calcite.util.Bug; import org.apache.calcite.util.BuiltInMethod; -import org.apache.calcite.util.Util; /** * RelMdMinRowCount supplies a default implementation of @@ -162,19 +160,7 @@ public Double getMinRowCount(Values values, RelMetadataQuery mq) { } public Double getMinRowCount(RelSubset rel, RelMetadataQuery mq) { - // FIXME This is a short-term fix for [CALCITE-1018]. A complete - // solution will come with [CALCITE-1048]. - Util.discard(Bug.CALCITE_1048_FIXED); - for (RelNode node : rel.getRels()) { - if (node instanceof Sort) { - Sort sort = (Sort) node; - if (sort.fetch != null) { - return (double) RexLiteral.intValue(sort.fetch); - } - } - } - - return 0D; + return getMinRowCount(rel.getOriginal(), mq); } // Catch-all rule when none of the others apply. diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdNodeTypes.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdNodeTypes.java index 5259b3ffca5b..71c0d015c13a 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdNodeTypes.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdNodeTypes.java @@ -37,7 +37,6 @@ import org.apache.calcite.rel.core.Values; import org.apache.calcite.rel.core.Window; import org.apache.calcite.util.BuiltInMethod; -import org.apache.calcite.util.Util; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; @@ -76,7 +75,7 @@ public Multimap, RelNode> getNodeTypes(HepRelVertex rel public Multimap, RelNode> getNodeTypes(RelSubset rel, RelMetadataQuery mq) { - return mq.getNodeTypes(Util.first(rel.getBest(), rel.getOriginal())); + return mq.getNodeTypes(rel.getOriginal()); } public Multimap, RelNode> getNodeTypes(Union rel, diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java index 00610429a38b..fb8ab5d8f2dc 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java @@ -53,7 +53,6 @@ import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.util.BitSets; -import org.apache.calcite.util.Bug; import org.apache.calcite.util.BuiltInMethod; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.Util; @@ -488,18 +487,7 @@ public RelOptPredicateList getPredicates(Exchange exchange, /** @see RelMetadataQuery#getPulledUpPredicates(RelNode) */ public RelOptPredicateList getPredicates(RelSubset r, RelMetadataQuery mq) { - if (!Bug.CALCITE_1048_FIXED) { - return RelOptPredicateList.EMPTY; - } - final RexBuilder rexBuilder = r.getCluster().getRexBuilder(); - RelOptPredicateList list = null; - for (RelNode r2 : r.getRels()) { - RelOptPredicateList list2 = mq.getPulledUpPredicates(r2); - if (list2 != null) { - list = list == null ? list2 : list.union(rexBuilder, list2); - } - } - return Util.first(list, RelOptPredicateList.EMPTY); + return getPredicates(r.getOriginal(), mq); } /** diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java index a42ed2ab0930..48fc8a56b2e0 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java @@ -35,11 +35,8 @@ import org.apache.calcite.rel.core.Values; import org.apache.calcite.rex.RexDynamicParam; import org.apache.calcite.rex.RexLiteral; -import org.apache.calcite.util.Bug; import org.apache.calcite.util.BuiltInMethod; import org.apache.calcite.util.ImmutableBitSet; -import org.apache.calcite.util.NumberUtil; -import org.apache.calcite.util.Util; /** * RelMdRowCount supplies a default implementation of @@ -68,20 +65,7 @@ public Double getRowCount(RelNode rel, RelMetadataQuery mq) { } public Double getRowCount(RelSubset subset, RelMetadataQuery mq) { - if (!Bug.CALCITE_1048_FIXED) { - return mq.getRowCount(Util.first(subset.getBest(), subset.getOriginal())); - } - Double v = null; - for (RelNode r : subset.getRels()) { - try { - v = NumberUtil.min(v, mq.getRowCount(r)); - } catch (CyclicMetadataException e) { - // ignore this rel; there will be other, non-cyclic ones - } catch (Throwable e) { - e.printStackTrace(); - } - } - return Util.first(v, 1e6d); // if set is empty, estimate large + return mq.getRowCount(subset.getOriginal()); } public Double getRowCount(Union rel, RelMetadataQuery mq) { diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java index e554728e0bee..d2d270b1cfba 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java @@ -33,7 +33,6 @@ import org.apache.calcite.rel.core.Window; import org.apache.calcite.rex.RexTableInputRef.RelTableRef; import org.apache.calcite.util.BuiltInMethod; -import org.apache.calcite.util.Util; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableSet; @@ -85,7 +84,7 @@ public Set getTableReferences(HepRelVertex rel, RelMetadataQuery mq } public Set getTableReferences(RelSubset rel, RelMetadataQuery mq) { - return mq.getTableReferences(Util.first(rel.getBest(), rel.getOriginal())); + return mq.getTableReferences(rel.getOriginal()); } /** diff --git a/core/src/main/java/org/apache/calcite/rel/rules/MultiJoin.java b/core/src/main/java/org/apache/calcite/rel/rules/MultiJoin.java index 1b09be8850bc..64b488a63b8b 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/MultiJoin.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/MultiJoin.java @@ -21,6 +21,7 @@ import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.AbstractRelNode; +import org.apache.calcite.rel.LogicalNode; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelWriter; import org.apache.calcite.rel.core.JoinRelType; @@ -44,7 +45,7 @@ * A MultiJoin represents a join of N inputs, whereas regular Joins * represent strictly binary joins. */ -public final class MultiJoin extends AbstractRelNode { +public final class MultiJoin extends AbstractRelNode implements LogicalNode { //~ Instance fields -------------------------------------------------------- private final List inputs; @@ -266,6 +267,10 @@ public RexNode getPostJoinFilter() { return postJoinFilter; } + @Override public StatsEstimateConfidenceLevel getStatsEstimateConfidence() { + return StatsEstimateConfidenceLevel.Low; + } + boolean containsOuter() { for (JoinRelType joinType : joinTypes) { if (joinType.isOuterJoin()) { diff --git a/core/src/test/java/org/apache/calcite/tools/PlannerTest.java b/core/src/test/java/org/apache/calcite/tools/PlannerTest.java index e6ce8a05eee1..ea68624e7759 100644 --- a/core/src/test/java/org/apache/calcite/tools/PlannerTest.java +++ b/core/src/test/java/org/apache/calcite/tools/PlannerTest.java @@ -988,13 +988,13 @@ private void checkJoinNWay(int n) throws Exception { + "left join \"depts\" as d on e.\"deptno\" = d.\"deptno\"\n" + "join \"dependents\" as p on e.\"empid\" = p.\"empid\""; final String expected = "" - + "EnumerableProject(empid=[$2], deptno=[$3], name=[$4], salary=[$5], commission=[$6], deptno0=[$7], name0=[$8], employees=[$9], location=[ROW($10, $11)], empid0=[$0], name1=[$1])\n" - + " EnumerableHashJoin(condition=[=($0, $2)], joinType=[inner])\n" - + " EnumerableTableScan(table=[[hr, dependents]])\n" + + "EnumerableProject(empid=[$0], deptno=[$1], name=[$2], salary=[$3], commission=[$4], deptno0=[$5], name0=[$6], employees=[$7], location=[ROW($8, $9)], empid0=[$10], name1=[$11])\n" + + " EnumerableHashJoin(condition=[=($0, $10)], joinType=[inner])\n" + " EnumerableHashJoin(condition=[=($1, $5)], joinType=[left])\n" + " EnumerableTableScan(table=[[hr, emps]])\n" + " EnumerableProject(deptno=[$0], name=[$1], employees=[$2], x=[$3.x], y=[$3.y])\n" - + " EnumerableTableScan(table=[[hr, depts]])"; + + " EnumerableTableScan(table=[[hr, depts]])\n" + + " EnumerableTableScan(table=[[hr, dependents]])"; checkHeuristic(sql, expected); } @@ -1009,14 +1009,14 @@ private void checkJoinNWay(int n) throws Exception { + "right join \"depts\" as d on e.\"deptno\" = d.\"deptno\"\n" + "join \"dependents\" as p on e.\"empid\" = p.\"empid\""; final String expected = "" - + "EnumerableProject(empid=[$2], deptno=[$3], name=[$4], salary=[$5], commission=[$6], deptno0=[$7], name0=[$8], employees=[$9], location=[ROW($10, $11)], empid0=[$0], name1=[$1])\n" - + " EnumerableHashJoin(condition=[=($0, $2)], joinType=[inner])\n" - + " EnumerableTableScan(table=[[hr, dependents]])\n" + + "EnumerableProject(empid=[$0], deptno=[$1], name=[$2], salary=[$3], commission=[$4], deptno0=[$5], name0=[$6], employees=[$7], location=[ROW($8, $9)], empid0=[$10], name1=[$11])\n" + + " EnumerableHashJoin(condition=[=($0, $10)], joinType=[inner])\n" + " EnumerableProject(empid=[$5], deptno=[$6], name=[$7], salary=[$8], commission=[$9], deptno0=[$0], name0=[$1], employees=[$2], x=[$3], y=[$4])\n" + " EnumerableHashJoin(condition=[=($0, $6)], joinType=[left])\n" + " EnumerableProject(deptno=[$0], name=[$1], employees=[$2], x=[$3.x], y=[$3.y])\n" + " EnumerableTableScan(table=[[hr, depts]])\n" - + " EnumerableTableScan(table=[[hr, emps]])"; + + " EnumerableTableScan(table=[[hr, emps]])\n" + + " EnumerableTableScan(table=[[hr, dependents]])"; checkHeuristic(sql, expected); } @@ -1027,13 +1027,13 @@ private void checkJoinNWay(int n) throws Exception { + "join \"depts\" as d on e.\"deptno\" = d.\"deptno\"\n" + "right join \"dependents\" as p on e.\"empid\" = p.\"empid\""; final String expected = "" - + "EnumerableProject(empid=[$2], deptno=[$3], name=[$4], salary=[$5], commission=[$6], deptno0=[$7], name0=[$8], employees=[$9], location=[ROW($10, $11)], empid0=[$0], name1=[$1])\n" - + " EnumerableHashJoin(condition=[=($0, $2)], joinType=[left])\n" - + " EnumerableTableScan(table=[[hr, dependents]])\n" + + "EnumerableProject(empid=[$0], deptno=[$1], name=[$2], salary=[$3], commission=[$4], deptno0=[$5], name0=[$6], employees=[$7], location=[ROW($8, $9)], empid0=[$10], name1=[$11])\n" + + " EnumerableHashJoin(condition=[=($0, $10)], joinType=[right])\n" + " EnumerableHashJoin(condition=[=($1, $5)], joinType=[inner])\n" + " EnumerableTableScan(table=[[hr, emps]])\n" + " EnumerableProject(deptno=[$0], name=[$1], employees=[$2], x=[$3.x], y=[$3.y])\n" - + " EnumerableTableScan(table=[[hr, depts]])"; + + " EnumerableTableScan(table=[[hr, depts]])\n" + + " EnumerableTableScan(table=[[hr, dependents]])"; checkHeuristic(sql, expected); } diff --git a/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml b/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml index 3442857776b7..820cf5c3a075 100644 --- a/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml @@ -1080,11 +1080,11 @@ LogicalSort(sort0=[$1], dir0=[ASC]) @@ -1130,11 +1130,11 @@ LogicalSort(sort0=[$1], dir0=[ASC]) @@ -1183,12 +1183,12 @@ LogicalSort(sort0=[$1], dir0=[ASC])