You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by da...@apache.org on 2019/11/25 01:58:23 UTC

[calcite] branch master updated: [CALCITE-3454] Support Exchange, SetOp and TableModify for builtin metadata query (xy2953396112)

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 a3c8a1b  [CALCITE-3454] Support Exchange, SetOp and TableModify for builtin metadata query (xy2953396112)
a3c8a1b is described below

commit a3c8a1b3c70f3aee0fbfe7de0997743d997877bd
Author: dz <95...@qq.com>
AuthorDate: Mon Oct 28 08:41:07 2019 +0800

    [CALCITE-3454] Support Exchange, SetOp and TableModify for builtin
    metadata query (xy2953396112)
    
    close apache/calcite#1552
---
 .../calcite/rel/metadata/RelMdAllPredicates.java   |  8 +++
 .../calcite/rel/metadata/RelMdCollation.java       |  6 ++
 .../calcite/rel/metadata/RelMdColumnOrigins.java   |  6 ++
 .../rel/metadata/RelMdColumnUniqueness.java        |  7 ++
 .../rel/metadata/RelMdDistinctRowCount.java        |  6 ++
 .../calcite/rel/metadata/RelMdDistribution.java    |  5 ++
 .../rel/metadata/RelMdExpressionLineage.java       |  9 +++
 .../calcite/rel/metadata/RelMdMaxRowCount.java     |  5 ++
 .../calcite/rel/metadata/RelMdMinRowCount.java     |  5 ++
 .../calcite/rel/metadata/RelMdNodeTypes.java       | 30 +++++++++
 .../calcite/rel/metadata/RelMdPopulationSize.java  |  6 ++
 .../calcite/rel/metadata/RelMdPredicates.java      |  8 +++
 .../apache/calcite/rel/metadata/RelMdRowCount.java |  5 ++
 .../calcite/rel/metadata/RelMdSelectivity.java     |  6 ++
 .../org/apache/calcite/rel/metadata/RelMdSize.java |  5 ++
 .../calcite/rel/metadata/RelMdTableReferences.java | 31 ++++++++-
 .../calcite/rel/metadata/RelMdUniqueKeys.java      |  6 ++
 .../org/apache/calcite/test/RelMetadataTest.java   | 76 ++++++++++++++++++++--
 18 files changed, 222 insertions(+), 8 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 2c735c3..fa06ad3 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
@@ -27,6 +27,7 @@ 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.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;
@@ -249,6 +250,13 @@ public class RelMdAllPredicates
   }
 
   /**
+   * Extract predicates for an TableModify.
+   */
+  public RelOptPredicateList getAllPredicates(TableModify tableModify, RelMetadataQuery mq) {
+    return mq.getAllPredicates(tableModify.getInput());
+  }
+
+  /**
    * Extract predicates for a Union.
    */
   public RelOptPredicateList getAllPredicates(Union union, RelMetadataQuery mq) {
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
index eb97ece..4358373 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdCollation.java
@@ -37,6 +37,7 @@ import org.apache.calcite.rel.core.Match;
 import org.apache.calcite.rel.core.Project;
 import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.core.SortExchange;
+import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.core.Values;
 import org.apache.calcite.rel.core.Window;
@@ -133,6 +134,11 @@ public class RelMdCollation
     return mq.collations(rel.getInput());
   }
 
+  public ImmutableList<RelCollation> collations(TableModify rel,
+      RelMetadataQuery mq) {
+    return mq.collations(rel.getInput());
+  }
+
   public ImmutableList<RelCollation> collations(TableScan scan,
       RelMetadataQuery mq) {
     return ImmutableList.copyOf(table(scan.getTable()));
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 1cfeb65..8b034ae 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
@@ -27,6 +27,7 @@ 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.TableFunctionScan;
+import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexVisitor;
@@ -157,6 +158,11 @@ public class RelMdColumnOrigins
     return mq.getColumnOrigins(rel.getInput(), iOutputColumn);
   }
 
