You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2016/01/11 05:47:13 UTC

[12/27] calcite git commit: [CALCITE-794] Detect cycles when computing statistics

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/runtime/FlatLists.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/runtime/FlatLists.java b/core/src/main/java/org/apache/calcite/runtime/FlatLists.java
index f3cfae4..64ce699 100644
--- a/core/src/main/java/org/apache/calcite/runtime/FlatLists.java
+++ b/core/src/main/java/org/apache/calcite/runtime/FlatLists.java
@@ -16,6 +16,8 @@
  */
 package org.apache.calcite.runtime;
 
+import org.apache.calcite.util.ImmutableNullableList;
+
 import java.util.AbstractList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -53,7 +55,7 @@ public class FlatLists {
    * @param <T> Element type
    * @return List containing the given members
    */
-  public static <T> List<T> of(T... t) {
+  public static <T extends Comparable> List<T> of(T... t) {
     return flatList_(t, false);
   }
 
@@ -65,21 +67,54 @@ public class FlatLists {
    * @param <T> Element type
    * @return List containing the given members
    */
+  @Deprecated // to be removed before 2.0
   public static <T> List<T> copy(T... t) {
+    return flatListNotComparable(t);
+  }
+
+  /**
+   * Creates a memory-, CPU- and cache-efficient comparable immutable list,
+   * always copying the contents.
+   *
+   * <p>The elements are comparable, and so is the returned list.
+   * Elements may be null.
+   *
+   * @param t Array of members of list
+   * @param <T> Element type
+   * @return List containing the given members
+   */
+  public static <T extends Comparable> List<T> copyOf(T... t) {
     return flatList_(t, true);
   }
 
   /**
-   * Creates a memory-, CPU- and cache-efficient immutable list, optionally
-   * copying the list.
+   * Creates a memory-, CPU- and cache-efficient immutable list,
+   * always copying the contents.
+   *
+   * <p>The elements need not be comparable,
+   * and the returned list may not implement {@link Comparable}.
+   * Elements may be null.
+   *
+   * @param t Array of members of list
+   * @param <T> Element type
+   * @return List containing the given members
+   */
+  public static <T> List<T> copyOf(T... t) {
+    return flatListNotComparable(t);
+  }
+
+  /**
+   * Creates a memory-, CPU- and cache-efficient comparable immutable list,
+   * optionally copying the list.
    *
    * @param copy Whether to always copy the list
    * @param t Array of members of list
    * @return List containing the given members
    */
-  private static <T> List<T> flatList_(T[] t, boolean copy) {
+  private static <T extends Comparable> List<T> flatList_(T[] t, boolean copy) {
     switch (t.length) {
     case 0:
+      //noinspection unchecked
       return COMPARABLE_EMPTY_LIST;
     case 1:
       return Collections.singletonList(t[0]);
@@ -92,14 +127,37 @@ public class FlatLists {
       //   write our own implementation and reduce creation overhead a
       //   bit.
       if (copy) {
-        return new ComparableListImpl(Arrays.asList(t.clone()));
+        return new ComparableListImpl<>(Arrays.asList(t.clone()));
       } else {
-        return new ComparableListImpl(Arrays.asList(t));
+        return new ComparableListImpl<>(Arrays.asList(t));
       }
     }
   }
 
   /**
+   * Creates a memory-, CPU- and cache-efficient immutable list,
+   * always copying the list.
+   *
+   * @param t Array of members of list
+   * @return List containing the given members
+   */
+  private static <T> List<T> flatListNotComparable(T[] t) {
+    switch (t.length) {
+    case 0:
+      //noinspection unchecked
+      return COMPARABLE_EMPTY_LIST;
+    case 1:
+      return Collections.singletonList(t[0]);
+    case 2:
+      return new Flat2List<>(t[0], t[1]);
+    case 3:
+      return new Flat3List<>(t[0], t[1], t[2]);
+    default:
+      return ImmutableNullableList.copyOf(t);
+    }
+  }
+
+  /**
    * Creates a memory-, CPU- and cache-efficient immutable list from an
    * existing list. The list is always copied.
    *
@@ -110,13 +168,14 @@ public class FlatLists {
   public static <T> List<T> of(List<T> t) {
     switch (t.size()) {
     case 0:
+      //noinspection unchecked
       return COMPARABLE_EMPTY_LIST;
     case 1:
       return Collections.singletonList(t.get(0));
     case 2:
-      return new Flat2List<T>(t.get(0), t.get(1));
+      return new Flat2List<>(t.get(0), t.get(1));
     case 3:
-      return new Flat3List<T>(t.get(0), t.get(1), t.get(2));
+      return new Flat3List<>(t.get(0), t.get(1), t.get(2));
     default:
       // REVIEW: AbstractList contains a modCount field; we could
       //   write our own implementation and reduce creation overhead a

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/schema/impl/StarTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/schema/impl/StarTable.java b/core/src/main/java/org/apache/calcite/schema/impl/StarTable.java
index 25e7480..27f3cf8 100644
--- a/core/src/main/java/org/apache/calcite/schema/impl/StarTable.java
+++ b/core/src/main/java/org/apache/calcite/schema/impl/StarTable.java
@@ -25,6 +25,7 @@ import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.schema.Schema;
@@ -129,7 +130,8 @@ public class StarTable extends AbstractTable implements TranslatableTable {
       super(cluster, cluster.traitSetOf(Convention.NONE), relOptTable);
     }
 
-    @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeInfiniteCost();
     }
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java b/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java
index e1d9f93..ba196db 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java
@@ -48,6 +48,7 @@ import org.apache.calcite.rel.logical.LogicalJoin;
 import org.apache.calcite.rel.logical.LogicalProject;
 import org.apache.calcite.rel.logical.LogicalSort;
 import org.apache.calcite.rel.metadata.RelMdUtil;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.rules.FilterCorrelateRule;
 import org.apache.calcite.rel.rules.FilterJoinRule;
 import org.apache.calcite.rel.rules.FilterProjectTransposeRule;
@@ -1741,8 +1742,8 @@ public class RelDecorrelator implements ReflectiveVisitor {
 
         // The join filters out the nulls.  So, it's ok if there are
         // nulls in the join keys.
-        if (!RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(
-            right,
+        final RelMetadataQuery mq = RelMetadataQuery.instance();
+        if (!RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq, right,
             rightJoinKeys)) {
           SQL2REL_LOGGER.fine(rightJoinKeys.toString()
               + "are not unique keys for "
@@ -1956,8 +1957,8 @@ public class RelDecorrelator implements ReflectiveVisitor {
 
         // The join filters out the nulls.  So, it's ok if there are
         // nulls in the join keys.
-        if (!RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(
-            left,
+        final RelMetadataQuery mq = RelMetadataQuery.instance();
+        if (!RelMdUtil.areColumnsDefinitelyUniqueWhenNullsFiltered(mq, left,
             correlatedInputRefJoinKeys)) {
           SQL2REL_LOGGER.fine(correlatedJoinKeys.toString()
               + "are not unique keys for "
@@ -2035,9 +2036,8 @@ public class RelDecorrelator implements ReflectiveVisitor {
         // leftInputRel contains unique keys
         // i.e. each row is distinct and can group by on all the left
         // fields
-        if (!RelMdUtil.areColumnsDefinitelyUnique(
-            left,
-            allCols)) {
+        final RelMetadataQuery mq = RelMetadataQuery.instance();
+        if (!RelMdUtil.areColumnsDefinitelyUnique(mq, left, allCols)) {
           SQL2REL_LOGGER.fine("There are no unique keys for " + left);
           return;
         }

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java b/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
index 8638df0..bd62c87 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
@@ -70,10 +70,8 @@ import com.google.common.collect.Iterables;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.logging.Level;
 
@@ -107,7 +105,6 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
 
   private final ReflectUtil.MethodDispatcher<TrimResult> trimFieldsDispatcher;
   private final RelBuilder relBuilder;
-  private Map<RelNode, Mapping> map = new HashMap<>();
 
   //~ Constructors -----------------------------------------------------------
 
@@ -189,8 +186,8 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
     final ImmutableBitSet.Builder fieldsUsedBuilder = fieldsUsed.rebuild();
 
     // Fields that define the collation cannot be discarded.
-    final ImmutableList<RelCollation> collations =
-        RelMetadataQuery.collations(input);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    final ImmutableList<RelCollation> collations = mq.collations(input);
     for (RelCollation collation : collations) {
       for (RelFieldCollation fieldCollation : collation.getFieldCollations()) {
         fieldsUsedBuilder.set(fieldCollation.getFieldIndex());
@@ -293,9 +290,7 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
   }
 
   private TrimResult result(RelNode r, final Mapping mapping) {
-    map.put(r, mapping);
     final RexBuilder rexBuilder = relBuilder.getRexBuilder();
-    final RelNode r0 = r;
     for (final CorrelationId correlation : r.getVariablesSet()) {
       r = r.accept(
           new CorrelationReferenceFinder() {
@@ -362,7 +357,6 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
     final RelDataType rowType = project.getRowType();
     final int fieldCount = rowType.getFieldCount();
     final RelNode input = project.getInput();
-    final RelDataType inputRowType = input.getRowType();
 
     // Which fields are required from the input?
     final Set<RelDataTypeField> inputExtraFields =

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/util/Bug.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/util/Bug.java b/core/src/main/java/org/apache/calcite/util/Bug.java
index 884b967..f60fbd1 100644
--- a/core/src/main/java/org/apache/calcite/util/Bug.java
+++ b/core/src/main/java/org/apache/calcite/util/Bug.java
@@ -171,9 +171,9 @@ public abstract class Bug {
   public static final boolean CALCITE_673_FIXED = false;
 
   /** Whether
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-794">[CALCITE-794]
-   * Detect cycles when computing statistics</a> is fixed. */
-  public static final boolean CALCITE_794_FIXED = false;
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-1048">[CALCITE-1048]
+   * Make metadata more robust</a> is fixed. */
+  public static final boolean CALCITE_1048_FIXED = false;
 
   /** Whether
    * <a href="https://issues.apache.org/jira/browse/CALCITE-1045">[CALCITE-1045]

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index c899cb8..9ea40b4 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -176,7 +176,7 @@ public enum BuiltInMethod {
   FUNCTION1_APPLY(Function1.class, "apply", Object.class),
   ARRAYS_AS_LIST(Arrays.class, "asList", Object[].class),
   ARRAY(SqlFunctions.class, "array", Object[].class),
-  LIST_N(FlatLists.class, "of", Object[].class),
+  LIST_N(FlatLists.class, "copyOf", Comparable[].class),
   LIST2(FlatLists.class, "of", Object.class, Object.class),
   LIST3(FlatLists.class, "of", Object.class, Object.class, Object.class),
   COMPARABLE_EMPTY_LIST(FlatLists.class, "COMPARABLE_EMPTY_LIST", true),
@@ -346,6 +346,7 @@ public enum BuiltInMethod {
   COLUMN_ORIGIN(ColumnOrigin.class, "getColumnOrigins", int.class),
   CUMULATIVE_COST(CumulativeCost.class, "getCumulativeCost"),
   NON_CUMULATIVE_COST(NonCumulativeCost.class, "getNonCumulativeCost"),
+  PREDICATES(Predicates.class, "getPredicates"),
   EXPLAIN_VISIBILITY(ExplainVisibility.class, "isVisibleInExplain",
       SqlExplainLevel.class),
   SCALAR_EXECUTE1(Scalar.class, "execute", Context.class),
@@ -353,7 +354,6 @@ public enum BuiltInMethod {
   CONTEXT_VALUES(Context.class, "values", true),
   CONTEXT_ROOT(Context.class, "root", true),
   DATA_CONTEXT_GET_QUERY_PROVIDER(DataContext.class, "getQueryProvider"),
-  PREDICATES(Predicates.class, "getPredicates"),
   METADATA_REL(Metadata.class, "rel");
 
   public final Method method;
@@ -373,7 +373,7 @@ public enum BuiltInMethod {
     MAP = builder.build();
   }
 
-  private BuiltInMethod(Method method, Constructor constructor, Field field) {
+  BuiltInMethod(Method method, Constructor constructor, Field field) {
     this.method = method;
     this.constructor = constructor;
     this.field = field;

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/main/java/org/apache/calcite/util/NumberUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/util/NumberUtil.java b/core/src/main/java/org/apache/calcite/util/NumberUtil.java
index 4d5f71a..7e9d532 100644
--- a/core/src/main/java/org/apache/calcite/util/NumberUtil.java
+++ b/core/src/main/java/org/apache/calcite/util/NumberUtil.java
@@ -155,6 +155,17 @@ public class NumberUtil {
 
     return a * b;
   }
+
+  /** Like {@link Math#min} but null safe. */
+  public static Double min(Double a, Double b) {
+    if (a == null) {
+      return b;
+    } else if (b == null) {
+      return a;
+    } else {
+      return Math.min(a, b);
+    }
+  }
 }
 
 // End NumberUtil.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java b/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java
index 8acd917..8d4dbd4 100644
--- a/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java
+++ b/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java
@@ -110,8 +110,9 @@ public class TraitPropagationTest {
           RelOptUtil.dumpPlan("LOGICAL PLAN", planned, false,
               SqlExplainLevel.ALL_ATTRIBUTES));
     }
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
     assertEquals("Sortedness was not propagated", 3,
-        RelMetadataQuery.getCumulativeCost(planned).getRows(), 0);
+        mq.getCumulativeCost(planned).getRows(), 0);
   }
 
   /**
@@ -306,7 +307,8 @@ public class TraitPropagationTest {
           groupSets, aggCalls);
     }
 
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeCost(1, 1, 1);
     }
   }
@@ -321,13 +323,14 @@ public class TraitPropagationTest {
     public static PhysProj create(final RelNode input,
         final List<RexNode> projects, RelDataType rowType) {
       final RelOptCluster cluster = input.getCluster();
+      final RelMetadataQuery mq = RelMetadataQuery.instance();
       final RelTraitSet traitSet =
           cluster.traitSet().replace(PHYSICAL)
               .replaceIfs(
                   RelCollationTraitDef.INSTANCE,
                   new Supplier<List<RelCollation>>() {
                     public List<RelCollation> get() {
-                      return RelMdCollation.project(input, projects);
+                      return RelMdCollation.project(mq, input, projects);
                     }
                   });
       return new PhysProj(cluster, traitSet, input, projects, rowType);
@@ -338,7 +341,8 @@ public class TraitPropagationTest {
       return new PhysProj(getCluster(), traitSet, input, exps, rowType);
     }
 
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeCost(1, 1, 1);
     }
   }
@@ -359,7 +363,8 @@ public class TraitPropagationTest {
           offset, fetch);
     }
 
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeCost(1, 1, 1);
     }
   }
@@ -375,7 +380,8 @@ public class TraitPropagationTest {
           .add("i", integerType).build();
     }
 
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeCost(1, 1, 1);
     }
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java b/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java
index a44ab94..aea52f6 100644
--- a/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java
+++ b/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java
@@ -34,6 +34,7 @@ import org.apache.calcite.rel.SingleRel;
 import org.apache.calcite.rel.convert.ConverterImpl;
 import org.apache.calcite.rel.convert.ConverterRule;
 import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.rules.ProjectRemoveRule;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
@@ -495,7 +496,8 @@ public class VolcanoPlannerTest {
     }
 
     // implement RelNode
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeInfiniteCost();
     }
 
@@ -523,7 +525,8 @@ public class VolcanoPlannerTest {
     }
 
     // implement RelNode
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeInfiniteCost();
     }
 
@@ -582,7 +585,8 @@ public class VolcanoPlannerTest {
     }
 
     // implement RelNode
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeTinyCost();
     }
 
@@ -605,7 +609,8 @@ public class VolcanoPlannerTest {
     }
 
     // implement RelNode
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeTinyCost();
     }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTraitTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTraitTest.java b/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTraitTest.java
index e97a07c..c8530a2 100644
--- a/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTraitTest.java
+++ b/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTraitTest.java
@@ -36,6 +36,7 @@ import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.SingleRel;
 import org.apache.calcite.rel.convert.ConverterImpl;
 import org.apache.calcite.rel.convert.ConverterRule;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.util.Pair;
@@ -324,6 +325,7 @@ public class VolcanoPlannerTraitTest {
       RelTrait fromTrait = rel.getTraitSet().getTrait(this);
 
       if (conversionMap.containsKey(fromTrait)) {
+        final RelMetadataQuery mq = RelMetadataQuery.instance();
         for (Pair<RelTrait, ConverterRule> traitAndRule
             : conversionMap.get(fromTrait)) {
           RelTrait trait = traitAndRule.left;
@@ -332,7 +334,7 @@ public class VolcanoPlannerTraitTest {
           if (trait == toTrait) {
             RelNode converted = rule.convert(rel);
             if ((converted != null)
-                && (!planner.getCost(converted).isInfinite()
+                && (!planner.getCost(converted, mq).isInfinite()
                 || allowInfiniteCostConverters)) {
               return converted;
             }
@@ -369,8 +371,7 @@ public class VolcanoPlannerTraitTest {
       RelTrait fromTrait = converterRule.getInTrait();
       RelTrait toTrait = converterRule.getOutTrait();
 
-      conversionMap.put(fromTrait,
-          new Pair<RelTrait, ConverterRule>(toTrait, converterRule));
+      conversionMap.put(fromTrait, Pair.of(toTrait, converterRule));
     }
   }
 
@@ -391,7 +392,8 @@ public class VolcanoPlannerTraitTest {
     }
 
     // implement RelNode
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeInfiniteCost();
     }
 
@@ -437,7 +439,8 @@ public class VolcanoPlannerTraitTest {
     }
 
     // implement RelNode
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeTinyCost();
     }
 
@@ -454,7 +457,8 @@ public class VolcanoPlannerTraitTest {
     }
 
     // implement RelNode
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeInfiniteCost();
     }
 
@@ -508,7 +512,8 @@ public class VolcanoPlannerTraitTest {
     }
 
     // implement RelNode
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeTinyCost();
     }
 
@@ -731,7 +736,8 @@ public class VolcanoPlannerTraitTest {
           label);
     }
 
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
       return planner.getCostFactory().makeZeroCost();
     }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
index 51a4a70..8f4e5f3 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
@@ -214,26 +214,24 @@ public class JdbcAdapterTest {
             + "inner join scott.salgrade s \n"
             + "on e.sal > s.losal and e.sal < s.hisal")
         .explainContains("PLAN=JdbcToEnumerableConverter\n"
-            + "  JdbcProject(EMPNO=[$2], ENAME=[$3], DNAME=[$1], GRADE=[$6])\n"
-            + "    JdbcJoin(condition=[=($5, $0)], joinType=[inner])\n"
-            + "      JdbcProject(DEPTNO=[$0], DNAME=[$1])\n"
-            + "        JdbcTableScan(table=[[SCOTT, DEPT]])\n"
-            + "      JdbcJoin(condition=[AND(>($2, $5), <($2, $6))], joinType=[inner])\n"
+            + "  JdbcProject(EMPNO=[$3], ENAME=[$4], DNAME=[$8], GRADE=[$0])\n"
+            + "    JdbcJoin(condition=[AND(>($5, $1), <($5, $2))], joinType=[inner])\n"
+            + "      JdbcTableScan(table=[[SCOTT, SALGRADE]])\n"
+            + "      JdbcJoin(condition=[=($3, $4)], joinType=[inner])\n"
             + "        JdbcProject(EMPNO=[$0], ENAME=[$1], SAL=[$5], DEPTNO=[$7])\n"
             + "          JdbcTableScan(table=[[SCOTT, EMP]])\n"
-            + "        JdbcTableScan(table=[[SCOTT, SALGRADE]])")
+            + "        JdbcProject(DEPTNO=[$0], DNAME=[$1])\n"
+            + "          JdbcTableScan(table=[[SCOTT, DEPT]])")
         .runs()
         .enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.HSQLDB)
-        .planHasSql("SELECT \"t0\".\"EMPNO\", \"t0\".\"ENAME\", "
-            + "\"t\".\"DNAME\", \"SALGRADE\".\"GRADE\"\n"
-            + "FROM (SELECT \"DEPTNO\", \"DNAME\"\n"
-            + "FROM \"SCOTT\".\"DEPT\") AS \"t\"\n"
+        .planHasSql("SELECT \"t\".\"EMPNO\", \"t\".\"ENAME\", "
+            + "\"t0\".\"DNAME\", \"SALGRADE\".\"GRADE\"\n"
+            + "FROM \"SCOTT\".\"SALGRADE\"\n"
             + "INNER JOIN ((SELECT \"EMPNO\", \"ENAME\", \"SAL\", \"DEPTNO\"\n"
-            + "FROM \"SCOTT\".\"EMP\") AS \"t0\"\n"
-            + "INNER JOIN \"SCOTT\".\"SALGRADE\" "
-            + "ON \"t0\".\"SAL\" > \"SALGRADE\".\"LOSAL\" "
-            + "AND \"t0\".\"SAL\" < \"SALGRADE\".\"HISAL\") "
-            + "ON \"t\".\"DEPTNO\" = \"t0\".\"DEPTNO\"");
+            + "FROM \"SCOTT\".\"EMP\") AS \"t\"\n"
+            + "INNER JOIN (SELECT \"DEPTNO\", \"DNAME\"\n"
+            + "FROM \"SCOTT\".\"DEPT\") AS \"t0\" ON \"t\".\"DEPTNO\" = \"t0\".\"DEPTNO\")"
+            + " ON \"SALGRADE\".\"LOSAL\" < \"t\".\"SAL\" AND \"SALGRADE\".\"HISAL\" > \"t\".\"SAL\"");
   }
 
   @Test public void testCrossJoinWithJoinKeyPlan() {

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/test/java/org/apache/calcite/test/JdbcTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 41a462a..0e10877 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -3060,8 +3060,8 @@ public class JdbcTest {
         .query("select \"store_id\", \"grocery_sqft\" from \"store\"\n"
             + "where \"store_id\" < 10\n"
             + "order by 1 fetch first 5 rows only")
-        .explainContains(""
-            + "PLAN=EnumerableCalc(expr#0..23=[{inputs}], store_id=[$t0], grocery_sqft=[$t16])\n"
+        .explainContains("PLAN="
+            + "EnumerableCalc(expr#0..23=[{inputs}], store_id=[$t0], grocery_sqft=[$t16])\n"
             + "  EnumerableLimit(fetch=[5])\n"
             + "    EnumerableCalc(expr#0..23=[{inputs}], expr#24=[10], expr#25=[<($t0, $t24)], proj#0..23=[{exprs}], $condition=[$t25])\n"
             + "      EnumerableTableScan(table=[[foodmart2, store]])\n")
@@ -4778,10 +4778,10 @@ public class JdbcTest {
               return new Function<String, Object>() {
                 public Object apply(String v) {
                   switch (v) {
-                  case "calcite794":
-                    return Bug.CALCITE_794_FIXED;
                   case "calcite1045":
                     return Bug.CALCITE_1045_FIXED;
+                  case "calcite1048":
+                    return Bug.CALCITE_1048_FIXED;
                   }
                   return null;
                 }

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
----------------------------------------------------------------------
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 f8c4b2f..96cd23b 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -148,7 +148,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
       double expected,
       double epsilon) {
     RelNode rel = convertSql(sql);
-    Double result = RelMetadataQuery.getPercentageOriginalRows(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    Double result = mq.getPercentageOriginalRows(rel);
     assertTrue(result != null);
     assertEquals(expected, result, epsilon);
   }
@@ -233,7 +234,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
 
   private Set<RelColumnOrigin> checkColumnOrigin(String sql) {
     RelNode rel = convertSql(sql);
-    return RelMetadataQuery.getColumnOrigins(rel, 0);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    return mq.getColumnOrigins(rel, 0);
   }
 
   private void checkNoColumnOrigin(String sql) {
@@ -435,7 +437,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
       String sql,
       double expected) {
     RelNode rel = convertSql(sql);
-    Double result = RelMetadataQuery.getRowCount(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    Double result = mq.getRowCount(rel);
     assertThat(result, notNullValue());
     assertEquals(expected, result, 0d);
   }
@@ -444,7 +447,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
       String sql,
       double expected) {
     RelNode rel = convertSql(sql);
-    Double result = RelMetadataQuery.getMaxRowCount(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    Double result = mq.getMaxRowCount(rel);
     assertThat(result, notNullValue());
     assertEquals(expected, result, 0d);
   }
@@ -658,7 +662,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
       String sql,
       double expected) {
     RelNode rel = convertSql(sql);
-    Double result = RelMetadataQuery.getSelectivity(rel, null);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    Double result = mq.getSelectivity(rel, null);
     assertTrue(result != null);
     assertEquals(expected, result, EPSILON);
   }
@@ -702,7 +707,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
   private void checkRelSelectivity(
       RelNode rel,
       double expected) {
-    Double result = RelMetadataQuery.getSelectivity(rel, null);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    Double result = mq.getSelectivity(rel, null);
     assertTrue(result != null);
     assertEquals(expected, result, EPSILON);
   }
@@ -746,7 +752,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
         new CachingRelMetadataProvider(
             rel.getCluster().getMetadataProvider(),
             rel.getCluster().getPlanner()));
-    Double result = RelMetadataQuery.getSelectivity(rel, null);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    Double result = mq.getSelectivity(rel, null);
     assertThat(result,
         nearTo(DEFAULT_COMP_SELECTIVITY * DEFAULT_EQUAL_SELECTIVITY, EPSILON));
   }
@@ -754,20 +761,18 @@ public class RelMetadataTest extends SqlToRelTestBase {
   @Test public void testDistinctRowCountTable() {
     // no unique key information is available so return null
     RelNode rel = convertSql("select * from emp where deptno = 10");
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
     ImmutableBitSet groupKey =
         ImmutableBitSet.of(rel.getRowType().getFieldNames().indexOf("DEPTNO"));
-    Double result =
-        RelMetadataQuery.getDistinctRowCount(
-            rel, groupKey, null);
+    Double result = mq.getDistinctRowCount(rel, groupKey, null);
     assertThat(result, nullValue());
   }
 
   @Test public void testDistinctRowCountTableEmptyKey() {
     RelNode rel = convertSql("select * from emp where deptno = 10");
     ImmutableBitSet groupKey = ImmutableBitSet.of(); // empty key
-    Double result =
-        RelMetadataQuery.getDistinctRowCount(
-            rel, groupKey, null);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    Double result = mq.getDistinctRowCount(rel, groupKey, null);
     assertThat(result, is(1D));
   }
 
@@ -775,11 +780,12 @@ public class RelMetadataTest extends SqlToRelTestBase {
    * and {@link RelMetadataQuery#areColumnsUnique(RelNode, ImmutableBitSet)}
    * return consistent results. */
   private void assertUniqueConsistent(RelNode rel) {
-    Set<ImmutableBitSet> uniqueKeys = RelMetadataQuery.getUniqueKeys(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    final Set<ImmutableBitSet> uniqueKeys = mq.getUniqueKeys(rel);
     final ImmutableBitSet allCols =
         ImmutableBitSet.range(0, rel.getRowType().getFieldCount());
     for (ImmutableBitSet key : allCols.powerSet()) {
-      Boolean result2 = RelMetadataQuery.areColumnsUnique(rel, key);
+      Boolean result2 = mq.areColumnsUnique(rel, key);
       assertTrue(result2 == null || result2 == isUnique(uniqueKeys, key));
     }
   }
@@ -801,14 +807,16 @@ public class RelMetadataTest extends SqlToRelTestBase {
    * NullPointerException"</a>. */
   @Test public void testJoinUniqueKeys() {
     RelNode rel = convertSql("select * from emp join dept using (deptno)");
-    Set<ImmutableBitSet> result = RelMetadataQuery.getUniqueKeys(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    Set<ImmutableBitSet> result = mq.getUniqueKeys(rel);
     assertThat(result.isEmpty(), is(true));
     assertUniqueConsistent(rel);
   }
 
   @Test public void testGroupByEmptyUniqueKeys() {
     RelNode rel = convertSql("select count(*) from emp");
-    Set<ImmutableBitSet> result = RelMetadataQuery.getUniqueKeys(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    Set<ImmutableBitSet> result = mq.getUniqueKeys(rel);
     assertThat(result,
         CoreMatchers.<Set<ImmutableBitSet>>equalTo(
             ImmutableSet.of(ImmutableBitSet.of())));
@@ -817,7 +825,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
 
   @Test public void testGroupByEmptyHavingUniqueKeys() {
     RelNode rel = convertSql("select count(*) from emp where 1 = 1");
-    Set<ImmutableBitSet> result = RelMetadataQuery.getUniqueKeys(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    final Set<ImmutableBitSet> result = mq.getUniqueKeys(rel);
     assertThat(result,
         CoreMatchers.<Set<ImmutableBitSet>>equalTo(
             ImmutableSet.of(ImmutableBitSet.of())));
@@ -827,7 +836,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
   @Test public void testGroupBy() {
     RelNode rel = convertSql("select deptno, count(*), sum(sal) from emp\n"
             + "group by deptno");
-    Set<ImmutableBitSet> result = RelMetadataQuery.getUniqueKeys(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    final Set<ImmutableBitSet> result = mq.getUniqueKeys(rel);
     assertThat(result,
         CoreMatchers.<Set<ImmutableBitSet>>equalTo(
             ImmutableSet.of(ImmutableBitSet.of(0))));
@@ -838,7 +848,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
     RelNode rel = convertSql("select deptno from emp\n"
             + "union\n"
             + "select deptno from dept");
-    Set<ImmutableBitSet> result = RelMetadataQuery.getUniqueKeys(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    final Set<ImmutableBitSet> result = mq.getUniqueKeys(rel);
     assertThat(result,
         CoreMatchers.<Set<ImmutableBitSet>>equalTo(
             ImmutableSet.of(ImmutableBitSet.of(0))));
@@ -859,22 +870,23 @@ public class RelMetadataTest extends SqlToRelTestBase {
 
     // Top node is a filter. Its metadata uses getColType(RelNode, int).
     assertThat(rel, instanceOf(LogicalFilter.class));
-    assertThat(rel.metadata(ColType.class).getColType(0),
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    assertThat(rel.metadata(ColType.class, mq).getColType(0),
         equalTo("DEPTNO-rel"));
-    assertThat(rel.metadata(ColType.class).getColType(1),
+    assertThat(rel.metadata(ColType.class, mq).getColType(1),
         equalTo("EXPR$1-rel"));
 
     // Next node is an aggregate. Its metadata uses
     // getColType(LogicalAggregate, int).
     final RelNode input = rel.getInput(0);
     assertThat(input, instanceOf(LogicalAggregate.class));
-    assertThat(input.metadata(ColType.class).getColType(0),
+    assertThat(input.metadata(ColType.class, mq).getColType(0),
         equalTo("DEPTNO-agg"));
 
     // There is no caching. Another request causes another call to the provider.
     assertThat(buf.toString(), equalTo("[DEPTNO-rel, EXPR$1-rel, DEPTNO-agg]"));
     assertThat(buf.size(), equalTo(3));
-    assertThat(input.metadata(ColType.class).getColType(0),
+    assertThat(input.metadata(ColType.class, mq).getColType(0),
         equalTo("DEPTNO-agg"));
     assertThat(buf.size(), equalTo(4));
 
@@ -884,19 +896,19 @@ public class RelMetadataTest extends SqlToRelTestBase {
     rel.getCluster().setMetadataProvider(
         new CachingRelMetadataProvider(
             rel.getCluster().getMetadataProvider(), planner));
-    assertThat(input.metadata(ColType.class).getColType(0),
+    assertThat(input.metadata(ColType.class, mq).getColType(0),
         equalTo("DEPTNO-agg"));
     assertThat(buf.size(), equalTo(5));
-    assertThat(input.metadata(ColType.class).getColType(0),
+    assertThat(input.metadata(ColType.class, mq).getColType(0),
         equalTo("DEPTNO-agg"));
     assertThat(buf.size(), equalTo(5));
-    assertThat(input.metadata(ColType.class).getColType(1),
+    assertThat(input.metadata(ColType.class, mq).getColType(1),
         equalTo("EXPR$1-agg"));
     assertThat(buf.size(), equalTo(6));
-    assertThat(input.metadata(ColType.class).getColType(1),
+    assertThat(input.metadata(ColType.class, mq).getColType(1),
         equalTo("EXPR$1-agg"));
     assertThat(buf.size(), equalTo(6));
-    assertThat(input.metadata(ColType.class).getColType(0),
+    assertThat(input.metadata(ColType.class, mq).getColType(0),
         equalTo("DEPTNO-agg"));
     assertThat(buf.size(), equalTo(6));
 
@@ -904,10 +916,10 @@ public class RelMetadataTest extends SqlToRelTestBase {
     long timestamp = planner.getRelMetadataTimestamp(rel);
     assertThat(timestamp, equalTo(0L));
     ((MockRelOptPlanner) planner).setRelMetadataTimestamp(timestamp + 1);
-    assertThat(input.metadata(ColType.class).getColType(0),
+    assertThat(input.metadata(ColType.class, mq).getColType(0),
         equalTo("DEPTNO-agg"));
     assertThat(buf.size(), equalTo(7));
-    assertThat(input.metadata(ColType.class).getColType(0),
+    assertThat(input.metadata(ColType.class, mq).getColType(0),
         equalTo("DEPTNO-agg"));
     assertThat(buf.size(), equalTo(7));
   }
@@ -957,7 +969,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
                 rexBuilder.makeInputRef(empSort, 0),
                 rexBuilder.makeInputRef(empSort, 3)));
 
-    collations = RelMdCollation.project(empSort, projects);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    collations = RelMdCollation.project(mq, empSort, projects);
     assertThat(collations.size(), equalTo(1));
     assertThat(collations.get(0).getFieldCollations().size(), equalTo(2));
     assertThat(collations.get(0).getFieldCollations().get(0).getFieldIndex(),
@@ -986,12 +999,13 @@ public class RelMetadataTest extends SqlToRelTestBase {
       throw Throwables.propagate(e);
     }
     collations =
-        RelMdCollation.mergeJoin(project, deptSort, leftKeys, rightKeys);
+        RelMdCollation.mergeJoin(mq, project, deptSort, leftKeys,
+            rightKeys);
     assertThat(collations,
         equalTo(join.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE)));
 
     // Values (empty)
-    collations = RelMdCollation.values(empTable.getRowType(),
+    collations = RelMdCollation.values(mq, empTable.getRowType(),
         ImmutableList.<ImmutableList<RexLiteral>>of());
     assertThat(collations.toString(),
         equalTo("[[0, 1, 2, 3, 4, 5, 6, 7, 8], "
@@ -1006,7 +1020,7 @@ public class RelMetadataTest extends SqlToRelTestBase {
 
     final LogicalValues emptyValues =
         LogicalValues.createEmpty(cluster, empTable.getRowType());
-    assertThat(RelMetadataQuery.collations(emptyValues), equalTo(collations));
+    assertThat(mq.collations(emptyValues), equalTo(collations));
 
     // Values (non-empty)
     final RelDataType rowType = cluster.getTypeFactory().builder()
@@ -1024,13 +1038,13 @@ public class RelMetadataTest extends SqlToRelTestBase {
     addRow(tuples, rexBuilder, 1, 2, 0, 3);
     addRow(tuples, rexBuilder, 2, 3, 2, 2);
     addRow(tuples, rexBuilder, 3, 3, 1, 4);
-    collations = RelMdCollation.values(rowType, tuples.build());
+    collations = RelMdCollation.values(mq, rowType, tuples.build());
     assertThat(collations.toString(),
         equalTo("[[0, 1, 2, 3], [1, 3]]"));
 
     final LogicalValues values =
         LogicalValues.create(cluster, rowType, tuples.build());
-    assertThat(RelMetadataQuery.collations(values), equalTo(collations));
+    assertThat(mq.collations(values), equalTo(collations));
   }
 
   private void addRow(ImmutableList.Builder<ImmutableList<RexLiteral>> builder,
@@ -1073,10 +1087,11 @@ public class RelMetadataTest extends SqlToRelTestBase {
   private void checkAverageRowSize(RelOptCluster cluster, RelOptTable empTable,
       RelOptTable deptTable) {
     final RexBuilder rexBuilder = cluster.getRexBuilder();
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
     final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable);
 
-    Double rowSize = RelMetadataQuery.getAverageRowSize(empScan);
-    List<Double> columnSizes = RelMetadataQuery.getAverageColumnSizes(empScan);
+    Double rowSize = mq.getAverageRowSize(empScan);
+    List<Double> columnSizes = mq.getAverageColumnSizes(empScan);
 
     assertThat(columnSizes.size(),
         equalTo(empScan.getRowType().getFieldCount()));
@@ -1087,8 +1102,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
     // Empty values
     final LogicalValues emptyValues =
         LogicalValues.createEmpty(cluster, empTable.getRowType());
-    rowSize = RelMetadataQuery.getAverageRowSize(emptyValues);
-    columnSizes = RelMetadataQuery.getAverageColumnSizes(emptyValues);
+    rowSize = mq.getAverageRowSize(emptyValues);
+    columnSizes = mq.getAverageColumnSizes(emptyValues);
     assertThat(columnSizes.size(),
         equalTo(emptyValues.getRowType().getFieldCount()));
     assertThat(columnSizes,
@@ -1108,8 +1123,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
     addRow(tuples, rexBuilder, 3, "2",          null);
     final LogicalValues values =
         LogicalValues.create(cluster, rowType, tuples.build());
-    rowSize = RelMetadataQuery.getAverageRowSize(values);
-    columnSizes = RelMetadataQuery.getAverageColumnSizes(values);
+    rowSize = mq.getAverageRowSize(values);
+    columnSizes = mq.getAverageColumnSizes(values);
     assertThat(columnSizes.size(),
         equalTo(values.getRowType().getFieldCount()));
     assertThat(columnSizes, equalTo(Arrays.asList(4.0, 8.0, 3.0)));
@@ -1119,8 +1134,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
     final LogicalUnion union =
         LogicalUnion.create(ImmutableList.<RelNode>of(empScan, emptyValues),
             true);
-    rowSize = RelMetadataQuery.getAverageRowSize(union);
-    columnSizes = RelMetadataQuery.getAverageColumnSizes(union);
+    rowSize = mq.getAverageRowSize(union);
+    columnSizes = mq.getAverageColumnSizes(union);
     assertThat(columnSizes.size(), equalTo(9));
     assertThat(columnSizes,
         equalTo(Arrays.asList(4.0, 40.0, 20.0, 4.0, 8.0, 4.0, 4.0, 4.0, 1.0)));
@@ -1134,8 +1149,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
             rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN,
                 rexBuilder.makeInputRef(deptScan, 0),
                 rexBuilder.makeExactLiteral(BigDecimal.TEN)));
-    rowSize = RelMetadataQuery.getAverageRowSize(filter);
-    columnSizes = RelMetadataQuery.getAverageColumnSizes(filter);
+    rowSize = mq.getAverageRowSize(filter);
+    columnSizes = mq.getAverageColumnSizes(filter);
     assertThat(columnSizes.size(), equalTo(2));
     assertThat(columnSizes, equalTo(Arrays.asList(4.0, 20.0)));
     assertThat(rowSize, equalTo(24.0));
@@ -1152,8 +1167,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
                 rexBuilder.makeCall(SqlStdOperatorTable.CHAR_LENGTH,
                     rexBuilder.makeInputRef(filter, 1))),
             (List<String>) null);
-    rowSize = RelMetadataQuery.getAverageRowSize(deptProject);
-    columnSizes = RelMetadataQuery.getAverageColumnSizes(deptProject);
+    rowSize = mq.getAverageRowSize(deptProject);
+    columnSizes = mq.getAverageColumnSizes(deptProject);
     assertThat(columnSizes.size(), equalTo(4));
     assertThat(columnSizes, equalTo(Arrays.asList(4.0, 20.0, 4.0, 4.0)));
     assertThat(rowSize, equalTo(32.0));
@@ -1162,8 +1177,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
     final LogicalJoin join =
         LogicalJoin.create(empScan, deptProject, rexBuilder.makeLiteral(true),
             ImmutableSet.<CorrelationId>of(), JoinRelType.INNER);
-    rowSize = RelMetadataQuery.getAverageRowSize(join);
-    columnSizes = RelMetadataQuery.getAverageColumnSizes(join);
+    rowSize = mq.getAverageRowSize(join);
+    columnSizes = mq.getAverageColumnSizes(join);
     assertThat(columnSizes.size(), equalTo(13));
     assertThat(columnSizes,
         equalTo(
@@ -1177,26 +1192,26 @@ public class RelMetadataTest extends SqlToRelTestBase {
             ImmutableList.<ImmutableBitSet>of(),
             ImmutableList.of(
                 AggregateCall.create(
-                    SqlStdOperatorTable.COUNT, false, ImmutableIntList.of(), -1,
-                    2, join, null, null)));
-    rowSize = RelMetadataQuery.getAverageRowSize(aggregate);
-    columnSizes = RelMetadataQuery.getAverageColumnSizes(aggregate);
+                    SqlStdOperatorTable.COUNT, false, ImmutableIntList.of(),
+                    -1, 2, join, null, null)));
+    rowSize = mq.getAverageRowSize(aggregate);
+    columnSizes = mq.getAverageColumnSizes(aggregate);
     assertThat(columnSizes.size(), equalTo(3));
     assertThat(columnSizes, equalTo(Arrays.asList(4.0, 20.0, 8.0)));
     assertThat(rowSize, equalTo(32.0));
 
     // Smoke test Parallelism and Memory metadata providers
-    assertThat(RelMetadataQuery.memory(aggregate), nullValue());
-    assertThat(RelMetadataQuery.cumulativeMemoryWithinPhase(aggregate),
+    assertThat(mq.memory(aggregate), nullValue());
+    assertThat(mq.cumulativeMemoryWithinPhase(aggregate),
         nullValue());
-    assertThat(RelMetadataQuery.cumulativeMemoryWithinPhaseSplit(aggregate),
+    assertThat(mq.cumulativeMemoryWithinPhaseSplit(aggregate),
         nullValue());
-    assertThat(RelMetadataQuery.isPhaseTransition(aggregate), is(false));
-    assertThat(RelMetadataQuery.splitCount(aggregate), is(1));
+    assertThat(mq.isPhaseTransition(aggregate), is(false));
+    assertThat(mq.splitCount(aggregate), is(1));
   }
 
   /** Unit test for
-   * {@link org.apache.calcite.rel.metadata.RelMdPredicates#getPredicates(SemiJoin)}. */
+   * {@link org.apache.calcite.rel.metadata.RelMdPredicates#getPredicates(SemiJoin, RelMetadataQuery)}. */
   @Test public void testPredicates() {
     final Project rel = (Project) convertSql("select * from emp, dept");
     final Join join = (Join) rel.getInput();
@@ -1216,10 +1231,11 @@ public class RelMetadataTest extends SqlToRelTestBase {
   private void checkPredicates(RelOptCluster cluster, RelOptTable empTable,
       RelOptTable deptTable) {
     final RexBuilder rexBuilder = cluster.getRexBuilder();
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
     final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable);
 
     RelOptPredicateList predicates =
-        RelMetadataQuery.getPulledUpPredicates(empScan);
+        mq.getPulledUpPredicates(empScan);
     assertThat(predicates.pulledUpPredicates.isEmpty(), is(true));
 
     final LogicalFilter filter =
@@ -1229,7 +1245,7 @@ public class RelMetadataTest extends SqlToRelTestBase {
                     empScan.getRowType().getFieldNames().indexOf("EMPNO")),
                 rexBuilder.makeExactLiteral(BigDecimal.ONE)));
 
-    predicates = RelMetadataQuery.getPulledUpPredicates(filter);
+    predicates = mq.getPulledUpPredicates(filter);
     assertThat(predicates.pulledUpPredicates.toString(), is("[=($0, 1)]"));
 
     final LogicalTableScan deptScan =
@@ -1253,7 +1269,7 @@ public class RelMetadataTest extends SqlToRelTestBase {
             ImmutableIntList.of(rightDeptnoField.getIndex()
                     + empScan.getRowType().getFieldCount()));
 
-    predicates = RelMetadataQuery.getPulledUpPredicates(semiJoin);
+    predicates = mq.getPulledUpPredicates(semiJoin);
     assertThat(predicates.pulledUpPredicates, sortsAs("[=($0, 1)]"));
     assertThat(predicates.leftInferredPredicates, sortsAs("[]"));
     assertThat(predicates.rightInferredPredicates.isEmpty(), is(true));
@@ -1261,14 +1277,15 @@ public class RelMetadataTest extends SqlToRelTestBase {
 
   /**
    * Unit test for
-   * {@link org.apache.calcite.rel.metadata.RelMdPredicates#getPredicates(Aggregate)}.
+   * {@link org.apache.calcite.rel.metadata.RelMdPredicates#getPredicates(Aggregate, RelMetadataQuery)}.
    */
   @Test public void testPullUpPredicatesFromAggregation() {
     final String sql = "select a, max(b) from (\n"
         + "  select 1 as a, 2 as b from emp)subq\n"
         + "group by a";
     final Aggregate rel = (Aggregate) convertSql(sql);
-    RelOptPredicateList inputSet = RelMetadataQuery.getPulledUpPredicates(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    RelOptPredicateList inputSet = mq.getPulledUpPredicates(rel);
     ImmutableList<RexNode> pulledUpPredicates = inputSet.pulledUpPredicates;
     assertThat(pulledUpPredicates, sortsAs("[=($0, 1)]"));
   }
@@ -1279,7 +1296,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
         + "  from emp\n"
         + "  where mgr is null and deptno < 10)";
     final RelNode rel = convertSql(sql);
-    RelOptPredicateList list = RelMetadataQuery.getPulledUpPredicates(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    RelOptPredicateList list = mq.getPulledUpPredicates(rel);
     assertThat(list.pulledUpPredicates,
         sortsAs("[<($0, 10), =($3, 'y'), =($4, CAST('1'):INTEGER NOT NULL), "
             + "IS NULL($1), IS NULL($2)]"));
@@ -1290,7 +1308,8 @@ public class RelMetadataTest extends SqlToRelTestBase {
         + "  from emp\n"
         + "  where mgr is null and deptno < 10";
     final RelNode rel = convertSql(sql);
-    RelOptPredicateList list = RelMetadataQuery.getPulledUpPredicates(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    RelOptPredicateList list = mq.getPulledUpPredicates(rel);
     // Uses "IS NOT DISTINCT FROM" rather than "=" because cannot guarantee not null.
     assertThat(list.pulledUpPredicates,
         sortsAs("[IS NOT DISTINCT FROM($0, CASE(=(1, 1), null, 1))]"));
@@ -1347,7 +1366,7 @@ public class RelMetadataTest extends SqlToRelTestBase {
      * {@link org.apache.calcite.rel.logical.LogicalAggregate}, called via
      * reflection. */
     @SuppressWarnings("UnusedDeclaration")
-    public String getColType(Aggregate rel, int column) {
+    public String getColType(Aggregate rel, RelMetadataQuery mq, int column) {
       final String name =
           rel.getRowType().getFieldList().get(column).getName() + "-agg";
       THREAD_LIST.get().add(name);
@@ -1357,7 +1376,7 @@ public class RelMetadataTest extends SqlToRelTestBase {
     /** Implementation of {@link ColType#getColType(int)} for
      * {@link RelNode}, called via reflection. */
     @SuppressWarnings("UnusedDeclaration")
-    public String getColType(RelNode rel, int column) {
+    public String getColType(RelNode rel, RelMetadataQuery mq, int column) {
       final String name =
           rel.getRowType().getFieldList().get(column).getName() + "-rel";
       THREAD_LIST.get().add(name);

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/test/java/org/apache/calcite/tools/PlannerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/tools/PlannerTest.java b/core/src/test/java/org/apache/calcite/tools/PlannerTest.java
index fae8cb9..d604938 100644
--- a/core/src/test/java/org/apache/calcite/tools/PlannerTest.java
+++ b/core/src/test/java/org/apache/calcite/tools/PlannerTest.java
@@ -275,8 +275,8 @@ public class PlannerTest {
     SqlNode parse = planner.parse(sql);
     SqlNode validate = planner.validate(parse);
     RelNode rel = planner.rel(validate).project();
-    final RelOptPredicateList predicates =
-        RelMetadataQuery.getPulledUpPredicates(rel);
+    final RelMetadataQuery mq = RelMetadataQuery.instance();
+    final RelOptPredicateList predicates = mq.getPulledUpPredicates(rel);
     final String buf = predicates.pulledUpPredicates.toString();
     assertThat(buf, equalTo(expectedPredicates));
   }
@@ -562,7 +562,7 @@ public class PlannerTest {
         Programs.of(ruleSet2));
     SqlNode parse = planner.parse("select * from \"emps\"");
     SqlNode validate = planner.validate(parse);
-    RelNode convert = planner.convert(validate);
+    RelNode convert = planner.rel(validate).rel;
     RelTraitSet traitSet = planner.getEmptyTraitSet()
         .replace(EnumerableConvention.INSTANCE);
     RelNode transform = planner.transform(0, traitSet, convert);
@@ -1071,7 +1071,8 @@ public class PlannerTest {
   @Test public void testMergeProjectForceMode() throws Exception {
     RuleSet ruleSet =
         RuleSets.ofList(
-            new ProjectMergeRule(true, RelFactories.DEFAULT_PROJECT_FACTORY));
+            new ProjectMergeRule(true,
+                RelBuilder.proto(RelFactories.DEFAULT_PROJECT_FACTORY)));
     Planner planner = getPlanner(null, Programs.of(ruleSet));
     planner.close();
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/test/java/org/apache/calcite/util/UtilTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/util/UtilTest.java b/core/src/test/java/org/apache/calcite/util/UtilTest.java
index 60122fb..8bedcbc 100644
--- a/core/src/test/java/org/apache/calcite/util/UtilTest.java
+++ b/core/src/test/java/org/apache/calcite/util/UtilTest.java
@@ -950,6 +950,16 @@ public class UtilTest {
     assertEquals(ab, ab0);
     assertEquals(ab.hashCode(), ab0.hashCode());
 
+    final List<String> abc = FlatLists.of("A", "B", "C");
+    final List<String> abc0 = Arrays.asList("A", "B", "C");
+    assertEquals(abc, abc0);
+    assertEquals(abc.hashCode(), abc0.hashCode());
+
+    final List<Object> abc1 = FlatLists.of((Object) "A", "B", "C");
+    assertEquals(abc1, abc0);
+    assertEquals(abc, abc0);
+    assertEquals(abc1.hashCode(), abc0.hashCode());
+
     final List<String> an = FlatLists.of("A", null);
     final List<String> an0 = Arrays.asList("A", null);
     assertEquals(an, an0);

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/core/src/test/resources/sql/agg.iq
----------------------------------------------------------------------
diff --git a/core/src/test/resources/sql/agg.iq b/core/src/test/resources/sql/agg.iq
index b76cc90..52a15cc 100644
--- a/core/src/test/resources/sql/agg.iq
+++ b/core/src/test/resources/sql/agg.iq
@@ -1393,7 +1393,7 @@ group by deptno, job;
 (3 rows)
 
 !ok
-!if (fixed.calcite794) {
+!if (fixed.calcite1048) {
 select job, sum(sal) as sum_sal, deptno
 from "scott".emp
 where deptno = 10

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java
----------------------------------------------------------------------
diff --git a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java
index 45b4baf..8d2ae04 100644
--- a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java
+++ b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java
@@ -23,6 +23,7 @@ import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Filter;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLiteral;
@@ -54,8 +55,9 @@ public class MongoFilter extends Filter implements MongoRel {
     assert getConvention() == child.getConvention();
   }
 
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
-    return super.computeSelfCost(planner).multiplyBy(0.1);
+  @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+      RelMetadataQuery mq) {
+    return super.computeSelfCost(planner, mq).multiplyBy(0.1);
   }
 
   public MongoFilter copy(RelTraitSet traitSet, RelNode input,

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoProject.java
----------------------------------------------------------------------
diff --git a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoProject.java b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoProject.java
index 4e40788..d8a17ec 100644
--- a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoProject.java
+++ b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoProject.java
@@ -23,6 +23,7 @@ import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.util.Pair;
@@ -56,8 +57,9 @@ public class MongoProject extends Project implements MongoRel {
         rowType);
   }
 
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
-    return super.computeSelfCost(planner).multiplyBy(0.1);
+  @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+      RelMetadataQuery mq) {
+    return super.computeSelfCost(planner, mq).multiplyBy(0.1);
   }
 
   public void implement(Implementor implementor) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSort.java
----------------------------------------------------------------------
diff --git a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSort.java b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSort.java
index c1bb26e..193e225 100644
--- a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSort.java
+++ b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSort.java
@@ -24,6 +24,7 @@ import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.RelFieldCollation;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Sort;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
@@ -44,8 +45,9 @@ public class MongoSort extends Sort implements MongoRel {
     assert getConvention() == child.getConvention();
   }
 
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
-    return super.computeSelfCost(planner).multiplyBy(0.05);
+  @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+      RelMetadataQuery mq) {
+    return super.computeSelfCost(planner, mq).multiplyBy(0.05);
   }
 
   @Override public Sort copy(RelTraitSet traitSet, RelNode input,

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTableScan.java
----------------------------------------------------------------------
diff --git a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTableScan.java b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTableScan.java
index 36e220b..a47adee 100644
--- a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTableScan.java
+++ b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTableScan.java
@@ -24,6 +24,7 @@ import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.type.RelDataType;
 
 import java.util.List;
@@ -66,11 +67,12 @@ public class MongoTableScan extends TableScan implements MongoRel {
     return projectRowType != null ? projectRowType : super.deriveRowType();
   }
 
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
+  @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+      RelMetadataQuery mq) {
     // scans with a small project list are cheaper
     final float f = projectRowType == null ? 1f
         : (float) projectRowType.getFieldCount() / 100f;
-    return super.computeSelfCost(planner).multiplyBy(.1 * f);
+    return super.computeSelfCost(planner, mq).multiplyBy(.1 * f);
   }
 
   @Override public void register(RelOptPlanner planner) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
----------------------------------------------------------------------
diff --git a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
index d6a4475..cbbeb86 100644
--- a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
+++ b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
@@ -33,6 +33,7 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.runtime.Hook;
 import org.apache.calcite.util.BuiltInMethod;
@@ -62,8 +63,9 @@ public class MongoToEnumerableConverter
         getCluster(), traitSet, sole(inputs));
   }
 
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
-    return super.computeSelfCost(planner).multiplyBy(.1);
+  @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+      RelMetadataQuery mq) {
+    return super.computeSelfCost(planner, mq).multiplyBy(.1);
   }
 
   public Result implement(EnumerableRelImplementor implementor, Prefer pref) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/spark/src/main/java/org/apache/calcite/adapter/spark/EnumerableToSparkConverter.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/calcite/adapter/spark/EnumerableToSparkConverter.java b/spark/src/main/java/org/apache/calcite/adapter/spark/EnumerableToSparkConverter.java
index 11f7820..ae7aae0 100644
--- a/spark/src/main/java/org/apache/calcite/adapter/spark/EnumerableToSparkConverter.java
+++ b/spark/src/main/java/org/apache/calcite/adapter/spark/EnumerableToSparkConverter.java
@@ -31,6 +31,7 @@ import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 
 import java.util.List;
 
@@ -55,8 +56,9 @@ public class EnumerableToSparkConverter
         getCluster(), traitSet, sole(inputs));
   }
 
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
-    return super.computeSelfCost(planner).multiplyBy(.01);
+  @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+      RelMetadataQuery mq) {
+    return super.computeSelfCost(planner, mq).multiplyBy(.01);
   }
 
   public Result implementSpark(Implementor implementor) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java b/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
index b919931..bca76c2 100644
--- a/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
+++ b/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
@@ -36,6 +36,7 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.sql.SqlDialect;
 import org.apache.calcite.util.BuiltInMethod;
 
@@ -59,8 +60,9 @@ public class JdbcToSparkConverter
         getCluster(), traitSet, sole(inputs));
   }
 
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
-    return super.computeSelfCost(planner).multiplyBy(.1);
+  @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+      RelMetadataQuery mq) {
+    return super.computeSelfCost(planner, mq).multiplyBy(.1);
   }
 
   public SparkRel.Result implementSpark(SparkRel.Implementor implementor) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/spark/src/main/java/org/apache/calcite/adapter/spark/SparkRules.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/calcite/adapter/spark/SparkRules.java b/spark/src/main/java/org/apache/calcite/adapter/spark/SparkRules.java
index 24199cb..2bea47b 100644
--- a/spark/src/main/java/org/apache/calcite/adapter/spark/SparkRules.java
+++ b/spark/src/main/java/org/apache/calcite/adapter/spark/SparkRules.java
@@ -43,8 +43,8 @@ import org.apache.calcite.rel.SingleRel;
 import org.apache.calcite.rel.convert.ConverterRule;
 import org.apache.calcite.rel.core.Values;
 import org.apache.calcite.rel.logical.LogicalCalc;
-import org.apache.calcite.rel.logical.LogicalFilter;
 import org.apache.calcite.rel.logical.LogicalValues;
+import org.apache.calcite.rel.metadata.RelMdUtil;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.rules.FilterToCalcRule;
 import org.apache.calcite.rel.rules.ProjectToCalcRule;
@@ -271,15 +271,15 @@ public abstract class SparkRules {
       return program.explainCalc(super.explainTerms(pw));
     }
 
-    public double getRows() {
-      return LogicalFilter.estimateFilteredRows(getInput(), program);
+    @Override public double estimateRowCount(RelMetadataQuery mq) {
+      return RelMdUtil.estimateFilteredRows(getInput(), program, mq);
     }
 
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
-      double dRows = RelMetadataQuery.getRowCount(this);
-      double dCpu =
-          RelMetadataQuery.getRowCount(getInput())
-              * program.getExprCount();
+    @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+        RelMetadataQuery mq) {
+      double dRows = mq.getRowCount(this);
+      double dCpu = mq.getRowCount(getInput())
+          * program.getExprCount();
       double dIo = 0;
       return planner.getCostFactory().makeCost(dRows, dCpu, dIo);
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/cabdcf44/spark/src/main/java/org/apache/calcite/adapter/spark/SparkToEnumerableConverter.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/calcite/adapter/spark/SparkToEnumerableConverter.java b/spark/src/main/java/org/apache/calcite/adapter/spark/SparkToEnumerableConverter.java
index e270d44..b96dd5f 100644
--- a/spark/src/main/java/org/apache/calcite/adapter/spark/SparkToEnumerableConverter.java
+++ b/spark/src/main/java/org/apache/calcite/adapter/spark/SparkToEnumerableConverter.java
@@ -33,6 +33,7 @@ import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 
 import java.util.List;
 
@@ -59,8 +60,9 @@ public class SparkToEnumerableConverter
         getCluster(), traitSet, sole(inputs));
   }
 
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner) {
-    return super.computeSelfCost(planner).multiplyBy(.01);
+  @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+      RelMetadataQuery mq) {
+    return super.computeSelfCost(planner, mq).multiplyBy(.01);
   }
 
   public Result implement(EnumerableRelImplementor implementor, Prefer pref) {