Add Drill implementations of Project and Filter relational operators.

Signed-off-by: Jacques Nadeau <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/6095ca95
Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/6095ca95
Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/6095ca95

Branch: refs/heads/execwork
Commit: 6095ca955d3e83f80769eb2b4a02438706ee3fab
Parents: a302547
Author: Julian Hyde <[email protected]>
Authored: Tue Mar 12 01:16:00 2013 -0700
Committer: Jacques Nadeau <[email protected]>
Committed: Thu Jun 6 11:06:42 2013 -0700

----------------------------------------------------------------------
 .../java/org/apache/drill/jdbc/DrillTable.java     |    5 +-
 .../org/apache/drill/optiq/DrillFilterRel.java     |   66 ++++++++++
 .../org/apache/drill/optiq/DrillFilterRule.java    |   52 ++++++++
 .../org/apache/drill/optiq/DrillImplementor.java   |    5 +
 .../java/org/apache/drill/optiq/DrillOptiq.java    |   96 ++++++++++++---
 .../org/apache/drill/optiq/DrillProjectRel.java    |   83 +++++++++++++
 .../org/apache/drill/optiq/DrillProjectRule.java   |   51 ++++++++
 .../main/java/org/apache/drill/optiq/DrillRel.java |    5 +
 .../java/org/apache/drill/optiq/DrillScan.java     |    2 +-
 .../org/apache/drill/optiq/EnumerableDrill.java    |   60 ++++++----
 .../org/apache/drill/optiq/EnumerableDrillRel.java |   62 +++++++---
 .../apache/drill/optiq/EnumerableDrillRule.java    |   12 +--
 .../org/apache/drill/jdbc/test/JdbcAssert.java     |    7 +-
 .../java/org/apache/drill/jdbc/test/JdbcTest.java  |   10 ++
 14 files changed, 447 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/jdbc/DrillTable.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/jdbc/DrillTable.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/jdbc/DrillTable.java
index e98cfaa..7f1c334 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/jdbc/DrillTable.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/jdbc/DrillTable.java
@@ -34,8 +34,7 @@ import org.apache.drill.common.logical.StorageEngineConfig;
 import org.apache.drill.exec.ref.rops.DataWriter;
 import org.apache.drill.exec.ref.rse.ClasspathRSE;
 import org.apache.drill.exec.ref.rse.ClasspathRSE.ClasspathInputConfig;
-import org.apache.drill.optiq.DrillOptiq;
-import org.apache.drill.optiq.DrillScan;
+import org.apache.drill.optiq.*;
 
 import org.eigenbase.rel.RelNode;
 import org.eigenbase.relopt.RelOptTable;