+  public Set<RelColumnOrigin> getColumnOrigins(TableModify rel, RelMetadataQuery mq,
+      int iOutputColumn) {
+    return mq.getColumnOrigins(rel.getInput(), iOutputColumn);
+  }
+
   public Set<RelColumnOrigin> getColumnOrigins(Exchange rel,
       RelMetadataQuery mq, int iOutputColumn) {
     return mq.getColumnOrigins(rel.getInput(), iOutputColumn);
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
index 182732c..5235065 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java
@@ -33,6 +33,7 @@ import org.apache.calcite.rel.core.Minus;
 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.Values;
 import org.apache.calcite.rel.type.RelDataType;
@@ -145,6 +146,12 @@ public class RelMdColumnUniqueness
     return mq.areColumnsUnique(rel.getInput(), columns, ignoreNulls);
   }
 
+  public Boolean areColumnsUnique(TableModify rel, RelMetadataQuery mq,
+      ImmutableBitSet columns, boolean ignoreNulls) {
+    columns = decorateWithConstantColumnsFromPredicates(columns, rel, mq);
+    return mq.areColumnsUnique(rel.getInput(), columns, ignoreNulls);
+  }
+
   public Boolean areColumnsUnique(Exchange rel, RelMetadataQuery mq,
       ImmutableBitSet columns, boolean ignoreNulls) {
     columns = decorateWithConstantColumnsFromPredicates(columns, rel, mq);
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java
index 0cca9a4..7293b49 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdDistinctRowCount.java
@@ -25,6 +25,7 @@ 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.Sort;
+import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rel.core.Union;
 import org.apache.calcite.rel.core.Values;
 import org.apache.calcite.rex.RexBuilder;
@@ -112,6 +113,11 @@ public class RelMdDistinctRowCount
     return mq.getDistinctRowCount(rel.getInput(), groupKey, predicate);
   }
 
+  public Double getDistinctRowCount(TableModify rel, RelMetadataQuery mq,
+      ImmutableBitSet groupKey, RexNode predicate) {
+    return mq.getDistinctRowCount(rel.getInput(), groupKey, predicate);
+  }
+
   public Double getDistinctRowCount(Exchange rel, RelMetadataQuery mq,
       ImmutableBitSet groupKey, RexNode predicate) {
     return mq.getDistinctRowCount(rel.getInput(), groupKey, predicate);
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 6aac9ab..2403935 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
@@ -29,6 +29,7 @@ import org.apache.calcite.rel.core.Project;
 import org.apache.calcite.rel.core.SetOp;
 import org.apache.calcite.rel.core.Snapshot;
 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.Values;
 import org.apache.calcite.rel.type.RelDataType;
@@ -85,6 +86,10 @@ public class RelMdDistribution
     return mq.distribution(rel.getInputs().get(0));
   }
 
+  public RelDistribution distribution(TableModify rel, RelMetadataQuery mq) {
+    return mq.distribution(rel.getInput());
+  }
+
   public RelDistribution distribution(TableScan scan, RelMetadataQuery mq) {
     return table(scan.getTable());
   }
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 0eb933d..f23c4cf 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
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.JoinRelType;
 import org.apache.calcite.rel.core.Project;
 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;
@@ -391,6 +392,14 @@ public class RelMdExpressionLineage
   }
 
   /**
+   * Expression lineage from TableModify.
+   */
+  public Set<RexNode> getExpressionLineage(TableModify rel, RelMetadataQuery mq,
+      RexNode outputExpression) {
+    return mq.getExpressionLineage(rel.getInput(), outputExpression);
+  }
+
+  /**
    * Expression lineage from Exchange.
    */
   public Set<RexNode> getExpressionLineage(Exchange rel,
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java
index a2b7645..23681cd 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMaxRowCount.java
@@ -28,6 +28,7 @@ import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.Minus;
 import org.apache.calcite.rel.core.Project;
 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.core.Values;
@@ -191,6 +192,10 @@ public class RelMdMaxRowCount
     return (double) values.getTuples().size();
   }
 
