You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by kr...@apache.org on 2016/05/04 14:46:03 UTC

lucene-solr:jira/solr-8593: Cleanup rules. New rules broke some tests

Repository: lucene-solr
Updated Branches:
  refs/heads/jira/solr-8593 101945858 -> d3f0700c9


Cleanup rules. New rules broke some tests


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/d3f0700c
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/d3f0700c
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/d3f0700c

Branch: refs/heads/jira/solr-8593
Commit: d3f0700c9ba456168029312623a55341b3eca080
Parents: 1019458
Author: Kevin Risden <kr...@apache.org>
Authored: Wed May 4 09:45:55 2016 -0500
Committer: Kevin Risden <kr...@apache.org>
Committed: Wed May 4 09:45:55 2016 -0500

----------------------------------------------------------------------
 lucene/ivy-versions.properties                  |   4 +-
 solr/core/ivy.xml                               |   2 +-
 .../solr/handler/sql/CalciteSolrDriver.java     |   8 +-
 .../apache/solr/handler/sql/LimitStream.java    |  16 +--
 .../apache/solr/handler/sql/SolrAggregate.java  | 104 +++++++++++++++
 .../apache/solr/handler/sql/SolrEnumerator.java |   6 +-
 .../org/apache/solr/handler/sql/SolrFilter.java |  79 ++++++------
 .../org/apache/solr/handler/sql/SolrMethod.java |  20 +--
 .../apache/solr/handler/sql/SolrProject.java    |  14 +--
 .../org/apache/solr/handler/sql/SolrRel.java    |  42 ++++---
 .../org/apache/solr/handler/sql/SolrRules.java  |  56 ++++++---
 .../org/apache/solr/handler/sql/SolrSchema.java |  22 ++--
 .../org/apache/solr/handler/sql/SolrSort.java   |  10 +-
 .../org/apache/solr/handler/sql/SolrTable.java  | 125 ++++++++++++-------
 .../apache/solr/handler/sql/SolrTableScan.java  |  14 +--
 .../handler/sql/SolrToEnumerableConverter.java  |  29 ++---
 .../org/apache/solr/handler/TestSQLHandler.java |   6 -
 17 files changed, 349 insertions(+), 208 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/lucene/ivy-versions.properties
----------------------------------------------------------------------
diff --git a/lucene/ivy-versions.properties b/lucene/ivy-versions.properties
index 1d403d7..47a45a5 100644
--- a/lucene/ivy-versions.properties
+++ b/lucene/ivy-versions.properties
@@ -91,8 +91,8 @@ com.sun.jersey.version = 1.9
 /org.apache.ant/ant = 1.8.2
 /org.apache.avro/avro = 1.7.5
 
-org.apache.calcite.version = 1.6.0
-/org.apache.calcite/calcite-avatica = ${org.apache.calcite.version}
+org.apache.calcite.version = 1.7.0
+/org.apache.calcite.avatica/avatica = 1.7.1
 /org.apache.calcite/calcite-core = ${org.apache.calcite.version}
 /org.apache.calcite/calcite-linq4j = ${org.apache.calcite.version}
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/ivy.xml
----------------------------------------------------------------------
diff --git a/solr/core/ivy.xml b/solr/core/ivy.xml
index c87d6c9..9f3c190 100644
--- a/solr/core/ivy.xml
+++ b/solr/core/ivy.xml
@@ -135,7 +135,7 @@
     <!-- SQL Parser -->
     <dependency org="org.apache.calcite" name="calcite-core" rev="${/org.apache.calcite/calcite-core}"/>
     <dependency org="org.apache.calcite" name="calcite-linq4j" rev="${/org.apache.calcite/calcite-linq4j}"/>
-    <dependency org="org.apache.calcite" name="calcite-avatica" rev="${/org.apache.calcite/calcite-avatica}"/>
+    <dependency org="org.apache.calcite.avatica" name="avatica" rev="${/org.apache.calcite.avatica/avatica}"/>
     <dependency org="net.hydromatic" name="eigenbase-properties" rev="1.1.5"/>
     <dependency org="org.codehaus.janino" name="janino" rev="2.7.6"/>
     <dependency org="org.codehaus.janino" name="commons-compiler" rev="2.7.6"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/CalciteSolrDriver.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/CalciteSolrDriver.java b/solr/core/src/java/org/apache/solr/handler/sql/CalciteSolrDriver.java