@@ -107,7 +106,7 @@ public class DrillTable extends BaseQueryable<Object>
 
   public RelNode toRel(RelOptTable.ToRelContext context, RelOptTable table) {
     return new DrillScan(context.getCluster(),
-        context.getCluster().traitSetOf(DrillOptiq.CONVENTION),
+        context.getCluster().traitSetOf(DrillRel.CONVENTION),
         table);
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRel.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRel.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRel.java
new file mode 100644
index 0000000..c2f747c
--- /dev/null
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRel.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.drill.optiq;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import org.eigenbase.rel.FilterRelBase;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.*;
+import org.eigenbase.rex.RexNode;
+
+import java.util.List;
+
+/**
+ * Filter implemented in Drill.
+ */
+public class DrillFilterRel extends FilterRelBase implements DrillRel {
+  protected DrillFilterRel(RelOptCluster cluster, RelTraitSet traits,
+      RelNode child, RexNode condition) {
+    super(cluster, traits, child, condition);
+    assert getConvention() == CONVENTION;
+  }
+
+  @Override
+  public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+    return new DrillFilterRel(getCluster(), traitSet, sole(inputs),
+        getCondition());
+  }
+
+  @Override
+  public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    return super.computeSelfCost(planner).multiplyBy(0.1);
+  }
+
+  @Override
+  public void implement(DrillImplementor implementor) {
+    implementor.visitChild(this, 0, getChild());
+    final ObjectNode node = implementor.mapper.createObjectNode();
+/*
+      E.g. {
+             op: "filter",
+             expr: "donuts.ppu < 1.00"
+           }
+*/
+    node.put("op", "filter");
+    node.put("expr", DrillOptiq.toDrill(getCondition(), "donuts"));
+    implementor.add(node);
+  }
+}
+
+// End DrillFilterRel.java

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRule.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRule.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRule.java
new file mode 100644
index 0000000..8687304
--- /dev/null
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRule.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.drill.optiq;
+
+import org.eigenbase.rel.FilterRel;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.*;
+
+/**
+ * Rule that converts a {@link org.eigenbase.rel.FilterRel} to a Drill
+ * "filter" operation.
+ */
+public class DrillFilterRule extends RelOptRule {
+  public static final RelOptRule INSTANCE = new DrillFilterRule();
+
+  private DrillFilterRule() {
+    super(
+        new RelOptRuleOperand(
+            FilterRel.class,
+            Convention.NONE,
+            new RelOptRuleOperand(RelNode.class, ANY)),
+        "DrillFilterRule");
+  }
+
+  @Override
+  public void onMatch(RelOptRuleCall call) {
+    final FilterRel filter = (FilterRel) call.getRels()[0];
+    final RelNode input = call.getRels()[1];
+    final RelTraitSet traits = filter.getTraitSet().plus(DrillRel.CONVENTION);
+    final RelNode convertedInput = convert(input, traits);
+    call.transformTo(
+        new DrillFilterRel(filter.getCluster(), traits, convertedInput,
+            filter.getCondition()));
+  }
+}
+
+// End DrillFilterRule.java

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillImplementor.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillImplementor.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillImplementor.java
index 445b118..ccbd924 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillImplementor.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillImplementor.java
@@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.eigenbase.rel.RelNode;
 
 /**
  * Context for converting a tree of {@link DrillRel} nodes into a Drill logical
@@ -107,6 +108,10 @@ public class DrillImplementor {
     System.out.println(s);
     return s;
   }
+
+  public void visitChild(DrillRel parent, int ordinal, RelNode child) {
+    ((DrillRel) child).implement(this);
+  }
 }
 
 // End DrillImplementor.java

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
index d219706..a1c2f21 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
@@ -17,30 +17,96 @@
  
******************************************************************************/
 package org.apache.drill.optiq;
 
-import org.eigenbase.relopt.Convention;
 import org.eigenbase.relopt.RelOptPlanner;