+  public Double getMaxRowCount(TableModify rel, RelMetadataQuery mq) {
+    return mq.getMaxRowCount(rel.getInput());
+  }
+
   public Double getMaxRowCount(RelSubset rel, RelMetadataQuery mq) {
     // FIXME This is a short-term fix for [CALCITE-1018]. A complete
     // solution will come with [CALCITE-1048].
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMinRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMinRowCount.java
index 11067ad..d0554ba 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMinRowCount.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdMinRowCount.java
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.Minus;
 import org.apache.calcite.rel.core.Project;
 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.core.Values;
@@ -82,6 +83,10 @@ public class RelMdMinRowCount
     return mq.getMinRowCount(rel.getInput());
   }
 
+  public Double getMinRowCount(TableModify rel, RelMetadataQuery mq) {
+    return mq.getMinRowCount(rel.getInput());
+  }
+
   public Double getMinRowCount(Sort rel, RelMetadataQuery mq) {
     Double rowCount = mq.getMinRowCount(rel.getInput());
     if (rowCount == null) {
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdNodeTypes.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdNodeTypes.java
index c0d8566..83023e0 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdNodeTypes.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdNodeTypes.java
@@ -21,16 +21,21 @@ 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.Correlate;
+import org.apache.calcite.rel.core.Exchange;
 import org.apache.calcite.rel.core.Filter;
 import org.apache.calcite.rel.core.Intersect;
 import org.apache.calcite.rel.core.Join;
+import org.apache.calcite.rel.core.Match;
 import org.apache.calcite.rel.core.Minus;
 import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.core.Sample;
 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.core.Values;
+import org.apache.calcite.rel.core.Window;
 import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Util;
 
@@ -134,6 +139,31 @@ public class RelMdNodeTypes
     return getNodeTypes(rel, TableModify.class, mq);
   }
 
+  public Multimap<Class<? extends RelNode>, RelNode> getNodeTypes(Exchange rel,
+      RelMetadataQuery mq) {
+    return getNodeTypes(rel, Exchange.class, mq);
+  }
+
+  public Multimap<Class<? extends RelNode>, RelNode> getNodeTypes(Sample rel,
+      RelMetadataQuery mq) {
+    return getNodeTypes(rel, Sample.class, mq);
+  }
+
+  public Multimap<Class<? extends RelNode>, RelNode> getNodeTypes(Correlate rel,
+      RelMetadataQuery mq) {
+    return getNodeTypes(rel, Correlate.class, mq);
+  }
+
+  public Multimap<Class<? extends RelNode>, RelNode> getNodeTypes(Window rel,
+      RelMetadataQuery mq) {
+    return getNodeTypes(rel, Window.class, mq);
+  }
+
+  public Multimap<Class<? extends RelNode>, RelNode> getNodeTypes(Match rel,
+      RelMetadataQuery mq) {
+    return getNodeTypes(rel, Match.class, mq);
+  }
+
   private static Multimap<Class<? extends RelNode>, RelNode> getNodeTypes(RelNode rel,
       Class<? extends RelNode> c, RelMetadataQuery mq) {
     final Multimap<Class<? extends RelNode>, RelNode> nodeTypeCount = ArrayListMultimap.create();
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java
index 8e21963..38990f3 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPopulationSize.java
@@ -23,6 +23,7 @@ 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.Sort;
+import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rel.core.Union;
 import org.apache.calcite.rel.core.Values;
 import org.apache.calcite.rex.RexNode;
@@ -66,6 +67,11 @@ public class RelMdPopulationSize
     return mq.getPopulationSize(rel.getInput(), groupKey);
   }
 
+  public Double getPopulationSize(TableModify rel, RelMetadataQuery mq,
+      ImmutableBitSet groupKey) {
+    return mq.getPopulationSize(rel.getInput(), groupKey);
+  }
+
   public Double getPopulationSize(Union rel, RelMetadataQuery mq,
       ImmutableBitSet groupKey) {
     double population = 0.0;
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
index 7355f30..58c53c6 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java
@@ -35,6 +35,7 @@ import org.apache.calcite.rel.core.JoinRelType;
 import org.apache.calcite.rel.core.Minus;
 import org.apache.calcite.rel.core.Project;
 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.rex.RexBuilder;
@@ -469,6 +470,13 @@ public class RelMdPredicates
   }
 
   /**
+   * Infers predicates for a TableModify.
+   */
+  public RelOptPredicateList getPredicates(TableModify tableModify, RelMetadataQuery mq) {
+    return mq.getPulledUpPredicates(tableModify.getInput());
+  }
+
+  /**
    * Infers predicates for an Exchange.
    */
   public RelOptPredicateList getPredicates(Exchange exchange,
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java
index 4c2d311..20abaca 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdRowCount.java
@@ -29,6 +29,7 @@ import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.Minus;
 import org.apache.calcite.rel.core.Project;
 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.core.Values;
@@ -217,6 +218,10 @@ public class RelMdRowCount
   public Double getRowCount(Exchange rel, RelMetadataQuery mq) {
     return mq.getRowCount(rel.getInput());
   }
+
+  public Double getRowCount(TableModify rel, RelMetadataQuery mq) {
+    return mq.getRowCount(rel.getInput());
+  }
 }
 
 // End RelMdRowCount.java
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java
index f4e1516..9bf3fd0 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java
@@ -23,6 +23,7 @@ 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.Sort;
+import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rel.core.Union;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexNode;
@@ -96,6 +97,11 @@ public class RelMdSelectivity
     return mq.getSelectivity(rel.getInput(), predicate);
   }
 
