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")
