This is an automated email from the ASF dual-hosted git repository. danny0405 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push: new 69f2586 [CALCITE-3786] Add Digest interface to enable efficient hashCode(equals) for RexNode and RelNode 69f2586 is described below commit 69f25863f5f4197c17927a39a82cbf1cffd12b80 Author: yuzhao.cyz <yuzhao....@gmail.com> AuthorDate: Tue Jun 9 21:16:22 2020 +0800 [CALCITE-3786] Add Digest interface to enable efficient hashCode(equals) for RexNode and RelNode * Add class Digest used to identify the node; * There is a pre-computed hashcode to speedup #hashCode and #equals; * Change RexCall to use object#equals instead of pure string digest comparison; * We only support RexInputRef normalization which is the most common case; * Remove RexNode#toStringRaw because it makes the thing complicated, RexNode can always be normalized(default true). --- .../org/apache/calcite/adapter/jdbc/JdbcRules.java | 2 +- .../apache/calcite/plan/AbstractRelOptPlanner.java | 14 -- .../main/java/org/apache/calcite/plan/Digest.java | 256 +++++++++++++++++++++ .../plan/MaterializedViewSubstitutionVisitor.java | 2 +- .../java/org/apache/calcite/plan/RelOptNode.java | 2 +- .../java/org/apache/calcite/plan/RelOptUtil.java | 19 +- .../org/apache/calcite/plan/hep/HepPlanner.java | 13 +- .../org/apache/calcite/plan/hep/HepRelVertex.java | 5 +- .../org/apache/calcite/plan/volcano/RelSubset.java | 10 +- .../calcite/plan/volcano/VolcanoPlanner.java | 39 ++-- .../org/apache/calcite/rel/AbstractRelNode.java | 81 ++----- .../main/java/org/apache/calcite/rel/RelNode.java | 3 +- .../java/org/apache/calcite/rel/RelWriter.java | 15 -- .../java/org/apache/calcite/rel/core/Match.java | 10 + .../java/org/apache/calcite/rel/core/Window.java | 22 +- .../calcite/rel/externalize/RelJsonWriter.java | 5 +- .../calcite/rel/externalize/RelWriterImpl.java | 21 +- .../rel/metadata/RelMdExpressionLineage.java | 2 +- .../calcite/rel/rel2sql/RelToSqlConverter.java | 4 +- .../rel/rules/JoinProjectTransposeRule.java | 4 +- .../rel/rules/ProjectWindowTransposeRule.java | 4 +- .../materialize/MaterializedViewAggregateRule.java | 22 +- .../materialize/MaterializedViewJoinRule.java | 4 +- .../rules/materialize/MaterializedViewRule.java | 2 +- .../main/java/org/apache/calcite/rex/RexCall.java | 148 +++++------- .../main/java/org/apache/calcite/rex/RexNode.java | 63 +---- .../main/java/org/apache/calcite/rex/RexOver.java | 21 ++ .../java/org/apache/calcite/rex/RexSubQuery.java | 10 + .../main/java/org/apache/calcite/sql/SqlKind.java | 19 ++ .../calcite/sql/fun/SqlStdOperatorTable.java | 20 ++ .../calcite/materialize/LatticeSuggesterTest.java | 4 +- .../org/apache/calcite/plan/RelOptUtilTest.java | 8 +- .../calcite/plan/volcano/TraitPropagationTest.java | 4 +- .../calcite/plan/volcano/VolcanoPlannerTest.java | 10 +- .../calcite/rel/rules/DateRangeRulesTest.java | 4 +- .../calcite/rex/RexCallNormalizationTest.java | 76 +++--- .../org/apache/calcite/rex/RexProgramTest.java | 8 +- .../org/apache/calcite/rex/RexProgramTestBase.java | 39 ++-- .../rex/RexSqlStandardConvertletTableTest.java | 6 +- .../org/apache/calcite/test/HepPlannerTest.java | 6 +- .../org/apache/calcite/test/JdbcAdapterTest.java | 4 +- .../java/org/apache/calcite/test/LatticeTest.java | 6 +- .../test/MaterializedViewRelOptRulesTest.java | 3 +- .../MaterializedViewSubstitutionVisitorTest.java | 10 +- .../org/apache/calcite/test/RelBuilderTest.java | 6 +- .../org/apache/calcite/test/RelMetadataTest.java | 14 +- .../org/apache/calcite/test/RelOptRulesTest.java | 2 +- .../apache/calcite/test/RexTransformerTest.java | 4 +- .../apache/calcite/test/SqlHintsConverterTest.java | 6 +- .../test/enumerable/EnumerableCorrelateTest.java | 8 +- .../org/apache/calcite/test/RelOptRulesTest.xml | 74 +++--- .../apache/calcite/test/SqlToRelConverterTest.xml | 24 +- .../org/apache/calcite/test/TopDownOptTest.xml | 4 +- core/src/test/resources/sql/blank.iq | 2 +- core/src/test/resources/sql/sub-query.iq | 4 +- .../apache/calcite/adapter/druid/DruidRules.java | 2 +- .../calcite/piglet/PigToSqlAggregateRule.java | 6 +- 57 files changed, 664 insertions(+), 522 deletions(-) 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 4b9b1b4..438781b 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 @@ -523,7 +523,7 @@ public class JdbcRules { private static boolean userDefinedFunctionInProject(Project project) { CheckingUserDefinedFunctionVisitor visitor = new CheckingUserDefinedFunctionVisitor(); - for (RexNode node : project.getChildExps()) { + for (RexNode node : project.getProjects()) { node.accept(visitor); if (visitor.containsUserDefinedFunction()) { return true; 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 cf350b6..08731a8 100644 --- a/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java +++ b/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java @@ -20,7 +20,6 @@ import org.apache.calcite.plan.volcano.RelSubset; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.metadata.RelMetadataProvider; import org.apache.calcite.rel.metadata.RelMetadataQuery; -import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rex.RexExecutor; import org.apache.calcite.util.CancelFlag; import org.apache.calcite.util.Pair; @@ -443,19 +442,6 @@ public abstract class AbstractRelOptPlanner implements RelOptPlanner { }); } - /** Computes the key for relational expression digest cache. */ - protected static Pair<String, List<RelDataType>> key(RelNode rel) { - return key(rel.getDigest(), rel.getRowType()); - } - - /** Computes the key for relational expression digest cache. */ - protected static Pair<String, List<RelDataType>> key(String digest, RelDataType relType) { - final List<RelDataType> v = relType.isStruct() - ? Pair.right(relType.getFieldList()) - : Collections.singletonList(relType); - return Pair.of(digest, v); - } - /** Listener for counting the attempts of each rule. Only enabled under DEBUG level.*/ private class RuleAttemptsListener implements RelOptListener { private long beforeTimestamp; diff --git a/core/src/main/java/org/apache/calcite/plan/Digest.java b/core/src/main/java/org/apache/calcite/plan/Digest.java new file mode 100644 index 0000000..494cb14 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/plan/Digest.java @@ -0,0 +1,256 @@ +/* + * 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.plan; + +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.hint.Hintable; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.util.Pair; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nonnull; + +/** + * A short description of relational expression's type, inputs, and + * other properties. The digest uniquely identifies the node; another node + * is equivalent if and only if it has the same value. + * + * <p>Row type is part of the digest for the rare occasion that similar + * expressions have different types, e.g. variants of + * {@code Project(child=rel#1, a=null)} where a is a null INTEGER or a + * null VARCHAR(10). Row type is represented as fieldTypes only, so {@code RelNode} + * that differ with field names only are treated equal. + * For instance, {@code Project(input=rel#1,empid=$0)} and {@code Project(input=rel#1,deptno=$0)} + * are equal. + * + * <p>Computed by {@code org.apache.calcite.rel.AbstractRelNode#computeDigest}, + * assigned by {@link org.apache.calcite.rel.AbstractRelNode#onRegister}, + * returned by {@link org.apache.calcite.rel.AbstractRelNode#getDigest()}. + */ +public class Digest implements Comparable<Digest> { + + //~ Instance fields -------------------------------------------------------- + + private final int hashCode; + private final List<Pair<String, Object>> items; + private final RelNode rel; + + // Used for debugging, computed lazily. + private String digest = null; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a digest with given rel and properties. + * + * @param rel The rel + * @param items The properties, e.g. the inputs, the type, the traits and so on + */ + private Digest(RelNode rel, List<Pair<String, Object>> items) { + this.rel = rel; + this.items = normalizeContents(items); + this.hashCode = computeIdentity(rel, this.items); + } + + /** + * Creates a digest with given rel, the digest is computed as simple, + * see {@link #simpleRelDigest(RelNode)}. + */ + private Digest(RelNode rel) { + this(rel, simpleRelDigest(rel)); + } + + /** Creates a digest with given rel and string format digest. */ + private Digest(RelNode rel, String digest) { + this.rel = rel; + this.items = Collections.emptyList(); + this.digest = digest; + this.hashCode = this.digest.hashCode(); + } + + /** Returns the identity of this digest which is used to speedup hashCode and equals. */ + private static int computeIdentity(RelNode rel, List<Pair<String, Object>> contents) { + return Objects.hash(collect(rel, contents, false)); + } + + /** + * Collects the items used for {@link #hashCode} and {@link #equals}. + * + * <p>Generally, the items used for hashCode and equals should be the same. The exception + * is the row type of the relational expression: the row type is needed because during + * planning, new equivalent rels may be produced with changed fields nullability + * (i.e. most of them comes from the rex simplify or constant reduction). + * This expects to be rare case, so the hashcode is computed without row type + * but when it conflicts, we compare with the row type involved(sans field names). + * + * @param rel The rel to compute digest + * @param contents The rel properties should be considered in digest + * @param withType Whether to involve the row type + */ + private static Object[] collect( + RelNode rel, + List<Pair<String, Object>> contents, + boolean withType) { + List<Object> hashCodeItems = new ArrayList<>(); + // The type name. + hashCodeItems.add(rel.getRelTypeName()); + // The traits. + hashCodeItems.addAll(rel.getTraitSet()); + // The hints. + if (rel instanceof Hintable) { + hashCodeItems.addAll(((Hintable) rel).getHints()); + } + if (withType) { + // The row type sans field names. + RelDataType relType = rel.getRowType(); + if (relType.isStruct()) { + hashCodeItems.addAll(Pair.right(relType.getFieldList())); + } else { + // Make a decision here because + // some downstream projects have custom rel type which has no explicit fields. + hashCodeItems.add(relType); + } + } + // The rel node contents(e.g. the inputs or exprs). + hashCodeItems.addAll(contents); + return hashCodeItems.toArray(); + } + + /** Normalizes the rel node properties, currently, just to replace the + * {@link RelNode} with a simple string format digest. **/ + private static List<Pair<String, Object>> normalizeContents( + List<Pair<String, Object>> items) { + List<Pair<String, Object>> normalized = new ArrayList<>(); + for (Pair<String, Object> item : items) { + if (item.right instanceof RelNode) { + RelNode input = (RelNode) item.right; + normalized.add(Pair.of(item.left, simpleRelDigest(input))); + } else { + normalized.add(item); + } + } + return normalized; + } + + /** + * Returns a simple string format digest. + * + * <p>Currently, returns composition of class name and id. + * + * @param rel The rel + */ + private static String simpleRelDigest(RelNode rel) { + return rel.getRelTypeName() + '#' + rel.getId(); + } + + @Override public String toString() { + if (null != digest) { + return digest; + } + StringBuilder sb = new StringBuilder(); + sb.append(rel.getRelTypeName()); + + for (RelTrait trait : rel.getTraitSet()) { + sb.append('.'); + sb.append(trait.toString()); + } + + sb.append('('); + int j = 0; + for (Pair<String, Object> item : items) { + if (j++ > 0) { + sb.append(','); + } + sb.append(item.left); + sb.append('='); + sb.append(item.right); + } + sb.append(')'); + digest = sb.toString(); + return digest; + } + + @Override public int compareTo(@Nonnull Digest other) { + return this.equals(other) ? 0 : this.rel.getId() - other.rel.getId(); + } + + @Override public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Digest that = (Digest) o; + return hashCode == that.hashCode && deepEquals(that); + } + + /** + * The method is used to resolve hash conflict, in current 6000+ tests, there are about 8 + * tests with conflict, so we do not cache the hash code items in order to + * reduce mem consumption. + */ + private boolean deepEquals(Digest other) { + Object[] thisItems = collect(this.rel, this.items, true); + Object[] thatItems = collect(other.rel, other.items, true); + if (thisItems.length != thatItems.length) { + return false; + } + for (int i = 0; i < thisItems.length; i++) { + if (!Objects.equals(thisItems[i], thatItems[i])) { + return false; + } + } + return true; + } + + @Override public int hashCode() { + return hashCode; + } + + /** + * Creates a digest with given rel and properties. + */ + public static Digest create(RelNode rel, List<Pair<String, Object>> contents) { + return new Digest(rel, contents); + } + + /** + * Creates a digest with given rel. + */ + public static Digest create(RelNode rel) { + return new Digest(rel); + } + + /** + * Creates a digest with given rel and string format digest + */ + public static Digest create(RelNode rel, String digest) { + return new Digest(rel, digest); + } + + /** + * Instantiates a digest with solid string format digest, this digest should only + * be used as a initial. + */ + public static Digest initial(RelNode rel) { + return new Digest(rel, simpleRelDigest(rel)); + } +} diff --git a/core/src/main/java/org/apache/calcite/plan/MaterializedViewSubstitutionVisitor.java b/core/src/main/java/org/apache/calcite/plan/MaterializedViewSubstitutionVisitor.java index 0ddee54..cc3692c 100644 --- a/core/src/main/java/org/apache/calcite/plan/MaterializedViewSubstitutionVisitor.java +++ b/core/src/main/java/org/apache/calcite/plan/MaterializedViewSubstitutionVisitor.java @@ -22,7 +22,7 @@ import org.apache.calcite.tools.RelBuilderFactory; /** * Extension to {@link SubstitutionVisitor}. */ -@Deprecated // Kept for backward compatibility and to be removed before 2.0 +@Deprecated // to be removed before 2.0 public class MaterializedViewSubstitutionVisitor extends SubstitutionVisitor { public MaterializedViewSubstitutionVisitor(RelNode target_, RelNode query_) { diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptNode.java b/core/src/main/java/org/apache/calcite/plan/RelOptNode.java index 2a0f077..8484f54 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptNode.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptNode.java @@ -47,7 +47,7 @@ public interface RelOptNode { * * @return Digest of this {@code RelNode} */ - String getDigest(); + Digest getDigest(); /** * Retrieves this RelNode's traits. Note that although the RelTraitSet 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 8ace22d..1083047 100644 --- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java +++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java @@ -182,20 +182,14 @@ public abstract class RelOptUtil { * Whether this node contains a limit specification. */ public static boolean isLimit(RelNode rel) { - if ((rel instanceof Sort) && ((Sort) rel).fetch != null) { - return true; - } - return false; + return (rel instanceof Sort) && ((Sort) rel).fetch != null; } /** * Whether this node contains a sort specification. */ public static boolean isOrder(RelNode rel) { - if ((rel instanceof Sort) && !((Sort) rel).getCollation().getFieldCollations().isEmpty()) { - return true; - } - return false; + return (rel instanceof Sort) && !((Sort) rel).getCollation().getFieldCollations().isEmpty(); } /** @@ -227,8 +221,9 @@ public abstract class RelOptUtil { * or its children. */ public static List<String> findAllTableQualifiedNames(RelNode rel) { - return Lists.transform(findAllTables(rel), - table -> table.getQualifiedName().toString()); + return findAllTables(rel).stream() + .map(table -> table.getQualifiedName().toString()) + .collect(Collectors.toList()); } /** @@ -3802,7 +3797,7 @@ public abstract class RelOptUtil { return true; } final RexImplicationChecker checker = - new RexImplicationChecker(rexBuilder, (RexExecutorImpl) executor, + new RexImplicationChecker(rexBuilder, executor, rowType); final RexNode first = RexUtil.composeConjunction(rexBuilder, predicates.pulledUpPredicates); @@ -4185,7 +4180,6 @@ public abstract class RelOptUtil { /** Converts types to descriptive strings. */ public static class TypeDumper { - private final String extraIndent = " "; private String indent; private final PrintWriter pw; @@ -4203,6 +4197,7 @@ public abstract class RelOptUtil { // J VARCHAR(240)) pw.println("RECORD ("); String prevIndent = indent; + String extraIndent = " "; this.indent = indent + extraIndent; acceptFields(fields); this.indent = prevIndent; diff --git a/core/src/main/java/org/apache/calcite/plan/hep/HepPlanner.java b/core/src/main/java/org/apache/calcite/plan/hep/HepPlanner.java index 44b4fb8..36bd186 100644 --- a/core/src/main/java/org/apache/calcite/plan/hep/HepPlanner.java +++ b/core/src/main/java/org/apache/calcite/plan/hep/HepPlanner.java @@ -21,6 +21,7 @@ import org.apache.calcite.linq4j.function.Functions; import org.apache.calcite.plan.AbstractRelOptPlanner; import org.apache.calcite.plan.CommonRelSubExprRule; import org.apache.calcite.plan.Context; +import org.apache.calcite.plan.Digest; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptCostFactory; import org.apache.calcite.plan.RelOptCostImpl; @@ -84,7 +85,7 @@ public class HepPlanner extends AbstractRelOptPlanner { * {@link RelDataType} is represented with its field types as {@code List<RelDataType>}. * This enables to treat as equal projects that differ in expression names only. */ - private final Map<Pair<String, List<RelDataType>>, HepRelVertex> mapDigestToVertex = + private final Map<Digest, HepRelVertex> mapDigestToVertex = new HashMap<>(); private int nTransformations; @@ -810,8 +811,7 @@ public class HepPlanner extends AbstractRelOptPlanner { // try to find equivalent rel only if DAG is allowed if (!noDag) { // Now, check if an equivalent vertex already exists in graph. - Pair<String, List<RelDataType>> key = key(rel); - HepRelVertex equivVertex = mapDigestToVertex.get(key); + HepRelVertex equivVertex = mapDigestToVertex.get(rel.getDigest()); if (equivVertex != null) { // Use existing vertex. return equivVertex; @@ -900,7 +900,7 @@ public class HepPlanner extends AbstractRelOptPlanner { // reachable from here. notifyDiscard(vertex.getCurrentRel()); } - Pair<String, List<RelDataType>> oldKey = key(vertex.getCurrentRel()); + Digest oldKey = vertex.getCurrentRel().getDigest(); if (mapDigestToVertex.get(oldKey) == vertex) { mapDigestToVertex.remove(oldKey); } @@ -911,8 +911,7 @@ public class HepPlanner extends AbstractRelOptPlanner { // otherwise the digest will be removed wrongly in the mapDigestToVertex // when collectGC // so it must update the digest that map to vertex - Pair<String, List<RelDataType>> newKey = key(rel); - mapDigestToVertex.put(newKey, vertex); + mapDigestToVertex.put(rel.getDigest(), vertex); if (rel != vertex.getCurrentRel()) { vertex.replaceRel(rel); } @@ -978,7 +977,7 @@ public class HepPlanner extends AbstractRelOptPlanner { graphSizeLastGC = graph.vertexSet().size(); // Clean up digest map too. - Iterator<Map.Entry<Pair<String, List<RelDataType>>, HepRelVertex>> digestIter = + Iterator<Map.Entry<Digest, HepRelVertex>> digestIter = mapDigestToVertex.entrySet().iterator(); while (digestIter.hasNext()) { HepRelVertex vertex = digestIter.next().getValue(); diff --git a/core/src/main/java/org/apache/calcite/plan/hep/HepRelVertex.java b/core/src/main/java/org/apache/calcite/plan/hep/HepRelVertex.java index 6ec8a6c..92394b1 100644 --- a/core/src/main/java/org/apache/calcite/plan/hep/HepRelVertex.java +++ b/core/src/main/java/org/apache/calcite/plan/hep/HepRelVertex.java @@ -16,6 +16,7 @@ */ package org.apache.calcite.plan.hep; +import org.apache.calcite.plan.Digest; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelTraitSet; @@ -75,8 +76,8 @@ public class HepRelVertex extends AbstractRelNode { return currentRel.getRowType(); } - @Override protected String computeDigest() { - return "HepRelVertex(" + currentRel + ")"; + @Override protected Digest computeDigest() { + return Digest.create(this, getRelTypeName() + '#' + getCurrentRel().getId()); } /** 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 8b0a78a..e821496 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 @@ -17,6 +17,7 @@ package org.apache.calcite.plan.volcano; import org.apache.calcite.linq4j.Linq4j; +import org.apache.calcite.plan.Digest; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptListener; @@ -224,13 +225,14 @@ public class RelSubset extends AbstractRelNode { pw.done(input); } - @Override protected String computeDigest() { - StringBuilder digest = new StringBuilder("Subset#"); + @Override protected Digest computeDigest() { + StringBuilder digest = new StringBuilder(getRelTypeName()); + digest.append('#'); digest.append(set.id); - for (RelTrait trait : traitSet) { + for (RelTrait trait : getTraitSet()) { digest.append('.').append(trait); } - return digest.toString(); + return Digest.create(this, digest.toString()); } @Override protected RelDataType deriveRowType() { 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 8374f1b..4842932 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 @@ -22,6 +22,7 @@ import org.apache.calcite.plan.AbstractRelOptPlanner; import org.apache.calcite.plan.Context; import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.ConventionTraitDef; +import org.apache.calcite.plan.Digest; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptCostFactory; import org.apache.calcite.plan.RelOptLattice; @@ -48,7 +49,6 @@ import org.apache.calcite.rel.metadata.RelMdUtil; import org.apache.calcite.rel.metadata.RelMetadataProvider; import org.apache.calcite.rel.metadata.RelMetadataQuery; import org.apache.calcite.rel.rules.TransformationRule; -import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.runtime.Hook; import org.apache.calcite.sql.SqlExplainLevel; import org.apache.calcite.util.Litmus; @@ -102,17 +102,8 @@ public class VolcanoPlanner extends AbstractRelOptPlanner { /** * Canonical map from {@link String digest} to the unique * {@link RelNode relational expression} with that digest. - * - * <p>Row type is part of the key for the rare occasion that similar - * expressions have different types, e.g. variants of - * {@code Project(child=rel#1, a=null)} where a is a null INTEGER or a - * null VARCHAR(10).</p> - * <p>Row type is represented as fieldTypes only, so {@code RelNode} that differ - * with field names only are treated equal. - * For instance, {@code Project(input=rel#1,empid=$0)} and {@code Project(input=rel#1,deptno=$0)} - * are equal</p> */ - private final Map<Pair<String, List<RelDataType>>, RelNode> mapDigestToRel = + private final Map<Digest, RelNode> mapDigestToRel = new HashMap<>(); /** @@ -898,15 +889,13 @@ public class VolcanoPlanner extends AbstractRelOptPlanner { * @param rel Relational expression */ void rename(RelNode rel) { - final String oldDigest = rel.getDigest(); + final Digest oldDigest = rel.getDigest(); if (fixUpInputs(rel)) { - final Pair<String, List<RelDataType>> oldKey = key(oldDigest, rel.getRowType()); - final RelNode removed = mapDigestToRel.remove(oldKey); + final RelNode removed = mapDigestToRel.remove(oldDigest); assert removed == rel; - final String newDigest = rel.recomputeDigest(); + final Digest newDigest = rel.recomputeDigest(); LOGGER.trace("Rename #{} from '{}' to '{}'", rel.getId(), oldDigest, newDigest); - final Pair<String, List<RelDataType>> key = key(rel); - final RelNode equivRel = mapDigestToRel.put(key, rel); + final RelNode equivRel = mapDigestToRel.put(newDigest, rel); if (equivRel != null) { assert equivRel != rel; @@ -915,7 +904,7 @@ public class VolcanoPlanner extends AbstractRelOptPlanner { LOGGER.trace("After renaming rel#{} it is now equivalent to rel#{}", rel.getId(), equivRel.getId()); - mapDigestToRel.put(key, equivRel); + mapDigestToRel.put(newDigest, equivRel); checkPruned(equivRel, rel); RelSubset equivRelSubset = getSubset(equivRel); @@ -970,8 +959,7 @@ public class VolcanoPlanner extends AbstractRelOptPlanner { // Is there an equivalent relational expression? (This might have // just occurred because the relational expression's child was just // found to be equivalent to another set.) - final Pair<String, List<RelDataType>> key = key(rel); - RelNode equivRel = mapDigestToRel.get(key); + RelNode equivRel = mapDigestToRel.get(rel.getDigest()); if (equivRel != null && equivRel != rel) { assert equivRel.getClass() == rel.getClass(); assert equivRel.getTraitSet().equals(rel.getTraitSet()); @@ -1180,8 +1168,8 @@ public class VolcanoPlanner extends AbstractRelOptPlanner { // If it is equivalent to an existing expression, return the set that // the equivalent expression belongs to. - Pair<String, List<RelDataType>> key = key(rel); - RelNode equivExp = mapDigestToRel.get(key); + Digest digest = rel.getDigest(); + RelNode equivExp = mapDigestToRel.get(digest); if (equivExp == null) { // do nothing } else if (equivExp == rel) { @@ -1218,9 +1206,8 @@ public class VolcanoPlanner extends AbstractRelOptPlanner { // check whether we are now equivalent to an existing // expression. if (fixUpInputs(rel)) { - rel.recomputeDigest(); - key = key(rel); - RelNode equivRel = mapDigestToRel.get(key); + digest = rel.recomputeDigest(); + RelNode equivRel = mapDigestToRel.get(digest); if ((equivRel != rel) && (equivRel != null)) { // make sure this bad rel didn't get into the @@ -1261,7 +1248,7 @@ public class VolcanoPlanner extends AbstractRelOptPlanner { final int subsetBeforeCount = set.subsets.size(); RelSubset subset = addRelToSet(rel, set); - final RelNode xx = mapDigestToRel.put(key, rel); + final RelNode xx = mapDigestToRel.put(digest, rel); assert xx == null || xx == rel : rel.getDigest(); LOGGER.trace("Register {} in {}", rel, subset); 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 8240c60..c5ec873 100644 --- a/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java +++ b/core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java @@ -18,13 +18,13 @@ package org.apache.calcite.rel; import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.ConventionTraitDef; +import org.apache.calcite.plan.Digest; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelOptQuery; 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.metadata.Metadata; @@ -70,13 +70,9 @@ public abstract class AbstractRelNode implements RelNode { protected RelDataType rowType; /** - * A short description of this relational expression's type, inputs, and - * other properties. The string uniquely identifies the node; another node - * is equivalent if and only if it has the same value. Computed by - * {@link #computeDigest}, assigned by {@link #onRegister}, returned by - * {@link #getDigest()}. + * The digest that uniquely identifies the node. */ - protected String digest; + protected Digest digest; private final RelOptCluster cluster; @@ -101,7 +97,7 @@ public abstract class AbstractRelNode implements RelNode { this.cluster = cluster; this.traitSet = traitSet; this.id = NEXT_ID.getAndIncrement(); - this.digest = getRelTypeName() + "#" + id; + this.digest = Digest.initial(this); LOGGER.trace("new {}", digest); } @@ -148,13 +144,13 @@ public abstract class AbstractRelNode implements RelNode { return null; } - @SuppressWarnings("deprecation") + @Deprecated // to be removed before 1.25 public boolean isDistinct() { final RelMetadataQuery mq = cluster.getMetadataQuery(); return Boolean.TRUE.equals(mq.areRowsUnique(this)); } - @SuppressWarnings("deprecation") + @Deprecated // to be removed before 1.25 public boolean isKey(ImmutableBitSet columns) { final RelMetadataQuery mq = cluster.getMetadataQuery(); return Boolean.TRUE.equals(mq.areColumnsUnique(this, columns)); @@ -169,7 +165,7 @@ public abstract class AbstractRelNode implements RelNode { return inputs.get(i); } - @SuppressWarnings("deprecation") + @Deprecated // to be removed before 1.25 public final RelOptQuery getQuery() { return getCluster().getQuery(); } @@ -193,7 +189,7 @@ public abstract class AbstractRelNode implements RelNode { return litmus.succeed(); } - @SuppressWarnings("deprecation") + @Deprecated // to be removed before 1.25 public boolean isValid(boolean fail) { return isValid(Litmus.THROW, null); } @@ -226,7 +222,7 @@ public abstract class AbstractRelNode implements RelNode { return Collections.emptyList(); } - @SuppressWarnings("deprecation") + @Deprecated // to be removed before 1.25 public final double getRows() { return estimateRowCount(cluster.getMetadataQuery()); } @@ -235,7 +231,7 @@ public abstract class AbstractRelNode implements RelNode { return 1.0; } - @SuppressWarnings("deprecation") + @Deprecated // to be removed before 1.25 public final Set<String> getVariablesStopped() { return CorrelationId.names(getVariablesSet()); } @@ -281,7 +277,6 @@ public abstract class AbstractRelNode implements RelNode { RelMetadataQuery mq) { // by default, assume cost is proportional to number of rows double rowCount = mq.getRowCount(this); - double bytesPerRow = 1; return planner.getCostFactory().makeCost(rowCount, rowCount, 0); } @@ -323,15 +318,11 @@ public abstract class AbstractRelNode implements RelNode { List<RelNode> inputs = new ArrayList<>(oldInputs.size()); for (final RelNode input : oldInputs) { RelNode e = planner.ensureRegistered(input, null); - if (e != input) { - // TODO: change 'equal' to 'eq', which is stronger. - assert RelOptUtil.equal( - "rowtype of rel before registration", - input.getRowType(), - "rowtype of rel after registration", - e.getRowType(), - Litmus.THROW); - } + assert e == input || RelOptUtil.equal("rowtype of rel before registration", + input.getRowType(), + "rowtype of rel after registration", + e.getRowType(), + Litmus.THROW); inputs.add(e); } RelNode r = this; @@ -343,7 +334,7 @@ public abstract class AbstractRelNode implements RelNode { return r; } - public String recomputeDigest() { + public Digest recomputeDigest() { digest = computeDigest(); assert digest != null : "computeDigest() should be non-null"; return digest; @@ -355,20 +346,20 @@ public abstract class AbstractRelNode implements RelNode { throw new UnsupportedOperationException("replaceInput called on " + this); } - /* Description, consists of id plus digest */ + /** Description, consists of id plus digest */ public String toString() { StringBuilder sb = new StringBuilder(); - sb = RelOptUtil.appendRelDescription(sb, this); + RelOptUtil.appendRelDescription(sb, this); return sb.toString(); } - /* Description, consists of id plus digest */ + /** Description, consists of id plus digest */ @Deprecated // to be removed before 2.0 public final String getDescription() { return this.toString(); } - public final String getDigest() { + public final Digest getDigest() { return digest; } @@ -381,7 +372,7 @@ public abstract class AbstractRelNode implements RelNode { * * @return Digest */ - protected String computeDigest() { + protected Digest computeDigest() { RelDigestWriter rdw = new RelDigestWriter(); explain(rdw); return rdw.digest; @@ -421,7 +412,7 @@ public abstract class AbstractRelNode implements RelNode { private final List<Pair<String, Object>> values = new ArrayList<>(); - String digest = null; + Digest digest = null; @Override public void explain(final RelNode rel, final List<Pair<String, Object>> valueList) { throw new IllegalStateException("Should not be called for computing digest"); @@ -437,33 +428,7 @@ public abstract class AbstractRelNode implements RelNode { } @Override public RelWriter done(RelNode node) { - StringBuilder sb = new StringBuilder(); - sb.append(node.getRelTypeName()); - - for (RelTrait trait : node.getTraitSet()) { - sb.append('.'); - sb.append(trait.toString()); - } - - sb.append('('); - int j = 0; - for (Pair<String, Object> value : values) { - if (j++ > 0) { - sb.append(','); - } - sb.append(value.left); - sb.append('='); - if (value.right instanceof RelNode) { - RelNode input = (RelNode) value.right; - sb.append(input.getRelTypeName()); - sb.append('#'); - sb.append(input.getId()); - } else { - sb.append(value.right); - } - } - sb.append(')'); - digest = sb.toString(); + digest = Digest.create(node, values); return this; } } 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 11c35ef..18ff76f 100644 --- a/core/src/main/java/org/apache/calcite/rel/RelNode.java +++ b/core/src/main/java/org/apache/calcite/rel/RelNode.java @@ -17,6 +17,7 @@ package org.apache.calcite.rel; import org.apache.calcite.plan.Convention; +import org.apache.calcite.plan.Digest; import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptNode; import org.apache.calcite.plan.RelOptPlanner; @@ -308,7 +309,7 @@ public interface RelNode extends RelOptNode, Cloneable { * * @return Digest of this relational expression */ - String recomputeDigest(); + Digest recomputeDigest(); /** * Replaces the <code>ordinalInParent</code><sup>th</sup> input. You must diff --git a/core/src/main/java/org/apache/calcite/rel/RelWriter.java b/core/src/main/java/org/apache/calcite/rel/RelWriter.java index 4f6d114..92f78b6 100644 --- a/core/src/main/java/org/apache/calcite/rel/RelWriter.java +++ b/core/src/main/java/org/apache/calcite/rel/RelWriter.java @@ -16,12 +16,9 @@ */ package org.apache.calcite.rel; -import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.SqlExplainLevel; import org.apache.calcite.util.Pair; -import org.apiguardian.api.API; - import java.util.List; /** @@ -88,16 +85,4 @@ public interface RelWriter { default boolean nest() { return false; } - - /** - * Activates {@link RexNode} normalization if {@link SqlExplainLevel#DIGEST_ATTRIBUTES} is used. - * Note: the returned value must be closed, and the API is designed to be used with a - * try-with-resources. - * @return a handle that should be closed to revert normalization state - */ - @API(since = "1.22", status = API.Status.EXPERIMENTAL) - default RexNode.Closeable withRexNormalize() { - boolean needNormalize = getDetailLevel() == SqlExplainLevel.DIGEST_ATTRIBUTES; - return RexNode.withNormalize(needNormalize); - } } diff --git a/core/src/main/java/org/apache/calcite/rel/core/Match.java b/core/src/main/java/org/apache/calcite/rel/core/Match.java index 12fe3b9..4b1a5ca 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/Match.java +++ b/core/src/main/java/org/apache/calcite/rel/core/Match.java @@ -332,5 +332,15 @@ public abstract class Match extends SingleRel { @Override public int compareTo(RexMRAggCall o) { return toString().compareTo(o.toString()); } + + @Override public boolean equals(Object obj) { + return obj == this + || obj instanceof RexMRAggCall + && toString().equals(obj.toString()); + } + + @Override public int hashCode() { + return toString().hashCode(); + } } } diff --git a/core/src/main/java/org/apache/calcite/rel/core/Window.java b/core/src/main/java/org/apache/calcite/rel/core/Window.java index 71176e5..620afe6 100644 --- a/core/src/main/java/org/apache/calcite/rel/core/Window.java +++ b/core/src/main/java/org/apache/calcite/rel/core/Window.java @@ -394,16 +394,24 @@ public abstract class Window extends SingleRel { this.ignoreNulls = ignoreNulls; } - /** {@inheritDoc} - * - * <p>Override {@link RexCall}, defining equality based on identity. - */ - @Override public boolean equals(Object obj) { - return this == obj; + @Override public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + RexWinAggCall that = (RexWinAggCall) o; + return ordinal == that.ordinal + && distinct == that.distinct + && ignoreNulls == that.ignoreNulls; } @Override public int hashCode() { - return Objects.hash(digest, ordinal, distinct); + return Objects.hash(super.hashCode(), ordinal, distinct, ignoreNulls); } @Override public RexCall clone(RelDataType type, List<RexNode> operands) { diff --git a/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonWriter.java b/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonWriter.java index acdd2cf..5b6a346 100644 --- a/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonWriter.java +++ b/core/src/main/java/org/apache/calcite/rel/externalize/RelJsonWriter.java @@ -18,7 +18,6 @@ package org.apache.calcite.rel.externalize; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelWriter; -import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.SqlExplainLevel; import org.apache.calcite.util.JsonBuilder; import org.apache.calcite.util.Pair; @@ -141,8 +140,6 @@ public class RelJsonWriter implements RelWriter { public String asString() { final Map<String, Object> map = jsonBuilder.map(); map.put("rels", relList); - try (RexNode.Closeable ignored = withRexNormalize()) { - return jsonBuilder.toJsonString(map); - } + return jsonBuilder.toJsonString(map); } } diff --git a/core/src/main/java/org/apache/calcite/rel/externalize/RelWriterImpl.java b/core/src/main/java/org/apache/calcite/rel/externalize/RelWriterImpl.java index 02eec8b..3fd1ebc 100644 --- a/core/src/main/java/org/apache/calcite/rel/externalize/RelWriterImpl.java +++ b/core/src/main/java/org/apache/calcite/rel/externalize/RelWriterImpl.java @@ -21,7 +21,6 @@ import org.apache.calcite.linq4j.Ord; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelWriter; import org.apache.calcite.rel.metadata.RelMetadataQuery; -import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.SqlExplainLevel; import org.apache.calcite.util.Pair; @@ -125,9 +124,7 @@ public class RelWriterImpl implements RelWriter { } public final void explain(RelNode rel, List<Pair<String, Object>> valueList) { - try (RexNode.Closeable ignored = withRexNormalize()) { - explain_(rel, valueList); - } + explain_(rel, valueList); } public SqlExplainLevel getDetailLevel() { @@ -144,9 +141,7 @@ public class RelWriterImpl implements RelWriter { final List<Pair<String, Object>> valuesCopy = ImmutableList.copyOf(values); values.clear(); - try (RexNode.Closeable ignored = withRexNormalize()) { - explain_(node, valuesCopy); - } + explain_(node, valuesCopy); pw.flush(); return this; } @@ -169,15 +164,13 @@ public class RelWriterImpl implements RelWriter { */ public String simple() { final StringBuilder buf = new StringBuilder("("); - try (RexNode.Closeable ignored = withRexNormalize()) { - for (Ord<Pair<String, Object>> ord : Ord.zip(values)) { - if (ord.i > 0) { - buf.append(", "); - } - buf.append(ord.e.left).append("=[").append(ord.e.right).append("]"); + for (Ord<Pair<String, Object>> ord : Ord.zip(values)) { + if (ord.i > 0) { + buf.append(", "); } - buf.append(")"); + buf.append(ord.e.left).append("=[").append(ord.e.right).append("]"); } + buf.append(")"); return buf.toString(); } } 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 7f495b1..6aba8b3 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 @@ -361,7 +361,7 @@ public class RelMdExpressionLineage // Infer column origin expressions for given references final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>(); for (int idx : inputFieldsUsed) { - final RexNode inputExpr = rel.getChildExps().get(idx); + final RexNode inputExpr = rel.getProjects().get(idx); final Set<RexNode> originalExprs = mq.getExpressionLineage(input, inputExpr); if (originalExprs == null) { // Bail out diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java index a4fcd42..083e5e1 100644 --- a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java +++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java @@ -326,13 +326,13 @@ public class RelToSqlConverter extends SqlImplementor e.getVariablesSet(); Result x = visitChild(0, e.getInput()); parseCorrelTable(e, x); - if (isStar(e.getChildExps(), e.getInput().getRowType(), e.getRowType())) { + if (isStar(e.getProjects(), e.getInput().getRowType(), e.getRowType())) { return x; } final Builder builder = x.builder(e, Clause.SELECT); final List<SqlNode> selectList = new ArrayList<>(); - for (RexNode ref : e.getChildExps()) { + for (RexNode ref : e.getProjects()) { SqlNode sqlExpr = builder.context.toSql(null, ref); if (SqlUtil.isNullLiteral(sqlExpr, false)) { sqlExpr = castNullType(sqlExpr, e.getRowType().getFieldList().get(selectList.size())); diff --git a/core/src/main/java/org/apache/calcite/rel/rules/JoinProjectTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/JoinProjectTransposeRule.java index 085b3e6..b3104dc 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/JoinProjectTransposeRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/JoinProjectTransposeRule.java @@ -171,11 +171,11 @@ public class JoinProjectTransposeRule extends RelOptRule implements Transformati } // Skip projects containing over clause - if (leftProj != null && RexOver.containsOver(leftProj.getChildExps(), null)) { + if (leftProj != null && RexOver.containsOver(leftProj.getProjects(), null)) { leftProj = null; leftJoinChild = joinRel.getLeft(); } - if (rightProj != null && RexOver.containsOver(rightProj.getChildExps(), null)) { + if (rightProj != null && RexOver.containsOver(rightProj.getProjects(), null)) { rightProj = null; rightJoinChild = joinRel.getRight(); } diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ProjectWindowTransposeRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ProjectWindowTransposeRule.java index 74b9a96..de52288 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/ProjectWindowTransposeRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/ProjectWindowTransposeRule.java @@ -174,7 +174,7 @@ public class ProjectWindowTransposeRule extends RelOptRule implements Transforma // Modify the top LogicalProject final List<RexNode> topProjExps = - indexAdjustment.visitList(project.getChildExps()); + indexAdjustment.visitList(project.getProjects()); final LogicalProject newTopProj = project.copy( newLogicalWindow.getTraitSet(), @@ -205,7 +205,7 @@ public class ProjectWindowTransposeRule extends RelOptRule implements Transforma }; // Reference in LogicalProject - referenceFinder.visitEach(project.getChildExps()); + referenceFinder.visitEach(project.getProjects()); // Reference in LogicalWindow for (Window.Group group : window.groups) { diff --git a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java index f4c318d..9ccacf6 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java @@ -225,9 +225,9 @@ public abstract class MaterializedViewAggregateRule extends MaterializedViewRule 0, 0, aggregateViewNode.getGroupCount(), newViewNode.getGroupCount(), aggregateViewNode.getGroupCount(), aggregateViewNode.getAggCallList().size()); - for (int i = 0; i < topViewProject.getChildExps().size(); i++) { + for (int i = 0; i < topViewProject.getProjects().size(); i++) { nodes.add( - topViewProject.getChildExps().get(i).accept( + topViewProject.getProjects().get(i).accept( new RexPermuteInputsShuttle(shiftMapping, newViewNode))); fieldNames.add(topViewProject.getRowType().getFieldNames().get(i)); } @@ -414,7 +414,7 @@ public abstract class MaterializedViewAggregateRule extends MaterializedViewRule // We have a Project on top, gather only what is needed final RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(new LinkedHashSet<>()); - inputFinder.visitEach(topProject.getChildExps()); + inputFinder.visitEach(topProject.getProjects()); references = inputFinder.build(); for (int i = 0; i < queryAggregate.getGroupCount(); i++) { indexes.set(queryAggregate.getGroupSet().nth(i)); @@ -561,8 +561,8 @@ public abstract class MaterializedViewAggregateRule extends MaterializedViewRule final ImmutableBitSet refs = RelOptUtil.InputFinder.bits(targetNode); for (int childTargetIdx : refs) { added = false; - for (int k = 0; k < topViewProject.getChildExps().size() && !added; k++) { - RexNode n = topViewProject.getChildExps().get(k); + for (int k = 0; k < topViewProject.getProjects().size() && !added; k++) { + RexNode n = topViewProject.getProjects().get(k); if (!n.isA(SqlKind.INPUT_REF)) { continue; } @@ -589,8 +589,8 @@ public abstract class MaterializedViewAggregateRule extends MaterializedViewRule added = true; } else { // This expression should be referenced directly - for (int k = 0; k < topViewProject.getChildExps().size() && !added; k++) { - RexNode n = topViewProject.getChildExps().get(k); + for (int k = 0; k < topViewProject.getProjects().size() && !added; k++) { + RexNode n = topViewProject.getProjects().get(k); if (!n.isA(SqlKind.INPUT_REF)) { continue; } @@ -623,8 +623,8 @@ public abstract class MaterializedViewAggregateRule extends MaterializedViewRule } AggregateCall queryAggCall = queryAggregate.getAggCallList().get(i); boolean added = false; - for (int k = 0; k < topViewProject.getChildExps().size() && !added; k++) { - RexNode n = topViewProject.getChildExps().get(k); + for (int k = 0; k < topViewProject.getProjects().size() && !added; k++) { + RexNode n = topViewProject.getProjects().get(k); if (!n.isA(SqlKind.INPUT_REF)) { continue; } @@ -701,7 +701,7 @@ public abstract class MaterializedViewAggregateRule extends MaterializedViewRule final RelDataType topRowType; final List<RexNode> topExprs = new ArrayList<>(); if (topProject != null && !unionRewriting) { - topExprs.addAll(topProject.getChildExps()); + topExprs.addAll(topProject.getProjects()); topRowType = topProject.getRowType(); } else { // Add all @@ -713,7 +713,7 @@ public abstract class MaterializedViewAggregateRule extends MaterializedViewRule // Available in view. final Multimap<RexNode, Integer> viewExprs = ArrayListMultimap.create(); int numberViewExprs = 0; - for (RexNode viewExpr : topViewProject.getChildExps()) { + for (RexNode viewExpr : topViewProject.getProjects()) { viewExprs.put(viewExpr, numberViewExprs++); } for (RexNode additionalViewExpr : additionalViewExprs) { diff --git a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewJoinRule.java b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewJoinRule.java index 7b470fb..ef0fcd2 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewJoinRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewJoinRule.java @@ -245,7 +245,7 @@ public abstract class MaterializedViewJoinRule extends MaterializedViewRule { EquivalenceClasses queryEC) { List<RexNode> exprs = topProject == null ? extractReferences(rexBuilder, node) - : topProject.getChildExps(); + : topProject.getProjects(); List<RexNode> exprsLineage = new ArrayList<>(exprs.size()); for (RexNode expr : exprs) { Set<RexNode> s = mq.getExpressionLineage(node, expr); @@ -262,7 +262,7 @@ public abstract class MaterializedViewJoinRule extends MaterializedViewRule { } List<RexNode> viewExprs = topViewProject == null ? extractReferences(rexBuilder, viewNode) - : topViewProject.getChildExps(); + : topViewProject.getProjects(); List<RexNode> rewrittenExprs = rewriteExpressions(rexBuilder, mq, input, viewNode, viewExprs, queryToViewTableMapping.inverse(), queryEC, true, exprsLineage); if (rewrittenExprs == null) { diff --git a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewRule.java b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewRule.java index fc3741c..00e9722 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewRule.java @@ -428,7 +428,7 @@ public abstract class MaterializedViewRule extends RelOptRule { // in the view output (condition 2). List<RexNode> viewExprs = topViewProject == null ? extractReferences(rexBuilder, view) - : topViewProject.getChildExps(); + : topViewProject.getProjects(); // For compensationColumnsEquiPred, we use the view equivalence classes, // since we want to enforce the rest if (!compensationColumnsEquiPred.isAlwaysTrue()) { diff --git a/core/src/main/java/org/apache/calcite/rex/RexCall.java b/core/src/main/java/org/apache/calcite/rex/RexCall.java index d5c2cea..6b8f2ac 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexCall.java +++ b/core/src/main/java/org/apache/calcite/rex/RexCall.java @@ -22,18 +22,16 @@ import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSyntax; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.Litmus; +import org.apache.calcite.util.Pair; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Sets; import java.util.ArrayList; -import java.util.Comparator; -import java.util.EnumSet; import java.util.List; import java.util.Objects; -import java.util.Set; import javax.annotation.Nonnull; /** @@ -53,12 +51,6 @@ import javax.annotation.Nonnull; * no one is going to be generating source code from this tree.)</p> */ public class RexCall extends RexNode { - /** - * Sort shorter digests first, then order by string representation. - * The result is designed for consistent output and better readability. - */ - private static final Comparator<String> OPERAND_READABILITY_COMPARATOR = - Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder()); //~ Instance fields -------------------------------------------------------- @@ -67,22 +59,6 @@ public class RexCall extends RexNode { public final RelDataType type; public final int nodeCount; - /** - * Simple binary operators are those operators which expects operands from the same Domain. - * - * <p>Example: simple comparisions ({@code =}, {@code <}). - * - * <p>Note: it does not contain {@code IN} because that is defined on D x D^n. - */ - private static final Set<SqlKind> SIMPLE_BINARY_OPS; - - static { - EnumSet<SqlKind> kinds = EnumSet.of(SqlKind.PLUS, SqlKind.MINUS, SqlKind.TIMES, SqlKind.DIVIDE); - kinds.addAll(SqlKind.COMPARISON); - kinds.remove(SqlKind.IN); - SIMPLE_BINARY_OPS = Sets.immutableEnumSet(kinds); - } - //~ Constructors ----------------------------------------------------------- protected RexCall( @@ -90,8 +66,11 @@ public class RexCall extends RexNode { SqlOperator op, List<? extends RexNode> operands) { this.type = Objects.requireNonNull(type, "type"); - this.op = Objects.requireNonNull(op, "operator"); - this.operands = ImmutableList.copyOf(operands); + Objects.requireNonNull(op, "operator"); + final Pair<SqlOperator, ImmutableList<RexNode>> normalized = + normalize(op, operands); + this.op = normalized.left; + this.operands = normalized.right; this.nodeCount = RexUtil.nodeCount(1, this.operands); assert op.getKind() != null : op; assert op.validRexOperands(operands.size(), Litmus.THROW) : this; @@ -108,11 +87,10 @@ public class RexCall extends RexNode { * * @see RexLiteral#computeDigest(RexDigestIncludeType) * @param sb destination - * @return original StringBuilder for fluent API */ - protected final StringBuilder appendOperands(StringBuilder sb) { + protected final void appendOperands(StringBuilder sb) { if (operands.isEmpty()) { - return sb; + return; } List<String> operandDigests = new ArrayList<>(operands.size()); for (int i = 0; i < operands.size(); i++) { @@ -123,15 +101,16 @@ public class RexCall extends RexNode { } // Type information might be omitted in certain cases to improve readability // For instance, AND/OR arguments should be BOOLEAN, so - // AND(true, null) is better than AND(true, null:BOOLEAN), and we keep the same info - // +($0, 2) is better than +($0, 2:BIGINT). Note: if $0 has BIGINT, then 2 is expected to be + // AND(true, null) is better than AND(true, null:BOOLEAN), and we keep the same info. + + // +($0, 2) is better than +($0, 2:BIGINT). Note: if $0 is BIGINT, then 2 is expected to be // of BIGINT type as well. RexDigestIncludeType includeType = RexDigestIncludeType.OPTIONAL; if ((isA(SqlKind.AND) || isA(SqlKind.OR)) && operand.getType().getSqlTypeName() == SqlTypeName.BOOLEAN) { includeType = RexDigestIncludeType.NO_TYPE; } - if (SIMPLE_BINARY_OPS.contains(getKind()) && operands.size() == 2) { + if (SqlKind.SIMPLE_BINARY_OPS.contains(getKind())) { RexNode otherArg = operands.get(1 - i); if ((!(otherArg instanceof RexLiteral) || ((RexLiteral) otherArg).digestIncludesType() == RexDigestIncludeType.NO_TYPE) @@ -146,7 +125,6 @@ public class RexCall extends RexNode { totalLength += s.length(); } sb.ensureCapacity(sb.length() + totalLength); - sortOperandsIfNeeded(sb, operands, operandDigests); for (int i = 0; i < operandDigests.size(); i++) { String op = operandDigests.get(i); if (i != 0) { @@ -154,72 +132,58 @@ public class RexCall extends RexNode { } sb.append(op); } - return sb; } - private void sortOperandsIfNeeded(StringBuilder sb, - List<RexNode> operands, List<String> operandDigests) { - if (operands.isEmpty() || !needNormalize()) { - return; + private Pair<SqlOperator, ImmutableList<RexNode>> normalize( + SqlOperator operator, + List<? extends RexNode> operands) { + final ImmutableList<RexNode> oldOperands = ImmutableList.copyOf(operands); + final Pair<SqlOperator, ImmutableList<RexNode>> original = Pair.of(operator, oldOperands); + if (!needNormalize()) { + return original; + } + if (operands.size() != 2 + || !operands.stream().allMatch(operand -> operand.getClass() == RexInputRef.class)) { + return original; } - final SqlKind kind = op.getKind(); + final RexInputRef operand0 = (RexInputRef) operands.get(0); + final RexInputRef operand1 = (RexInputRef) operands.get(1); + final SqlKind kind = operator.getKind(); + if (operand0.getIndex() < operand1.getIndex()) { + return original; + } + // If arguments are the same, then we normalize < vs > + // '<' == 60, '>' == 62, so we prefer <. + if (operand0.getIndex() == operand1.getIndex()) { + if (kind.reverse().compareTo(kind) < 0) { + return Pair.of(SqlStdOperatorTable.reverse(operator), oldOperands); + } else { + return original; + } + } + if (SqlKind.SYMMETRICAL_SAME_ARG_TYPE.contains(kind)) { final RelDataType firstType = operands.get(0).getType(); for (int i = 1; i < operands.size(); i++) { if (!equalSansNullability(firstType, operands.get(i).getType())) { // Arguments have different type, thus they must not be sorted - return; + return original; } } // fall through: order arguments below } else if (!SqlKind.SYMMETRICAL.contains(kind) - && (kind == kind.reverse() - || !op.getName().equals(kind.sql) - || sb.length() < kind.sql.length() + 1 - || sb.charAt(sb.length() - 1) != '(')) { + && kind == kind.reverse()) { // The operations have to be either symmetrical or reversible // Nothing matched => we skip argument sorting - // Note: RexCall digest uses op.getName() that might be different from kind.sql - // for certain calls. So we skip normalizing the calls that have customized op.getName() - // We ensure the current string contains enough room for preceding kind.sql otherwise - // we won't have an option to replace the operator to reverse it in case the operands are - // reordered. - return; + return original; } - // $0=$1 is the same as $1=$0, so we make sure the digest is the same for them - String oldFirstArg = operandDigests.get(0); - operandDigests.sort(OPERAND_READABILITY_COMPARATOR); + // $0=$1 is the same as $1=$0, so we make sure the digest is the same for them. // When $1 > $0 is normalized, the operation needs to be flipped - // So we sort arguments first, then flip the sign - if (kind != kind.reverse()) { - assert operands.size() == 2 - : "Compare operation must have 2 arguments: " + this - + ". Actual arguments are " + operandDigests; - int operatorEnd = sb.length() - 1 /* ( */; - int operatorStart = operatorEnd - op.getName().length(); - assert op.getName().contentEquals(sb.subSequence(operatorStart, operatorEnd)) - : "Operation name must precede opening brace like in <=(x, y). Actual content is " - + sb.subSequence(operatorStart, operatorEnd) - + " at position " + operatorStart + " in " + sb; - - SqlKind newKind = kind.reverse(); - - // If arguments are the same, then we normalize < vs > - // '<' == 60, '>' == 62, so we prefer < - if (operandDigests.get(0).equals(operandDigests.get(1))) { - if (newKind.compareTo(kind) > 0) { - // If reverse kind is greater, then skip reversing - return; - } - } else if (oldFirstArg.equals(operandDigests.get(0))) { - // The sorting did not shuffle the operands, so we do not need to update operation name - // in the digest - return; - } - // Replace operator name in the digest - sb.replace(operatorStart, operatorEnd, newKind.sql); - } + // So we sort arguments first, then flip the sign. + final SqlOperator newOp = SqlStdOperatorTable.reverse(operator); + final ImmutableList<RexNode> newOperands = ImmutableList.of(operand1, operand0); + return Pair.of(newOp, newOperands); } /** @@ -359,13 +323,19 @@ public class RexCall extends RexNode { return new RexCall(type, op, operands); } - @Override public boolean equals(Object obj) { - return obj == this - || obj instanceof RexCall - && toString().equals(obj.toString()); + @Override public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RexCall rexCall = (RexCall) o; + return op.equals(rexCall.op) + && operands.equals(rexCall.operands); } @Override public int hashCode() { - return toString().hashCode(); + return Objects.hash(op, operands); } } diff --git a/core/src/main/java/org/apache/calcite/rex/RexNode.java b/core/src/main/java/org/apache/calcite/rex/RexNode.java index 7a8f058..88332a2 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexNode.java +++ b/core/src/main/java/org/apache/calcite/rex/RexNode.java @@ -23,7 +23,6 @@ import org.apache.calcite.sql.SqlKind; import org.apiguardian.api.API; import java.util.Collection; -import java.util.concurrent.atomic.AtomicInteger; /** * Row expression. @@ -40,54 +39,6 @@ import java.util.concurrent.atomic.AtomicInteger; * <p>All sub-classes of RexNode are immutable.</p> */ public abstract class RexNode { - /** - * Sometimes RexCall nodes are located deep (e.g. inside Lists), - * If the value is non-zero, then a non-normalized representation is printed. - * int is used to allow for re-entrancy. - */ - private static final ThreadLocal<AtomicInteger> DESCRIBE_WITHOUT_NORMALIZE = - ThreadLocal.withInitial(AtomicInteger::new); - - /** Removes a Hook after use. */ - @API(since = "1.22", status = API.Status.EXPERIMENTAL) - public interface Closeable extends AutoCloseable { - // override, removing "throws" - @Override void close(); - } - - private static final Closeable DECREMENT_ON_CLOSE = () -> { - DESCRIBE_WITHOUT_NORMALIZE.get().decrementAndGet(); - }; - - private static final Closeable EMPTY = () -> { }; - - /** - * The digest of {@code RexNode} is normalized by default, however, sometimes a non-normalized - * representation is required. - * This API enables to skip normalization. - * Note: the returned value must be closed, and the API is designed to be used with a - * try-with-resources. - * @param needNormalize true if normalization should be enabled or false if it should be skipped - * @return a handle that should be closed to revert normalization state - */ - @API(since = "1.22", status = API.Status.EXPERIMENTAL) - public static Closeable withNormalize(boolean needNormalize) { - return needNormalize ? EMPTY : skipNormalize(); - } - - /** - * The digest of {@code RexNode} is normalized by default, however, sometimes a non-normalized - * representation is required. - * This API enables to skip normalization. - * Note: the returned value must be closed, and the API is designed to be used with a - * try-with-resources. - * @return a handle that should be closed to revert normalization state - */ - @API(since = "1.22", status = API.Status.EXPERIMENTAL) - public static Closeable skipNormalize() { - DESCRIBE_WITHOUT_NORMALIZE.get().incrementAndGet(); - return DECREMENT_ON_CLOSE; - } /** * The digest of {@code RexNode} is normalized by default, however, sometimes a non-normalized @@ -97,8 +48,7 @@ public abstract class RexNode { */ @API(since = "1.22", status = API.Status.EXPERIMENTAL) protected static boolean needNormalize() { - return DESCRIBE_WITHOUT_NORMALIZE.get().get() == 0 - && CalciteSystemProperty.ENABLE_REX_DIGEST_NORMALIZE.value(); + return CalciteSystemProperty.ENABLE_REX_DIGEST_NORMALIZE.value(); } //~ Instance fields -------------------------------------------------------- @@ -147,17 +97,6 @@ public abstract class RexNode { return digest; } - /** - * Returns string representation of this node. - * @return the same as {@link #toString()}, but without normalizing the output - */ - @API(since = "1.22", status = API.Status.EXPERIMENTAL) - public String toStringRaw() { - try (Closeable ignored = skipNormalize()) { - return toString(); - } - } - /** Returns the number of nodes in this expression. * * <p>Leaf nodes, such as {@link RexInputRef} or {@link RexLiteral}, have diff --git a/core/src/main/java/org/apache/calcite/rex/RexOver.java b/core/src/main/java/org/apache/calcite/rex/RexOver.java index cfdd6c2..e90fa3c 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexOver.java +++ b/core/src/main/java/org/apache/calcite/rex/RexOver.java @@ -196,4 +196,25 @@ public class RexOver extends RexCall { throw OverFound.INSTANCE; } } + + @Override public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + RexOver rexOver = (RexOver) o; + return distinct == rexOver.distinct + && ignoreNulls == rexOver.ignoreNulls + && window.equals(rexOver.window) + && op.allowsFraming() == rexOver.op.allowsFraming(); + } + + @Override public int hashCode() { + return Objects.hash(super.hashCode(), window, distinct, ignoreNulls, op.allowsFraming()); + } } diff --git a/core/src/main/java/org/apache/calcite/rex/RexSubQuery.java b/core/src/main/java/org/apache/calcite/rex/RexSubQuery.java index 5a081dc..d702387 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexSubQuery.java +++ b/core/src/main/java/org/apache/calcite/rex/RexSubQuery.java @@ -136,4 +136,14 @@ public class RexSubQuery extends RexCall { public RexSubQuery clone(RelNode rel) { return new RexSubQuery(type, getOperator(), operands, rel); } + + @Override public boolean equals(Object obj) { + return obj == this + || obj instanceof RexCall + && toString().equals(obj.toString()); + } + + @Override public int hashCode() { + return toString().hashCode(); + } } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlKind.java b/core/src/main/java/org/apache/calcite/sql/SqlKind.java index b3e42a8..f98a0c2 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlKind.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlKind.java @@ -16,6 +16,8 @@ */ package org.apache.calcite.sql; +import com.google.common.collect.Sets; + import org.apiguardian.api.API; import java.util.Collection; @@ -1373,6 +1375,23 @@ public enum SqlKind { EnumSet.of( PLUS, TIMES); + /** + * Simple binary operators are those operators which expects operands from the same Domain. + * + * <p>Example: simple comparisions ({@code =}, {@code <}). + * + * <p>Note: it does not contain {@code IN} because that is defined on D x D^n. + */ + @API(since = "1.24", status = API.Status.EXPERIMENTAL) + public static final Set<SqlKind> SIMPLE_BINARY_OPS; + + static { + EnumSet<SqlKind> kinds = EnumSet.of(SqlKind.PLUS, SqlKind.MINUS, SqlKind.TIMES, SqlKind.DIVIDE); + kinds.addAll(SqlKind.COMPARISON); + kinds.remove(SqlKind.IN); + SIMPLE_BINARY_OPS = Sets.immutableEnumSet(kinds); + } + /** Lower-case name. */ public final String lowerName = name().toLowerCase(Locale.ROOT); public final String sql; diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java index e026b95..3a6027d 100644 --- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java +++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java @@ -2595,4 +2595,24 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable { } } + /** Returns the binary operator that corresponds to this operator but in the opposite + * direction. Or returns this, if its kind is not reversible. + * + * <p>For example, {@code reverse(GREATER_THAN)} returns {@link #LESS_THAN}. + */ + public static SqlOperator reverse(SqlOperator operator) { + switch (operator.getKind()) { + case GREATER_THAN: + return LESS_THAN; + case GREATER_THAN_OR_EQUAL: + return LESS_THAN_OR_EQUAL; + case LESS_THAN: + return GREATER_THAN; + case LESS_THAN_OR_EQUAL: + return GREATER_THAN_OR_EQUAL; + default: + return operator; + } + } + } diff --git a/core/src/test/java/org/apache/calcite/materialize/LatticeSuggesterTest.java b/core/src/test/java/org/apache/calcite/materialize/LatticeSuggesterTest.java index bc3cc8e..f56d49c 100644 --- a/core/src/test/java/org/apache/calcite/materialize/LatticeSuggesterTest.java +++ b/core/src/test/java/org/apache/calcite/materialize/LatticeSuggesterTest.java @@ -670,12 +670,12 @@ class LatticeSuggesterTest { t.addQuery(q0); assertThat(t.s.latticeMap.size(), is(1)); assertThat(t.s.latticeMap.keySet().iterator().next(), - is("sales_fact_1997 (customer:+(2, $2)):[MIN(customer.fname)]")); + is("sales_fact_1997 (customer:+($2, 2)):[MIN(customer.fname)]")); assertThat(t.s.space.g.toString(), is("graph(vertices: [[foodmart, customer]," + " [foodmart, sales_fact_1997]], " + "edges: [Step([foodmart, sales_fact_1997]," - + " [foodmart, customer], +(2, $2):+(1, $0))])")); + + " [foodmart, customer], +($2, 2):+($0, 1))])")); } /** Tests that we can run the suggester against non-JDBC schemas. diff --git a/core/src/test/java/org/apache/calcite/plan/RelOptUtilTest.java b/core/src/test/java/org/apache/calcite/plan/RelOptUtilTest.java index d567ce1..5af0d27 100644 --- a/core/src/test/java/org/apache/calcite/plan/RelOptUtilTest.java +++ b/core/src/test/java/org/apache/calcite/plan/RelOptUtilTest.java @@ -389,7 +389,7 @@ class RelOptUtilTest { .toString())); assertThat(newJoin.getLeft(), is(instanceOf(Project.class))); Project leftInput = (Project) newJoin.getLeft(); - assertThat(leftInput.getChildExps().get(empRow.getFieldCount()).toString(), + assertThat(leftInput.getProjects().get(empRow.getFieldCount()).toString(), is(relBuilder.call(SqlStdOperatorTable.PLUS, leftKeyInputRef, relBuilder.literal(1)) .toString())); } @@ -434,7 +434,7 @@ class RelOptUtilTest { .toString())); assertThat(newJoin.getLeft(), is(instanceOf(Project.class))); Project leftInput = (Project) newJoin.getLeft(); - assertThat(leftInput.getChildExps().get(empRow.getFieldCount()).toString(), + assertThat(leftInput.getProjects().get(empRow.getFieldCount()).toString(), is(relBuilder.call(SqlStdOperatorTable.PLUS, leftKeyInputRef, relBuilder.literal(1)) .toString())); @@ -486,7 +486,7 @@ class RelOptUtilTest { .toString())); assertThat(newJoin.getLeft(), is(instanceOf(Project.class))); Project leftInput = (Project) newJoin.getLeft(); - assertThat(leftInput.getChildExps().get(empRow.getFieldCount()).toString(), + assertThat(leftInput.getProjects().get(empRow.getFieldCount()).toString(), is(relBuilder.call(SqlStdOperatorTable.PLUS, leftKeyInputRef, relBuilder.literal(1)) .toString())); } @@ -538,7 +538,7 @@ class RelOptUtilTest { .toString())); assertThat(newJoin.getLeft(), is(instanceOf(Project.class))); Project leftInput = (Project) newJoin.getLeft(); - assertThat(leftInput.getChildExps().get(empRow.getFieldCount()).toString(), + assertThat(leftInput.getProjects().get(empRow.getFieldCount()).toString(), is(relBuilder.call(SqlStdOperatorTable.PLUS, leftKeyInputRef, relBuilder.literal(1)) .toString())); } diff --git a/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java b/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java index b671282..809174b 100644 --- a/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java +++ b/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java @@ -242,12 +242,12 @@ class TraitPropagationTest { RelTraitSet outcome = child.getTraitSet().replace(PHYSICAL); call.transformTo( new PhysProj(rel.getCluster(), outcome, convert(child, outcome), - rel.getChildExps(), rel.getRowType())); + rel.getProjects(), rel.getRowType())); } } } else { call.transformTo( - PhysProj.create(input, rel.getChildExps(), rel.getRowType())); + PhysProj.create(input, rel.getProjects(), rel.getRowType())); } } diff --git a/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java b/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java index d93a223..d98b2bf 100644 --- a/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java +++ b/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java @@ -240,9 +240,9 @@ class VolcanoPlannerTest { assertThat(sort(buf), equalTo( sort( - "NoneSingleRel:Subset#0.NONE.[]", - "PhysSingleRel:Subset#0.PHYS.[0]", - "PhysSingleRel:Subset#0.PHYS.[]"))); + "NoneSingleRel:RelSubset#0.NONE.[]", + "PhysSingleRel:RelSubset#0.PHYS.[0]", + "PhysSingleRel:RelSubset#0.PHYS.[]"))); } private static <E extends Comparable> List<E> sort(List<E> list) { @@ -281,8 +281,8 @@ class VolcanoPlannerTest { assertTrue(result instanceof PhysSingleRel); assertThat(sort(buf), equalTo( - sort("PhysSingleRel:Subset#0.PHYS.[]", - "PhysSingleRel:Subset#0.PHYS_3.[]"))); + sort("PhysSingleRel:RelSubset#0.PHYS.[]", + "PhysSingleRel:RelSubset#0.PHYS_3.[]"))); } /** diff --git a/core/src/test/java/org/apache/calcite/rel/rules/DateRangeRulesTest.java b/core/src/test/java/org/apache/calcite/rel/rules/DateRangeRulesTest.java index e729288..bf4ca05 100644 --- a/core/src/test/java/org/apache/calcite/rel/rules/DateRangeRulesTest.java +++ b/core/src/test/java/org/apache/calcite/rel/rules/DateRangeRulesTest.java @@ -700,9 +700,9 @@ class DateRangeRulesTest { private void checkDateRange(Fixture f, RexNode e, String timeZone, Matcher<String> matcher, Matcher<String> simplifyMatcher) { e = DateRangeRules.replaceTimeUnits(f.rexBuilder, e, timeZone); - assertThat(e.toStringRaw(), matcher); + assertThat(e.toString(), matcher); final RexNode e2 = f.simplify.simplify(e); - assertThat(e2.toStringRaw(), simplifyMatcher); + assertThat(e2.toString(), simplifyMatcher); } /** Common expressions across tests. */ diff --git a/core/src/test/java/org/apache/calcite/rex/RexCallNormalizationTest.java b/core/src/test/java/org/apache/calcite/rex/RexCallNormalizationTest.java index e1bcbe4..38d08c1 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexCallNormalizationTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexCallNormalizationTest.java @@ -20,54 +20,40 @@ import org.junit.jupiter.api.Test; class RexCallNormalizationTest extends RexProgramTestBase { @Test void digestIsNormalized() { - final RexNode node = and(or(vBool(1), vBool()), vBool()); - checkDigest(node, "AND(?0.bool0, OR(?0.bool0, ?0.bool1))"); - checkRaw(node, "AND(OR(?0.bool1, ?0.bool0), ?0.bool0)"); + final RexNode node = and(or(input(tBool(), 1), input(tBool(), 0)), input(tBool(), 0)); + checkDigest(node, "AND(OR($0, $1), $0)"); - checkDigest(eq(vVarchar(), literal("0123456789012345")), - "=(?0.varchar0, '0123456789012345')"); - checkDigest(eq(vVarchar(), literal("01")), "=('01', ?0.varchar0)"); - } - - @Test void skipNormalizationWorks() { - final RexNode node = and(or(vBool(1), vBool()), vBool()); - try (RexNode.Closeable ignored = RexNode.skipNormalize()) { - checkDigest(node, "AND(OR(?0.bool1, ?0.bool0), ?0.bool0)"); - checkRaw(node, "AND(OR(?0.bool1, ?0.bool0), ?0.bool0)"); - } - } - - @Test void skipNormalizeWorks() { - checkDigest(and(or(vBool(1), vBool()), vBool()), - "AND(?0.bool0, OR(?0.bool0, ?0.bool1))"); + checkDigest(eq(input(tVarchar(), 0), literal("0123456789012345")), + "=($0, '0123456789012345')"); + checkDigest(eq(input(tVarchar(), 0), literal("01")), "=($0, '01')"); } @Test void reversibleSameArgOpsNormalizedToLess() { - checkDigest(lt(vBool(), vBool()), "<(?0.bool0, ?0.bool0)"); - checkDigest(gt(vBool(), vBool()), "<(?0.bool0, ?0.bool0)"); - checkDigest(le(vBool(), vBool()), "<=(?0.bool0, ?0.bool0)"); - checkDigest(ge(vBool(), vBool()), "<=(?0.bool0, ?0.bool0)"); + checkDigest(lt(input(tBool(), 0), input(tBool(), 0)), "<($0, $0)"); + checkDigest(gt(input(tBool(), 0), input(tBool(), 0)), "<($0, $0)"); + checkDigest(le(input(tBool(), 0), input(tBool(), 0)), "<=($0, $0)"); + checkDigest(ge(input(tBool(), 0), input(tBool(), 0)), "<=($0, $0)"); } @Test void reversibleDifferentArgTypesShouldNotBeShuffled() { - checkDigest(plus(vSmallInt(), vInt()), "+(?0.smallint0, ?0.int0)"); - checkDigest(plus(vInt(), vSmallInt()), "+(?0.int0, ?0.smallint0)"); - checkDigest(mul(vSmallInt(), vInt()), "*(?0.smallint0, ?0.int0)"); - checkDigest(mul(vInt(), vSmallInt()), "*(?0.int0, ?0.smallint0)"); + checkDigest(plus(input(tSmallInt(), 0), input(tInt(), 1)), "+($0, $1)"); + checkDigest(plus(input(tInt(), 0), input(tSmallInt(), 1)), "+($0, $1)"); + checkDigest(mul(input(tSmallInt(), 0), input(tInt(), 1)), "*($0, $1)"); + checkDigest(mul(input(tInt(), 0), input(tSmallInt(), 1)), "*($0, $1)"); } @Test void reversibleDifferentNullabilityArgsAreNormalized() { - checkDigest(plus(vIntNotNull(), vInt()), "+(?0.int0, ?0.notNullInt0)"); - checkDigest(plus(vInt(), vIntNotNull()), "+(?0.int0, ?0.notNullInt0)"); - checkDigest(mul(vIntNotNull(), vInt()), "*(?0.int0, ?0.notNullInt0)"); - checkDigest(mul(vInt(), vIntNotNull()), "*(?0.int0, ?0.notNullInt0)"); + checkDigest(plus(input(tInt(false), 1), input(tInt(), 0)), "+($0, $1)"); + checkDigest(plus(input(tInt(), 1), input(tInt(false), 0)), "+($0, $1)"); + checkDigest(mul(input(tInt(false), 1), input(tInt(), 0)), "*($0, $1)"); + checkDigest(mul(input(tInt(), 1), input(tInt(false), 0)), "*($0, $1)"); } @Test void symmetricalDifferentArgOps() { for (int i = 0; i < 2; i++) { int j = 1 - i; - checkDigest(eq(vBool(i), vBool(j)), "=(?0.bool0, ?0.bool1)"); - checkDigest(ne(vBool(i), vBool(j)), "<>(?0.bool0, ?0.bool1)"); + checkDigest(eq(input(tBool(), i), input(tBool(), j)), "=($0, $1)"); + checkDigest(ne(input(tBool(), i), input(tBool(), j)), "<>($0, $1)"); } } @@ -75,25 +61,25 @@ class RexCallNormalizationTest extends RexProgramTestBase { for (int i = 0; i < 2; i++) { int j = 1 - i; checkDigest( - lt(vBool(i), vBool(j)), + lt(input(tBool(), i), input(tBool(), j)), i < j - ? "<(?0.bool0, ?0.bool1)" - : ">(?0.bool0, ?0.bool1)"); + ? "<($0, $1)" + : ">($0, $1)"); checkDigest( - le(vBool(i), vBool(j)), + le(input(tBool(), i), input(tBool(), j)), i < j - ? "<=(?0.bool0, ?0.bool1)" - : ">=(?0.bool0, ?0.bool1)"); + ? "<=($0, $1)" + : ">=($0, $1)"); checkDigest( - gt(vBool(i), vBool(j)), + gt(input(tBool(), i), input(tBool(), j)), i < j - ? ">(?0.bool0, ?0.bool1)" - : "<(?0.bool0, ?0.bool1)"); + ? ">($0, $1)" + : "<($0, $1)"); checkDigest( - ge(vBool(i), vBool(j)), + ge(input(tBool(), i), input(tBool(), j)), i < j - ? ">=(?0.bool0, ?0.bool1)" - : "<=(?0.bool0, ?0.bool1)"); + ? ">=($0, $1)" + : "<=($0, $1)"); } } } diff --git a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java index 53676e4..a5d14c8 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java @@ -741,7 +741,7 @@ class RexProgramTest extends RexProgramTestBase { final int nodeCount = cnf.nodeCount(); assertThat((n + 1) * (int) Math.pow(2, n) + 1, equalTo(nodeCount)); if (n == 3) { - assertThat(cnf.toStringRaw(), + assertThat(cnf.toString(), equalTo("AND(OR(?0.x0, ?0.x1, ?0.x2), OR(?0.x0, ?0.x1, ?0.y2)," + " OR(?0.x0, ?0.y1, ?0.x2), OR(?0.x0, ?0.y1, ?0.y2)," + " OR(?0.y0, ?0.x1, ?0.x2), OR(?0.y0, ?0.x1, ?0.y2)," @@ -1104,7 +1104,7 @@ class RexProgramTest extends RexProgramTestBase { // as previous, using simplifyFilterPredicates assertThat(simplify .simplifyFilterPredicates(args) - .toStringRaw(), + .toString(), equalTo("AND(=(?0.a, 1), =(?0.b, 1))")); // "a = 1 and a = 10" is always false @@ -1410,7 +1410,7 @@ class RexProgramTest extends RexProgramTestBase { // TODO: "b is not unknown" would be the best simplification. final RexNode simplified = this.simplify.simplifyUnknownAs(neOrEq, RexUnknownAs.UNKNOWN); - assertThat(simplified.toStringRaw(), + assertThat(simplified.toString(), equalTo("OR(<>(?0.b, 1), =(?0.b, 1))")); // "a is null or a is not null" ==> "true" @@ -2171,7 +2171,7 @@ class RexProgramTest extends RexProgramTestBase { private void assertTypeAndToString( RexNode rexNode, String representation, String type) { - assertEquals(representation, rexNode.toStringRaw()); + assertEquals(representation, rexNode.toString()); assertEquals(type, rexNode.getType().toString() + (rexNode.getType().isNullable() ? "" : " NOT NULL"), "type of " + rexNode); } diff --git a/core/src/test/java/org/apache/calcite/rex/RexProgramTestBase.java b/core/src/test/java/org/apache/calcite/rex/RexProgramTestBase.java index 140fb11..c3a634c 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexProgramTestBase.java +++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTestBase.java @@ -30,32 +30,27 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class RexProgramTestBase extends RexProgramBuilderBase { protected void checkDigest(RexNode node, String expected) { - assertEquals(expected, node.toString(), () -> "Digest of " + node.toStringRaw()); - } - - protected void checkRaw(RexNode node, String expected) { - assertEquals(expected, node.toStringRaw(), - () -> "Raw representation of node with digest " + node); + assertEquals(expected, node.toString(), () -> "Digest of " + node.toString()); } protected void checkCnf(RexNode node, String expected) { assertThat("RexUtil.toCnf(rexBuilder, " + node + ")", - RexUtil.toCnf(rexBuilder, node).toStringRaw(), equalTo(expected)); + RexUtil.toCnf(rexBuilder, node).toString(), equalTo(expected)); } protected void checkThresholdCnf(RexNode node, int threshold, String expected) { assertThat("RexUtil.toCnf(rexBuilder, threshold=" + threshold + " , " + node + ")", - RexUtil.toCnf(rexBuilder, threshold, node).toStringRaw(), + RexUtil.toCnf(rexBuilder, threshold, node).toString(), equalTo(expected)); } protected void checkPullFactorsUnchanged(RexNode node) { - checkPullFactors(node, node.toStringRaw()); + checkPullFactors(node, node.toString()); } protected void checkPullFactors(RexNode node, String expected) { assertThat("RexUtil.pullFactors(rexBuilder, " + node + ")", - RexUtil.pullFactors(rexBuilder, node).toStringRaw(), + RexUtil.pullFactors(rexBuilder, node).toString(), equalTo(expected)); } @@ -69,7 +64,7 @@ class RexProgramTestBase extends RexProgramBuilderBase { String actual; if (node.isA(SqlKind.CAST) || node.isA(SqlKind.NEW_SPECIFICATION)) { // toString contains type (see RexCall.toString) - actual = node.toStringRaw(); + actual = node.toString(); } else { actual = node + ":" + node.getType() + (node.getType().isNullable() ? "" : " NOT NULL"); } @@ -78,17 +73,17 @@ class RexProgramTestBase extends RexProgramBuilderBase { /** Simplifies an expression and checks that the result is as expected. */ protected void checkSimplify(RexNode node, String expected) { - final String nodeString = node.toStringRaw(); + final String nodeString = node.toString(); checkSimplify3_(node, expected, expected, expected); if (expected.equals(nodeString)) { - throw new AssertionError("expected == node.toStringRaw(); " + throw new AssertionError("expected == node.toString(); " + "use checkSimplifyUnchanged"); } } /** Simplifies an expression and checks that the result is unchanged. */ protected void checkSimplifyUnchanged(RexNode node) { - final String expected = node.toStringRaw(); + final String expected = node.toString(); checkSimplify3_(node, expected, expected, expected); } @@ -126,16 +121,16 @@ class RexProgramTestBase extends RexProgramBuilderBase { final RexNode simplified = simplify.simplifyUnknownAs(node, RexUnknownAs.UNKNOWN); assertThat("simplify(unknown as unknown): " + node, - simplified.toStringRaw(), equalTo(expected)); + simplified.toString(), equalTo(expected)); if (node.getType().getSqlTypeName() == SqlTypeName.BOOLEAN) { final RexNode simplified2 = simplify.simplifyUnknownAs(node, RexUnknownAs.FALSE); assertThat("simplify(unknown as false): " + node, - simplified2.toStringRaw(), equalTo(expectedFalse)); + simplified2.toString(), equalTo(expectedFalse)); final RexNode simplified3 = simplify.simplifyUnknownAs(node, RexUnknownAs.TRUE); assertThat("simplify(unknown as true): " + node, - simplified3.toStringRaw(), equalTo(expectedTrue)); + simplified3.toString(), equalTo(expectedTrue)); } else { assertThat("node type is not BOOLEAN, so <<expectedFalse>> should match <<expected>>", expectedFalse, is(expected)); @@ -147,7 +142,7 @@ class RexProgramTestBase extends RexProgramBuilderBase { protected void checkSimplifyFilter(RexNode node, String expected) { final RexNode simplified = this.simplify.simplifyUnknownAs(node, RexUnknownAs.FALSE); - assertThat(simplified.toStringRaw(), equalTo(expected)); + assertThat(simplified.toString(), equalTo(expected)); } protected void checkSimplifyFilter(RexNode node, RelOptPredicateList predicates, @@ -155,7 +150,7 @@ class RexProgramTestBase extends RexProgramBuilderBase { final RexNode simplified = simplify.withPredicates(predicates) .simplifyUnknownAs(node, RexUnknownAs.FALSE); - assertThat(simplified.toStringRaw(), equalTo(expected)); + assertThat(simplified.toString(), equalTo(expected)); } /** Checks that {@link RexNode#isAlwaysTrue()}, @@ -163,11 +158,11 @@ class RexProgramTestBase extends RexProgramBuilderBase { * an expression reduces to true or false. */ protected void checkIs(RexNode e, boolean expected) { assertThat( - "isAlwaysTrue() of expression: " + e.toStringRaw(), e.isAlwaysTrue(), is(expected)); + "isAlwaysTrue() of expression: " + e.toString(), e.isAlwaysTrue(), is(expected)); assertThat( - "isAlwaysFalse() of expression: " + e.toStringRaw(), e.isAlwaysFalse(), is(!expected)); + "isAlwaysFalse() of expression: " + e.toString(), e.isAlwaysFalse(), is(!expected)); assertThat( - "Simplification is not using isAlwaysX informations", simplify(e).toStringRaw(), + "Simplification is not using isAlwaysX informations", simplify(e).toString(), is(expected ? "true" : "false")); } diff --git a/core/src/test/java/org/apache/calcite/rex/RexSqlStandardConvertletTableTest.java b/core/src/test/java/org/apache/calcite/rex/RexSqlStandardConvertletTableTest.java index 8ad8357..f5e235b 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexSqlStandardConvertletTableTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexSqlStandardConvertletTableTest.java @@ -44,7 +44,7 @@ class RexSqlStandardConvertletTableTest extends SqlToRelTestBase { @Test void testCoalesce() { final Project project = (Project) convertSqlToRel( "SELECT COALESCE(NULL, 'a')", false); - final RexNode rex = project.getChildExps().get(0); + final RexNode rex = project.getProjects().get(0); final RexToSqlNodeConverter rexToSqlNodeConverter = rexToSqlNodeConverter(); final SqlNode convertedSql = rexToSqlNodeConverter.convertNode(rex); assertEquals( @@ -56,7 +56,7 @@ class RexSqlStandardConvertletTableTest extends SqlToRelTestBase { final Project project = (Project) convertSqlToRel( "SELECT CASE NULL WHEN NULL THEN NULL ELSE 'a' END", false); - final RexNode rex = project.getChildExps().get(0); + final RexNode rex = project.getProjects().get(0); final RexToSqlNodeConverter rexToSqlNodeConverter = rexToSqlNodeConverter(); final SqlNode convertedSql = rexToSqlNodeConverter.convertNode(rex); assertEquals( @@ -67,7 +67,7 @@ class RexSqlStandardConvertletTableTest extends SqlToRelTestBase { @Test void testCaseNoValue() { final Project project = (Project) convertSqlToRel( "SELECT CASE WHEN NULL IS NULL THEN NULL ELSE 'a' END", false); - final RexNode rex = project.getChildExps().get(0); + final RexNode rex = project.getProjects().get(0); final RexToSqlNodeConverter rexToSqlNodeConverter = rexToSqlNodeConverter(); final SqlNode convertedSql = rexToSqlNodeConverter.convertNode(rex); assertEquals( diff --git a/core/src/test/java/org/apache/calcite/test/HepPlannerTest.java b/core/src/test/java/org/apache/calcite/test/HepPlannerTest.java index 5b5fcc2..a4269c5 100644 --- a/core/src/test/java/org/apache/calcite/test/HepPlannerTest.java +++ b/core/src/test/java/org/apache/calcite/test/HepPlannerTest.java @@ -150,8 +150,10 @@ class HepPlannerTest extends RelOptTestBase { // Bad digest includes full tree like rel#66:LogicalProject(input=rel#64:LogicalUnion(...)) // So the assertion is to ensure digest includes LogicalUnion exactly once - assertIncludesExactlyOnce("best.getDescription()", best.toString(), "LogicalUnion"); - assertIncludesExactlyOnce("best.getDigest()", best.getDigest(), "LogicalUnion"); + assertIncludesExactlyOnce("best.getDescription()", + best.toString(), "LogicalUnion"); + assertIncludesExactlyOnce("best.getDigest()", + best.getDigest().toString(), "LogicalUnion"); } private void assertIncludesExactlyOnce(String message, String digest, String substring) { diff --git a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java index 93d9225..d92a451 100644 --- a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java +++ b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java @@ -249,7 +249,7 @@ class JdbcAdapterTest { + "on s.losal <= e.sal and s.hisal >= e.sal") .explainContains("PLAN=JdbcToEnumerableConverter\n" + " JdbcProject(EMPNO=[$0], ENAME=[$1], GRADE=[$3])\n" - + " JdbcJoin(condition=[AND(<=($4, $2), >=($5, $2))], joinType=[inner])\n" + + " JdbcJoin(condition=[AND(>=($2, $4), <=($2, $5))], joinType=[inner])\n" + " JdbcProject(EMPNO=[$0], ENAME=[$1], SAL=[$5])\n" + " JdbcTableScan(table=[[SCOTT, EMP]])\n" + " JdbcTableScan(table=[[SCOTT, SALGRADE]])") @@ -292,7 +292,7 @@ class JdbcAdapterTest { + "e.mgr = m.empno and (e.sal > m.sal or m.hiredate > e.hiredate)") .explainContains("PLAN=JdbcToEnumerableConverter\n" + " JdbcProject(EMPNO=[$0], ENAME=[$1], EMPNO0=[$0], ENAME0=[$1])\n" - + " JdbcJoin(condition=[AND(=($2, $5), OR(>($4, $7), >($6, $3)))], joinType=[inner])\n" + + " JdbcJoin(condition=[AND(=($2, $5), OR(>($4, $7), <($3, $6)))], joinType=[inner])\n" + " JdbcProject(EMPNO=[$0], ENAME=[$1], MGR=[$3], HIREDATE=[$4], SAL=[$5])\n" + " JdbcTableScan(table=[[SCOTT, EMP]])\n" + " JdbcProject(EMPNO=[$0], HIREDATE=[$4], SAL=[$5])\n" diff --git a/core/src/test/java/org/apache/calcite/test/LatticeTest.java b/core/src/test/java/org/apache/calcite/test/LatticeTest.java index 1a68667..a6591d3 100644 --- a/core/src/test/java/org/apache/calcite/test/LatticeTest.java +++ b/core/src/test/java/org/apache/calcite/test/LatticeTest.java @@ -239,9 +239,9 @@ class LatticeTest { final Map.Entry<String, CalciteSchema.LatticeEntry> entry = adhoc.unwrap(CalciteSchema.class).getLatticeMap().firstEntry(); final Lattice lattice = entry.getValue().getLattice(); - assertThat(lattice.firstColumn("S"), is(10)); - assertThat(lattice.firstColumn("P"), is(18)); - assertThat(lattice.firstColumn("T"), is(0)); + assertThat(lattice.firstColumn("S"), is(0)); + assertThat(lattice.firstColumn("P"), is(8)); + assertThat(lattice.firstColumn("T"), is(23)); assertThat(lattice.firstColumn("PC"), is(-1)); assertThat(lattice.defaultMeasures.size(), is(1)); assertThat(lattice.rootNode.descendants.size(), is(3)); diff --git a/core/src/test/java/org/apache/calcite/test/MaterializedViewRelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/MaterializedViewRelOptRulesTest.java index 8e45d23..58019b4 100644 --- a/core/src/test/java/org/apache/calcite/test/MaterializedViewRelOptRulesTest.java +++ b/core/src/test/java/org/apache/calcite/test/MaterializedViewRelOptRulesTest.java @@ -821,8 +821,7 @@ public class MaterializedViewRelOptRulesTest extends AbstractMaterializedViewTes .withChecker( resultContains("" + "EnumerableCalc(expr#0=[{inputs}], expr#1=[CAST($t0):JavaType(int) NOT NULL], " - + "expr#2=[1], expr#3=[CAST($t1):INTEGER NOT NULL], expr#4=[=($t2, $t3)], " - + "EXPR$0=[$t1], $condition=[$t4])\n" + + "expr#2=[1], expr#3=[=($t2, $t0)], EXPR$0=[$t1], $condition=[$t3])\n" + " EnumerableTableScan(table=[[hr, MV0]])")) .ok(); } diff --git a/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java b/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java index e599382..2dd25cd 100644 --- a/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java +++ b/core/src/test/java/org/apache/calcite/test/MaterializedViewSubstitutionVisitorTest.java @@ -1146,7 +1146,7 @@ public class MaterializedViewSubstitutionVisitorTest extends AbstractMaterialize private void checkSatisfiable(RexNode e, String s) { assertTrue(SubstitutionVisitor.mayBeSatisfiable(e)); final RexNode simple = simplify.simplifyUnknownAsFalse(e); - assertEquals(s, simple.toStringRaw()); + assertEquals(s, simple.toString()); } @Test void testSplitFilter() { @@ -1219,7 +1219,7 @@ public class MaterializedViewSubstitutionVisitorTest extends AbstractMaterialize newFilter = SubstitutionVisitor.splitFilter(simplify, x_eq_1, rexBuilder.makeCall(SqlStdOperatorTable.OR, x_eq_1, z_eq_3)); - assertThat(newFilter.toStringRaw(), equalTo("=($0, 1)")); + assertThat(newFilter.toString(), equalTo("=($0, 1)")); // 2b. // condition: x = 1 or y = 2 @@ -1229,7 +1229,7 @@ public class MaterializedViewSubstitutionVisitorTest extends AbstractMaterialize newFilter = SubstitutionVisitor.splitFilter(simplify, rexBuilder.makeCall(SqlStdOperatorTable.OR, x_eq_1, y_eq_2), rexBuilder.makeCall(SqlStdOperatorTable.OR, x_eq_1, y_eq_2, z_eq_3)); - assertThat(newFilter.toStringRaw(), equalTo("OR(=($0, 1), =($1, 2))")); + assertThat(newFilter.toString(), equalTo("OR(=($0, 1), =($1, 2))")); // 2c. // condition: x = 1 @@ -1239,7 +1239,7 @@ public class MaterializedViewSubstitutionVisitorTest extends AbstractMaterialize newFilter = SubstitutionVisitor.splitFilter(simplify, x_eq_1, rexBuilder.makeCall(SqlStdOperatorTable.OR, x_eq_1, y_eq_2, z_eq_3)); - assertThat(newFilter.toStringRaw(), + assertThat(newFilter.toString(), equalTo("=($0, 1)")); // 2d. @@ -1287,7 +1287,7 @@ public class MaterializedViewSubstitutionVisitorTest extends AbstractMaterialize newFilter = SubstitutionVisitor.splitFilter(simplify, rexBuilder.makeCall(SqlStdOperatorTable.AND, x_eq_1, y_eq_2), y_eq_2); - assertThat(newFilter.toStringRaw(), equalTo("=($0, 1)")); + assertThat(newFilter.toString(), equalTo("=($0, 1)")); // Example 5. // condition: x = 1 diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java index ac45e49..d00228f 100644 --- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java @@ -1978,7 +1978,7 @@ public class RelBuilderTest { + " LogicalTableScan(table=[[scott, DEPT]])\n"; final String expectedWithoutSimplify = "" + "LogicalJoin(condition=[OR(null:NULL, " - + "AND(=($7, 1), =($7, 2), =($8, $7)))], joinType=[inner])\n" + + "AND(=($7, 1), =($7, 2), =($7, $8)))], joinType=[inner])\n" + " LogicalTableScan(table=[[scott, EMP]])\n" + " LogicalTableScan(table=[[scott, DEPT]])\n"; assertThat(f.apply(createBuilder()), hasTree(expected)); @@ -2151,7 +2151,7 @@ public class RelBuilderTest { builder.field("e", "MGR"))) .build(); final String expected = "" - + "LogicalFilter(condition=[AND(=($7, $16), =($8, $3))])\n" + + "LogicalFilter(condition=[AND(=($7, $16), =($3, $8))])\n" + " LogicalJoin(condition=[true], joinType=[inner])\n" + " LogicalTableScan(table=[[scott, EMP]])\n" + " LogicalJoin(condition=[true], joinType=[inner])\n" @@ -3544,7 +3544,7 @@ public class RelBuilderTest { builder.field("EMPNO"), builder.literal(1), builder.literal(5)); - assertThat(call.toStringRaw(), is("BETWEEN ASYMMETRIC($0, 1, 5)")); + assertThat(call.toString(), is("BETWEEN ASYMMETRIC($0, 1, 5)")); } /** Test case for diff --git a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java index 962e484..74abc71 100644 --- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java @@ -2037,7 +2037,7 @@ public class RelMetadataTest extends SqlToRelTestBase { + "select empno, comm, deptno from emp where empno=1 and comm=4"); final RelMetadataQuery mq = rel.getCluster().getMetadataQuery(); assertThat(mq.getPulledUpPredicates(rel).pulledUpPredicates, - sortsAs("[=($0, 1), OR(AND(=($2, 3), =($1, 2)), =($1, 4))]")); + sortsAs("[=($0, 1), OR(AND(=($1, 2), =($2, 3)), =($1, 4))]")); } @@ -3066,14 +3066,12 @@ public class RelMetadataTest extends SqlToRelTestBase { */ public static <T> Matcher<Iterable<? extends T>> sortsAs(final String value) { return Matchers.compose(equalTo(value), item -> { - try (RexNode.Closeable ignored = RexNode.skipNormalize()) { - final List<String> strings = new ArrayList<>(); - for (T t : item) { - strings.add(t.toString()); - } - Collections.sort(strings); - return strings.toString(); + final List<String> strings = new ArrayList<>(); + for (T t : item) { + strings.add(t.toString()); } + Collections.sort(strings); + return strings.toString(); }); } diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java index ec2d30d..a5abb11 100644 --- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java @@ -6848,7 +6848,7 @@ class RelOptRulesTest extends RelOptTestBase { final LogicalProject logicalProject = call.rel(0); final RelNode input = logicalProject.getInput(); final MyProject myProject = new MyProject(input.getCluster(), input.getTraitSet(), input, - logicalProject.getChildExps(), logicalProject.getRowType()); + logicalProject.getProjects(), logicalProject.getRowType()); call.transformTo(myProject); } } diff --git a/core/src/test/java/org/apache/calcite/test/RexTransformerTest.java b/core/src/test/java/org/apache/calcite/test/RexTransformerTest.java index b7b6104..978d1b3 100644 --- a/core/src/test/java/org/apache/calcite/test/RexTransformerTest.java +++ b/core/src/test/java/org/apache/calcite/test/RexTransformerTest.java @@ -114,7 +114,7 @@ class RexTransformerTest { RexTransformer transformer = new RexTransformer(root, rexBuilder); RexNode result = transformer.transformNullSemantics(); - String actual = result.toStringRaw(); + String actual = result.toString(); if (!actual.equals(expected)) { String msg = "\nExpected=<" + expected + ">\n Actual=<" + actual + ">"; @@ -374,7 +374,7 @@ class RexTransformerTest { null, null); - assertThat(remaining.toStringRaw(), is("<>($0, $9)")); + assertThat(remaining.toString(), is("<>($0, $9)")); assertThat(leftJoinKeys.isEmpty(), is(true)); assertThat(rightJoinKeys.isEmpty(), is(true)); } diff --git a/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java index 4e7a3f6..bf9079a 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlHintsConverterTest.java @@ -76,8 +76,6 @@ import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.spi.LoggingEvent; -import com.google.common.collect.ImmutableList; - import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -510,11 +508,11 @@ class SqlHintsConverterTest extends SqlToRelTestBase { public void onMatch(RelOptRuleCall call) { LogicalJoin join = call.rel(0); - assertThat(1, is(join.getHints().size())); + assertThat(join.getHints().size(), is(1)); call.transformTo( LogicalJoin.create(join.getLeft(), join.getRight(), - ImmutableList.of(), + join.getHints(), join.getCondition(), join.getVariablesSet(), join.getJoinType())); diff --git a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java index 11aa4aa..d0a65e9 100644 --- a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java +++ b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java @@ -96,11 +96,11 @@ class EnumerableCorrelateTest { planner.removeRule(EnumerableRules.ENUMERABLE_MERGE_JOIN_RULE); }) .explainContains("" - + "EnumerableCalc(expr#0..3=[{inputs}], empid=[$t1], name=[$t3])\n" + + "PLAN=EnumerableCalc(expr#0..3=[{inputs}], empid=[$t1], name=[$t3])\n" + " EnumerableCorrelate(correlation=[$cor1], joinType=[inner], requiredColumns=[{0}])\n" + " EnumerableAggregate(group=[{0}])\n" + " EnumerableTableScan(table=[[s, depts]])\n" - + " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[$cor1], expr#6=[$t5.deptno], expr#7=[=($t1, $t6)], proj#0..2=[{exprs}], $condition=[$t7])\n" + + " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[$cor1], expr#6=[$t5.deptno], expr#7=[=($t6, $t1)], proj#0..2=[{exprs}], $condition=[$t7])\n" + " EnumerableTableScan(table=[[s, emps]])") .returnsUnordered( "empid=100; name=Bill", @@ -126,11 +126,11 @@ class EnumerableCorrelateTest { planner.removeRule(EnumerableRules.ENUMERABLE_MERGE_JOIN_RULE); }) .explainContains("" - + "EnumerableCalc(expr#0..3=[{inputs}], empid=[$t1], name=[$t3])\n" + + "PLAN=EnumerableCalc(expr#0..3=[{inputs}], empid=[$t1], name=[$t3])\n" + " EnumerableCorrelate(correlation=[$cor1], joinType=[inner], requiredColumns=[{0}])\n" + " EnumerableAggregate(group=[{0}])\n" + " EnumerableTableScan(table=[[s, depts]])\n" - + " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[$cor1], expr#6=[$t5.deptno], expr#7=[=($t1, $t6)], expr#8=[100], expr#9=[>($t0, $t8)], expr#10=[AND($t7, $t9)], proj#0..2=[{exprs}], $condition=[$t10])\n" + + " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[$cor1], expr#6=[$t5.deptno], expr#7=[=($t6, $t1)], expr#8=[100], expr#9=[>($t0, $t8)], expr#10=[AND($t7, $t9)], proj#0..2=[{exprs}], $condition=[$t10])\n" + " EnumerableTableScan(table=[[s, emps]])") .returnsUnordered( "empid=110; name=Theodore", diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml index 57fd8c4..e8c29b6 100644 --- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml @@ -638,7 +638,7 @@ LogicalProject(MGR=[$3]) </Resource> <Resource name="planMid"> <![CDATA[ -LogicalProject(DEPTNO=[$0], EXPR$1=[OR(AND(IS NOT NULL($5), <>($2, 0)), AND(<($3, $2), null, <>($2, 0), IS NULL($5)))]) +LogicalProject(DEPTNO=[$0], EXPR$1=[OR(AND(IS NOT NULL($5), <>($2, 0)), AND(>($2, $3), null, <>($2, 0), IS NULL($5)))]) LogicalJoin(condition=[=($1, $4)], joinType=[left]) LogicalJoin(condition=[true], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) @@ -652,7 +652,7 @@ LogicalProject(DEPTNO=[$0], EXPR$1=[OR(AND(IS NOT NULL($5), <>($2, 0)), AND(<($3 </Resource> <Resource name="planAfter"> <![CDATA[ -LogicalProject(DEPTNO=[$0], EXPR$1=[OR(AND(IS NOT NULL($5), <>($2, 0)), AND(<($3, $2), null, <>($2, 0), IS NULL($5)))]) +LogicalProject(DEPTNO=[$0], EXPR$1=[OR(AND(IS NOT NULL($5), <>($2, 0)), AND(>($2, $3), null, <>($2, 0), IS NULL($5)))]) LogicalJoin(condition=[=($1, $4)], joinType=[left]) LogicalJoin(condition=[true], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) @@ -1837,7 +1837,7 @@ group by case when e.sal < 11 then 11 else -1 * e.sal end]]> LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalAggregate(group=[{0}], EXPR$0=[COUNT()]) LogicalProject(EXPR$1=[CASE(<($9, 11), 11, *(-1, $9))]) - LogicalJoin(condition=[=($5, $0)], joinType=[left]) + LogicalJoin(condition=[=($0, $5)], joinType=[left]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> @@ -1847,7 +1847,7 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalAggregate(group=[{0}], EXPR$0=[COUNT()]) LogicalProject(EXPR$1=[CASE($2, 11, $3)]) - LogicalJoin(condition=[=($1, $0)], joinType=[left]) + LogicalJoin(condition=[=($0, $1)], joinType=[left]) LogicalProject(ENAME=[$0]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalProject(ENAME=[$1], <=[<($5, 11)], *=[*(-1, $5)]) @@ -1866,7 +1866,7 @@ group by case when e.sal < 11 then -1 * e.sal else e.sal end]]> LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalAggregate(group=[{0}], EXPR$0=[COUNT()]) LogicalProject(EXPR$1=[CASE(<($9, 11), *(-1, $9), $9)]) - LogicalJoin(condition=[=($5, $0)], joinType=[left]) + LogicalJoin(condition=[=($0, $5)], joinType=[left]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> @@ -1876,7 +1876,7 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalAggregate(group=[{0}], EXPR$0=[COUNT()]) LogicalProject(EXPR$1=[$2]) - LogicalJoin(condition=[=($1, $0)], joinType=[left]) + LogicalJoin(condition=[=($0, $1)], joinType=[left]) LogicalProject(ENAME=[$0]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalProject(ENAME=[$1], CASE=[CASE(<($5, 11), *(-1, $5), $5)]) @@ -1983,7 +1983,7 @@ group by case when e.sal < 11 then 11 else -1 * e.sal end]]> LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalAggregate(group=[{0}], EXPR$0=[COUNT()]) LogicalProject(EXPR$1=[CASE(<($9, 11), 11, *(-1, $9))]) - LogicalJoin(condition=[=($5, $0)], joinType=[right]) + LogicalJoin(condition=[=($0, $5)], joinType=[right]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> @@ -1993,7 +1993,7 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalAggregate(group=[{0}], EXPR$0=[COUNT()]) LogicalProject(EXPR$1=[$2]) - LogicalJoin(condition=[=($1, $0)], joinType=[right]) + LogicalJoin(condition=[=($0, $1)], joinType=[right]) LogicalProject(ENAME=[$0]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalProject(ENAME=[$1], CASE=[CASE(<($5, 11), 11, *(-1, $5))]) @@ -2012,7 +2012,7 @@ group by case when e.sal < 11 then -1 * e.sal else e.sal end]]> LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalAggregate(group=[{0}], EXPR$0=[COUNT()]) LogicalProject(EXPR$1=[CASE(<($9, 11), *(-1, $9), $9)]) - LogicalJoin(condition=[=($5, $0)], joinType=[right]) + LogicalJoin(condition=[=($0, $5)], joinType=[right]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> @@ -2022,7 +2022,7 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalProject(EXPR$0=[$1], EXPR$1=[$0]) LogicalAggregate(group=[{0}], EXPR$0=[COUNT()]) LogicalProject(EXPR$1=[$2]) - LogicalJoin(condition=[=($1, $0)], joinType=[right]) + LogicalJoin(condition=[=($0, $1)], joinType=[right]) LogicalProject(ENAME=[$0]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalProject(ENAME=[$1], CASE=[CASE(<($5, 11), *(-1, $5), $5)]) @@ -3582,7 +3582,7 @@ join sales.emp e on e.deptno = d.deptno and d.deptno not in (4, 6)]]> <Resource name="planBefore"> <![CDATA[ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], EMPNO0=[$9], ENAME0=[$10], JOB0=[$11], MGR0=[$12], HIREDATE0=[$13], SAL0=[$14], COMM0=[$15], DEPTNO0=[$16], SLACKER0=[$17]) - LogicalJoin(condition=[AND(=($16, $7), NOT(OR(=($7, 4), =($7, 6))))], joinType=[inner]) + LogicalJoin(condition=[AND(=($7, $16), NOT(OR(=($7, 4), =($7, 6))))], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> @@ -3590,7 +3590,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$ <Resource name="planAfter"> <![CDATA[ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], EMPNO0=[$9], ENAME0=[$10], JOB0=[$11], MGR0=[$12], HIREDATE0=[$13], SAL0=[$14], COMM0=[$15], DEPTNO0=[$16], SLACKER0=[$17]) - LogicalJoin(condition=[=($16, $7)], joinType=[inner]) + LogicalJoin(condition=[=($7, $16)], joinType=[inner]) LogicalFilter(condition=[AND(<>($7, 4), <>($7, 6))]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalFilter(condition=[AND(<>($7, 4), <>($7, 6))]) @@ -3750,10 +3750,10 @@ LogicalProject(SAL=[$5]) LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], SLACKER=[$8]) LogicalFilter(condition=[AND(=($7, 20), >($5, 1000))]) LogicalTableScan(table=[[CATALOG, SALES, EMPNULLABLES]]) - LogicalFilter(condition=[=($1, $0)]) + LogicalFilter(condition=[=($0, $1)]) LogicalAggregate(group=[{0, 1}]) LogicalProject(SAL=[$5], SAL0=[$8]) - LogicalJoin(condition=[OR(=($8, $5), =($8, 4))], joinType=[inner]) + LogicalJoin(condition=[OR(=($5, $8), =($8, 4))], joinType=[inner]) LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], SLACKER=[$8]) LogicalFilter(condition=[AND(=($7, 20), >($5, 1000))]) LogicalTableScan(table=[[CATALOG, SALES, EMPNULLABLES]]) @@ -6414,7 +6414,7 @@ group by e.job]]> <![CDATA[ LogicalAggregate(group=[{2}]) LogicalJoin(condition=[AND(=($2, $11), =($9, $12))], joinType=[full]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalProject(DEPTNO=[$0], NAME=[$1], $f2=[+($0, 5)]) @@ -6426,7 +6426,7 @@ LogicalAggregate(group=[{2}]) LogicalAggregate(group=[{0}]) LogicalJoin(condition=[AND(=($0, $2), =($1, $3))], joinType=[full]) LogicalAggregate(group=[{2, 9}]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalAggregate(group=[{1, 2}]) @@ -6596,7 +6596,7 @@ group by e.job]]> <![CDATA[ LogicalAggregate(group=[{2}]) LogicalJoin(condition=[AND(=($2, $11), =($9, $12))], joinType=[left]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalProject(DEPTNO=[$0], NAME=[$1], $f2=[+($0, 5)]) @@ -6608,7 +6608,7 @@ LogicalAggregate(group=[{2}]) LogicalAggregate(group=[{0}]) LogicalJoin(condition=[AND(=($0, $2), =($1, $3))], joinType=[left]) LogicalAggregate(group=[{2, 9}]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalAggregate(group=[{1, 2}]) @@ -6629,7 +6629,7 @@ group by d.name]]> <![CDATA[ LogicalAggregate(group=[{11}]) LogicalJoin(condition=[AND(=($2, $11), =($9, $12))], joinType=[left]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalProject(DEPTNO=[$0], NAME=[$1], $f2=[+($0, 5)]) @@ -6641,7 +6641,7 @@ LogicalAggregate(group=[{11}]) LogicalAggregate(group=[{2}]) LogicalJoin(condition=[AND(=($0, $2), =($1, $3))], joinType=[left]) LogicalAggregate(group=[{2, 9}]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalAggregate(group=[{1, 2}]) @@ -6662,7 +6662,7 @@ group by e.job, d.name]]> <![CDATA[ LogicalAggregate(group=[{2, 11}]) LogicalJoin(condition=[AND(=($2, $11), =($9, $12))], joinType=[left]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalProject(DEPTNO=[$0], NAME=[$1], $f2=[+($0, 5)]) @@ -6674,7 +6674,7 @@ LogicalAggregate(group=[{2, 11}]) LogicalAggregate(group=[{0, 2}]) LogicalJoin(condition=[AND(=($0, $2), =($1, $3))], joinType=[left]) LogicalAggregate(group=[{2, 9}]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalAggregate(group=[{1, 2}]) @@ -6743,7 +6743,7 @@ join sales.dept as d on e.empno = d.deptno and e.deptno + e.empno = d.deptno + 5 <![CDATA[ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], DEPTNO0=[$10], NAME=[$11]) LogicalJoin(condition=[AND(=($0, $10), =($9, $12))], joinType=[inner]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($0, 10)]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalProject(DEPTNO=[$0], NAME=[$1], $f2=[+($0, 5)]) @@ -6754,7 +6754,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$ <![CDATA[ LogicalProject(EMPNO=[10], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], DEPTNO0=[10], NAME=[$11]) LogicalJoin(condition=[=($9, 15)], joinType=[inner]) - LogicalProject(EMPNO=[10], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, 10)]) + LogicalProject(EMPNO=[10], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+(10, $7)]) LogicalFilter(condition=[=($0, 10)]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalProject(DEPTNO=[10], NAME=[$1], $f2=[15]) @@ -7868,13 +7868,13 @@ from emp]]> <![CDATA[ LogicalProject($0=[$3], $1=[$4]) LogicalWindow(window#0=[window(partition {1} order by [0] aggs [SUM($1), SUM($2)])]) - LogicalProject(SAL=[$5], DEPTNO=[$7], $2=[+($7, $5)]) + LogicalProject(SAL=[$5], DEPTNO=[$7], $2=[+($5, $7)]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> </Resource> <Resource name="planBefore"> <![CDATA[ -LogicalProject(SUM1=[SUM($7) OVER (PARTITION BY $7 ORDER BY $5)], SUM2=[SUM(+($7, $5)) OVER (PARTITION BY $7 ORDER BY $5)]) +LogicalProject(SUM1=[SUM($7) OVER (PARTITION BY $7 ORDER BY $5)], SUM2=[SUM(+($5, $7)) OVER (PARTITION BY $7 ORDER BY $5)]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> </Resource> @@ -7920,7 +7920,7 @@ group by e.job,d.name]]> <![CDATA[ LogicalAggregate(group=[{2, 11}]) LogicalJoin(condition=[AND(=($2, $11), =($9, $12))], joinType=[inner]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalProject(DEPTNO=[$0], NAME=[$1], $f2=[+($0, 5)]) @@ -7932,7 +7932,7 @@ LogicalAggregate(group=[{2, 11}]) LogicalAggregate(group=[{0, 2}]) LogicalJoin(condition=[AND(=($0, $2), =($1, $3))], joinType=[inner]) LogicalAggregate(group=[{2, 9}]) - LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, $0)]) + LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($0, $7)]) LogicalFilter(condition=[=($1, 'A')]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalAggregate(group=[{1, 2}]) @@ -8466,7 +8466,7 @@ LogicalProject(EXPR$0=[1]) <![CDATA[ LogicalProject(EXPR$0=[1]) LogicalProject(DEPTNO=[$9], NAME=[$10], EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO0=[$7], SLACKER=[$8]) - LogicalJoin(condition=[=($9, $7)], joinType=[right]) + LogicalJoin(condition=[=($7, $9)], joinType=[right]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) ]]> @@ -9742,7 +9742,7 @@ RIGHT JOIN sales.emp e ON e.deptno = d.deptno]]> <Resource name="planBefore"> <![CDATA[ LogicalProject(DEPTNO=[$9]) - LogicalJoin(condition=[=($9, $0)], joinType=[right]) + LogicalJoin(condition=[=($0, $9)], joinType=[right]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> @@ -9786,7 +9786,7 @@ RIGHT JOIN sales.emp e ON e.deptno = d.deptno]]> <Resource name="planBefore"> <![CDATA[ LogicalProject(DEPTNO=[$9], NAME=[$1]) - LogicalJoin(condition=[=($9, $0)], joinType=[right]) + LogicalJoin(condition=[=($0, $9)], joinType=[right]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> @@ -11289,7 +11289,7 @@ LogicalProject(DEPTNO=[$1]) </Resource> <Resource name="planAfter"> <![CDATA[ -LogicalProject(EMPNO=[$0], D=[CASE(=($9, 0), false, IS NULL(CASE(true, CAST($7):INTEGER, null:INTEGER)), null:BOOLEAN, IS NOT NULL($12), true, <($10, $9), null:BOOLEAN, false)]) +LogicalProject(EMPNO=[$0], D=[CASE(=($9, 0), false, IS NULL(CASE(true, CAST($7):INTEGER, null:INTEGER)), null:BOOLEAN, IS NOT NULL($12), true, >($9, $10), null:BOOLEAN, false)]) LogicalJoin(condition=[=(CASE(true, CAST($7):INTEGER, null:INTEGER), $11)], joinType=[left]) LogicalJoin(condition=[true], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) @@ -11337,7 +11337,7 @@ LogicalProject(EXPR$0=[CASE(true, CAST($7):INTEGER, null:INTEGER)]) <![CDATA[ LogicalProject(EMPNO=[$0]) LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8]) - LogicalFilter(condition=[<($0, CASE(OR(AND(IS NOT NULL($12), <>($9, 0)), AND(<($10, $9), null, <>($9, 0), IS NULL($12))), 10, AND(OR(IS NULL($12), =($9, 0)), OR(>=($10, $9), =($9, 0), IS NOT NULL($12))), 20, 30))]) + LogicalFilter(condition=[<($0, CASE(OR(AND(IS NOT NULL($12), <>($9, 0)), AND(>($9, $10), null, <>($9, 0), IS NULL($12))), 10, AND(OR(IS NULL($12), =($9, 0)), OR(<=($9, $10), =($9, 0), IS NOT NULL($12))), 20, 30))]) LogicalJoin(condition=[=($7, $11)], joinType=[left]) LogicalJoin(condition=[true], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) @@ -11764,7 +11764,7 @@ LogicalProject(DEPTNO=[$0]) <Resource name="planAfter"> <![CDATA[ LogicalProject(SAL=[$5]) - LogicalFilter(condition=[OR(=($10, 0), IS NOT TRUE(OR(IS NOT NULL($13), <($11, $10))))]) + LogicalFilter(condition=[OR(=($10, 0), IS NOT TRUE(OR(IS NOT NULL($13), >($10, $11))))]) LogicalJoin(condition=[AND(=($0, $12), =($2, $14))], joinType=[left]) LogicalJoin(condition=[=($2, $9)], joinType=[left]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) @@ -11779,7 +11779,7 @@ LogicalProject(SAL=[$5]) <![CDATA[ LogicalProject(SAL=[$5]) LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8]) - LogicalFilter(condition=[OR(=($9, 0), IS NOT TRUE(OR(IS NOT NULL($12), <($10, $9))))]) + LogicalFilter(condition=[OR(=($9, 0), IS NOT TRUE(OR(IS NOT NULL($12), >($9, $10))))]) LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{2}]) LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{2}]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) @@ -11856,7 +11856,7 @@ LogicalProject(EMPNO=[$1]) <![CDATA[ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8]) LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8]) - LogicalFilter(condition=[OR(=($9, 0), IS NOT TRUE(OR(IS NOT NULL($12), <($10, $9))))]) + LogicalFilter(condition=[OR(=($9, 0), IS NOT TRUE(OR(IS NOT NULL($12), >($9, $10))))]) LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{1}]) LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{1}]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) @@ -11875,7 +11875,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$ <Resource name="planAfter"> <![CDATA[ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8]) - LogicalFilter(condition=[OR(=($10, 0), IS NOT TRUE(OR(IS NOT NULL($13), <($11, $10))))]) + LogicalFilter(condition=[OR(=($10, 0), IS NOT TRUE(OR(IS NOT NULL($13), >($10, $11))))]) LogicalJoin(condition=[AND(=($0, $12), =($1, $14))], joinType=[left]) LogicalJoin(condition=[=($1, $9)], joinType=[left]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) diff --git a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml index bff936c..2473830 100644 --- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml @@ -104,7 +104,7 @@ LogicalAggregate(group=[{0, 1}]) <![CDATA[ LogicalProject(D=[$0], EXPR$1=[+($0, $1)]) LogicalAggregate(group=[{0, 1}]) - LogicalProject(D=[+($7, $0)], MGR=[$3]) + LogicalProject(D=[+($0, $7)], MGR=[$3]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> </Resource> @@ -1565,7 +1565,7 @@ order by sal + empno desc, sal * empno, sal + empno desc]]> <![CDATA[ LogicalProject(EMPNO=[$0]) LogicalSort(sort0=[$1], sort1=[$2], dir0=[DESC], dir1=[ASC]) - LogicalProject(EMPNO=[$0], EXPR$1=[+($5, $0)], EXPR$2=[*($5, $0)]) + LogicalProject(EMPNO=[$0], EXPR$1=[+($0, $5)], EXPR$2=[*($0, $5)]) LogicalJoin(condition=[true], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) @@ -1879,8 +1879,8 @@ order by c + a]]> <![CDATA[ LogicalProject(A=[$0], B=[$1], C=[$2], DEPTNO=[$3], NAME=[$4]) LogicalSort(sort0=[$5], dir0=[ASC]) - LogicalProject(A=[$0], B=[$1], C=[$2], DEPTNO=[$3], NAME=[$4], EXPR$5=[+($2, $0)]) - LogicalJoin(condition=[=($3, $2)], joinType=[inner]) + LogicalProject(A=[$0], B=[$1], C=[$2], DEPTNO=[$3], NAME=[$4], EXPR$5=[+($0, $2)]) + LogicalJoin(condition=[=($2, $3)], joinType=[inner]) LogicalProject(A=[$2], B=[$1], C=[$0]) LogicalValues(tuples=[[{ 1, 2, 3 }]]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) @@ -2317,7 +2317,7 @@ JOIN dept on dept.deptno = emp.deptno + 0]]> <Resource name="plan"> <![CDATA[ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], DEPTNO0=[$10], NAME=[$11]) - LogicalJoin(condition=[=($10, $9)], joinType=[inner]) + LogicalJoin(condition=[=($9, $10)], joinType=[inner]) LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f9=[+($7, 0)]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) @@ -2407,7 +2407,7 @@ LogicalProject(D2=[$0], D3=[$1]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) LogicalAggregate(group=[{0, 1}], agg#0=[MIN($2)]) LogicalProject(D4=[$0], D6=[$2], $f0=[true]) - LogicalFilter(condition=[=($1, $0)]) + LogicalFilter(condition=[=($0, $1)]) LogicalProject(D4=[+($0, 4)], D5=[+($0, 5)], D6=[+($0, 6)]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) ]]> @@ -2590,7 +2590,7 @@ from dept]]> </Resource> <Resource name="plan"> <![CDATA[ -LogicalProject(NAME=[$1], EXPR$1=[OR(AND(IS NOT NULL($6), <>($2, 0)), AND(<($3, $2), null, <>($2, 0), IS NULL($6)))]) +LogicalProject(NAME=[$1], EXPR$1=[OR(AND(IS NOT NULL($6), <>($2, 0)), AND(>($2, $3), null, <>($2, 0), IS NULL($6)))]) LogicalJoin(condition=[=($4, $5)], joinType=[left]) LogicalProject(DEPTNO=[$0], NAME=[$1], $f0=[$2], $f1=[$3], DEPTNO0=[$0]) LogicalJoin(condition=[true], joinType=[inner]) @@ -2612,7 +2612,7 @@ from emp]]> </Resource> <Resource name="plan"> <![CDATA[ -LogicalProject(EMPNO=[$0], EXPR$1=[OR(=($9, 0), AND(<($10, $9), null, <>($9, 0), IS NULL($13)), AND(<>($9, 0), IS NULL($13), >=($10, $9)))]) +LogicalProject(EMPNO=[$0], EXPR$1=[OR(=($9, 0), AND(>($9, $10), null, <>($9, 0), IS NULL($13)), AND(<>($9, 0), IS NULL($13), <=($9, $10)))]) LogicalJoin(condition=[=($11, $12)], joinType=[left]) LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f0=[$9], $f1=[$10], DEPTNO0=[$7]) LogicalJoin(condition=[true], joinType=[inner]) @@ -2756,7 +2756,7 @@ from emp]]> </Resource> <Resource name="plan"> <![CDATA[ -LogicalProject(EMPNO=[$0], EXPR$1=[OR(=($9, 0), AND(<($10, $9), null, <>($9, 0), IS NULL($13)), AND(<>($9, 0), IS NULL($13), >=($10, $9)))]) +LogicalProject(EMPNO=[$0], EXPR$1=[OR(=($9, 0), AND(>($9, $10), null, <>($9, 0), IS NULL($13)), AND(<>($9, 0), IS NULL($13), <=($9, $10)))]) LogicalJoin(condition=[=($11, $12)], joinType=[left]) LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f0=[$9], $f1=[$10], DEPTNO0=[$7]) LogicalJoin(condition=[true], joinType=[inner]) @@ -5711,7 +5711,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$ LogicalJoin(condition=[=($7, $11)], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalProject(DEPTNO=[$0], NAME=[$1], DEPTNO0=[$2]) - LogicalJoin(condition=[<($2, $0)], joinType=[inner]) + LogicalJoin(condition=[>($0, $2)], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) LogicalAggregate(group=[{0}]) LogicalProject(DEPTNO=[$7]) @@ -5759,7 +5759,7 @@ LogicalProject(D2=[$0], D3=[$1]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) LogicalAggregate(group=[{0, 1}], agg#0=[MIN($2)]) LogicalProject(D4=[$0], D6=[$2], $f0=[true]) - LogicalFilter(condition=[=($1, $0)]) + LogicalFilter(condition=[=($0, $1)]) LogicalProject(D4=[+($0, 4)], D5=[+($0, 5)], D6=[+($0, 6)]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) ]]> @@ -5883,7 +5883,7 @@ LogicalProject(EMPNO=[$0]) LogicalTableScan(table=[[CATALOG, SALES, DEPT]]) LogicalAggregate(group=[{0}], agg#0=[MIN($1)]) LogicalProject(EMPNO0=[$9], $f0=[true]) - LogicalJoin(condition=[<($9, $0)], joinType=[inner]) + LogicalJoin(condition=[>($0, $9)], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalAggregate(group=[{0}]) LogicalProject(EMPNO=[$0]) 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 3442857..f2507fa 100644 --- a/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/TopDownOptTest.xml @@ -579,7 +579,7 @@ on r.job=s.job and r.ename=s.ename]]> <Resource name="planBefore"> <![CDATA[ LogicalProject(ENAME=[$0], JOB=[$1], SAL=[$2], COMM=[$3], ENAME0=[$4], JOB0=[$5], EXPR$2=[$6]) - LogicalJoin(condition=[AND(=($5, $1), =($4, $0))], joinType=[inner]) + LogicalJoin(condition=[AND(=($1, $5), =($0, $4))], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalAggregate(group=[{0, 1}], EXPR$2=[MAX($2)]) LogicalProject(ENAME=[$1], JOB=[$2], SAL=[$5]) @@ -606,7 +606,7 @@ on r.job=s.job and r.ename=s.ename]]> <Resource name="planBefore"> <![CDATA[ LogicalProject(ENAME=[$0], JOB=[$1], SAL=[$2], COMM=[$3], ENAME0=[$4], JOB0=[$5], MGR=[$6], EXPR$3=[$7]) - LogicalJoin(condition=[AND(=($5, $1), =($4, $0))], joinType=[inner]) + LogicalJoin(condition=[AND(=($1, $5), =($0, $4))], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, BONUS]]) LogicalAggregate(group=[{0, 1, 2}], EXPR$3=[MAX($3)]) LogicalProject(ENAME=[$1], JOB=[$2], MGR=[$3], SAL=[$5]) diff --git a/core/src/test/resources/sql/blank.iq b/core/src/test/resources/sql/blank.iq index 2d69aaf..32d3bcb 100644 --- a/core/src/test/resources/sql/blank.iq +++ b/core/src/test/resources/sql/blank.iq @@ -89,7 +89,7 @@ insert into table2 values (NULL, 1), (2, 1); # Checked on Oracle !set lateDecorrelate true select i, j from table1 where table1.j NOT IN (select i from table2 where table1.i=table2.j); -EnumerableCalc(expr#0..7=[{inputs}], expr#8=[0], expr#9=[=($t3, $t8)], expr#10=[IS NULL($t1)], expr#11=[IS NOT NULL($t7)], expr#12=[<($t4, $t3)], expr#13=[OR($t10, $t11, $t12)], expr#14=[IS NOT TRUE($t13)], expr#15=[OR($t9, $t14)], proj#0..1=[{exprs}], $condition=[$t15]) +EnumerableCalc(expr#0..7=[{inputs}], expr#8=[0], expr#9=[=($t3, $t8)], expr#10=[IS NULL($t1)], expr#11=[IS NOT NULL($t7)], expr#12=[>($t3, $t4)], expr#13=[OR($t10, $t11, $t12)], expr#14=[IS NOT TRUE($t13)], expr#15=[OR($t9, $t14)], proj#0..1=[{exprs}], $condition=[$t15]) EnumerableHashJoin(condition=[AND(=($0, $6), =($1, $5))], joinType=[left]) EnumerableHashJoin(condition=[=($0, $2)], joinType=[left]) EnumerableTableScan(table=[[BLANK, TABLE1]]) diff --git a/core/src/test/resources/sql/sub-query.iq b/core/src/test/resources/sql/sub-query.iq index 9a9df2f..254738d 100644 --- a/core/src/test/resources/sql/sub-query.iq +++ b/core/src/test/resources/sql/sub-query.iq @@ -32,7 +32,7 @@ where t1.x not in (select t2.x from t2); (0 rows) !ok -EnumerableCalc(expr#0..4=[{inputs}], expr#5=[0], expr#6=[=($t1, $t5)], expr#7=[IS NULL($t4)], expr#8=[>=($t2, $t1)], expr#9=[IS NOT NULL($t0)], expr#10=[AND($t7, $t8, $t9)], expr#11=[OR($t6, $t10)], X=[$t0], $condition=[$t11]) +EnumerableCalc(expr#0..4=[{inputs}], expr#5=[0], expr#6=[=($t1, $t5)], expr#7=[IS NULL($t4)], expr#8=[<=($t1, $t2)], expr#9=[IS NOT NULL($t0)], expr#10=[AND($t7, $t8, $t9)], expr#11=[OR($t6, $t10)], X=[$t0], $condition=[$t11]) EnumerableHashJoin(condition=[=($0, $3)], joinType=[left]) EnumerableNestedLoopJoin(condition=[true], joinType=[inner]) EnumerableUnion(all=[true]) @@ -2048,7 +2048,7 @@ where sal + 100 not in ( !ok EnumerableAggregate(group=[{}], C=[COUNT()]) - EnumerableCalc(expr#0..9=[{inputs}], expr#10=[0], expr#11=[=($t4, $t10)], expr#12=[IS NULL($t2)], expr#13=[IS NOT NULL($t7)], expr#14=[<($t5, $t4)], expr#15=[OR($t12, $t13, $t14)], expr#16=[IS NOT TRUE($t15)], expr#17=[OR($t11, $t16)], proj#0..9=[{exprs}], $condition=[$t17]) + EnumerableCalc(expr#0..9=[{inputs}], expr#10=[0], expr#11=[=($t4, $t10)], expr#12=[IS NULL($t2)], expr#13=[IS NOT NULL($t7)], expr#14=[>($t4, $t5)], expr#15=[OR($t12, $t13, $t14)], expr#16=[IS NOT TRUE($t15)], expr#17=[OR($t11, $t16)], proj#0..9=[{exprs}], $condition=[$t17]) EnumerableHashJoin(condition=[AND(=($1, $8), =($2, $9))], joinType=[left]) EnumerableHashJoin(condition=[=($1, $3)], joinType=[left]) EnumerableCalc(expr#0..7=[{inputs}], proj#0..1=[{exprs}], SAL=[$t5]) diff --git a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidRules.java b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidRules.java index c3b5d1d..9c4f4be 100644 --- a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidRules.java +++ b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidRules.java @@ -384,7 +384,7 @@ public class DruidRules { return; } boolean hasRexCalls = false; - for (RexNode rexNode : project.getChildExps()) { + for (RexNode rexNode : project.getProjects()) { if (rexNode instanceof RexCall) { hasRexCalls = true; break; diff --git a/piglet/src/main/java/org/apache/calcite/piglet/PigToSqlAggregateRule.java b/piglet/src/main/java/org/apache/calcite/piglet/PigToSqlAggregateRule.java index bd94628..fb66415 100644 --- a/piglet/src/main/java/org/apache/calcite/piglet/PigToSqlAggregateRule.java +++ b/piglet/src/main/java/org/apache/calcite/piglet/PigToSqlAggregateRule.java @@ -200,7 +200,7 @@ public class PigToSqlAggregateRule extends RelOptRule { relBuilder.push(oldBottomProject.getInput()); // First project all group keys, just copy from old one for (int i = 0; i < oldAgg.getGroupCount(); i++) { - newBottomProjects.add(oldBottomProject.getChildExps().get(i)); + newBottomProjects.add(oldBottomProject.getProjects().get(i)); } // If grouping aggregate is needed, project the whole ROW if (needGoupingCol) { @@ -235,8 +235,8 @@ public class PigToSqlAggregateRule extends RelOptRule { } else { // Add it to the projection list if we never project it before // First get the ROW operator call - final RexCall rowCall = (RexCall) oldBottomProject.getChildExps() - .get(oldAgg.getGroupCount()); + final RexCall rowCall = (RexCall) oldBottomProject.getProjects() + .get(oldAgg.getGroupCount()); // Get the corresponding column index in parent rel through the call operand list final RexInputRef columRef = (RexInputRef) rowCall.getOperands().get(col); final int newIndex = newBottomProjects.size();