+  public Double getSelectivity(TableModify rel, RelMetadataQuery mq,
+      RexNode predicate) {
+    return mq.getSelectivity(rel.getInput(), predicate);
+  }
+
   public Double getSelectivity(Filter rel, RelMetadataQuery mq,
       RexNode predicate) {
     // Take the difference between the predicate passed in and the
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
index 3d67ee9..c453495 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdSize.java
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.Minus;
 import org.apache.calcite.rel.core.Project;
 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.core.Values;
@@ -118,6 +119,10 @@ public class RelMdSize implements MetadataHandler<BuiltInMetadata.Size> {
     return mq.getAverageColumnSizes(rel.getInput());
   }
 
+  public List<Double> averageColumnSizes(TableModify rel, RelMetadataQuery mq) {
+    return mq.getAverageColumnSizes(rel.getInput());
+  }
+
   public List<Double> averageColumnSizes(Exchange rel, RelMetadataQuery mq) {
     return mq.getAverageColumnSizes(rel.getInput());
   }
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java
index 6e4f153..1ac81e8 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdTableReferences.java
@@ -24,9 +24,12 @@ 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.Sample;
+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.core.Window;
 import org.apache.calcite.rex.RexTableInputRef.RelTableRef;
 import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Util;
@@ -143,12 +146,12 @@ public class RelMdTableReferences
   }
 
   /**
-   * Table references from {@link Union}.
+   * Table references from Union, Intersect, Minus.
    *
    * <p>For Union operator, we might be able to extract multiple table
    * references.
    */