index 46cfee5..35c9f9d 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/CalciteSolrDriver.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/CalciteSolrDriver.java
@@ -16,14 +16,14 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Properties;
-
 import org.apache.calcite.jdbc.CalciteConnection;
 import org.apache.calcite.jdbc.Driver;
 import org.apache.calcite.schema.SchemaPlus;
 
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
 /**
  * JDBC driver for Calcite Solr.
  *

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/LimitStream.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/LimitStream.java b/solr/core/src/java/org/apache/solr/handler/sql/LimitStream.java
index 403ec45..0d4bb72 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/LimitStream.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/LimitStream.java
@@ -16,12 +16,6 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.comp.StreamComparator;
 import org.apache.solr.client.solrj.io.stream.StreamContext;
@@ -30,10 +24,16 @@ import org.apache.solr.client.solrj.io.stream.expr.Explanation;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExplanation;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 class LimitStream extends TupleStream {
 
-  private TupleStream stream;
-  private int limit;
+  private final TupleStream stream;
+  private final int limit;
   private int count;
 
   LimitStream(TupleStream stream, int limit) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrAggregate.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrAggregate.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrAggregate.java
new file mode 100644
index 0000000..582b9c4
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrAggregate.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.handler.sql;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Aggregate;
+import org.apache.calcite.rel.core.AggregateCall;
+import org.apache.calcite.sql.SqlAggFunction;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.solr.client.solrj.io.stream.metrics.*;
+
+import java.util.*;
+
+/**
+ * Implementation of {@link org.apache.calcite.rel.core.Aggregate} relational expression in Solr.
+ */
+class SolrAggregate extends Aggregate implements SolrRel {
+  SolrAggregate(
+      RelOptCluster cluster,
+      RelTraitSet traitSet,
+      RelNode child,
+      boolean indicator,
+      ImmutableBitSet groupSet,
+      List<ImmutableBitSet> groupSets,
+      List<AggregateCall> aggCalls) {
+    super(cluster, traitSet, child, indicator, groupSet, groupSets, aggCalls);
+    assert getConvention() == SolrRel.CONVENTION;
+    assert getConvention() == child.getConvention();
+  }
+
+  @Override
+  public Aggregate copy(RelTraitSet traitSet, RelNode input,
+                        boolean indicator, ImmutableBitSet groupSet,
+                        List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
+    return new SolrAggregate(getCluster(), traitSet, input, indicator, groupSet, groupSets, aggCalls);
+  }
+
+  public void implement(Implementor implementor) {
+    implementor.visitChild(0, getInput());
+
+    final List<String> inNames = SolrRules.solrFieldNames(getInput().getRowType());
+    final List<String> outNames = SolrRules.solrFieldNames(getRowType());
+
+    List<Metric> metrics = new ArrayList<>();
+    Map<String, String> fieldMappings = new HashMap<>();
+    for(AggregateCall aggCall : aggCalls) {
+      Metric metric = toSolrMetric(aggCall.getAggregation(), inNames, aggCall.getArgList());
+      metrics.add(metric);
+      fieldMappings.put(aggCall.getName(), metric.getIdentifier());
+    }
+
+    List<String> buckets = new ArrayList<>();
+    for(int group : groupSet) {
+      final String inName = inNames.get(group);
+      buckets.add(inName);
+      fieldMappings.put(inName, inName);
+    }
+
+    implementor.addBuckets(buckets);
+    implementor.addMetrics(metrics);
+    implementor.addFieldMappings(fieldMappings);
+  }
+
+  private Metric toSolrMetric(SqlAggFunction aggregation, List<String> inNames, List<Integer> args) {
+    switch (args.size()) {
+      case 0:
+        if(aggregation.equals(SqlStdOperatorTable.COUNT)) {
+          return new CountMetric();
+        }
+      case 1:
+        final String inName = inNames.get(args.get(0));
+        if (aggregation.equals(SqlStdOperatorTable.SUM) || aggregation.equals(SqlStdOperatorTable.SUM0)) {
+          return new SumMetric(inName);
+        } else if (aggregation.equals(SqlStdOperatorTable.MIN)) {
+          return new MinMetric(inName);
+        } else if (aggregation.equals(SqlStdOperatorTable.MAX)) {
+          return new MaxMetric(inName);
+        } else if (aggregation.equals(SqlStdOperatorTable.AVG)) {
+          return new MeanMetric(inName);
+        }
+      default:
+        throw new AssertionError("Invalid aggregation " + aggregation + " with args " + args + " with names" + inNames);
+    }
+  }
+}
+
+// End SolrAggregate.java

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrEnumerator.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrEnumerator.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrEnumerator.java
index e807fcd..b9d0cec 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrEnumerator.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrEnumerator.java
@@ -16,13 +16,13 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.io.IOException;
-import java.util.List;
-
 import org.apache.calcite.linq4j.Enumerator;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.TupleStream;
 
