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",

Reply via email to