-  public Set<RelTableRef> getTableReferences(Union rel, RelMetadataQuery mq) {
+  public Set<RelTableRef> getTableReferences(SetOp rel, RelMetadataQuery mq) {
     final Set<RelTableRef> result = new HashSet<>();
 
     // Infer column origin expressions for given references
@@ -205,11 +208,33 @@ public class RelMdTableReferences
   }
 
   /**
+   * Table references from TableModify.
+   */
+  public Set<RelTableRef> getTableReferences(TableModify rel, RelMetadataQuery mq) {
+    return mq.getTableReferences(rel.getInput());
+  }
+
+  /**
    * Table references from Exchange.
    */
   public Set<RelTableRef> getTableReferences(Exchange rel, RelMetadataQuery mq) {
     return mq.getTableReferences(rel.getInput());
   }
+
+  /**
+   * Table references from Window.
+   */
+  public Set<RelTableRef> getTableReferences(Window rel, RelMetadataQuery mq) {
+    return mq.getTableReferences(rel.getInput());
+  }
+
+  /**
+   * Table references from Sample.
+   */
+  public Set<RelTableRef> getTableReferences(Sample rel, RelMetadataQuery mq) {
+    return mq.getTableReferences(rel.getInput());
+  }
+
 }
 
 // End RelMdTableReferences.java
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
index d33873e..9ced406 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
@@ -25,6 +25,7 @@ import org.apache.calcite.rel.core.JoinInfo;
 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.rex.RexInputRef;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.util.BuiltInMethod;
@@ -73,6 +74,11 @@ public class RelMdUniqueKeys
     return mq.getUniqueKeys(rel.getLeft(), ignoreNulls);
   }
 