+import org.eigenbase.rex.*;
+import org.eigenbase.sql.SqlSyntax;
+import org.eigenbase.sql.fun.SqlStdOperatorTable;
 
 /**
- * @author jhyde
+ * Utilities for Drill's planner.
  */
 public class DrillOptiq {
-  /** Calling convention for relational expressions that are "implemented" by
-   * generating Drill logical plans. */
-  public static final Convention CONVENTION = new Convention.Impl("DRILL", 
DrillRel.class);
-
   static void registerStandardPlannerRules(RelOptPlanner planner) {
     planner.addRule(EnumerableDrillRule.ARRAY_INSTANCE);
     planner.addRule(EnumerableDrillRule.CUSTOM_INSTANCE);
 
-//    planner.addRule( CascadingTableModificationConverterRule.INSTANCE );
-//    planner.addRule( CascadingAggregateConverterRule.INSTANCE );
-//    planner.addRule( CascadingCalcConverterRule.INSTANCE );
+//    planner.addRule(DrillTableModificationConverterRule.INSTANCE);
+//    planner.addRule(DrillAggregateConverterRule.INSTANCE);
+//    planner.addRule(DrillCalcConverterRule.INSTANCE);
+
+    planner.addRule(DrillFilterRule.INSTANCE);
+    planner.addRule(DrillProjectRule.INSTANCE);
+//    planner.addRule(DrillSortRule.INSTANCE);
+//    planner.addRule(DrillJoinRule.INSTANCE);
+//    planner.addRule(DrillUnionRule.INSTANCE);
+//    planner.addRule(AbstractConverter.ExpandConversionRule.instance);
+  }
+
+  /** Converts a tree of {@link RexNode} operators into a scalar expression in
+   * Drill syntax. */
+  static String toDrill(RexNode expr, String inputName) {
+    final RexToDrill visitor = new RexToDrill(inputName);
+    expr.accept(visitor);
+    return visitor.buf.toString();
+  }
+
+  private static class RexToDrill extends RexVisitorImpl<StringBuilder> {
+    final StringBuilder buf = new StringBuilder();
+    private final String inputName;
+
+    RexToDrill(String inputName) {
+      super(true);
+      this.inputName = inputName;
+    }
+
+    @Override
+    public StringBuilder visitCall(RexCall call) {
+      final SqlSyntax syntax = call.getOperator().getSyntax();
+      switch (syntax) {
+      case Binary:
+        buf.append("(");
+        call.getOperandList().get(0).accept(this)
+            .append(" ")
+            .append(call.getOperator().getName())
+            .append(" ");
+        return call.getOperandList().get(1).accept(this)
+            .append(")");
+      case Special:
+        switch (call.getKind()) {
+        case Cast:
+          // Ignore casts. Drill is type-less.
+          return call.getOperandList().get(0).accept(this);
+        }
+        if (call.getOperator() == SqlStdOperatorTable.itemOp) {
+          final RexNode left = call.getOperandList().get(0);
+          final RexLiteral literal = (RexLiteral) call.getOperandList().get(1);
+          final String field = (String) literal.getValue2();
+          if (left instanceof RexInputRef) {
+            return buf.append(field);
+          } else {
+            return left.accept(this)
+                .append('.')
+                .append(field);
+          }
+        }
+        // fall through
+      default:
+        throw new AssertionError("todo: implement syntax " + syntax + "(" + 
call
+            + ")");
+      }
+    }
 
-//    planner.addRule( CascadingFilterRule.INSTANCE );
-//    planner.addRule( CascadingProjectRule.INSTANCE );
-//    planner.addRule( CascadingSortRule.INSTANCE );
-//    planner.addRule( CascadingJoinRule.INSTANCE );
-//    planner.addRule( CascadingUnionRule.INSTANCE );
-//    planner.addRule( AbstractConverter.ExpandConversionRule.instance );
+    @Override
+    public StringBuilder visitInputRef(RexInputRef inputRef) {
+      assert inputRef.getIndex() == 0;
+      return buf.append(inputName);
+    }
+
+    @Override
+    public StringBuilder visitLiteral(RexLiteral literal) {
+      return buf.append(literal);
+    }
   }
 }
