This is an automated email from the ASF dual-hosted git repository.
hyuan 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 0115bd1 [CALCITE-3348] AssertionError while determining distribution
of Calc (Wang Yanlin)
0115bd1 is described below
commit 0115bd102fdbab66a2a7447b96b9f7bf49f14308
Author: yanzhi <[email protected]>
AuthorDate: Sat Sep 14 19:42:03 2019 +0800
[CALCITE-3348] AssertionError while determining distribution of Calc (Wang
Yanlin)
---
.../calcite/rel/metadata/RelMdDistribution.java | 11 +++++--
.../java/org/apache/calcite/rex/RexProgram.java | 28 +++++++++++++++++
.../org/apache/calcite/test/RelOptRulesTest.java | 35 ++++++++++++++++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 21 ++++++++++++-
4 files changed, 92 insertions(+), 3 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java
index 91b9185..6aac9ab 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistribution.java
@@ -141,10 +141,17 @@ public class RelMdDistribution
* {@link org.apache.calcite.rel.core.Calc}'s distribution. */
public static RelDistribution calc(RelMetadataQuery mq, RelNode input,
RexProgram program) {
- throw new AssertionError(); // TODO:
+ assert program.getCondition() != null ||
!program.getProjectList().isEmpty();
+ final RelDistribution inputDistribution = mq.distribution(input);
+ if (!program.getProjectList().isEmpty()) {
+ final Mappings.TargetMapping mapping = program.getPartialMapping(
+ input.getRowType().getFieldCount());
+ return inputDistribution.apply(mapping);
+ }
+ return inputDistribution;
}
- /** Helper method to determine a {@link Project}'s collation. */
+ /** Helper method to determine a {@link Project}'s distribution. */
public static RelDistribution project(RelMetadataQuery mq, RelNode input,
List<? extends RexNode> projects) {
final RelDistribution inputDistribution = mq.distribution(input);
diff --git a/core/src/main/java/org/apache/calcite/rex/RexProgram.java
b/core/src/main/java/org/apache/calcite/rex/RexProgram.java
index 7aafac0..13e4d7f 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexProgram.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexProgram.java
@@ -16,6 +16,7 @@
*/
package org.apache.calcite.rex;
+import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.plan.RelOptPredicateList;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rel.RelCollation;
@@ -34,6 +35,8 @@ import org.apache.calcite.sql.type.SqlTypeUtil;
import org.apache.calcite.util.Litmus;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Permutation;
+import org.apache.calcite.util.mapping.MappingType;
+import org.apache.calcite.util.mapping.Mappings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
@@ -821,6 +824,31 @@ public class RexProgram {
: null);
}
+ /**
+ * Returns a partial mapping of a set of project expressions.
+ *
+ * <p>The mapping is an inverse function.
+ * Every target has a source field, but
+ * a source might have 0, 1 or more targets.
+ * Project expressions that do not consist of
+ * a mapping are ignored.
+ *
+ * @param inputFieldCount Number of input fields
+ * @return Mapping of a set of project expressions, never null
+ */
+ public Mappings.TargetMapping getPartialMapping(int inputFieldCount) {
+ Mappings.TargetMapping mapping =
+ Mappings.create(MappingType.INVERSE_FUNCTION,
+ inputFieldCount, projects.size());
+ for (Ord<RexLocalRef> exp : Ord.zip(projects)) {
+ RexNode rexNode = expandLocalRef(exp.e);
+ if (rexNode instanceof RexInputRef) {
+ mapping.set(((RexInputRef) rexNode).getIndex(), exp.i);
+ }
+ }
+ return mapping;
+ }
+
//~ Inner Classes ----------------------------------------------------------
/**
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 ed063f7..4720fca 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -38,6 +38,7 @@ import org.apache.calcite.prepare.Prepare;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelCollationTraitDef;
import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelDistributionTraitDef;
import org.apache.calcite.rel.RelDistributions;
import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.rel.RelNode;
@@ -6314,6 +6315,40 @@ public class RelOptRulesTest extends RelOptTestBase {
.build();
checkPlanning(program, "select ename from emp where sal > cast (100.0 as
decimal(4, 1))");
}
+
+ @Test public void testEnumerableCalcRule() {
+ final String sql = "select FNAME, LNAME from SALES.CUSTOMER where
CONTACTNO > 10";
+ VolcanoPlanner planner = new VolcanoPlanner(null, null);
+ planner.addRelTraitDef(ConventionTraitDef.INSTANCE);
+ planner.addRelTraitDef(RelDistributionTraitDef.INSTANCE);
+
+ Tester dynamicTester = createDynamicTester().withDecorrelation(true)
+ .withClusterFactory(
+ relOptCluster -> RelOptCluster.create(planner,
relOptCluster.getRexBuilder()));
+
+ RelRoot root = dynamicTester.convertSqlToRel(sql);
+
+ String planBefore = NL + RelOptUtil.toString(root.rel);
+ getDiffRepos().assertEquals("planBefore", "${planBefore}", planBefore);
+
+ RuleSet ruleSet =
+ RuleSets.ofList(
+ FilterToCalcRule.INSTANCE,
+ EnumerableRules.ENUMERABLE_PROJECT_RULE,
+ EnumerableRules.ENUMERABLE_TABLE_SCAN_RULE,
+ EnumerableRules.ENUMERABLE_CALC_RULE);
+ Program program = Programs.of(ruleSet);
+
+ RelTraitSet toTraits =
+ root.rel.getCluster().traitSet()
+ .replace(0, EnumerableConvention.INSTANCE);
+
+ RelNode relAfter = program.run(planner, root.rel, toTraits,
+ Collections.emptyList(), Collections.emptyList());
+
+ String planAfter = NL + RelOptUtil.toString(relAfter);
+ getDiffRepos().assertEquals("planAfter", "${planAfter}", planAfter);
+ }
}
// End RelOptRulesTest.java
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 fd445c5..4762ecb 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -11647,7 +11647,7 @@ LogicalSort(sort0=[$0], dir0=[ASC])
</TestCase>
<TestCase name="testReduceDecimal">
<Resource name="sql">
- <![CDATA[select ename from emp where sal > 100]]]>
+ <![CDATA[select ename from emp where sal > cast (100.0 as
decimal(4, 1))]]]>
</Resource>
<Resource name="planBefore">
<![CDATA[
@@ -11664,4 +11664,23 @@ LogicalProject(ENAME=[$1])
]]>
</Resource>
</TestCase>
+ <TestCase name="testEnumerableCalcRule">
+ <Resource name="sql">
+ <![CDATA[select ename from emp where sal > 10.0]]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(FNAME=[$1], LNAME=[$2])
+ LogicalFilter(condition=[>($0, 10)])
+ LogicalTableScan(table=[[CATALOG, SALES, CUSTOMER]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+EnumerableProject(FNAME=[$1], LNAME=[$2])
+ EnumerableCalc(expr#0..2=[{inputs}], expr#3=[10], expr#4=[>($t0, $t3)],
proj#0..2=[{exprs}], $condition=[$t4])
+ EnumerableTableScan(table=[[CATALOG, SALES, CUSTOMER]])
+]]>
+ </Resource>
+ </TestCase>
</Root>