This is an automated email from the ASF dual-hosted git repository.
yanlin 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 99251a5 [CALCITE-4251] Support Calc and SetOp operator in
RelMdAllPredicates (Xu Zhaohui)
99251a5 is described below
commit 99251a51842483bc80688364195a159b740bd53f
Author: xzh <[email protected]>
AuthorDate: Sat May 16 23:51:59 2020 +0800
[CALCITE-4251] Support Calc and SetOp operator in RelMdAllPredicates (Xu
Zhaohui)
---
.../calcite/rel/metadata/RelMdAllPredicates.java | 59 +++++++++++++++-------
.../org/apache/calcite/test/RelMetadataTest.java | 49 ++++++++++++++++++
2 files changed, 89 insertions(+), 19 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdAllPredicates.java
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdAllPredicates.java
index 10ad7a0..0ece757 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdAllPredicates.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdAllPredicates.java
@@ -22,19 +22,21 @@ import org.apache.calcite.plan.hep.HepRelVertex;
import org.apache.calcite.plan.volcano.RelSubset;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
+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;
import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.core.SetOp;
import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rel.core.TableModify;
import org.apache.calcite.rel.core.TableScan;
-import org.apache.calcite.rel.core.Union;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexInputRef;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexProgram;
import org.apache.calcite.rex.RexTableInputRef;
import org.apache.calcite.rex.RexTableInputRef.RelTableRef;
import org.apache.calcite.rex.RexUtil;
@@ -101,7 +103,7 @@ public class RelMdAllPredicates
}
/**
- * Extract predicates for a table scan.
+ * Extracts predicates for a table scan.
*/
public RelOptPredicateList getAllPredicates(TableScan scan, RelMetadataQuery
mq) {
final BuiltInMetadata.AllPredicates.Handler handler =
@@ -113,21 +115,40 @@ public class RelMdAllPredicates
}
/**
- * Extract predicates for a project.
+ * Extracts predicates for a project.
*/
public RelOptPredicateList getAllPredicates(Project project,
RelMetadataQuery mq) {
return mq.getAllPredicates(project.getInput());
}
/**
- * Add the Filter condition to the list obtained from the input.
+ * Extracts predicates for a Filter.
*/
public RelOptPredicateList getAllPredicates(Filter filter, RelMetadataQuery
mq) {
- final RelNode input = filter.getInput();
- final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
- final RexNode pred = filter.getCondition();
+ return getAllFilterPredicates(filter.getInput(), mq,
filter.getCondition());
+ }
+
+ /**
+ * Extracts predicates for a Calc.
+ */
+ public RelOptPredicateList getAllPredicates(Calc calc, RelMetadataQuery mq) {
+ final RexProgram rexProgram = calc.getProgram();
+ if (rexProgram.getCondition() != null) {
+ final RexNode condition =
rexProgram.expandLocalRef(rexProgram.getCondition());
+ return getAllFilterPredicates(calc.getInput(), mq, condition);
+ } else {
+ return mq.getAllPredicates(calc.getInput());
+ }
+ }
- final RelOptPredicateList predsBelow = mq.getAllPredicates(input);
+ /**
+ * Add the Filter condition to the list obtained from the input.
+ * The pred comes from the parent of rel.
+ */
+ private RelOptPredicateList getAllFilterPredicates(RelNode rel,
+ RelMetadataQuery mq, RexNode pred) {
+ final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
+ final RelOptPredicateList predsBelow = mq.getAllPredicates(rel);
if (predsBelow == null) {
// Safety check
return null;
@@ -142,8 +163,8 @@ public class RelMdAllPredicates
// Infer column origin expressions for given references
final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
for (int idx : inputFieldsUsed) {
- final RexInputRef ref = RexInputRef.of(idx,
filter.getRowType().getFieldList());
- final Set<RexNode> originalExprs = mq.getExpressionLineage(filter, ref);
+ final RexInputRef ref = RexInputRef.of(idx,
rel.getRowType().getFieldList());
+ final Set<RexNode> originalExprs = mq.getExpressionLineage(rel, ref);
if (originalExprs == null) {
// Bail out
return null;
@@ -246,29 +267,29 @@ public class RelMdAllPredicates
}
/**
- * Extract predicates for an Aggregate.
+ * Extracts predicates for an Aggregate.
*/
public RelOptPredicateList getAllPredicates(Aggregate agg, RelMetadataQuery
mq) {
return mq.getAllPredicates(agg.getInput());
}
/**
- * Extract predicates for an TableModify.
+ * Extracts predicates for an TableModify.
*/
public RelOptPredicateList getAllPredicates(TableModify tableModify,
RelMetadataQuery mq) {
return mq.getAllPredicates(tableModify.getInput());
}
/**
- * Extract predicates for a Union.
+ * Extracts predicates for a SetOp.
*/
- public RelOptPredicateList getAllPredicates(Union union, RelMetadataQuery
mq) {
- final RexBuilder rexBuilder = union.getCluster().getRexBuilder();
+ public RelOptPredicateList getAllPredicates(SetOp setOp, RelMetadataQuery
mq) {
+ final RexBuilder rexBuilder = setOp.getCluster().getRexBuilder();
final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs =
HashMultimap.create();
RelOptPredicateList newPreds = RelOptPredicateList.EMPTY;
- for (int i = 0; i < union.getInputs().size(); i++) {
- final RelNode input = union.getInput(i);
+ for (int i = 0; i < setOp.getInputs().size(); i++) {
+ final RelNode input = setOp.getInput(i);
final RelOptPredicateList inputPreds = mq.getAllPredicates(input);
if (inputPreds == null) {
// Bail out
@@ -313,14 +334,14 @@ public class RelMdAllPredicates
}
/**
- * Extract predicates for a Sort.
+ * Extracts predicates for a Sort.
*/
public RelOptPredicateList getAllPredicates(Sort sort, RelMetadataQuery mq) {
return mq.getAllPredicates(sort.getInput());
}
/**
- * Extract predicates for an Exchange.
+ * Extracts predicates for an Exchange.
*/
public RelOptPredicateList getAllPredicates(Exchange exchange,
RelMetadataQuery mq) {
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 c517529..ae19f68 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -2688,6 +2688,25 @@ public class RelMetadataTest extends SqlToRelTestBase {
+ "[CATALOG, SALES, EMP].#2, [CATALOG, SALES, EMP].#3]"));
}
+ @Test void testAllPredicatesAndTablesCalc() {
+ final String sql = "select empno as a, sal as b from emp where empno > 5";
+ final RelNode relNode = convertSql(sql);
+ final HepProgram hepProgram = new HepProgramBuilder()
+ .addRuleInstance(CoreRules.PROJECT_TO_CALC)
+ .addRuleInstance(CoreRules.FILTER_TO_CALC)
+ .build();
+ final HepPlanner planner = new HepPlanner(hepProgram);
+ planner.setRoot(relNode);
+ final RelNode rel = planner.findBestExp();
+ final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
+ final RelOptPredicateList inputSet = mq.getAllPredicates(rel);
+ assertThat(inputSet.pulledUpPredicates,
+ sortsAs("[>([CATALOG, SALES, EMP].#0.$0, 5)]"));
+ final Set<RelTableRef> tableReferences =
Sets.newTreeSet(mq.getTableReferences(rel));
+ assertThat(tableReferences.toString(),
+ equalTo("[[CATALOG, SALES, EMP].#0]"));
+ }
+
@Test void testAllPredicatesAndTableUnion() {
final String sql = "select a.deptno, c.sal from (select * from emp limit
7) as a\n"
+ "cross join (select * from dept limit 1) as b\n"
@@ -2698,6 +2717,36 @@ public class RelMetadataTest extends SqlToRelTestBase {
+ "cross join (select * from dept limit 1) as b\n"
+ "inner join (select * from emp limit 2) as c\n"
+ "on a.deptno = c.deptno";
+ checkAllPredicatesAndTableSetOp(sql);
+ }
+
+ @Test void testAllPredicatesAndTableIntersect() {
+ final String sql = "select a.deptno, c.sal from (select * from emp limit
7) as a\n"
+ + "cross join (select * from dept limit 1) as b\n"
+ + "inner join (select * from emp limit 2) as c\n"
+ + "on a.deptno = c.deptno\n"
+ + "intersect all\n"
+ + "select a.deptno, c.sal from (select * from emp limit 7) as a\n"
+ + "cross join (select * from dept limit 1) as b\n"
+ + "inner join (select * from emp limit 2) as c\n"
+ + "on a.deptno = c.deptno";
+ checkAllPredicatesAndTableSetOp(sql);
+ }
+
+ @Test void testAllPredicatesAndTableMinus() {
+ final String sql = "select a.deptno, c.sal from (select * from emp limit
7) as a\n"
+ + "cross join (select * from dept limit 1) as b\n"
+ + "inner join (select * from emp limit 2) as c\n"
+ + "on a.deptno = c.deptno\n"
+ + "except all\n"
+ + "select a.deptno, c.sal from (select * from emp limit 7) as a\n"
+ + "cross join (select * from dept limit 1) as b\n"
+ + "inner join (select * from emp limit 2) as c\n"
+ + "on a.deptno = c.deptno";
+ checkAllPredicatesAndTableSetOp(sql);
+ }
+
+ public void checkAllPredicatesAndTableSetOp(String sql) {
final RelNode rel = convertSql(sql);
final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
final RelOptPredicateList inputSet = mq.getAllPredicates(rel);