+
+// End DrillOptiq.java

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRel.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRel.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRel.java
new file mode 100644
index 0000000..d6db766
--- /dev/null
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRel.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.drill.optiq;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import org.eigenbase.rel.*;
+import org.eigenbase.relopt.*;
+import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.rex.RexNode;
+import org.eigenbase.util.Pair;
+
+import java.util.*;
+
+/**
+ * Project implemented in Drill.
+ */
+public class DrillProjectRel extends ProjectRelBase implements DrillRel {
+  protected DrillProjectRel(RelOptCluster cluster, RelTraitSet traits,
+      RelNode child, RexNode[] exps, RelDataType rowType) {
+    super(cluster, traits, child, exps, rowType, Flags.Boxed,
+        Collections.<RelCollation>emptyList());
+    assert getConvention() == CONVENTION;
+  }
+
+  @Override
+  public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+    return new DrillProjectRel(getCluster(), traitSet, sole(inputs),
+        exps.clone(), rowType);
+  }
+
+  @Override
+  public RelOptCost computeSelfCost(RelOptPlanner planner) {
+    return super.computeSelfCost(planner).multiplyBy(0.1);
+  }
+
+  private List<Pair<RexNode, String>> projects() {
+    return Pair.zip(
+        Arrays.asList(exps),
+        RelOptUtil.getFieldNameList(getRowType()));
+  }
+
+  @Override
+  public void implement(DrillImplementor implementor) {
+    implementor.visitChild(this, 0, getChild());
+    final ObjectNode node = implementor.mapper.createObjectNode();
+/*
+    E.g. {
+      op: "transform",
+           transforms: [
+             { ref: "quantity", expr: "donuts.sales"}
+           ]
+*/
+    node.put("op", "transform");
+    final ArrayNode transforms = implementor.mapper.createArrayNode();
+    node.put("transforms", transforms);
+    for (Pair<RexNode, String> pair : projects()) {
+      final ObjectNode objectNode = implementor.mapper.createObjectNode();
+      transforms.add(objectNode);
+      objectNode.put("expr", DrillOptiq.toDrill(pair.left, "donuts"));
+      objectNode.put("ref", pair.right);
+    }
+    implementor.add(node);
+  }
+}
+
+// End DrillProjectRel.java

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRule.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRule.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRule.java
new file mode 100644
index 0000000..c0e983e
--- /dev/null
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRule.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.drill.optiq;
+
+import org.eigenbase.rel.*;
+import org.eigenbase.relopt.*;
+
+/**
+ * Rule that converts a {@link org.eigenbase.rel.ProjectRel} to a Drill
+ * "project" operation.
+ */
+public class DrillProjectRule extends RelOptRule {
+  public static final RelOptRule INSTANCE = new DrillProjectRule();
+
+  private DrillProjectRule() {
+    super(
+        new RelOptRuleOperand(
+            ProjectRel.class,
+            Convention.NONE,
+            new RelOptRuleOperand(RelNode.class, ANY)),
+        "DrillProjectRule");
+  }
+
+  @Override
+  public void onMatch(RelOptRuleCall call) {
+    final ProjectRel project = (ProjectRel) call.getRels()[0];
+    final RelNode input = call.getRels()[1];
+    final RelTraitSet traits = project.getTraitSet().plus(DrillRel.CONVENTION);
+    final RelNode convertedInput = convert(input, traits);
+    call.transformTo(
+        new DrillProjectRel(project.getCluster(), traits, convertedInput,
+            project.getProjectExps(), project.getRowType()));
+  }
+}
+
+// End DrillProjectRule.java

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
index 176a5dc..b6dae18 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
@@ -18,11 +18,16 @@
 package org.apache.drill.optiq;
 
 import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.Convention;
 
 /**
  * Relational expression that is implemented in Drill.
  */
 public interface DrillRel extends RelNode {
+  /** Calling convention for relational expressions that are "implemented" by
+   * generating Drill logical plans. */
+  Convention CONVENTION = new Convention.Impl("DRILL", DrillRel.class);
+
   void implement(DrillImplementor implementor);
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
index c18baaf..0285512 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
@@ -22,7 +22,7 @@ public class DrillScan extends TableAccessRelBase implements 
DrillRel {
       RelOptTable table)
   {
     super(cluster, traits, table);
-    assert traits.contains(DrillOptiq.CONVENTION);
+    assert getConvention() == CONVENTION;
     this.drillTable = table.unwrap(DrillTable.class);
     assert drillTable != null;
   }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
index 016a386..413861a 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
@@ -18,24 +18,8 @@
 package org.apache.drill.optiq;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CompletionService;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import java.util.*;
+import java.util.concurrent.*;
 
 import net.hydromatic.linq4j.AbstractEnumerable;
 import net.hydromatic.linq4j.Enumerable;
@@ -78,11 +62,43 @@ public class EnumerableDrill<E>
     config.setSinkQueues(0, queue);
   }
 