+  public Set<ImmutableBitSet> getUniqueKeys(TableModify rel, RelMetadataQuery mq,
+      boolean ignoreNulls) {
+    return mq.getUniqueKeys(rel.getInput(), ignoreNulls);
+  }
+
   public Set<ImmutableBitSet> getUniqueKeys(Project rel, RelMetadataQuery mq,
       boolean ignoreNulls) {
     // LogicalProject maps a set of rows to a different 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 39b5ea6..df4e0ed 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -36,11 +36,13 @@ import org.apache.calcite.rel.SingleRel;
 import org.apache.calcite.rel.core.Aggregate;
 import org.apache.calcite.rel.core.AggregateCall;
 import org.apache.calcite.rel.core.Correlate;
+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.JoinRelType;
 import org.apache.calcite.rel.core.Minus;
 import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.core.Sample;
 import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.rel.core.TableScan;
@@ -503,13 +505,13 @@ public class RelMetadataTest extends SqlToRelTestBase {
     final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
     final Double result = mq.getRowCount(rel);
     assertThat(result, notNullValue());
-    assertEquals(expected, result, 0d);
+    assertThat(result, is(expected));
     final Double max = mq.getMaxRowCount(rel);
     assertThat(max, notNullValue());
-    assertEquals(expectedMax, max, 0d);
+    assertThat(max, is(expectedMax));
     final Double min = mq.getMinRowCount(rel);
-    assertThat(max, notNullValue());
-    assertEquals(expectedMin, min, 0d);
+    assertThat(min, notNullValue());
+    assertThat(min, is(expectedMin));
   }
 
   @Test public void testRowCountEmp() {
@@ -645,6 +647,11 @@ public class RelMetadataTest extends SqlToRelTestBase {
     checkExchangeRowCount(exchange, EMP_SIZE, 0D, 123456D);
   }
 
+  @Test public void testRowCountTableModify() {
+    final String sql = "insert into emp select * from emp order by ename limit 123456";
+    checkRowCount(sql, EMP_SIZE, 0D, 123456D);
+  }
+
   @Test public void testRowCountSortHighLimit() {
     final String sql = "select * from emp order by ename limit 123456";
     checkRowCount(sql, EMP_SIZE, 0D, 123456D);
@@ -2427,6 +2434,34 @@ public class RelMetadataTest extends SqlToRelTestBase {
             + "[CATALOG, SALES, EMP].#2, [CATALOG, SALES, EMP].#3]"));
   }
 
+  @Test public void testTableReferenceForIntersect() {
+    final String sql1 = "select a.deptno, a.sal from emp a\n"
+        + "intersect all select b.deptno, b.sal from emp b where empno = 5";
+    final RelNode rel1 = convertSql(sql1);
+    final RelMetadataQuery mq1 = rel1.getCluster().getMetadataQuery();
+    final Set<RelTableRef> tableReferences1 = Sets.newTreeSet(mq1.getTableReferences(rel1));
+    assertThat(tableReferences1.toString(),
+        equalTo("[[CATALOG, SALES, EMP].#0, [CATALOG, SALES, EMP].#1]"));
+
+    final String sql2 = "select a.deptno from dept a intersect all select b.deptno from emp b";
+    final RelNode rel2 = convertSql(sql2);
+    final RelMetadataQuery mq2 = rel2.getCluster().getMetadataQuery();
+    final Set<RelTableRef> tableReferences2 = Sets.newTreeSet(mq2.getTableReferences(rel2));
+    assertThat(tableReferences2.toString(),
+        equalTo("[[CATALOG, SALES, DEPT].#0, [CATALOG, SALES, EMP].#0]"));
+
+  }
+
+  @Test public void testTableReferenceForMinus() {
+    final String sql = "select emp.deptno, emp.sal from emp\n"
+        + "except all select emp.deptno, emp.sal from emp where empno = 5";
+    final RelNode rel = convertSql(sql);
+    final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
+    final Set<RelTableRef> tableReferences = Sets.newTreeSet(mq.getTableReferences(rel));
+    assertThat(tableReferences.toString(),
+        equalTo("[[CATALOG, SALES, EMP].#0, [CATALOG, SALES, EMP].#1]"));
+  }
+
   @Test public void testAllPredicatesCrossJoinMultiTable() {
     final String sql = "select x.sal from\n"
         + "(select a.deptno, c.sal from (select * from emp limit 7) as a\n"
@@ -2548,7 +2583,7 @@ public class RelMetadataTest extends SqlToRelTestBase {
     checkNodeTypeCount(sql, expected);
   }
 
-  @Test public void testNodeTypeTableModify() {
+  @Test public void testNodeTypeCountTableModify() {
     final String sql = "insert into emp select * from emp";
     final Map<Class<? extends RelNode>, Integer> expected = new HashMap<>();
     expected.put(TableScan.class, 1);
@@ -2557,6 +2592,37 @@ public class RelMetadataTest extends SqlToRelTestBase {
     checkNodeTypeCount(sql, expected);
   }
 
+  @Test public void testNodeTypeCountExchange() {
+
+    final RelNode rel = convertSql("select * from emp");
+    final RelDistribution dist = RelDistributions.hash(ImmutableList.<Integer>of());
+    final LogicalExchange exchange = LogicalExchange.create(rel, dist);
+
+    final Map<Class<? extends RelNode>, Integer> expected = new HashMap<>();
+    expected.put(TableScan.class, 1);
+    expected.put(Exchange.class, 1);
+    expected.put(Project.class, 1);
+
+    final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
+    final Multimap<Class<? extends RelNode>, RelNode> result = mq.getNodeTypes(exchange);
+    assertThat(result, notNullValue());
+    final Map<Class<? extends RelNode>, Integer> resultCount = new HashMap<>();
+    for (Entry<Class<? extends RelNode>, Collection<RelNode>> e : result.asMap().entrySet()) {
+      resultCount.put(e.getKey(), e.getValue().size());
+    }
+    assertThat(expected, equalTo(resultCount));
+  }
+
+  @Test public void testNodeTypeCountSample() {
+    final String sql = "select * from emp tablesample system(50) where empno > 5";
+    final Map<Class<? extends RelNode>, Integer> expected = new HashMap<>();
+    expected.put(TableScan.class, 1);
+    expected.put(Filter.class, 1);
+    expected.put(Project.class, 1);
+    expected.put(Sample.class, 1);
+    checkNodeTypeCount(sql, expected);
+  }
+
   @Test public void testNodeTypeCountJoinFinite() {
     final String sql = "select * from (select * from emp limit 14) as emp\n"
         + "inner join (select * from dept limit 4) as dept\n"