+import java.io.IOException;
+import java.util.List;
+
 /** Enumerator that reads from a Solr collection. */
 class SolrEnumerator implements Enumerator<Object> {
   private final TupleStream tupleStream;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrFilter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrFilter.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrFilter.java
index 096c6e5..8c8d9cc 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrFilter.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrFilter.java
@@ -16,14 +16,7 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptCost;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.plan.*;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Filter;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
@@ -31,12 +24,16 @@ import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Implementation of a {@link org.apache.calcite.rel.core.Filter} relational expression in Solr.
  */
-public class SolrFilter extends Filter implements SolrRel {
-  public SolrFilter(
+class SolrFilter extends Filter implements SolrRel {
+  SolrFilter(
       RelOptCluster cluster,
       RelTraitSet traitSet,
       RelNode child,
@@ -91,46 +88,49 @@ public class SolrFilter extends Filter implements SolrRel {
     }
 
     private String translateMatch2(RexNode node) {
+      Pair<String, RexLiteral> binaryTranslated = translateBinary((RexCall) node);
+
       switch (node.getKind()) {
+//        case NOT:
+//          return translateBinary("-", "-", (RexCall) node);
         case EQUALS:
-          return translateBinary("", "", (RexCall) node);
-//        case NOT_EQUALS:
-//          return null;
-//        case LESS_THAN:
-//          return translateBinary("$lt", "$gt", (RexCall) node);
-//        case LESS_THAN_OR_EQUAL:
-//          return translateBinary("$lte", "$gte", (RexCall) node);
-        case NOT:
-          return translateBinary("-", "-", (RexCall) node);
-//        case GREATER_THAN:
-//          return translateBinary("$gt", "$lt", (RexCall) node);
-//        case GREATER_THAN_OR_EQUAL:
-//          return translateBinary("$gte", "$lte", (RexCall) node);
+          return binaryTranslated.getKey() + ":" + binaryTranslated.getValue().getValue2();
+        case NOT_EQUALS:
+          return "-" + binaryTranslated.getKey() + ":" + binaryTranslated.getValue().getValue2();
+        case LESS_THAN:
+          return binaryTranslated.getKey() + ": [ * TO " + binaryTranslated.getValue().getValue2() + " }";
+        case LESS_THAN_OR_EQUAL:
+          return binaryTranslated.getKey() + ": [ * TO " + binaryTranslated.getValue().getValue2() + " ]";
+        case GREATER_THAN:
+          return binaryTranslated.getKey() + ": { " + binaryTranslated.getValue().getValue2() + " TO * ]";
+        case GREATER_THAN_OR_EQUAL:
+          return binaryTranslated.getKey() + ": [ " + binaryTranslated.getValue().getValue2() + " TO * ]";
         default:
           throw new AssertionError("cannot translate " + node);
       }
     }
 
     /** Translates a call to a binary operator, reversing arguments if necessary. */
-    private String translateBinary(String op, String rop, RexCall call) {
-      if(call.operands.size() != 2) {
-        throw new AssertionError("hello");
+    private Pair<String, RexLiteral> translateBinary(RexCall call) {
+      List<RexNode> operands = call.getOperands();
+      if(operands.size() != 2) {
+        throw new AssertionError("Invalid number of arguments - " + operands.size());
       }
-      final RexNode left = call.operands.get(0);
-      final RexNode right = call.operands.get(1);
-      String b = translateBinary2(op, left, right);
-      if (b != null) {
-        return b;
+      final RexNode left = operands.get(0);
+      final RexNode right = operands.get(1);
+      final Pair<String, RexLiteral> a = translateBinary2(left, right);
+      if (a != null) {
+        return a;
       }
-      b = translateBinary2(rop, right, left);
+      final Pair<String, RexLiteral> b = translateBinary2(right, left);
       if (b != null) {
         return b;
       }
-      throw new AssertionError("cannot translate op " + op + " call " + call);
+      throw new AssertionError("cannot translate call " + call);
     }
 
     /** Translates a call to a binary operator. Returns whether successful. */
-    private String translateBinary2(String op, RexNode left, RexNode right) {
+    private Pair<String, RexLiteral> translateBinary2(RexNode left, RexNode right) {
       switch (right.getKind()) {
         case LITERAL:
           break;
@@ -142,9 +142,9 @@ public class SolrFilter extends Filter implements SolrRel {
         case INPUT_REF:
           final RexInputRef left1 = (RexInputRef) left;
           String name = fieldNames.get(left1.getIndex());
-          return translateOp2(op, name, rightLiteral);
+          return new Pair<>(name, rightLiteral);
         case CAST:
-          return translateBinary2(op, ((RexCall) left).operands.get(0), right);
+          return translateBinary2(((RexCall) left).operands.get(0), right);
 //        case OTHER_FUNCTION:
 //          String itemName = SolrRules.isItem((RexCall) left);
 //          if (itemName != null) {
@@ -154,12 +154,5 @@ public class SolrFilter extends Filter implements SolrRel {
           return null;
       }
     }
-
-    private String translateOp2(String op, String name, RexLiteral right) {
-      if (op == null) {
-        op = "";
-      }
-      return op + name + ":" + right.getValue2();
-      }
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrMethod.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrMethod.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrMethod.java
index bce569a..31c4548 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrMethod.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrMethod.java
@@ -16,30 +16,20 @@
  */
 package org.apache.solr.handler.sql;
 
+import org.apache.calcite.linq4j.tree.Types;
+
 import java.lang.reflect.Method;
 import java.util.List;
 
-import com.google.common.collect.ImmutableMap;
-import org.apache.calcite.linq4j.tree.Types;
-
 /**
  * Builtin methods in the Solr adapter.
  */
-public enum SolrMethod {
-  SOLR_QUERYABLE_QUERY(SolrTable.SolrQueryable.class, "query", List.class, String.class, List.class, String.class);
+enum SolrMethod {
+  SOLR_QUERYABLE_QUERY(SolrTable.SolrQueryable.class, "query", List.class, String.class, List.class, List.class,
+      List.class, String.class);
 
   public final Method method;
 
-  public static final ImmutableMap<Method, SolrMethod> MAP;
-
-  static {
-    final ImmutableMap.Builder<Method, SolrMethod> builder = ImmutableMap.builder();
-    for (SolrMethod value : SolrMethod.values()) {
-      builder.put(value.method, value);
-    }
-    MAP = builder.build();
-  }
-
   SolrMethod(Class clazz, String methodName, Class... argumentTypes) {
     this.method = Types.lookupMethod(clazz, methodName, argumentTypes);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrProject.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrProject.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrProject.java
index 7f8b38b..fb7e5e8 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrProject.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrProject.java
@@ -16,10 +16,6 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.calcite.adapter.java.JavaTypeFactory;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptCost;
@@ -32,12 +28,16 @@ import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.util.Pair;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Implementation of {@link org.apache.calcite.rel.core.Project} relational expression in Solr.
  */
-public class SolrProject extends Project implements SolrRel {
-  public SolrProject(RelOptCluster cluster, RelTraitSet traitSet,
-                     RelNode input, List<? extends RexNode> projects, RelDataType rowType) {
+class SolrProject extends Project implements SolrRel {
+  SolrProject(RelOptCluster cluster, RelTraitSet traitSet,
+              RelNode input, List<? extends RexNode> projects, RelDataType rowType) {
     super(cluster, traitSet, input, projects, rowType);
     assert getConvention() == SolrRel.CONVENTION;
     assert getConvention() == input.getConvention();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrRel.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrRel.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrRel.java
index fdeb4d0..9a11488 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrRel.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrRel.java
@@ -16,19 +16,20 @@
  */
 package org.apache.solr.handler.sql;
 
+import org.apache.calcite.plan.Convention;
+import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.rel.RelNode;
+import org.apache.solr.client.solrj.io.stream.metrics.Metric;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.calcite.plan.Convention;
-import org.apache.calcite.plan.RelOptTable;
-import org.apache.calcite.rel.RelNode;
-
 /**
  * Relational expression that uses Solr calling convention.
  */
-public interface SolrRel extends RelNode {
+interface SolrRel extends RelNode {
   void implement(Implementor implementor);
 
   /** Calling convention for relational operations that occur in Solr. */
@@ -40,29 +41,42 @@ public interface SolrRel extends RelNode {
     String query = null;
     String limitValue = null;
     final List<String> order = new ArrayList<>();
+    final List<String> buckets = new ArrayList<>();
+    final List<Metric> metrics = new ArrayList<>();
 
     RelOptTable table;
     SolrTable solrTable;
 
-    public void addFieldMappings(Map<String, String> fieldMappings) {
-      if (fieldMappings != null) {
-        this.fieldMappings.putAll(fieldMappings);
-      }
+    void addFieldMappings(Map<String, String> fieldMappings) {
+      this.fieldMappings.putAll(fieldMappings);
     }
 
-    public void addQuery(String query) {
+    void addQuery(String query) {
       this.query = query;
     }
 
-    public void addOrder(List<String> newOrder) {
-      order.addAll(newOrder);
+    void addOrder(List<String> order) {
+      for(String orderItem : order) {
+        String[] orderParts = orderItem.split(" ", 2);
+        String fieldName = orderParts[0];
+        String direction = orderParts[1];
+       this.order.add(this.fieldMappings.getOrDefault(fieldName, fieldName) + " " + direction);
+      }
+    }
+
+    void addBuckets(List<String> buckets) {
+      this.buckets.addAll(buckets);
+    }
+
+    void addMetrics(List<Metric> metrics) {
+      this.metrics.addAll(metrics);
     }
 
-    public void setLimit(String limit) {
+    void setLimit(String limit) {
       limitValue = limit;
     }
 
-    public void visitChild(int ordinal, RelNode input) {
+    void visitChild(int ordinal, RelNode input) {
       assert ordinal == 0;
       ((SolrRel) input).implement(this);
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrRules.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrRules.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrRules.java
index df85c94..a2d9eb1 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrRules.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrRules.java
@@ -16,11 +16,6 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.util.AbstractList;
-import java.util.List;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
 import org.apache.calcite.plan.Convention;
 import org.apache.calcite.plan.RelOptRule;
@@ -28,7 +23,9 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelCollations;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterRule;
+import org.apache.calcite.rel.core.Aggregate;
 import org.apache.calcite.rel.core.Sort;
+import org.apache.calcite.rel.logical.LogicalAggregate;
 import org.apache.calcite.rel.logical.LogicalFilter;
 import org.apache.calcite.rel.logical.LogicalProject;
 import org.apache.calcite.rel.type.RelDataType;
@@ -37,18 +34,21 @@ import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexVisitorImpl;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
 
+import java.util.AbstractList;
+import java.util.List;
+import java.util.function.Predicate;
+
 /**
  * Rules and relational operators for
  * {@link SolrRel#CONVENTION}
  * calling convention.
  */
-public class SolrRules {
-  private SolrRules() {}
-
+class SolrRules {
   static final RelOptRule[] RULES = {
     SolrFilterRule.INSTANCE,
     SolrProjectRule.INSTANCE,
-//    SolrSortRule.INSTANCE
+    SolrSortRule.INSTANCE,
+    SolrAggregateRule.INSTANCE,
   };
 
   static List<String> solrFieldNames(final RelDataType rowType) {
@@ -87,12 +87,12 @@ public class SolrRules {
   abstract static class SolrConverterRule extends ConverterRule {
     final Convention out;
 
-    public SolrConverterRule(Class<? extends RelNode> clazz, String description) {
-      this(clazz, Predicates.<RelNode>alwaysTrue(), description);
+    SolrConverterRule(Class<? extends RelNode> clazz, String description) {
+      this(clazz, relNode -> true, description);
     }
 
-    public <R extends RelNode> SolrConverterRule(Class<R> clazz, Predicate<? super R> predicate, String description) {
-      super(clazz, predicate, Convention.NONE, SolrRel.CONVENTION, description);
+    <R extends RelNode> SolrConverterRule(Class<R> clazz, Predicate<RelNode> predicate, String description) {
+      super(clazz, predicate::test, Convention.NONE, SolrRel.CONVENTION, description);
       this.out = SolrRel.CONVENTION;
     }
   }
@@ -119,7 +119,7 @@ public class SolrRules {
   }
 
   /**
-   * Rule to convert a {@link org.apache.calcite.rel.logical.LogicalProject} to a {@link SolrProject}.
+   * Rule to convert a {@link LogicalProject} to a {@link SolrProject}.
    */
   private static class SolrProjectRule extends SolrConverterRule {
     private static final SolrProjectRule INSTANCE = new SolrProjectRule();
@@ -141,10 +141,10 @@ public class SolrRules {
   }
 
   /**
-   * Rule to convert a {@link org.apache.calcite.rel.core.Sort} to a {@link SolrSort}.
+   * Rule to convert a {@link Sort} to a {@link SolrSort}.
    */
   private static class SolrSortRule extends SolrConverterRule {
-    public static final SolrSortRule INSTANCE = new SolrSortRule();
+    static final SolrSortRule INSTANCE = new SolrSortRule();
 
     private SolrSortRule() {
       super(Sort.class, "SolrSortRule");
@@ -161,4 +161,28 @@ public class SolrRules {
           sort.fetch);
     }
   }
+
+  /**
+   * Rule to convert an {@link org.apache.calcite.rel.logical.LogicalAggregate} to an {@link SolrAggregate}.
+   */
+  private static class SolrAggregateRule extends SolrConverterRule {
+    private static final RelOptRule INSTANCE = new SolrAggregateRule();
+
+    private SolrAggregateRule() {
+      super(LogicalAggregate.class, relNode -> Aggregate.IS_SIMPLE.apply(((LogicalAggregate)relNode)), "SolrAggregateRule");
+    }
+
+    public RelNode convert(RelNode rel) {
+      final LogicalAggregate agg = (LogicalAggregate) rel;
+      final RelTraitSet traitSet = agg.getTraitSet().replace(out);
+      return new SolrAggregate(
+          rel.getCluster(),
+          traitSet,
+          convert(agg.getInput(), traitSet.simplify()),
+          agg.indicator,
+          agg.getGroupSet(),
+          agg.getGroupSets(),
+          agg.getAggCallList());
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
index 9103f8b..892e93f 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
@@ -16,18 +16,8 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.io.IOException;
-import java.util.EnumSet;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
 import com.google.common.collect.ImmutableMap;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.rel.type.RelDataTypeImpl;
-import org.apache.calcite.rel.type.RelDataTypeSystem;
-import org.apache.calcite.rel.type.RelProtoDataType;
+import org.apache.calcite.rel.type.*;
 import org.apache.calcite.schema.Table;
 import org.apache.calcite.schema.impl.AbstractSchema;
 import org.apache.calcite.sql.type.SqlTypeFactoryImpl;
@@ -37,6 +27,12 @@ import org.apache.solr.client.solrj.request.LukeRequest;
 import org.apache.solr.client.solrj.response.LukeResponse;
 import org.apache.solr.common.luke.FieldFlag;
 
+import java.io.IOException;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
 class SolrSchema extends AbstractSchema {
   final Properties properties;
 
@@ -48,7 +44,7 @@ class SolrSchema extends AbstractSchema {
   @Override
   protected Map<String, Table> getTableMap() {
     String zk = this.properties.getProperty("zk");
-    try(CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zk).build()) {
+    try(CloudSolrClient cloudSolrClient = new CloudSolrClient(zk)) {
       cloudSolrClient.connect();
       Set<String> collections = cloudSolrClient.getZkStateReader().getClusterState().getCollections();
 
@@ -64,7 +60,7 @@ class SolrSchema extends AbstractSchema {
 
   private Map<String, LukeResponse.FieldInfo> getFieldInfo(String collection) {
     String zk = this.properties.getProperty("zk");
-    try(CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zk).build()) {
+    try(CloudSolrClient cloudSolrClient = new CloudSolrClient(zk)) {
       cloudSolrClient.connect();
       LukeRequest lukeRequest = new LukeRequest();
       lukeRequest.setNumTerms(0);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrSort.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrSort.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrSort.java
index 602375d..4f6cd4a 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrSort.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrSort.java
@@ -16,9 +16,6 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptCost;
 import org.apache.calcite.plan.RelOptPlanner;
@@ -32,12 +29,15 @@ import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Implementation of {@link org.apache.calcite.rel.core.Sort} relational expression in Solr.
  */
-public class SolrSort extends Sort implements SolrRel {
+class SolrSort extends Sort implements SolrRel {
 
-  public SolrSort(RelOptCluster cluster, RelTraitSet traitSet, RelNode child, RelCollation collation, RexNode fetch) {
+  SolrSort(RelOptCluster cluster, RelTraitSet traitSet, RelNode child, RelCollation collation, RexNode fetch) {
     super(cluster, traitSet, child, collation, null, fetch);
 
     assert getConvention() == SolrRel.CONVENTION;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrTable.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrTable.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrTable.java
index 1f704fe..d937d09 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrTable.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrTable.java
@@ -16,19 +16,8 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
 import org.apache.calcite.adapter.java.AbstractQueryableTable;
-import org.apache.calcite.linq4j.AbstractEnumerable;
-import org.apache.calcite.linq4j.Enumerable;
-import org.apache.calcite.linq4j.Enumerator;
-import org.apache.calcite.linq4j.QueryProvider;
-import org.apache.calcite.linq4j.Queryable;
+import org.apache.calcite.linq4j.*;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.rel.RelNode;
@@ -39,20 +28,29 @@ import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.schema.TranslatableTable;
 import org.apache.calcite.schema.impl.AbstractTableQueryable;
 import org.apache.solr.client.solrj.io.stream.CloudSolrStream;
+import org.apache.solr.client.solrj.io.stream.RollupStream;
+import org.apache.solr.client.solrj.io.stream.StatsStream;
 import org.apache.solr.client.solrj.io.stream.TupleStream;
+import org.apache.solr.client.solrj.io.stream.metrics.Bucket;
+import org.apache.solr.client.solrj.io.stream.metrics.Metric;
 import org.apache.solr.common.params.CommonParams;
 
+import java.io.IOException;
+import java.util.*;
+
 /**
  * Table based on a Solr collection
  */
-public class SolrTable extends AbstractQueryableTable implements TranslatableTable {
-  private static final String DEFAULT_SORT_FIELD = "_version_";
+class SolrTable extends AbstractQueryableTable implements TranslatableTable {
+  private static final String DEFAULT_QUERY = "*:*";
+  private static final String DEFAULT_VERSION_FIELD = "_version_";
+  private static final String DEFAULT_SCORE_FIELD = "score";
 
   private final String collection;
   private final SolrSchema schema;
   private RelProtoDataType protoRowType;
 
-  public SolrTable(SolrSchema schema, String collection) {
+  SolrTable(SolrSchema schema, String collection) {
     super(Object[].class);
     this.schema = schema;
     this.collection = collection;
@@ -69,8 +67,9 @@ public class SolrTable extends AbstractQueryableTable implements TranslatableTab
     return protoRowType.apply(typeFactory);
   }
   
-  public Enumerable<Object> query(final Properties properties) {
-    return query(properties, Collections.emptyList(), null, Collections.emptyList(), null);
+  private Enumerable<Object> query(final Properties properties) {
+    return query(properties, Collections.emptyList(), null, Collections.emptyList(), Collections.emptyList(),
+        Collections.emptyList(), null);
   }
 
   /** Executes a Solr query on the underlying table.
@@ -80,47 +79,80 @@ public class SolrTable extends AbstractQueryableTable implements TranslatableTab
    * @param query A string for the query
    * @return Enumerator of results
    */
-  public Enumerable<Object> query(final Properties properties, List<String> fields,
-                                  String query, List<String> order, String limit) {
+  private Enumerable<Object> query(final Properties properties, final List<String> fields,
+                                   final String query, final List<String> order, final List<String> buckets,
+                                   final List<Metric> metrics, final String limit) {
+    // SolrParams should be a ModifiableParams instead of a map
     Map<String, String> solrParams = new HashMap<>();
-    //solrParams.put(CommonParams.OMIT_HEADER, "true");
-    solrParams.put(CommonParams.Q, "*:*");
-    //solrParams.put(CommonParams.QT, "/export");
-
-    if (fields.isEmpty()) {
-      solrParams.put(CommonParams.FL, "*");
-    } else {
-      solrParams.put(CommonParams.FL, String.join(",", fields));
-    }
+    solrParams.put(CommonParams.OMIT_HEADER, "true");
 
     if (query == null) {
-      solrParams.put(CommonParams.FQ, "*:*");
+      solrParams.put(CommonParams.Q, DEFAULT_QUERY);
     } else {
-      // SolrParams should be a ModifiableParams instead of a map so we could add multiple FQs
-      solrParams.put(CommonParams.FQ, query);
+      solrParams.put(CommonParams.Q, DEFAULT_QUERY + " AND " + query);
     }
 
-    // Build and issue the query and return an Enumerator over the results
-    if (order.isEmpty()) {
-      solrParams.put(CommonParams.SORT, DEFAULT_SORT_FIELD + " desc");
+    // List<String> doesn't have add so must make a new ArrayList
+    List<String> fieldsList = new ArrayList<>(fields);
 
-      // Make sure the default sort field is in the field list
-      String fl = solrParams.get(CommonParams.FL);
-      if(!fl.contains(DEFAULT_SORT_FIELD)) {
-        solrParams.put(CommonParams.FL, String.join(",", fl, DEFAULT_SORT_FIELD));
+    if (order.isEmpty()) {
+      if(limit != null && Integer.parseInt(limit) > -1) {
+        solrParams.put(CommonParams.SORT, DEFAULT_SCORE_FIELD + " desc");
+
+        // Make sure the default score field is in the field list
+        if (!fieldsList.contains(DEFAULT_SCORE_FIELD)) {
+          fieldsList.add(DEFAULT_SCORE_FIELD);
+        }
+      } else {
+        solrParams.put(CommonParams.SORT, DEFAULT_VERSION_FIELD + " desc");
+
+        // Make sure the default sort field is in the field list
+        if (!fieldsList.contains(DEFAULT_VERSION_FIELD)) {
+          fieldsList.add(DEFAULT_VERSION_FIELD);
+        }
       }
     } else {
       solrParams.put(CommonParams.SORT, String.join(",", order));
     }
 
+    if (fieldsList.isEmpty()) {
+      solrParams.put(CommonParams.FL, "*");
+    } else {
+      solrParams.put(CommonParams.FL, String.join(",", fieldsList));
+    }
+
     TupleStream tupleStream;
+    String zk = properties.getProperty("zk");
     try {
-      String zk = properties.getProperty("zk");
-      tupleStream = new CloudSolrStream(zk, collection, solrParams);
-      if(limit != null) {
-        tupleStream = new LimitStream(tupleStream, Integer.parseInt(limit));
+      if(metrics.isEmpty()) {
+        if (limit == null) {
+          solrParams.put(CommonParams.QT, "/export");
+          tupleStream = new CloudSolrStream(zk, collection, solrParams);
+        } else {
+          solrParams.put(CommonParams.ROWS, limit);
+          tupleStream = new LimitStream(new CloudSolrStream(zk, collection, solrParams), Integer.parseInt(limit));
+        }
+      } else {
+        Metric[] metricsArray = metrics.toArray(new Metric[metrics.size()]);
+        if(buckets.isEmpty()) {
+          solrParams.remove(CommonParams.FL);
+          solrParams.remove(CommonParams.SORT);
+          tupleStream = new StatsStream(zk, collection, solrParams, metricsArray);
+        } else {
+          List<Bucket> bucketsList = new ArrayList<>();
+          for(String bucket : buckets) {
+            bucketsList.add(new Bucket(bucket));
+          }
+
+          solrParams.put(CommonParams.QT, "/export");
+          for(Metric metric : metrics) {
+            fieldsList.remove(metric.getIdentifier());
+          }
+          solrParams.put(CommonParams.FL, String.join(",", fieldsList));
+          tupleStream = new CloudSolrStream(zk, collection, solrParams);
+          tupleStream = new RollupStream(tupleStream, bucketsList.toArray(new Bucket[bucketsList.size()]), metricsArray);
+        }
       }
-
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
@@ -128,6 +160,7 @@ public class SolrTable extends AbstractQueryableTable implements TranslatableTab
     final TupleStream finalStream = tupleStream;
 
     return new AbstractEnumerable<Object>() {
+      // Use original fields list to make sure only the fields specified are enumerated
       public Enumerator<Object> enumerator() {
         return new SolrEnumerator(finalStream, fields);
       }
@@ -143,6 +176,7 @@ public class SolrTable extends AbstractQueryableTable implements TranslatableTab
     return new SolrTableScan(cluster, cluster.traitSetOf(SolrRel.CONVENTION), relOptTable, this, null);
   }
 
+  @SuppressWarnings("WeakerAccess")
   public static class SolrQueryable<T> extends AbstractTableQueryable<T> {
     SolrQueryable(QueryProvider queryProvider, SchemaPlus schema, SolrTable table, String tableName) {
       super(queryProvider, schema, table, tableName);
@@ -167,8 +201,9 @@ public class SolrTable extends AbstractQueryableTable implements TranslatableTab
      * @see SolrMethod#SOLR_QUERYABLE_QUERY
      */
     @SuppressWarnings("UnusedDeclaration")
-    public Enumerable<Object> query(List<String> fields, String query, List<String> order, String limit) {
-      return getTable().query(getProperties(), fields, query, order, limit);
+    public Enumerable<Object> query(List<String> fields, String query, List<String> order, List<String> buckets,
+                                    List<Metric> metrics, String limit) {
+      return getTable().query(getProperties(), fields, query, order, buckets, metrics, limit);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrTableScan.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrTableScan.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrTableScan.java
index 45eb09c..b12fb02 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrTableScan.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrTableScan.java
@@ -16,23 +16,19 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.util.List;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptTable;
-import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.plan.*;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.type.RelDataType;
 
+import java.util.List;
+
 /**
  * Relational expression representing a scan of a Solr collection.
  */
 class SolrTableScan extends TableScan implements SolrRel {
-  final SolrTable solrTable;
-  final RelDataType projectRowType;
+  private final SolrTable solrTable;
+  private final RelDataType projectRowType;
 
   /**
    * Creates a SolrTableScan.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/java/org/apache/solr/handler/sql/SolrToEnumerableConverter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrToEnumerableConverter.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrToEnumerableConverter.java
index d8b67ad..4cdc92b 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrToEnumerableConverter.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrToEnumerableConverter.java
@@ -16,25 +16,13 @@
  */
 package org.apache.solr.handler.sql;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
 import com.google.common.collect.Lists;
-import org.apache.calcite.adapter.enumerable.EnumerableRel;
-import org.apache.calcite.adapter.enumerable.EnumerableRelImplementor;
-import org.apache.calcite.adapter.enumerable.JavaRowFormat;
-import org.apache.calcite.adapter.enumerable.PhysType;
-import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
+import org.apache.calcite.adapter.enumerable.*;
 import org.apache.calcite.linq4j.tree.BlockBuilder;
 import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.Expressions;
 import org.apache.calcite.linq4j.tree.MethodCallExpression;
-import org.apache.calcite.plan.ConventionTraitDef;
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptCost;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.plan.*;
 import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
@@ -42,12 +30,17 @@ 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;
+import org.apache.solr.client.solrj.io.stream.metrics.Metric;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Relational expression representing a scan of a table in Solr
  */
-public class SolrToEnumerableConverter extends ConverterImpl implements EnumerableRel {
-  protected SolrToEnumerableConverter(RelOptCluster cluster, RelTraitSet traits, RelNode input) {
+class SolrToEnumerableConverter extends ConverterImpl implements EnumerableRel {
+  SolrToEnumerableConverter(RelOptCluster cluster, RelTraitSet traits, RelNode input) {
     super(cluster, ConventionTraitDef.INSTANCE, traits, input);
   }
 
@@ -73,9 +66,11 @@ public class SolrToEnumerableConverter extends ConverterImpl implements Enumerab
         constantArrayList(generateFields(SolrRules.solrFieldNames(rowType), solrImplementor.fieldMappings), String.class));
     final Expression filterQueries = list.append("query", Expressions.constant(solrImplementor.query, String.class));
     final Expression order = list.append("order", constantArrayList(solrImplementor.order, String.class));
+    final Expression buckets = list.append("buckets", constantArrayList(solrImplementor.buckets, String.class));
+    final Expression metrics = list.append("metrics", constantArrayList(solrImplementor.metrics, Metric.class));
     final Expression limit = list.append("limit", Expressions.constant(solrImplementor.limitValue));
     Expression enumerable = list.append("enumerable", Expressions.call(table, SolrMethod.SOLR_QUERYABLE_QUERY.method,
-        fields, filterQueries, order, limit));
+        fields, filterQueries, order, buckets, metrics, limit));
     if (CalcitePrepareImpl.DEBUG) {
       System.out.println("Solr: " + filterQueries);
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d3f0700c/solr/core/src/test/org/apache/solr/handler/TestSQLHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/TestSQLHandler.java b/solr/core/src/test/org/apache/solr/handler/TestSQLHandler.java
index 1756a3c..38922e1 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestSQLHandler.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestSQLHandler.java
@@ -1079,8 +1079,6 @@ public class TestSQLHandler extends AbstractFullDistribZkTestBase {
 
 
       // Test without a sort. Sort should be asc by default.
-      /*
-      // TODO figure out what should be sort asc by default (version?)
       params = new HashMap();
       params.put(CommonParams.QT, "/sql");
       params.put("stmt", "select distinct str_s, field_i from collection1");
@@ -1113,7 +1111,6 @@ public class TestSQLHandler extends AbstractFullDistribZkTestBase {
       tuple = tuples.get(5);
       assert(tuple.get("str_s").equals("c"));
       assert(tuple.getLong("field_i") == 60);
-      */
 
       // Test with a predicate.
       params = new HashMap();
@@ -1289,8 +1286,6 @@ public class TestSQLHandler extends AbstractFullDistribZkTestBase {
 
 
       // Test without a sort. Sort should be asc by default.
-      /*
-      // TODO figure out what should be sort asc by default (version?)
       params = new HashMap();
       params.put(CommonParams.QT, "/sql");
       params.put("numWorkers", "2");
@@ -1324,7 +1319,6 @@ public class TestSQLHandler extends AbstractFullDistribZkTestBase {
       tuple = tuples.get(5);
       assert(tuple.get("str_s").equals("c"));
       assert(tuple.getLong("field_i") == 60);
-      */
 
       // Test with a predicate.
       params = new HashMap();