-  /** Creates a DrillEnumerable from a plan represented as a string. */
-  public static <E extends JsonNode> EnumerableDrill<E> of(String plan,
-      Class<E> clazz) {
+  /** Creates a DrillEnumerable from a plan represented as a string. Each 
record
+   * returned is a {@link JsonNode}. */
+  public static <E> EnumerableDrill<E> of(String plan, Class<E> clazz) {
     DrillConfig config = DrillConfig.create();
-    return new EnumerableDrill<E>(config, LogicalPlan.parse(config, plan), 
clazz);
+    final LogicalPlan parse = LogicalPlan.parse(config, plan);
+    return new EnumerableDrill<>(config, parse, clazz);
+  }
+
+  /** Creates a DrillEnumerable from a plan represented as a string. Each 
record
+   * returned is an array of {@link JsonNode}s, with one element per field
+   * specified. */
+  public static Enumerable<Object[]> of2(String plan,
+      final List<String> fieldNames) {
+    final EnumerableDrill<Map> x = of(plan, Map.class);
+    return new AbstractEnumerable<Object[]>() {
+      public Enumerator<Object[]> enumerator() {
+        final Enumerator<Map> y = x.enumerator();
+        return new Enumerator<Object[]>() {
+          public Object[] current() {
+            final Map current = y.current();
+            final Object[] objects = new Object[fieldNames.size()];
+            for (int i = 0; i < objects.length; i++) {
+              objects[i] = current.get(fieldNames.get(i));
+            }
+            return objects;
+          }
+
+          public boolean moveNext() {
+            return y.moveNext();
+          }
+
+          public void reset() {
+            y.reset();
+          }
+        };
+      }
+    };
   }
 
   /** Runs the plan as a background task. */

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
index b914619..46ffb07 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
@@ -17,25 +17,22 @@
  
******************************************************************************/
 package org.apache.drill.optiq;
 
-import net.hydromatic.linq4j.expressions.BlockBuilder;
-import net.hydromatic.linq4j.expressions.BlockExpression;
-import net.hydromatic.linq4j.expressions.Expressions;
+import net.hydromatic.linq4j.expressions.*;
+import net.hydromatic.linq4j.function.Function1;
+import net.hydromatic.linq4j.function.Functions;
 import net.hydromatic.optiq.impl.java.JavaTypeFactory;
 import net.hydromatic.optiq.rules.java.*;
 
 import org.apache.drill.common.util.Hook;
 import org.eigenbase.rel.RelNode;
 import org.eigenbase.rel.SingleRel;
-import org.eigenbase.relopt.RelOptCluster;
-import org.eigenbase.relopt.RelOptCost;
-import org.eigenbase.relopt.RelOptPlanner;
-import org.eigenbase.relopt.RelTraitSet;
+import org.eigenbase.relopt.*;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Method;
-import java.util.List;
+import java.util.*;
 
 
 /**
@@ -47,14 +44,37 @@ public class EnumerableDrillRel extends SingleRel 
implements EnumerableRel {
   private static final Logger LOG =
       LoggerFactory.getLogger(EnumerableDrillRel.class);
 
+  private static final Function1<String,Expression> TO_LITERAL =
+      new Function1<String, Expression>() {
+        @Override
+        public Expression apply(String a0) {
+          return Expressions.constant(a0);
+        }
+      };
+
+  private static final Method OF2_METHOD;
+  private static final Method OF_METHOD;
+
   private PhysType physType;
 
+  static {
+    try {
+      OF2_METHOD =
+          EnumerableDrill.class.getMethod("of2", String.class, List.class);
+      OF_METHOD =
+          EnumerableDrill.class.getMethod("of", String.class, Class.class);
+    } catch (NoSuchMethodException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
   public EnumerableDrillRel(RelOptCluster cluster,
       RelTraitSet traitSet,
       RelNode input)
   {
     super(cluster, traitSet, input);
     assert getConvention() instanceof EnumerableConvention;
+    assert input.getConvention() == DrillRel.CONVENTION;
     physType = PhysTypeImpl.of((JavaTypeFactory) cluster.getTypeFactory(),
         input.getRowType(),
         (EnumerableConvention) getConvention());
@@ -81,21 +101,29 @@ public class EnumerableDrillRel extends SingleRel 
implements EnumerableRel {
     DrillRel input = (DrillRel) getChild();
 
     drillImplementor.go(input);
-    final Method method;
-    try {
-      method =
-          EnumerableDrill.class.getMethod("of", String.class, Class.class);
-    } catch (NoSuchMethodException e) {
-      throw new RuntimeException(e);
-    }
     String plan = drillImplementor.getJsonString();
     Hook.LOGICAL_PLAN.run(plan);
+    if (false)
+    return new BlockBuilder()
+        .append(
+            Expressions.call(
+                OF2_METHOD,
+                Expressions.constant(plan),
+                Expressions.call(
+                    Arrays.class,
+                    "asList",
+                    Expressions.newArrayInit(
+                        String.class,
+                        Functions.apply(RelOptUtil.getFieldNameList(rowType),
+                            TO_LITERAL)))))
+        .toBlock();
+    else
     return new BlockBuilder()
         .append(
             Expressions.call(
-                method,
+                OF_METHOD,
                 Expressions.constant(plan),
-                Expressions.constant(Class.class)))
+                Expressions.constant(Object.class)))
         .toBlock();
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRule.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRule.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRule.java
index eb3c9da..fa1bd4f 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRule.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRule.java
@@ -20,7 +20,6 @@ package org.apache.drill.optiq;
 import net.hydromatic.optiq.rules.java.EnumerableConvention;
 import org.eigenbase.rel.RelNode;
 import org.eigenbase.rel.convert.ConverterRule;
-import org.eigenbase.relopt.volcano.AbstractConverter;
 
 /**
  * Rule that converts any Drill relational expression to enumerable format by
@@ -33,10 +32,10 @@ public class EnumerableDrillRule extends ConverterRule {
       new EnumerableDrillRule(EnumerableConvention.CUSTOM);
 
   private EnumerableDrillRule(EnumerableConvention outConvention) {
-    super(AbstractConverter.class,
-        DrillOptiq.CONVENTION,
+    super(RelNode.class,
+        DrillRel.CONVENTION,
         outConvention,
-        "Convert drill rels to Enumerable " + outConvention);
+        "EnumerableDrillRule." + outConvention);
   }
 
   @Override
@@ -46,10 +45,7 @@ public class EnumerableDrillRule extends ConverterRule {
 
   @Override
   public RelNode convert(RelNode rel) {
-    if (!rel.getTraitSet().contains(DrillOptiq.CONVENTION)) {
-      return null;
-    }
-
+    assert rel.getTraitSet().contains(DrillRel.CONVENTION);
     return new EnumerableDrillRel(rel.getCluster(),
         rel.getTraitSet().replace(getOutConvention()),
         rel);

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
 
b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
index 1479673..d755448 100644
--- 
a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
+++ 
b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
@@ -114,14 +114,14 @@ public class JdbcAssert {
     }
 
     public void plainContains(String expected) {
-      final String[] plan = {null};
+      final String[] plan0 = {null};
       Connection connection = null;
       Statement statement = null;
       Hook.Closeable x =
           Hook.LOGICAL_PLAN.add(
               new Function<String, Void>() {
                 public Void apply(String o) {
-                  plan[0] = o;
+                  plan0[0] = o;
                   return null;
                 }
               });
@@ -129,7 +129,8 @@ public class JdbcAssert {
         connection = connectionFactory.createConnection();
         statement = connection.prepareStatement(sql);
         statement.close();
-        Assert.assertTrue(plan[0].contains(expected));
+        final String plan = plan0[0];
+        Assert.assertTrue(plan, plan.contains(expected));
       } catch (Exception e) {
         throw new RuntimeException(e);
       }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/6095ca95/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
 
b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
index 958990a..4952212 100644
--- 
a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
+++ 
b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
@@ -134,6 +134,16 @@ public class JdbcTest extends TestCase {
             + "NAME=Apple Fritter; XX=null\n");
   }
 
+  public void testProjectFilterSubqueryPlan() throws Exception {
+    JdbcAssert.withModel(MODEL, "DONUTS")
+        .sql("select d['name'] as name, d['xx'] as xx from (\n"
+            + " select _MAP['donuts'] as d from donuts)\n"
+            + "where cast(d['ppu'] as double) > 0.6")
+        .plainContains("NAME=Raised; XX=null\n"
+            + "NAME=Filled; XX=null\n"
+            + "NAME=Apple Fritter; XX=null\n");
+  }
+
   /** Query that projects one field. (Disabled; uses sugared syntax.) */
   public void _testProjectNestedFieldSugared() throws Exception {
     JdbcAssert.withModel(MODEL, "DONUTS")

Reply via email to