http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRel.java
new file mode 100644
index 0000000..b4c1bf9
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRel.java
@@ -0,0 +1,108 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.BitSet;
+import java.util.List;
+
+import net.hydromatic.linq4j.Ord;
+import net.hydromatic.optiq.util.BitSets;
+
+import org.apache.drill.common.expression.ExpressionPosition;
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.expression.ValueExpressions;
+import org.apache.drill.common.logical.data.GroupingAggregate;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.exec.planner.torel.ConversionContext;
+import org.eigenbase.rel.AggregateCall;
+import org.eigenbase.rel.AggregateRelBase;
+import org.eigenbase.rel.InvalidRelException;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelTraitSet;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Aggregation implemented in Drill.
+ */
+public class DrillAggregateRel extends AggregateRelBase implements DrillRel {
+ /** Creates a DrillAggregateRel. */
+ public DrillAggregateRel(RelOptCluster cluster, RelTraitSet traits, RelNode child, BitSet groupSet,
+ List<AggregateCall> aggCalls) throws InvalidRelException {
+ super(cluster, traits, child, groupSet, aggCalls);
+ for (AggregateCall aggCall : aggCalls) {
+ if (aggCall.isDistinct()) {
+ throw new InvalidRelException("DrillAggregateRel does not support DISTINCT aggregates");
+ }
+ }
+ }
+
+ @Override
+ public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+ try {
+ return new DrillAggregateRel(getCluster(), traitSet, sole(inputs), getGroupSet(), aggCalls);
+ } catch (InvalidRelException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public LogicalOperator implement(DrillImplementor implementor) {
+
+ GroupingAggregate.Builder builder = GroupingAggregate.builder();
+ builder.setInput(implementor.visitChild(this, 0, getChild()));
+ final List<String> childFields = getChild().getRowType().getFieldNames();
+ final List<String> fields = getRowType().getFieldNames();
+
+ for (int group : BitSets.toIter(groupSet)) {
+ FieldReference fr = new FieldReference(childFields.get(group), ExpressionPosition.UNKNOWN);
+ builder.addKey(fr, fr);
+ }
+
+ for (Ord<AggregateCall> aggCall : Ord.zip(aggCalls)) {
+ FieldReference ref = new FieldReference(fields.get(groupSet.cardinality() + aggCall.i));
+ LogicalExpression expr = toDrill(aggCall.e, childFields, implementor);
+ builder.addExpr(ref, expr);
+ }
+
+ return builder.build();
+ }
+
+
+
+
+ private LogicalExpression toDrill(AggregateCall call, List<String> fn, DrillImplementor implementor) {
+ List<LogicalExpression> args = Lists.newArrayList();
+ for(Integer i : call.getArgList()){
+ args.add(new FieldReference(fn.get(i)));
+ }
+
+ // for count(1).
+ if(args.isEmpty()) args.add(new ValueExpressions.LongExpression(1l));
+ LogicalExpression expr = implementor.getContext().getRegistry().createExpression(call.getAggregation().getName().toLowerCase(), ExpressionPosition.UNKNOWN, args);
+ return expr;
+ }
+
+ public static DrillAggregateRel convert(GroupingAggregate groupBy, ConversionContext value)
+ throws InvalidRelException {
+ throw new UnsupportedOperationException();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRule.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRule.java
new file mode 100644
index 0000000..77f1ba6
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRule.java
@@ -0,0 +1,53 @@
+/**
+ * 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.exec.planner.logical;
+
+import org.eigenbase.rel.AggregateRel;
+import org.eigenbase.rel.InvalidRelException;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.*;
+import org.eigenbase.trace.EigenbaseTrace;
+
+import java.util.logging.Logger;
+
+/**
+ * Rule that converts an {@link AggregateRel} to a {@link DrillAggregateRel}, implemented by a Drill "segment" operation
+ * followed by a "collapseaggregate" operation.
+ */
+public class DrillAggregateRule extends RelOptRule {
+ public static final RelOptRule INSTANCE = new DrillAggregateRule();
+ protected static final Logger tracer = EigenbaseTrace.getPlannerTracer();
+
+ private DrillAggregateRule() {
+ super(RelOptHelper.some(AggregateRel.class, Convention.NONE, RelOptHelper.any(RelNode.class)), "DrillAggregateRule");
+ }
+
+ @Override
+ public void onMatch(RelOptRuleCall call) {
+ final AggregateRel aggregate = (AggregateRel) call.rel(0);
+ final RelNode input = call.rel(1);
+ final RelTraitSet traits = aggregate.getTraitSet().plus(DrillRel.CONVENTION);
+ final RelNode convertedInput = convert(input, traits);
+ try {
+ call.transformTo(new DrillAggregateRel(aggregate.getCluster(), traits, convertedInput, aggregate.getGroupSet(),
+ aggregate.getAggCallList()));
+ } catch (InvalidRelException e) {
+ tracer.warning(e.toString());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRel.java
new file mode 100644
index 0000000..cc147e3
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/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.exec.planner.logical;
+
+import java.util.List;
+
+import org.apache.drill.common.logical.data.Filter;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.exec.planner.torel.ConversionContext;
+import org.eigenbase.rel.FilterRelBase;
+import org.eigenbase.rel.InvalidRelException;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelOptCost;
+import org.eigenbase.relopt.RelOptPlanner;
+import org.eigenbase.relopt.RelTraitSet;
+import org.eigenbase.rex.RexNode;
+
+/**
+ * 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 LogicalOperator implement(DrillImplementor implementor) {
+ final LogicalOperator input = implementor.visitChild(this, 0, getChild());
+ Filter f = new Filter(DrillOptiq.toDrill(implementor.getContext(), getChild(), getCondition()));
+ f.setInput(input);
+ return f;
+ }
+
+ public static DrillFilterRel convert(Filter filter, ConversionContext context) throws InvalidRelException{
+ RelNode input = context.toRel(filter.getInput());
+ return new DrillFilterRel(context.getCluster(), context.getLogicalTraits(), input, context.toRex(filter.getExpr()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRule.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRule.java
new file mode 100644
index 0000000..d4fb239
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRule.java
@@ -0,0 +1,42 @@
+/**
+ * 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.exec.planner.logical;
+
+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(RelOptHelper.some(FilterRel.class, Convention.NONE, RelOptHelper.any(RelNode.class)), "DrillFilterRule");
+ }
+
+ @Override
+ public void onMatch(RelOptRuleCall call) {
+ final FilterRel filter = (FilterRel) call.rel(0);
+ final RelNode input = call.rel(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()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillImplementor.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillImplementor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillImplementor.java
new file mode 100644
index 0000000..acd218c
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillImplementor.java
@@ -0,0 +1,88 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.Set;
+
+import org.apache.drill.common.logical.LogicalPlan;
+import org.apache.drill.common.logical.LogicalPlanBuilder;
+import org.apache.drill.common.logical.PlanProperties.Generator.ResultMode;
+import org.apache.drill.common.logical.PlanProperties.PlanType;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.visitors.AbstractLogicalVisitor;
+import org.eigenbase.rel.RelNode;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Context for converting a tree of {@link DrillRel} nodes into a Drill logical plan.
+ */
+public class DrillImplementor {
+
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillImplementor.class);
+
+ private Set<DrillTable> tables = Sets.newHashSet();
+ private LogicalPlanBuilder planBuilder = new LogicalPlanBuilder();
+ private LogicalPlan plan;
+ private final DrillParseContext context;
+
+
+ public DrillImplementor(DrillParseContext context, ResultMode mode) {
+ planBuilder.planProperties(PlanType.APACHE_DRILL_LOGICAL, 1, DrillImplementor.class.getName(), "", mode);
+ this.context = context;
+ }
+
+ public DrillParseContext getContext(){
+ return context;
+ }
+
+ public void registerSource(DrillTable table){
+ if(tables.add(table)){
+ planBuilder.addStorageEngine(table.getStorageEngineName(), table.getStorageEngineConfig());
+ }
+ }
+
+ public void go(DrillRel root) {
+ LogicalOperator rootLOP = root.implement(this);
+ rootLOP.accept(new AddOpsVisitor(), null);
+ }
+
+ public LogicalPlan getPlan(){
+ if(plan == null){
+ plan = planBuilder.build();
+ planBuilder = null;
+ }
+ return plan;
+ }
+
+ public LogicalOperator visitChild(DrillRel parent, int ordinal, RelNode child) {
+ return ((DrillRel) child).implement(this);
+ }
+
+ private class AddOpsVisitor extends AbstractLogicalVisitor<Void, Void, RuntimeException> {
+ @Override
+ public Void visitOp(LogicalOperator op, Void value) throws RuntimeException {
+ planBuilder.addLogicalOperator(op);
+ for(LogicalOperator o : op){
+ o.accept(this, null);
+ }
+ return null;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRel.java
new file mode 100644
index 0000000..c08712e
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRel.java
@@ -0,0 +1,165 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.logical.data.Join;
+import org.apache.drill.common.logical.data.JoinCondition;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.Project;
+import org.apache.drill.exec.planner.torel.ConversionContext;
+import org.eigenbase.rel.InvalidRelException;
+import org.eigenbase.rel.JoinRelBase;
+import org.eigenbase.rel.JoinRelType;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelOptUtil;
+import org.eigenbase.relopt.RelTraitSet;
+import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.reltype.RelDataTypeField;
+import org.eigenbase.rex.RexNode;
+import org.eigenbase.rex.RexUtil;
+import org.eigenbase.sql.fun.SqlStdOperatorTable;
+import org.eigenbase.util.Pair;
+
+/**
+ * Join implemented in Drill.
+ */
+public class DrillJoinRel extends JoinRelBase implements DrillRel {
+ private final List<Integer> leftKeys = new ArrayList<>();
+ private final List<Integer> rightKeys = new ArrayList<>();
+
+ /** Creates a DrillJoinRel. */
+ public DrillJoinRel(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right, RexNode condition,
+ JoinRelType joinType) throws InvalidRelException {
+ super(cluster, traits, left, right, condition, joinType, Collections.<String> emptySet());
+
+ RexNode remaining = RelOptUtil.splitJoinCondition(left, right, condition, leftKeys, rightKeys);
+ if (!remaining.isAlwaysTrue()) {
+ throw new InvalidRelException("DrillJoinRel only supports equi-join");
+ }
+ }
+
+ @Override
+ public DrillJoinRel copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType) {
+ try {
+ return new DrillJoinRel(getCluster(), traitSet, left, right, condition, joinType);
+ } catch (InvalidRelException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public LogicalOperator implement(DrillImplementor implementor) {
+ final List<String> fields = getRowType().getFieldNames();
+ assert isUnique(fields);
+ final int leftCount = left.getRowType().getFieldCount();
+ final List<String> leftFields = fields.subList(0, leftCount);
+ final List<String> rightFields = fields.subList(leftCount, fields.size());
+
+ final LogicalOperator leftOp = implementInput(implementor, 0, 0, left);
+ final LogicalOperator rightOp = implementInput(implementor, 1, leftCount, right);
+
+ Join.Builder builder = Join.builder();
+ builder.type(joinType);
+ builder.left(leftOp);
+ builder.right(rightOp);
+
+ for (Pair<Integer, Integer> pair : Pair.zip(leftKeys, rightKeys)) {
+ builder.addCondition("==", new FieldReference(leftFields.get(pair.left)), new FieldReference(rightFields.get(pair.right)));
+ }
+ return builder.build();
+ }
+
+ /**
+ * Check to make sure that the fields of the inputs are the same as the output field names. If not, insert a project renaming them.
+ * @param implementor
+ * @param i
+ * @param offset
+ * @param input
+ * @return
+ */
+ private LogicalOperator implementInput(DrillImplementor implementor, int i, int offset, RelNode input) {
+ final LogicalOperator inputOp = implementor.visitChild(this, i, input);
+ assert uniqueFieldNames(input.getRowType());
+ final List<String> fields = getRowType().getFieldNames();
+ final List<String> inputFields = input.getRowType().getFieldNames();
+ final List<String> outputFields = fields.subList(offset, offset + inputFields.size());
+ if (!outputFields.equals(inputFields)) {
+ // Ensure that input field names are the same as output field names.
+ // If there are duplicate field names on left and right, fields will get
+ // lost.
+ return rename(implementor, inputOp, inputFields, outputFields);
+ } else {
+ return inputOp;
+ }
+ }
+
+ private LogicalOperator rename(DrillImplementor implementor, LogicalOperator inputOp, List<String> inputFields, List<String> outputFields) {
+ Project.Builder builder = Project.builder();
+ builder.setInput(inputOp);
+ for (Pair<String, String> pair : Pair.zip(inputFields, outputFields)) {
+ builder.addExpr(new FieldReference(pair.right), new FieldReference(pair.left));
+ }
+ return builder.build();
+ }
+
+ public static DrillJoinRel convert(Join join, ConversionContext context) throws InvalidRelException{
+ RelNode left = context.toRel(join.getLeft());
+ RelNode right = context.toRel(join.getRight());
+
+ List<RexNode> joinConditions = new ArrayList<RexNode>();
+ // right fields appear after the LHS fields.
+ final int rightInputOffset = left.getRowType().getFieldCount();
+ for (JoinCondition condition : join.getConditions()) {
+ RelDataTypeField leftField = left.getRowType().getField(ExprHelper.getFieldName(condition.getLeft()), true);
+ RelDataTypeField rightField = right.getRowType().getField(ExprHelper.getFieldName(condition.getRight()), true);
+ joinConditions.add(
+ context.getRexBuilder().makeCall(
+ SqlStdOperatorTable.EQUALS,
+ context.getRexBuilder().makeInputRef(leftField.getType(), leftField.getIndex()),
+ context.getRexBuilder().makeInputRef(rightField.getType(), rightInputOffset + rightField.getIndex())
+ )
+ );
+ }
+ RexNode rexCondition = RexUtil.composeConjunction(context.getRexBuilder(), joinConditions, false);
+ return new DrillJoinRel(context.getCluster(), context.getLogicalTraits(), left, right, rexCondition, join.getJoinType());
+ }
+
+
+ /**
+ * Returns whether there are any elements in common between left and right.
+ */
+ private static <T> boolean intersects(List<T> left, List<T> right) {
+ return new HashSet<>(left).removeAll(right);
+ }
+
+ private boolean uniqueFieldNames(RelDataType rowType) {
+ return isUnique(rowType.getFieldNames());
+ }
+
+ private static <T> boolean isUnique(List<T> list) {
+ return new HashSet<>(list).size() == list.size();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRule.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRule.java
new file mode 100644
index 0000000..f32fa59
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRule.java
@@ -0,0 +1,57 @@
+/**
+ * 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.exec.planner.logical;
+
+import org.eigenbase.rel.InvalidRelException;
+import org.eigenbase.rel.JoinRel;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.*;
+import org.eigenbase.trace.EigenbaseTrace;
+
+import java.util.logging.Logger;
+
+/**
+ * Rule that converts a {@link JoinRel} to a {@link DrillJoinRel}, which is implemented by Drill "join" operation.
+ */
+public class DrillJoinRule extends RelOptRule {
+ public static final RelOptRule INSTANCE = new DrillJoinRule();
+ protected static final Logger tracer = EigenbaseTrace.getPlannerTracer();
+
+ private DrillJoinRule() {
+ super(
+ RelOptHelper.some(JoinRel.class, Convention.NONE, RelOptHelper.any(RelNode.class), RelOptHelper.any(RelNode.class)),
+ "DrillJoinRule");
+ }
+
+ @Override
+ public void onMatch(RelOptRuleCall call) {
+ final JoinRel join = (JoinRel) call.rel(0);
+ final RelNode left = call.rel(1);
+ final RelNode right = call.rel(2);
+ final RelTraitSet traits = join.getTraitSet().plus(DrillRel.CONVENTION);
+
+ final RelNode convertedLeft = convert(left, traits);
+ final RelNode convertedRight = convert(right, traits);
+ try {
+ call.transformTo(new DrillJoinRel(join.getCluster(), traits, convertedLeft, convertedRight, join.getCondition(),
+ join.getJoinType()));
+ } catch (InvalidRelException e) {
+ tracer.warning(e.toString());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillLimitRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillLimitRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillLimitRel.java
new file mode 100644
index 0000000..54be052
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillLimitRel.java
@@ -0,0 +1,73 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.apache.drill.common.logical.data.Limit;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.exec.planner.torel.ConversionContext;
+import org.eigenbase.rel.InvalidRelException;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.rel.SingleRel;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelTraitSet;
+import org.eigenbase.rex.RexLiteral;
+import org.eigenbase.rex.RexNode;
+import org.eigenbase.sql.type.SqlTypeName;
+
+public class DrillLimitRel extends SingleRel implements DrillRel {
+ private RexNode offset;
+ private RexNode fetch;
+
+ public DrillLimitRel(RelOptCluster cluster, RelTraitSet traitSet, RelNode child, RexNode offset, RexNode fetch) {
+ super(cluster, traitSet, child);
+ this.offset = offset;
+ this.fetch = fetch;
+ }
+
+ @Override
+ public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+ return new DrillLimitRel(getCluster(), traitSet, sole(inputs), offset, fetch);
+ }
+
+ @Override
+ public LogicalOperator implement(DrillImplementor implementor) {
+ LogicalOperator inputOp = implementor.visitChild(this, 0, getChild());
+
+ // First offset to include into results (inclusive). Null implies it is starting from offset 0
+ int first = offset != null ? Math.max(0, RexLiteral.intValue(offset)) : 0;
+
+ // Last offset to stop including into results (exclusive), translating fetch row counts into an offset.
+ // Null value implies including entire remaining result set from first offset
+ Integer last = fetch != null ? Math.max(0, RexLiteral.intValue(fetch)) + first : null;
+ Limit limit = new Limit(first, last);
+ limit.setInput(inputOp);
+ return limit;
+ }
+
+ public static DrillLimitRel convert(Limit limit, ConversionContext context) throws InvalidRelException{
+ RelNode input = context.toRel(limit.getInput());
+ RexNode first = context.getRexBuilder().makeExactLiteral(BigDecimal.valueOf(limit.getFirst()), context.getTypeFactory().createSqlType(SqlTypeName.INTEGER));
+ RexNode last = context.getRexBuilder().makeExactLiteral(BigDecimal.valueOf(limit.getLast()), context.getTypeFactory().createSqlType(SqlTypeName.INTEGER));
+ return new DrillLimitRel(context.getCluster(), context.getLogicalTraits(), input, first, last);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillLimitRule.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillLimitRule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillLimitRule.java
new file mode 100644
index 0000000..85c594e
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillLimitRule.java
@@ -0,0 +1,59 @@
+/**
+ * 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.exec.planner.logical;
+
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.rel.SortRel;
+import org.eigenbase.relopt.Convention;
+import org.eigenbase.relopt.RelOptRule;
+import org.eigenbase.relopt.RelOptRuleCall;
+import org.eigenbase.relopt.RelTraitSet;
+
+/**
+ * This rule converts a SortRel that has either a offset and fetch into a Drill Sort and Limit Rel
+ */
+public class DrillLimitRule extends RelOptRule {
+ public static DrillLimitRule INSTANCE = new DrillLimitRule();
+
+ private DrillLimitRule() {
+ super(RelOptHelper.some(SortRel.class, Convention.NONE, RelOptHelper.any(RelNode.class)), "DrillLimitRule");
+ }
+
+ @Override
+ public boolean matches(RelOptRuleCall call) {
+ final SortRel sort = call.rel(0);
+ return sort.offset != null || sort.fetch != null;
+ }
+
+ @Override
+ public void onMatch(RelOptRuleCall call) {
+ final SortRel incomingSort = call.rel(0);
+ final RelTraitSet incomingTraits = incomingSort.getTraitSet();
+ RelNode input = incomingSort.getChild();
+
+ // if the Optiq sort rel includes a collation and a limit, we need to create a copy the sort rel that excludes the
+ // limit information.
+ if (!incomingSort.getCollation().getFieldCollations().isEmpty()) {
+ input = incomingSort.copy(incomingTraits, input, incomingSort.getCollation(), null, null);
+ }
+
+ RelNode convertedInput = convert(input, input.getTraitSet().plus(DrillRel.CONVENTION));
+ call.transformTo(new DrillLimitRel(incomingSort.getCluster(), incomingTraits.plus(DrillRel.CONVENTION), convertedInput, incomingSort.offset, incomingSort.fetch));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
new file mode 100644
index 0000000..2e29bd4
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
@@ -0,0 +1,200 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.expression.SchemaPath;
+import org.apache.drill.common.expression.ValueExpressions;
+import org.apache.drill.common.expression.ValueExpressions.LongExpression;
+import org.apache.drill.exec.record.NullExpression;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.RelOptPlanner;
+import org.eigenbase.reltype.RelDataTypeField;
+import org.eigenbase.rex.RexCall;
+import org.eigenbase.rex.RexCorrelVariable;
+import org.eigenbase.rex.RexDynamicParam;
+import org.eigenbase.rex.RexFieldAccess;
+import org.eigenbase.rex.RexInputRef;
+import org.eigenbase.rex.RexLiteral;
+import org.eigenbase.rex.RexLocalRef;
+import org.eigenbase.rex.RexNode;
+import org.eigenbase.rex.RexOver;
+import org.eigenbase.rex.RexRangeRef;
+import org.eigenbase.rex.RexVisitorImpl;
+import org.eigenbase.sql.SqlSyntax;
+import org.eigenbase.sql.fun.SqlStdOperatorTable;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Utilities for Drill's planner.
+ */
+public class DrillOptiq {
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillOptiq.class);
+
+ /**
+ * Converts a tree of {@link RexNode} operators into a scalar expression in Drill syntax.
+ */
+ static LogicalExpression toDrill(DrillParseContext context, RelNode input, RexNode expr) {
+ final RexToDrill visitor = new RexToDrill(context, input);
+ return expr.accept(visitor);
+ }
+
+ private static class RexToDrill extends RexVisitorImpl<LogicalExpression> {
+ private final RelNode input;
+ private final DrillParseContext context;
+
+ RexToDrill(DrillParseContext context, RelNode input) {
+ super(true);
+ this.context = context;
+ this.input = input;
+ }
+
+ @Override
+ public LogicalExpression visitInputRef(RexInputRef inputRef) {
+ final int index = inputRef.getIndex();
+ final RelDataTypeField field = input.getRowType().getFieldList().get(index);
+ return new FieldReference(field.getName());
+ }
+
+ @Override
+ public LogicalExpression visitCall(RexCall call) {
+ logger.debug("RexCall {}, {}", call);
+ final SqlSyntax syntax = call.getOperator().getSyntax();
+ switch (syntax) {
+ case BINARY:
+ logger.debug("Binary");
+ LogicalExpression op1 = call.getOperands().get(0).accept(this);
+ LogicalExpression op2 = call.getOperands().get(1).accept(this);
+ return context.getRegistry().createExpression(call.getOperator().getName(), Lists.newArrayList(op1, op2));
+ case FUNCTION:
+ logger.debug("Function");
+ List<LogicalExpression> exprs = Lists.newArrayList();
+ for(RexNode n : call.getOperands()){
+ exprs.add(n.accept(this));
+ }
+ return context.getRegistry().createExpression(call.getOperator().getName().toLowerCase(), Lists.newArrayList(exprs));
+ case SPECIAL:
+ logger.debug("Special");
+ switch(call.getKind()){
+
+ case CAST:
+ return getDrillCastFunctionFromOptiq(call);
+ }
+
+ if (call.getOperator() == SqlStdOperatorTable.ITEM) {
+ SchemaPath left = (SchemaPath) call.getOperands().get(0).accept(this);
+ final RexLiteral literal = (RexLiteral) call.getOperands().get(1);
+ return left.getChild((String) literal.getValue2());
+ }
+
+ // fall through
+ default:
+ throw new AssertionError("todo: implement syntax " + syntax + "(" + call + ")");
+ }
+ }
+
+ private LogicalExpression doUnknown(Object o){
+ logger.warn("Doesn't currently support consumption of {}.", o);
+ return NullExpression.INSTANCE;
+ }
+ @Override
+ public LogicalExpression visitLocalRef(RexLocalRef localRef) {
+ return doUnknown(localRef);
+ }
+
+ @Override
+ public LogicalExpression visitOver(RexOver over) {
+ return doUnknown(over);
+ }
+
+ @Override
+ public LogicalExpression visitCorrelVariable(RexCorrelVariable correlVariable) {
+ return doUnknown(correlVariable);
+ }
+
+ @Override
+ public LogicalExpression visitDynamicParam(RexDynamicParam dynamicParam) {
+ return doUnknown(dynamicParam);
+ }
+
+ @Override
+ public LogicalExpression visitRangeRef(RexRangeRef rangeRef) {
+ return doUnknown(rangeRef);
+ }
+
+ @Override
+ public LogicalExpression visitFieldAccess(RexFieldAccess fieldAccess) {
+ return super.visitFieldAccess(fieldAccess);
+ }
+
+
+ private LogicalExpression getDrillCastFunctionFromOptiq(RexCall call){
+ LogicalExpression arg = call.getOperands().get(0).accept(this);
+ List<LogicalExpression> args = Collections.singletonList(arg);
+ String fname = null;
+ switch(call.getType().getSqlTypeName().getName()){
+ case "VARCHAR": {
+ args = Lists.newArrayList(arg, new LongExpression(call.getType().getPrecision()));
+ return context.getRegistry().createExpression("castVARCHAR", args);
+ }
+ case "INTEGER": fname = "castINT"; break;
+ case "FLOAT": fname = "castFLOAT4"; break;
+ case "DOUBLE": fname = "castFLOAT8"; break;
+ case "DECIMAL": throw new UnsupportedOperationException("Need to add decimal.");
+ default: fname = "cast" + call.getType().getSqlTypeName().getName();
+ }
+ return context.getRegistry().createExpression(fname, args);
+
+ }
+
+
+
+ @Override
+ public LogicalExpression visitLiteral(RexLiteral literal) {
+ switch(literal.getTypeName()){
+ case BIGINT:
+ long l = ((BigDecimal) literal.getValue()).longValue();
+ return ValueExpressions.getBigInt(l);
+ case BOOLEAN:
+ return ValueExpressions.getBit(((Boolean) literal.getValue()));
+ case CHAR:
+ return ValueExpressions.getChar(((String) literal.getValue()));
+ case DOUBLE:
+ double d = ((BigDecimal) literal.getValue()).doubleValue();
+ return ValueExpressions.getFloat8(d);
+ case FLOAT:
+ float f = ((BigDecimal) literal.getValue()).floatValue();
+ return ValueExpressions.getFloat4(f);
+ case INTEGER:
+ case DECIMAL:
+ int i = ((BigDecimal) literal.getValue()).intValue();
+ return ValueExpressions.getInt(i);
+ case VARCHAR:
+ return ValueExpressions.getChar(((String) literal.getValue()));
+ default:
+ throw new UnsupportedOperationException(String.format("Unable to convert the value of %s and type %s to a Drill constant expression.", literal, literal.getTypeName()));
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillParseContext.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillParseContext.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillParseContext.java
new file mode 100644
index 0000000..b82fef5
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillParseContext.java
@@ -0,0 +1,36 @@
+/**
+ * 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.exec.planner.logical;
+
+import org.apache.drill.common.expression.FunctionRegistry;
+
+public class DrillParseContext {
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillParseContext.class);
+
+ private final FunctionRegistry registry;
+
+ public DrillParseContext(FunctionRegistry registry) {
+ super();
+ this.registry = registry;
+ }
+
+ public FunctionRegistry getRegistry(){
+ return registry;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRel.java
new file mode 100644
index 0000000..ee3a0f4
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRel.java
@@ -0,0 +1,98 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.NamedExpression;
+import org.apache.drill.common.logical.data.Project;
+import org.apache.drill.exec.planner.torel.ConversionContext;
+import org.eigenbase.rel.InvalidRelException;
+import org.eigenbase.rel.ProjectRelBase;
+import org.eigenbase.rel.RelCollation;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelOptCost;
+import org.eigenbase.relopt.RelOptPlanner;
+import org.eigenbase.relopt.RelTraitSet;
+import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.reltype.RelDataTypeField;
+import org.eigenbase.reltype.RelDataTypeFieldImpl;
+import org.eigenbase.reltype.RelRecordType;
+import org.eigenbase.rex.RexNode;
+import org.eigenbase.sql.type.SqlTypeName;
+import org.eigenbase.util.Pair;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Lists;
+
+/**
+ * Project implemented in Drill.
+ */
+public class DrillProjectRel extends ProjectRelBase implements DrillRel {
+ protected DrillProjectRel(RelOptCluster cluster, RelTraitSet traits, RelNode child, List<RexNode> exps,
+ RelDataType rowType) {
+ super(cluster, traits, child, exps, rowType, Flags.BOXED);
+ assert getConvention() == CONVENTION;
+ }
+
+
+ @Override
+ public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+ return new DrillProjectRel(getCluster(), traitSet, sole(inputs), new ArrayList<RexNode>(exps), rowType);
+ }
+
+ @Override
+ public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ return super.computeSelfCost(planner).multiplyBy(0.1);
+ }
+
+ private List<Pair<RexNode, String>> projects() {
+ return Pair.zip(exps, getRowType().getFieldNames());
+ }
+
+ @Override
+ public LogicalOperator implement(DrillImplementor implementor) {
+ LogicalOperator inputOp = implementor.visitChild(this, 0, getChild());
+ Project.Builder builder = Project.builder();
+ builder.setInput(inputOp);
+ for (Pair<RexNode, String> pair : projects()) {
+ LogicalExpression expr = DrillOptiq.toDrill(implementor.getContext(), getChild(), pair.left);
+ builder.addExpr(new FieldReference("output." + pair.right), expr);
+ }
+ return builder.build();
+ }
+
+ public static DrillProjectRel convert(Project project, ConversionContext context) throws InvalidRelException{
+ RelNode input = context.toRel(project.getInput());
+ List<RelDataTypeField> fields = Lists.newArrayList();
+ List<RexNode> exps = Lists.newArrayList();
+ for(NamedExpression expr : project.getSelections()){
+ fields.add(new RelDataTypeFieldImpl(expr.getRef().getPath().toString(), fields.size(), context.getTypeFactory().createSqlType(SqlTypeName.ANY) ));
+ exps.add(context.toRex(expr.getExpr()));
+ }
+ return new DrillProjectRel(context.getCluster(), context.getLogicalTraits(), input, exps, new RelRecordType(fields));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRule.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRule.java
new file mode 100644
index 0000000..bf5bcff
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRule.java
@@ -0,0 +1,46 @@
+/**
+ * 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.exec.planner.logical;
+
+import org.eigenbase.rel.ProjectRel;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.Convention;
+import org.eigenbase.relopt.RelOptRule;
+import org.eigenbase.relopt.RelOptRuleCall;
+import org.eigenbase.relopt.RelTraitSet;
+
+/**
+ * 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(RelOptHelper.some(ProjectRel.class, Convention.NONE, RelOptHelper.any(RelNode.class)), "DrillProjectRule");
+ }
+
+ @Override
+ public void onMatch(RelOptRuleCall call) {
+ final ProjectRel project = (ProjectRel) call.rel(0);
+ final RelNode input = call.rel(1);
+ final RelTraitSet traits = project.getTraitSet().plus(DrillRel.CONVENTION);
+ final RelNode convertedInput = convert(input, traits);
+ call.transformTo(new DrillProjectRel(project.getCluster(), traits, convertedInput, project.getProjects(), project
+ .getRowType()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRel.java
new file mode 100644
index 0000000..63a7207
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRel.java
@@ -0,0 +1,33 @@
+/**
+ * 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.exec.planner.logical;
+
+import org.apache.drill.common.logical.data.LogicalOperator;
+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);
+
+ LogicalOperator implement(DrillImplementor implementor);
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRuleSets.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRuleSets.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRuleSets.java
new file mode 100644
index 0000000..53da67f
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRuleSets.java
@@ -0,0 +1,92 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.Iterator;
+
+import net.hydromatic.optiq.tools.RuleSet;
+
+import org.eigenbase.rel.rules.MergeProjectRule;
+import org.eigenbase.rel.rules.PushFilterPastJoinRule;
+import org.eigenbase.rel.rules.PushFilterPastProjectRule;
+import org.eigenbase.rel.rules.PushJoinThroughJoinRule;
+import org.eigenbase.rel.rules.PushSortPastProjectRule;
+import org.eigenbase.rel.rules.ReduceAggregatesRule;
+import org.eigenbase.rel.rules.RemoveDistinctAggregateRule;
+import org.eigenbase.rel.rules.RemoveDistinctRule;
+import org.eigenbase.rel.rules.RemoveSortRule;
+import org.eigenbase.rel.rules.RemoveTrivialCalcRule;
+import org.eigenbase.rel.rules.RemoveTrivialProjectRule;
+import org.eigenbase.rel.rules.SwapJoinRule;
+import org.eigenbase.rel.rules.TableAccessRule;
+import org.eigenbase.rel.rules.UnionToDistinctRule;
+import org.eigenbase.relopt.RelOptRule;
+import org.eigenbase.relopt.volcano.AbstractConverter.ExpandConversionRule;
+
+import com.google.common.collect.ImmutableSet;
+
+public class DrillRuleSets {
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillRuleSets.class);
+
+ public static final RuleSet DRILL_BASIC_RULES = new DrillRuleSet(ImmutableSet.of( //
+
+// ExpandConversionRule.instance,
+// SwapJoinRule.instance,
+// RemoveDistinctRule.instance,
+// UnionToDistinctRule.instance,
+// RemoveTrivialProjectRule.instance,
+// RemoveTrivialCalcRule.instance,
+// RemoveSortRule.INSTANCE,
+//
+// TableAccessRule.instance, //
+// MergeProjectRule.instance, //
+// PushFilterPastProjectRule.instance, //
+// PushFilterPastJoinRule.FILTER_ON_JOIN, //
+// RemoveDistinctAggregateRule.instance, //
+// ReduceAggregatesRule.instance, //
+// SwapJoinRule.instance, //
+// PushJoinThroughJoinRule.RIGHT, //
+// PushJoinThroughJoinRule.LEFT, //
+// PushSortPastProjectRule.INSTANCE, //
+
+ DrillScanRule.INSTANCE,
+ DrillFilterRule.INSTANCE,
+ DrillProjectRule.INSTANCE,
+ DrillAggregateRule.INSTANCE,
+
+ DrillLimitRule.INSTANCE,
+ DrillSortRule.INSTANCE,
+ DrillJoinRule.INSTANCE,
+ DrillUnionRule.INSTANCE
+ ));
+
+
+ private static class DrillRuleSet implements RuleSet{
+ final ImmutableSet<RelOptRule> rules;
+
+ public DrillRuleSet(ImmutableSet<RelOptRule> rules) {
+ super();
+ this.rules = rules;
+ }
+
+ @Override
+ public Iterator<RelOptRule> iterator() {
+ return rules.iterator();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScanRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScanRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScanRel.java
new file mode 100644
index 0000000..afc2d1b
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScanRel.java
@@ -0,0 +1,62 @@
+/**
+ * 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.exec.planner.logical;
+
+import org.apache.drill.common.JSONOptions;
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.Scan;
+import org.apache.drill.exec.planner.torel.ConversionContext;
+import org.eigenbase.rel.TableAccessRelBase;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelOptTable;
+import org.eigenbase.relopt.RelTraitSet;
+
+/**
+ * GroupScan of a Drill table.
+ */
+public class DrillScanRel extends TableAccessRelBase implements DrillRel {
+ private final DrillTable drillTable;
+
+ /** Creates a DrillScan. */
+ public DrillScanRel(RelOptCluster cluster, RelTraitSet traits, RelOptTable table) {
+ super(cluster, traits, table);
+ assert getConvention() == CONVENTION;
+ this.drillTable = table.unwrap(DrillTable.class);
+ assert drillTable != null;
+ }
+
+// @Override
+// public void register(RelOptPlanner planner) {
+// super.register(planner);
+// DrillOptiq.registerStandardPlannerRules(planner);
+// }
+
+ public LogicalOperator implement(DrillImplementor implementor) {
+ Scan.Builder builder = Scan.builder();
+ builder.storageEngine(drillTable.getStorageEngineName());
+ builder.selection(new JSONOptions(drillTable.getSelection()));
+ //builder.outputReference(new FieldReference("_MAP"));
+ implementor.registerSource(drillTable);
+ return builder.build();
+ }
+
+ public static DrillScanRel convert(Scan scan, ConversionContext context){
+ return new DrillScanRel(context.getCluster(), context.getLogicalTraits(), context.getTable(scan));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScanRule.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScanRule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScanRule.java
new file mode 100644
index 0000000..58e648a
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScanRule.java
@@ -0,0 +1,43 @@
+/**
+ * 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.exec.planner.logical;
+
+import net.hydromatic.optiq.rules.java.JavaRules.EnumerableTableAccessRel;
+
+import org.eigenbase.relopt.Convention;
+import org.eigenbase.relopt.RelOptRule;
+import org.eigenbase.relopt.RelOptRuleCall;
+import org.eigenbase.relopt.RelTraitSet;
+
+public class DrillScanRule extends RelOptRule {
+ public static final RelOptRule INSTANCE = new DrillScanRule();
+
+ private DrillScanRule() {
+ super(RelOptHelper.any(EnumerableTableAccessRel.class), "DrillTableRule");
+ }
+
+
+
+
+ @Override
+ public void onMatch(RelOptRuleCall call) {
+ final EnumerableTableAccessRel access = (EnumerableTableAccessRel) call.rel(0);
+ final RelTraitSet traits = access.getTraitSet().plus(DrillRel.CONVENTION);
+ call.transformTo(new DrillScanRel(access.getCluster(), traits, access.getTable()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScreenRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScreenRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScreenRel.java
new file mode 100644
index 0000000..829947a
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillScreenRel.java
@@ -0,0 +1,76 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.List;
+
+import net.hydromatic.optiq.impl.java.JavaTypeFactory;
+import net.hydromatic.optiq.rules.java.EnumerableConvention;
+import net.hydromatic.optiq.rules.java.EnumerableRel;
+import net.hydromatic.optiq.rules.java.EnumerableRelImplementor;
+import net.hydromatic.optiq.rules.java.JavaRowFormat;
+import net.hydromatic.optiq.rules.java.PhysType;
+import net.hydromatic.optiq.rules.java.PhysTypeImpl;
+
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.Store;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Relational expression that converts from Drill to Enumerable. At runtime it executes a Drill query and returns the
+ * results as an {@link net.hydromatic.linq4j.Enumerable}.
+ */
+public class DrillScreenRel extends SingleRel implements DrillRel {
+ private static final Logger logger = LoggerFactory.getLogger(DrillScreenRel.class);
+
+ private PhysType physType;
+
+ public DrillScreenRel(RelOptCluster cluster, RelTraitSet traitSet, RelNode input) {
+ super(cluster, traitSet, input);
+ assert input.getConvention() == DrillRel.CONVENTION;
+ physType = PhysTypeImpl.of((JavaTypeFactory) cluster.getTypeFactory(), input.getRowType(), JavaRowFormat.ARRAY);
+ }
+
+ public PhysType getPhysType() {
+ return physType;
+ }
+
+ @Override
+ public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ return super.computeSelfCost(planner).multiplyBy(.1);
+ }
+
+ @Override
+ public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+ return new DrillScreenRel(getCluster(), traitSet, sole(inputs));
+ }
+
+ @Override
+ public LogicalOperator implement(DrillImplementor implementor) {
+ LogicalOperator childOp = implementor.visitChild(this, 0, getChild());
+ return Store.builder().setInput(childOp).storageEngine("--SCREEN--").build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillSortRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillSortRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillSortRel.java
new file mode 100644
index 0000000..04af9d5
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillSortRel.java
@@ -0,0 +1,100 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.Order;
+import org.apache.drill.common.logical.data.Order.Ordering;
+import org.apache.drill.exec.planner.torel.ConversionContext;
+import org.eigenbase.rel.InvalidRelException;
+import org.eigenbase.rel.RelCollation;
+import org.eigenbase.rel.RelCollationImpl;
+import org.eigenbase.rel.RelFieldCollation;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.rel.SortRel;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelTraitSet;
+import org.eigenbase.rex.RexNode;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Sort implemented in Drill.
+ */
+public class DrillSortRel extends SortRel implements DrillRel {
+
+ /** Creates a DrillSortRel. */
+ public DrillSortRel(RelOptCluster cluster, RelTraitSet traits, RelNode input, RelCollation collation) {
+ super(cluster, traits, input, collation);
+ }
+
+ /** Creates a DrillSortRel with offset and fetch. */
+ public DrillSortRel(RelOptCluster cluster, RelTraitSet traits, RelNode input, RelCollation collation, RexNode offset, RexNode fetch) {
+ super(cluster, traits, input, collation, offset, fetch);
+ }
+
+ @Override
+ public DrillSortRel copy(RelTraitSet traitSet, RelNode input, RelCollation collation, RexNode offset, RexNode fetch) {
+ return new DrillSortRel(getCluster(), traitSet, input, collation, offset, fetch);
+ }
+
+ @Override
+ public LogicalOperator implement(DrillImplementor implementor) {
+ final Order.Builder builder = Order.builder();
+ builder.setInput(implementor.visitChild(this, 0, getChild()));
+
+ final List<String> childFields = getChild().getRowType().getFieldNames();
+ for(RelFieldCollation fieldCollation : this.collation.getFieldCollations()){
+ builder.addOrdering(fieldCollation.getDirection(),
+ new FieldReference(childFields.get(fieldCollation.getFieldIndex())),
+ fieldCollation.nullDirection);
+ }
+ return builder.build();
+ }
+
+
+ public static RelNode convert(Order order, ConversionContext context) throws InvalidRelException{
+
+ // if there are compound expressions in the order by, we need to convert into projects on either side.
+ RelNode input = context.toRel(order.getInput());
+ List<String> fields = input.getRowType().getFieldNames();
+
+ // build a map of field names to indices.
+ Map<String, Integer> fieldMap = Maps.newHashMap();
+ int i =0;
+ for(String field : fields){
+ fieldMap.put(field, i);
+ i++;
+ }
+
+ List<RelFieldCollation> collations = Lists.newArrayList();
+
+ for(Ordering o : order.getOrderings()){
+ String fieldName = ExprHelper.getFieldName(o.getExpr());
+ int fieldId = fieldMap.get(fieldName);
+ RelFieldCollation c = new RelFieldCollation(fieldId, o.getDirection(), o.getNullDirection());
+ }
+ return new DrillSortRel(context.getCluster(), context.getLogicalTraits(), input, RelCollationImpl.of(collations));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillSortRule.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillSortRule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillSortRule.java
new file mode 100644
index 0000000..c968e85
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillSortRule.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.exec.planner.logical;
+
+import org.eigenbase.rel.SortRel;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.*;
+
+/**
+ * Rule that converts an {@link SortRel} to a {@link DrillSortRel}, implemented by a Drill "order" operation.
+ */
+public class DrillSortRule extends RelOptRule {
+ public static final RelOptRule INSTANCE = new DrillSortRule();
+
+ private DrillSortRule() {
+ super(RelOptHelper.some(SortRel.class, Convention.NONE, RelOptHelper.any(RelNode.class)), "DrillSortRule");
+ }
+
+ @Override
+ public boolean matches(RelOptRuleCall call) {
+ final SortRel sort = call.rel(0);
+ return sort.offset == null && sort.fetch == null;
+ }
+
+ @Override
+ public void onMatch(RelOptRuleCall call) {
+
+ final SortRel sort = call.rel(0);
+
+ final RelNode input = call.rel(1);
+ final RelTraitSet traits = sort.getTraitSet().plus(DrillRel.CONVENTION);
+
+ final RelNode convertedInput = convert(input, input.getTraitSet().plus(DrillRel.CONVENTION));
+ call.transformTo(new DrillSortRel(sort.getCluster(), traits, convertedInput, sort.getCollation()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillStoreRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillStoreRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillStoreRel.java
new file mode 100644
index 0000000..30c7810
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillStoreRel.java
@@ -0,0 +1,45 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.List;
+
+import net.hydromatic.optiq.prepare.Prepare.CatalogReader;
+
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.rel.TableModificationRelBase;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelOptTable;
+import org.eigenbase.relopt.RelTraitSet;
+
+public class DrillStoreRel extends TableModificationRelBase implements DrillRel{
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillStoreRel.class);
+
+ protected DrillStoreRel(RelOptCluster cluster, RelTraitSet traits, RelOptTable table, CatalogReader catalogReader,
+ RelNode child, Operation operation, List<String> updateColumnList, boolean flattened) {
+ super(cluster, traits, table, catalogReader, child, operation, updateColumnList, flattened);
+
+ }
+
+ @Override
+ public LogicalOperator implement(DrillImplementor implementor) {
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillTable.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillTable.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillTable.java
new file mode 100644
index 0000000..30dd48d
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillTable.java
@@ -0,0 +1,107 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.Collections;
+
+import net.hydromatic.optiq.Schema.TableType;
+import net.hydromatic.optiq.Statistic;
+import net.hydromatic.optiq.Statistics;
+import net.hydromatic.optiq.Table;
+
+import org.apache.drill.common.logical.StorageEngineConfig;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.RelOptTable;
+import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.reltype.RelDataTypeFactory;
+import org.eigenbase.sql.type.SqlTypeName;
+
+/** Optiq Table used by Drill. */
+public class DrillTable implements Table{
+
+ private final String name;
+ private final String storageEngineName;
+ public final StorageEngineConfig storageEngineConfig;
+ private Object selection;
+
+
+ /** Creates a DrillTable. */
+ public DrillTable(String name, String storageEngineName, Object selection, StorageEngineConfig storageEngineConfig) {
+ this.name = name;
+ this.selection = selection;
+ this.storageEngineConfig = storageEngineConfig;
+ this.storageEngineName = storageEngineName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public StorageEngineConfig getStorageEngineConfig(){
+ return storageEngineConfig;
+ }
+
+ public Object getSelection() {
+ return selection;
+ }
+
+ public String getStorageEngineName() {
+ return storageEngineName;
+ }
+
+ @Override
+ public Statistic getStatistic() {
+ return Statistics.UNKNOWN;
+ }
+
+ public RelNode toRel(RelOptTable.ToRelContext context, RelOptTable table) {
+ return new DrillScanRel(context.getCluster(),
+ context.getCluster().traitSetOf(DrillRel.CONVENTION),
+ table);
+ }
+
+ @Override
+ public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+ return new RelDataTypeDrillImpl(typeFactory);
+ }
+
+ @Override
+ public TableType getJdbcTableType() {
+ return null;
+ }
+
+
+
+// /** Factory for custom tables in Optiq schema. */
+// @SuppressWarnings("UnusedDeclaration")
+// public static class Factory implements TableFactory<DrillTable> {
+//
+// @Override
+// public DrillTable create(Schema schema, String name, Map<String, Object> operand, RelDataType rowType) {
+//
+// final ClasspathRSE.ClasspathRSEConfig rseConfig = new ClasspathRSE.ClasspathRSEConfig();
+// final ClasspathInputConfig inputConfig = new ClasspathInputConfig();
+// inputConfig.path = "/" + name.toLowerCase() + ".json";
+// inputConfig.type = DataWriter.ConverterType.JSON;
+// return createTable(schema.getTypeFactory(), (MutableSchema) schema, name, "donuts-json", rseConfig, inputConfig);
+// }
+// }
+
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillUnionRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillUnionRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillUnionRel.java
new file mode 100644
index 0000000..1be9caf
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillUnionRel.java
@@ -0,0 +1,71 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.List;
+
+import net.hydromatic.linq4j.Ord;
+
+import org.apache.drill.common.logical.data.Limit;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.Union;
+import org.apache.drill.exec.planner.torel.ConversionContext;
+import org.eigenbase.rel.InvalidRelException;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.rel.UnionRelBase;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelOptCost;
+import org.eigenbase.relopt.RelOptPlanner;
+import org.eigenbase.relopt.RelTraitSet;
+
+/**
+ * Union implemented in Drill.
+ */
+public class DrillUnionRel extends UnionRelBase implements DrillRel {
+ /** Creates a DrillUnionRel. */
+ public DrillUnionRel(RelOptCluster cluster, RelTraitSet traits,
+ List<RelNode> inputs, boolean all) {
+ super(cluster, traits, inputs, all);
+ }
+
+ @Override
+ public DrillUnionRel copy(RelTraitSet traitSet, List<RelNode> inputs,
+ boolean all) {
+ return new DrillUnionRel(getCluster(), traitSet, inputs, all);
+ }
+
+ @Override
+ public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ // divide cost by two to ensure cheaper than EnumerableDrillRel
+ return super.computeSelfCost(planner).multiplyBy(.5);
+ }
+
+ @Override
+ public LogicalOperator implement(DrillImplementor implementor) {
+ Union.Builder builder = Union.builder();
+ for (Ord<RelNode> input : Ord.zip(inputs)) {
+ builder.addInput(implementor.visitChild(this, input.i, input.e));
+ }
+ builder.setDistinct(!all);
+ return builder.build();
+ }
+
+ public static DrillUnionRel convert(Union union, ConversionContext context) throws InvalidRelException{
+ throw new UnsupportedOperationException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillUnionRule.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillUnionRule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillUnionRule.java
new file mode 100644
index 0000000..bc1e6f4
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillUnionRule.java
@@ -0,0 +1,48 @@
+/**
+ * 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.exec.planner.logical;
+
+import org.eigenbase.rel.UnionRel;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Rule that converts a {@link UnionRel} to a {@link DrillUnionRel}, implemented by a "union" operation.
+ */
+public class DrillUnionRule extends RelOptRule {
+ public static final RelOptRule INSTANCE = new DrillUnionRule();
+
+ private DrillUnionRule() {
+ super(RelOptHelper.any(UnionRel.class, Convention.NONE), "DrillUnionRule");
+ }
+
+ @Override
+ public void onMatch(RelOptRuleCall call) {
+ final UnionRel union = (UnionRel) call.rel(0);
+ final RelTraitSet traits = union.getTraitSet().plus(DrillRel.CONVENTION);
+ final List<RelNode> convertedInputs = new ArrayList<>();
+ for (RelNode input : union.getInputs()) {
+ final RelNode convertedInput = convert(input, traits);
+ convertedInputs.add(convertedInput);
+ }
+ call.transformTo(new DrillUnionRel(union.getCluster(), traits, convertedInputs, union.all));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b3460af8/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillValuesRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillValuesRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillValuesRel.java
new file mode 100644
index 0000000..e770181
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillValuesRel.java
@@ -0,0 +1,57 @@
+/**
+ * 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.exec.planner.logical;
+
+import java.util.List;
+
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.rel.ValuesRelBase;
+import org.eigenbase.relopt.RelOptCluster;
+import org.eigenbase.relopt.RelOptCost;
+import org.eigenbase.relopt.RelOptPlanner;
+import org.eigenbase.relopt.RelTraitSet;
+import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.rex.RexLiteral;
+
+/**
+ * Values implemented in Drill.
+ */
+public class DrillValuesRel extends ValuesRelBase implements DrillRel {
+ protected DrillValuesRel(RelOptCluster cluster, RelDataType rowType, List<List<RexLiteral>> tuples, RelTraitSet traits) {
+ super(cluster, rowType, tuples, traits);
+ assert getConvention() == CONVENTION;
+ }
+
+ @Override
+ public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+ assert inputs.isEmpty();
+ return new DrillValuesRel(getCluster(), rowType, tuples, traitSet);
+ }
+
+ @Override
+ public RelOptCost computeSelfCost(RelOptPlanner planner) {
+ return super.computeSelfCost(planner).multiplyBy(0.1);
+ }
+
+ @Override
+ public LogicalOperator implement(DrillImplementor implementor) {
+ // Update when https://issues.apache.org/jira/browse/DRILL-57 fixed
+ throw new UnsupportedOperationException();
+ }
+}
|