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 d1aae57 [CALCITE-3971] Support Calc in RelMdColumnOrigins (Xu ZhaoHui)
d1aae57 is described below
commit d1aae57fad71bf10942d4c53b339363537927c29
Author: dz <[email protected]>
AuthorDate: Sat May 2 09:16:43 2020 +0800
[CALCITE-3971] Support Calc in RelMdColumnOrigins (Xu ZhaoHui)
---
.../calcite/rel/metadata/RelMdColumnOrigins.java | 63 ++++++++++++++++------
.../org/apache/calcite/test/RelMetadataTest.java | 19 +++++++
2 files changed, 66 insertions(+), 16 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
index 2dc7d83..d2b2d18 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnOrigins.java
@@ -20,6 +20,7 @@ import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.AggregateCall;
+import org.apache.calcite.rel.core.Calc;
import org.apache.calcite.rel.core.Exchange;
import org.apache.calcite.rel.core.Filter;
import org.apache.calcite.rel.core.Join;
@@ -29,12 +30,16 @@ import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rel.core.TableFunctionScan;
import org.apache.calcite.rel.core.TableModify;
import org.apache.calcite.rex.RexInputRef;
+import org.apache.calcite.rex.RexLocalRef;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexShuttle;
import org.apache.calcite.rex.RexVisitor;
import org.apache.calcite.rex.RexVisitorImpl;
import org.apache.calcite.util.BuiltInMethod;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
@@ -128,23 +133,31 @@ public class RelMdColumnOrigins
RexInputRef inputRef = (RexInputRef) rexNode;
return mq.getColumnOrigins(input, inputRef.getIndex());
}
+ // Anything else is a derivation, possibly from multiple columns.
+ final Set<RelColumnOrigin> set = getMultipleColumns(rexNode, input, mq);
+ return createDerivedColumnOrigins(set);
+ }
- // Anything else is a derivation, possibly from multiple
- // columns.
- final Set<RelColumnOrigin> set = new HashSet<>();
- RexVisitor visitor =
- new RexVisitorImpl<Void>(true) {
- public Void visitInputRef(RexInputRef inputRef) {
- Set<RelColumnOrigin> inputSet =
- mq.getColumnOrigins(input, inputRef.getIndex());
- if (inputSet != null) {
- set.addAll(inputSet);
- }
- return null;
- }
- };
- rexNode.accept(visitor);
-
+ public Set<RelColumnOrigin> getColumnOrigins(Calc rel,
+ final RelMetadataQuery mq, int iOutputColumn) {
+ final RelNode input = rel.getInput();
+ final RexShuttle rexShuttle = new RexShuttle() {
+ @Override public RexNode visitLocalRef(RexLocalRef localRef) {
+ return rel.getProgram().expandLocalRef(localRef);
+ }
+ };
+ final List<RexNode> projects = new ArrayList<>();
+ for (RexNode rex: rexShuttle.apply(rel.getProgram().getProjectList())) {
+ projects.add(rex);
+ }
+ final RexNode rexNode = projects.get(iOutputColumn);
+ if (rexNode instanceof RexInputRef) {
+ // Direct reference: no derivation added.
+ RexInputRef inputRef = (RexInputRef) rexNode;
+ return mq.getColumnOrigins(input, inputRef.getIndex());
+ }
+ // Anything else is a derivation, possibly from multiple columns.
+ final Set<RelColumnOrigin> set = getMultipleColumns(rexNode, input, mq);
return createDerivedColumnOrigins(set);
}
@@ -253,4 +266,22 @@ public class RelMdColumnOrigins
}
return set;
}
+
+ private Set<RelColumnOrigin> getMultipleColumns(RexNode rexNode, RelNode
input,
+ final RelMetadataQuery mq) {
+ final Set<RelColumnOrigin> set = new HashSet<>();
+ RexVisitor visitor =
+ new RexVisitorImpl<Void>(true) {
+ public Void visitInputRef(RexInputRef inputRef) {
+ Set<RelColumnOrigin> inputSet =
+ mq.getColumnOrigins(input, inputRef.getIndex());
+ if (inputSet != null) {
+ set.addAll(inputSet);
+ }
+ return null;
+ }
+ };
+ rexNode.accept(visitor);
+ return set;
+ }
}
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 9d8f011..fcc54aa 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -25,6 +25,9 @@ import org.apache.calcite.plan.RelOptPredicateList;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.plan.hep.HepPlanner;
+import org.apache.calcite.plan.hep.HepProgram;
+import org.apache.calcite.plan.hep.HepProgramBuilder;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelCollationTraitDef;
import org.apache.calcite.rel.RelCollations;
@@ -74,6 +77,7 @@ import org.apache.calcite.rel.metadata.RelMdColumnUniqueness;
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.ProjectToCalcRule;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rex.RexBuilder;
@@ -374,6 +378,21 @@ public class RelMetadataTest extends SqlToRelTestBase {
}
}
+ @Test void testCalcColumnOriginsTable() {
+ final String sql = "select name,deptno from dept where deptno > 10";
+ final RelNode relNode = convertSql(sql);
+ final HepProgram program = new HepProgramBuilder().
+ addRuleInstance(ProjectToCalcRule.INSTANCE).build();
+ final HepPlanner planner = new HepPlanner(program);
+ planner.setRoot(relNode);
+ final RelNode calc = planner.findBestExp();
+ final RelMetadataQuery mq = calc.getCluster().getMetadataQuery();
+ final RelColumnOrigin nameColumn = mq.getColumnOrigin(calc, 0);
+ assertThat(nameColumn.getOriginColumnOrdinal(), is(1));
+ final RelColumnOrigin deptnoColumn = mq.getColumnOrigin(calc, 1);
+ assertThat(deptnoColumn.getOriginColumnOrdinal(), is(0));
+ }
+
@Test void testColumnOriginsTableOnly() {
checkSingleColumnOrigin(
"select name as dname from dept",