drill-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jacq...@apache.org
Subject [33/45] drill git commit: DRILL-3987: (MOVE) Move logical expressions and operators out of common. Move to new drill-logical model.
Date Fri, 13 Nov 2015 02:38:03 GMT
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/expression/visitors/ExpressionValidator.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/ExpressionValidator.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/ExpressionValidator.java
new file mode 100644
index 0000000..eb1394c
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/ExpressionValidator.java
@@ -0,0 +1,234 @@
+/**
+ * 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.common.expression.visitors;
+
+import org.apache.drill.common.expression.BooleanOperator;
+import org.apache.drill.common.expression.CastExpression;
+import org.apache.drill.common.expression.ConvertExpression;
+import org.apache.drill.common.expression.ErrorCollector;
+import org.apache.drill.common.expression.FunctionCall;
+import org.apache.drill.common.expression.FunctionHolderExpression;
+import org.apache.drill.common.expression.IfExpression;
+import org.apache.drill.common.expression.IfExpression.IfCondition;
+import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.expression.NullExpression;
+import org.apache.drill.common.expression.SchemaPath;
+import org.apache.drill.common.expression.TypedNullConstant;
+import org.apache.drill.common.expression.ValueExpressions;
+import org.apache.drill.common.expression.ValueExpressions.BooleanExpression;
+import org.apache.drill.common.expression.ValueExpressions.DateExpression;
+import org.apache.drill.common.expression.ValueExpressions.Decimal18Expression;
+import org.apache.drill.common.expression.ValueExpressions.Decimal28Expression;
+import org.apache.drill.common.expression.ValueExpressions.Decimal38Expression;
+import org.apache.drill.common.expression.ValueExpressions.Decimal9Expression;
+import org.apache.drill.common.expression.ValueExpressions.DoubleExpression;
+import org.apache.drill.common.expression.ValueExpressions.IntervalDayExpression;
+import org.apache.drill.common.expression.ValueExpressions.IntervalYearExpression;
+import org.apache.drill.common.expression.ValueExpressions.LongExpression;
+import org.apache.drill.common.expression.ValueExpressions.QuotedString;
+import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
+import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.types.TypeProtos.DataMode;
+import org.apache.drill.common.types.TypeProtos.MajorType;
+import org.apache.drill.common.types.TypeProtos.MinorType;
+
+public class ExpressionValidator implements ExprVisitor<Void, ErrorCollector, RuntimeException> {
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ExpressionValidator.class);
+
+  @Override
+  public Void visitFunctionCall(FunctionCall call, ErrorCollector errors) throws RuntimeException {
+    // we throw an exception here because this is a fundamental operator programming problem as opposed to an expression
+    // problem. At this point in an expression's lifecycle, all function calls should have been converted into
+    // FunctionHolders.
+    throw new UnsupportedOperationException("FunctionCall is not expected here. "
+        + "It should have been converted to FunctionHolderExpression in materialization");
+  }
+
+  @Override
+  public Void visitFunctionHolderExpression(FunctionHolderExpression holder, ErrorCollector errors)
+      throws RuntimeException {
+    // make sure aggregate functions are not nested inside aggregate functions
+    AggregateChecker.isAggregating(holder, errors);
+
+    // make sure arguments are constant if the function implementation expects constants for any arguments
+    ConstantChecker.checkConstants(holder, errors);
+
+    return null;
+  }
+
+  @Override
+  public Void visitBooleanOperator(BooleanOperator op, ErrorCollector errors) throws RuntimeException {
+    int i = 0;
+    for (LogicalExpression arg : op.args) {
+      if ( arg.getMajorType().getMinorType() != MinorType.BIT) {
+        errors
+            .addGeneralError(
+                arg.getPosition(),
+                String
+                    .format(
+                        "Failure composing boolean operator %s.  All conditions must return a boolean type.  Condition %d was of Type %s.",
+                        op.getName(), i, arg.getMajorType().getMinorType()));
+      }
+      i++;
+    }
+
+    return null;
+  }
+
+  @Override
+  public Void visitIfExpression(IfExpression ifExpr, ErrorCollector errors) throws RuntimeException {
+    // confirm that all conditions are required boolean values.
+    IfCondition cond = ifExpr.ifCondition;
+    MajorType majorType = cond.condition.getMajorType();
+    if ( majorType
+        .getMinorType() != MinorType.BIT) {
+      errors
+          .addGeneralError(
+              cond.condition.getPosition(),
+              String
+                  .format(
+                      "Failure composing If Expression.  All conditions must return a boolean type.  Condition was of Type %s.",
+                      majorType.getMinorType()));
+    }
+
+    // confirm that all outcomes are the same type.
+    final MajorType mt = ifExpr.elseExpression.getMajorType();
+    cond = ifExpr.ifCondition;
+    MajorType innerT = cond.expression.getMajorType();
+    if ((innerT.getMode() == DataMode.REPEATED && mt.getMode() != DataMode.REPEATED) || //
+        ((innerT.getMinorType() != mt.getMinorType()) &&
+        (innerT.getMode() != DataMode.OPTIONAL && mt.getMode() != DataMode.OPTIONAL &&
+        (innerT.getMinorType() != MinorType.NULL && mt.getMinorType() != MinorType.NULL)))) {
+      errors
+          .addGeneralError(
+              cond.condition.getPosition(),
+              String
+                  .format(
+                      "Failure composing If Expression.  All expressions must return the same MinorType as the else expression.  The if condition returned type type %s but the else expression was of type %s",
+                      innerT, mt));
+    }
+    return null;
+  }
+
+  @Override
+  public Void visitSchemaPath(SchemaPath path, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitIntConstant(ValueExpressions.IntExpression intExpr, ErrorCollector value) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitFloatConstant(ValueExpressions.FloatExpression fExpr, ErrorCollector value) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitLongConstant(LongExpression intExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitDecimal9Constant(Decimal9Expression decExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitDecimal18Constant(Decimal18Expression decExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitDecimal28Constant(Decimal28Expression decExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitDecimal38Constant(Decimal38Expression decExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitDateConstant(DateExpression intExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitTimeConstant(TimeExpression intExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitIntervalYearConstant(IntervalYearExpression intExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitIntervalDayConstant(IntervalDayExpression intExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitTimeStampConstant(TimeStampExpression intExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitDoubleConstant(DoubleExpression dExpr, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitBooleanConstant(BooleanExpression e, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitQuotedStringConstant(QuotedString e, ErrorCollector errors) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitUnknown(LogicalExpression e, ErrorCollector value) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitCastExpression(CastExpression e, ErrorCollector value) throws RuntimeException {
+    return e.getInput().accept(this, value);
+  }
+
+  @Override
+  public Void visitNullConstant(TypedNullConstant e, ErrorCollector value) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitNullExpression(NullExpression e, ErrorCollector value) throws RuntimeException {
+    return null;
+  }
+
+  @Override
+  public Void visitConvertExpression(ConvertExpression e, ErrorCollector value)
+      throws RuntimeException {
+    return e.getInput().accept(this, value);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/expression/visitors/OpVisitor.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/OpVisitor.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/OpVisitor.java
new file mode 100644
index 0000000..b3c7879
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/OpVisitor.java
@@ -0,0 +1,24 @@
+/**
+ * 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.common.expression.visitors;
+
+import org.apache.drill.common.graph.GraphVisitor;
+import org.apache.drill.common.logical.data.LogicalOperator;
+
+public interface OpVisitor extends GraphVisitor<LogicalOperator> {
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/expression/visitors/SimpleExprVisitor.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/SimpleExprVisitor.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/SimpleExprVisitor.java
new file mode 100644
index 0000000..5f83e93
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/SimpleExprVisitor.java
@@ -0,0 +1,158 @@
+/**
+ * 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.common.expression.visitors;
+
+import org.apache.drill.common.expression.FunctionCall;
+import org.apache.drill.common.expression.FunctionHolderExpression;
+import org.apache.drill.common.expression.IfExpression;
+import org.apache.drill.common.expression.SchemaPath;
+import org.apache.drill.common.expression.ValueExpressions.BooleanExpression;
+import org.apache.drill.common.expression.ValueExpressions.DateExpression;
+import org.apache.drill.common.expression.ValueExpressions.Decimal18Expression;
+import org.apache.drill.common.expression.ValueExpressions.Decimal28Expression;
+import org.apache.drill.common.expression.ValueExpressions.Decimal38Expression;
+import org.apache.drill.common.expression.ValueExpressions.Decimal9Expression;
+import org.apache.drill.common.expression.ValueExpressions.DoubleExpression;
+import org.apache.drill.common.expression.ValueExpressions.FloatExpression;
+import org.apache.drill.common.expression.ValueExpressions.IntExpression;
+import org.apache.drill.common.expression.ValueExpressions.IntervalDayExpression;
+import org.apache.drill.common.expression.ValueExpressions.IntervalYearExpression;
+import org.apache.drill.common.expression.ValueExpressions.LongExpression;
+import org.apache.drill.common.expression.ValueExpressions.QuotedString;
+import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
+import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+
+public abstract class SimpleExprVisitor<T> implements ExprVisitor<T, Void, RuntimeException>{
+
+  @Override
+  public T visitFunctionCall(FunctionCall call, Void value) throws RuntimeException {
+    return visitFunctionCall(call);
+  }
+
+  @Override
+  public T visitFunctionHolderExpression(FunctionHolderExpression holder, Void value) throws RuntimeException {
+    return visitFunctionHolderExpression(holder);
+  }
+
+  @Override
+  public T visitIfExpression(IfExpression ifExpr, Void value) throws RuntimeException {
+    return visitIfExpression(ifExpr);
+  }
+
+  @Override
+  public T visitSchemaPath(SchemaPath path, Void value) throws RuntimeException {
+    return visitSchemaPath(path);
+  }
+
+  @Override
+  public T visitIntConstant(IntExpression intExpr, Void value) throws RuntimeException {
+    return visitIntConstant(intExpr);
+  }
+
+  @Override
+  public T visitFloatConstant(FloatExpression fExpr, Void value) throws RuntimeException {
+    return visitFloatConstant(fExpr);
+  }
+
+  @Override
+  public T visitLongConstant(LongExpression intExpr, Void value) throws RuntimeException {
+    return visitLongConstant(intExpr);
+  }
+
+  @Override
+  public T visitDateConstant(DateExpression intExpr, Void value) throws RuntimeException {
+    return visitDateConstant(intExpr);
+  }
+
+
+  @Override
+  public T visitTimeConstant(TimeExpression intExpr, Void value) throws RuntimeException {
+    return visitTimeConstant(intExpr);
+  }
+
+  @Override
+  public T visitIntervalYearConstant(IntervalYearExpression intExpr, Void value) throws RuntimeException {
+    return visitIntervalYearConstant(intExpr);
+  }
+
+  @Override
+  public T visitIntervalDayConstant(IntervalDayExpression intExpr, Void value) throws RuntimeException {
+    return visitIntervalDayConstant(intExpr);
+  }
+
+  @Override
+  public T visitTimeStampConstant(TimeStampExpression intExpr, Void value) throws RuntimeException {
+    return visitTimeStampConstant(intExpr);
+  }
+
+  @Override
+  public T visitDecimal9Constant(Decimal9Expression decExpr, Void value) throws RuntimeException {
+    return visitDecimal9Constant(decExpr);
+  }
+
+  @Override
+  public T visitDecimal18Constant(Decimal18Expression decExpr, Void value) throws RuntimeException {
+    return visitDecimal18Constant(decExpr);
+  }
+
+  @Override
+  public T visitDecimal28Constant(Decimal28Expression decExpr, Void value) throws RuntimeException {
+    return visitDecimal28Constant(decExpr);
+  }
+
+  @Override
+  public T visitDecimal38Constant(Decimal38Expression decExpr, Void value) throws RuntimeException {
+    return visitDecimal38Constant(decExpr);
+  }
+
+  @Override
+  public T visitDoubleConstant(DoubleExpression dExpr, Void value) throws RuntimeException {
+    return visitDoubleConstant(dExpr);
+  }
+
+  @Override
+  public T visitBooleanConstant(BooleanExpression e, Void value) throws RuntimeException {
+    return visitBooleanConstant(e);
+  }
+
+  @Override
+  public T visitQuotedStringConstant(QuotedString e, Void value) throws RuntimeException {
+    return visitQuotedStringConstant(e);
+  }
+
+
+  public abstract T visitFunctionCall(FunctionCall call);
+  public abstract T visitFunctionHolderExpression(FunctionHolderExpression call);
+  public abstract T visitIfExpression(IfExpression ifExpr);
+  public abstract T visitSchemaPath(SchemaPath path);
+  public abstract T visitIntConstant(IntExpression intExpr);
+  public abstract T visitFloatConstant(FloatExpression fExpr);
+  public abstract T visitLongConstant(LongExpression intExpr);
+  public abstract T visitDateConstant(DateExpression intExpr);
+  public abstract T visitTimeConstant(TimeExpression intExpr);
+  public abstract T visitIntervalYearConstant(IntervalYearExpression intExpr);
+  public abstract T visitIntervalDayConstant(IntervalDayExpression intExpr);
+  public abstract T visitTimeStampConstant(TimeStampExpression intExpr);
+  public abstract T visitDecimal9Constant(Decimal9Expression intExpr);
+  public abstract T visitDecimal18Constant(Decimal18Expression intExpr);
+  public abstract T visitDecimal28Constant(Decimal28Expression intExpr);
+  public abstract T visitDecimal38Constant(Decimal38Expression intExpr);
+  public abstract T visitDoubleConstant(DoubleExpression dExpr);
+  public abstract T visitBooleanConstant(BooleanExpression e);
+  public abstract T visitQuotedStringConstant(QuotedString e);
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/expression/visitors/package-info.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/package-info.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/package-info.java
new file mode 100644
index 0000000..b57362e
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/package-info.java
@@ -0,0 +1,24 @@
+/**
+ * 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.
+ */
+/**
+ * Visitors for validating or optimizing logical expressions.
+ *
+ * These visitors are used to provide feedback to users on invalid expressions
+ * as well as some basic optimizations applied during planning.
+ */
+package org.apache.drill.common.expression.visitors;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/graph/AdjacencyList.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/graph/AdjacencyList.java b/logical/src/main/java/org/apache/drill/common/graph/AdjacencyList.java
new file mode 100644
index 0000000..a4edfc1
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/graph/AdjacencyList.java
@@ -0,0 +1,190 @@
+/**
+ * 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.common.graph;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Multimaps;
+
+class AdjacencyList<V extends GraphValue<V>> {
+  private Set<Node> allNodes = new HashSet<Node>();
+  private ListMultimap<Node, Edge<Node>> adjacencies = ArrayListMultimap.create();
+
+  void addEdge(Node source, Node target, int weight) {
+    adjacencies.put(source, new Edge<Node>(source, target, weight));
+    allNodes.add(source);
+    allNodes.add(target);
+  }
+
+  void clearVisited() {
+    for (Edge<Node> e : adjacencies.values()) {
+      e.from.visited = false;
+      e.to.visited = false;
+    }
+  }
+
+  Node getNewNode(V value) {
+    return new Node(value);
+  }
+
+  public List<Edge<Node>> getAdjacent(AdjacencyList<V>.Node source) {
+    return adjacencies.get(source);
+  }
+
+  public void printEdges() {
+    for (Edge<Node> e : adjacencies.values()) {
+      System.out.println(e.from.index + " -> " + e.to.index);
+    }
+  }
+
+  public AdjacencyList<V> getReversedList() {
+    AdjacencyList<V> newlist = new AdjacencyList<V>();
+    for (Edge<Node> e : adjacencies.values()) {
+      newlist.addEdge(e.to, e.from, e.weight);
+    }
+    return newlist;
+  }
+
+  public Set<Node> getNodeSet() {
+    return adjacencies.keySet();
+  }
+
+
+  Collection<Node> getInternalLeafNodes() {
+    // we have to use the allNodes list as otherwise destination only nodes won't be found.
+    List<Node> nodes = new LinkedList<Node>(allNodes);
+
+    for (Iterator<Node> i = nodes.iterator(); i.hasNext();) {
+      final Node n = i.next();
+
+      // remove any nodes that have one or more outbound edges.
+      List<Edge<Node>> adjList = this.getAdjacent(n);
+      if (adjList != null && !adjList.isEmpty()) {
+        i.remove();
+      }
+
+    }
+    return nodes;
+  }
+
+  /**
+   * Get a list of nodes that have no outbound edges.
+   *
+   * @return
+   */
+  public Collection<V> getLeafNodes() {
+    return convert(getInternalLeafNodes());
+  }
+
+
+  Collection<Node> getInternalRootNodes() {
+    Set<Node> nodes = new HashSet<Node>(getNodeSet());
+    for (Edge<Node> e : adjacencies.values()) {
+      nodes.remove(e.to);
+    }
+    return nodes;
+  }
+
+  /**
+   * Get a list of all nodes that have no incoming edges.
+   *
+   * @return
+   */
+  public List<V> getRootNodes() {
+    return convert(getInternalRootNodes());
+  }
+
+  public Collection<Edge<Node>> getAllEdges() {
+    return adjacencies.values();
+  }
+
+  public void fix(boolean requireDirected) {
+    adjacencies = Multimaps.unmodifiableListMultimap(adjacencies);
+    allNodes = Collections.unmodifiableSet(allNodes);
+
+    if (requireDirected) {
+      List<List<Node>> cyclicReferences = GraphAlgos.checkDirected(this);
+      if (cyclicReferences.size() > 0) {
+        throw new IllegalArgumentException(
+            "A logical plan must be a valid DAG.  You have cyclic references in your graph.  " + cyclicReferences);
+      }
+    }
+  }
+
+  List<V> convert(Collection<Node> nodes) {
+    List<V> out = new ArrayList<V>(nodes.size());
+    for (Node o : nodes) {
+      out.add(o.getNodeValue());
+    }
+    return out;
+  }
+
+  class Node implements Comparable<Node> {
+    final V nodeValue;
+    boolean visited = false; // used for Kosaraju's algorithm and Edmonds's
+                             // algorithm
+    int lowlink = -1; // used for Tarjan's algorithm
+    int index = -1; // used for Tarjan's algorithm
+
+    public Node(final V operator) {
+      if (operator == null) {
+        throw new IllegalArgumentException("Operator node was null.");
+      }
+      this.nodeValue = operator;
+    }
+
+    public int compareTo(final Node argNode) {
+      // just do an identity compare since elsewhere you should ensure that only one node exists for each nodeValue.
+      return argNode == this ? 0 : -1;
+    }
+
+    @Override
+    public int hashCode() {
+      return nodeValue.hashCode();
+    }
+
+    public V getNodeValue() {
+      return nodeValue;
+    }
+
+    @Override
+    public String toString() {
+      return "Node [val=" + nodeValue + "]";
+    }
+
+  }
+
+  public static <V extends GraphValue<V>> AdjacencyList<V> newInstance(Collection<V> nodes) {
+    AdjacencyList<V> list = new AdjacencyList<V>();
+    AdjacencyListBuilder<V> builder = new AdjacencyListBuilder<V>(list);
+    for (V v : nodes) {
+      v.accept(builder);
+    }
+    return builder.getAdjacencyList();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/graph/AdjacencyListBuilder.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/graph/AdjacencyListBuilder.java b/logical/src/main/java/org/apache/drill/common/graph/AdjacencyListBuilder.java
new file mode 100644
index 0000000..e90d70a
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/graph/AdjacencyListBuilder.java
@@ -0,0 +1,75 @@
+/**
+ * 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.common.graph;
+
+import java.util.HashMap;
+import java.util.Map;
+
+ class AdjacencyListBuilder<V extends GraphValue<V>> implements GraphVisitor<V> {
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AdjacencyListBuilder.class);
+
+  private Map<V, AdjacencyList<V>.Node> ops = new HashMap<V, AdjacencyList<V>.Node>();
+  private final AdjacencyList<V> parent;
+
+  public AdjacencyListBuilder(AdjacencyList<V> parent) {
+    this.parent = parent;
+  }
+
+  protected boolean requireDirected() {
+    return true;
+  }
+
+  public boolean enter(V o) {
+    visit(o);
+    return true;
+  }
+
+  @Override
+  public void leave(V o) {
+  }
+
+  @Override
+  public boolean visit(V o) {
+    if (o == null) {
+      throw new IllegalArgumentException("Null operator.");
+    }
+
+    if (!ops.containsKey(o)) {
+      ops.put(o, parent.getNewNode(o));
+      return true;
+    }
+
+    return true;
+  }
+
+  public AdjacencyList<V> getAdjacencyList() {
+//    logger.debug("Values; {}", ops.values().toArray());
+    AdjacencyList<V> a = new AdjacencyList<V>();
+
+    for (AdjacencyList<V>.Node from : ops.values()) {
+      for (V t : from.getNodeValue()) {
+        AdjacencyList<V>.Node to = ops.get(t);
+        a.addEdge(from, to, 0);
+      }
+
+    }
+    a.fix(true);
+    return a;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/graph/Edge.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/graph/Edge.java b/logical/src/main/java/org/apache/drill/common/graph/Edge.java
new file mode 100644
index 0000000..7b9ca61
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/graph/Edge.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.common.graph;
+
+
+class Edge<N> implements Comparable<Edge<N>> {
+
+  final N from, to;
+  final int weight;
+
+  public Edge(final N argFrom, final N argTo, final int argWeight) {
+    from = argFrom;
+    to = argTo;
+    weight = argWeight;
+  }
+
+  public int compareTo(final Edge<N> argEdge) {
+    return weight - argEdge.weight;
+  }
+
+  @Override
+  public String toString() {
+    return "Edge [from=" + from + ", to=" + to + "]";
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/graph/Graph.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/graph/Graph.java b/logical/src/main/java/org/apache/drill/common/graph/Graph.java
new file mode 100644
index 0000000..3cf4e7a
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/graph/Graph.java
@@ -0,0 +1,68 @@
+/**
+ * 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.common.graph;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.drill.common.logical.UnexpectedOperatorType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class Graph<G extends GraphValue<G>, R extends G, T extends G> {
+
+  static final Logger logger = LoggerFactory.getLogger(Graph.class);
+
+  private AdjacencyList<G> adjList;
+  private final List<R> roots;
+  private final List<T> leaves;
+
+  public Graph(List<G> operators, Class<R> root, Class<T> leaf) {
+    adjList = AdjacencyList.newInstance(operators);
+    roots = checkOperatorType(adjList.getRootNodes(), root, String.format("Root nodes must be a subclass of %s.", root.getSimpleName()));
+    leaves = checkOperatorType(adjList.getLeafNodes(), leaf, String.format("Leaf nodes must be a subclass of %s.", leaf.getSimpleName()));
+  }
+
+  @SuppressWarnings("unchecked")
+  private <O extends G> List<O> checkOperatorType(Collection<G> ops, Class<O> classIdentifier, String error){
+    for(G o : ops){
+      if(!classIdentifier.isAssignableFrom(o.getClass())){
+        throw new UnexpectedOperatorType(o, error);
+      }
+    }
+    return (List<O>) ops;
+  }
+
+  public AdjacencyList<G> getAdjList() {
+    return adjList;
+  }
+
+  public Collection<R> getRoots() {
+    return roots;
+  }
+
+  public Collection<T> getLeaves() {
+    return leaves;
+  }
+
+  public static <G extends GraphValue<G>, R extends G, T extends G> Graph<G, R, T> newGraph(List<G> operators, Class<R> root, Class<T> leaf){
+    return new Graph<G, R, T>(operators, root, leaf);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/graph/GraphAlgos.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/graph/GraphAlgos.java b/logical/src/main/java/org/apache/drill/common/graph/GraphAlgos.java
new file mode 100644
index 0000000..0b82c7b
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/graph/GraphAlgos.java
@@ -0,0 +1,159 @@
+/**
+ * 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.common.graph;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GraphAlgos {
+  static final Logger logger = LoggerFactory.getLogger(GraphAlgos.class);
+
+  public static class TopoSorter<V extends GraphValue<V>> {
+    final List<AdjacencyList<V>.Node> sorted = new LinkedList<AdjacencyList<V>.Node>();
+    final AdjacencyList<V> rGraph;
+
+    private TopoSorter(AdjacencyList<V> graph, boolean reverse) {
+      graph.clearVisited();
+
+      if (reverse) {
+        this.rGraph = graph.getReversedList();
+      } else {
+        this.rGraph = graph;
+      }
+      Collection<AdjacencyList<V>.Node> sourceNodes = rGraph.getInternalRootNodes();
+
+      for (AdjacencyList<V>.Node n : sourceNodes) {
+        visit(n);
+      }
+    }
+
+    private void visit(AdjacencyList<V>.Node n) {
+      if (n.visited) {
+        return;
+      }
+
+      n.visited = true;
+      List<Edge<AdjacencyList<V>.Node>> edges = rGraph.getAdjacent(n);
+      if (edges != null) {
+        for (Edge<AdjacencyList<V>.Node> e : edges) {
+          visit(e.to);
+        }
+      }
+
+      sorted.add(n);
+
+    }
+
+    /**
+     * Execute a depth-first sort on the reversed DAG.
+     *
+     * @param graph
+     *          The adjacency list for the DAG.
+     * @param sourceNodes
+     *          List of nodes that
+     * @return
+     */
+    static <V extends GraphValue<V>> List<AdjacencyList<V>.Node> sortInternal(AdjacencyList<V> graph, boolean reverse) {
+      TopoSorter<V> ts = new TopoSorter<V>(graph, reverse);
+      return ts.sorted;
+    }
+
+    public static <V extends GraphValue<V>> List<V> sort(Graph<V, ?, ?> graph) {
+      AdjacencyList<V> l = graph.getAdjList();
+      return l.convert(sortInternal(l, true));
+    }
+
+      public static <V extends GraphValue<V>> List<V> sortLogical(Graph<V, ?, ?> graph) {
+          AdjacencyList<V> l = graph.getAdjList();
+          return l.convert(sortInternal(l, false));
+      }
+  }
+
+  static <V extends GraphValue<V>> List<List<AdjacencyList<V>.Node>> checkDirected(AdjacencyList<V> graph) {
+    Tarjan<V> t = new Tarjan<V>();
+    List<List<AdjacencyList<V>.Node>> subgraphs = t.executeTarjan(graph);
+    for (Iterator<List<AdjacencyList<V>.Node>> i = subgraphs.iterator(); i.hasNext();) {
+      List<AdjacencyList<V>.Node> l = i.next();
+      if (l.size() == 1) {
+        i.remove();
+      }
+    }
+    return subgraphs;
+  }
+
+  public static <V extends GraphValue<V>> List<List<AdjacencyList<V>.Node>> checkDirected(Graph<V, ?, ?> graph) {
+    return checkDirected(graph.getAdjList());
+  }
+
+  public static class Tarjan<V extends GraphValue<V>> {
+
+    private int index = 0;
+    private List<AdjacencyList<V>.Node> stack = new LinkedList<AdjacencyList<V>.Node>();
+    private List<List<AdjacencyList<V>.Node>> SCC = new LinkedList<List<AdjacencyList<V>.Node>>();
+
+    public List<List<AdjacencyList<V>.Node>> executeTarjan(AdjacencyList<V> graph) {
+      SCC.clear();
+      index = 0;
+      stack.clear();
+      if (graph != null) {
+        List<AdjacencyList<V>.Node> nodeList = new LinkedList<AdjacencyList<V>.Node>(graph.getNodeSet());
+        for (AdjacencyList<V>.Node node : nodeList) {
+          if (node.index == -1) {
+            tarjan(node, graph);
+          }
+        }
+      }
+      return SCC;
+    }
+
+    private List<List<AdjacencyList<V>.Node>> tarjan(AdjacencyList<V>.Node v, AdjacencyList<V> list) {
+      v.index = index;
+      v.lowlink = index;
+      index++;
+      stack.add(0, v);
+      List<Edge<AdjacencyList<V>.Node>> l = list.getAdjacent(v);
+      if (l != null) {
+        for (Edge<AdjacencyList<V>.Node> e : l) {
+          AdjacencyList<V>.Node n = e.to;
+          if (n.index == -1) {
+            tarjan(n, list);
+            v.lowlink = Math.min(v.lowlink, n.lowlink);
+          } else if (stack.contains(n)) {
+            v.lowlink = Math.min(v.lowlink, n.index);
+          }
+        }
+      }
+      if (v.lowlink == v.index) {
+        AdjacencyList<V>.Node n;
+        List<AdjacencyList<V>.Node> component = new LinkedList<AdjacencyList<V>.Node>();
+        do {
+          n = stack.remove(0);
+          component.add(n);
+        } while (n != v);
+        SCC.add(component);
+      }
+      return SCC;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/graph/GraphValue.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/graph/GraphValue.java b/logical/src/main/java/org/apache/drill/common/graph/GraphValue.java
new file mode 100644
index 0000000..a919008
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/graph/GraphValue.java
@@ -0,0 +1,26 @@
+/**
+ * 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.common.graph;
+
+
+public interface GraphValue<T> extends Iterable<T>{
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(GraphValue.class);
+
+  public void accept(GraphVisitor<T> visitor);
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/graph/GraphVisitor.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/graph/GraphVisitor.java b/logical/src/main/java/org/apache/drill/common/graph/GraphVisitor.java
new file mode 100644
index 0000000..810b738
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/graph/GraphVisitor.java
@@ -0,0 +1,25 @@
+/**
+ * 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.common.graph;
+
+
+public interface GraphVisitor<T> {
+  public boolean enter(T o);
+  public void leave(T o);
+  public boolean visit(T o);
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/graph/Visitable.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/graph/Visitable.java b/logical/src/main/java/org/apache/drill/common/graph/Visitable.java
new file mode 100644
index 0000000..c97062e
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/graph/Visitable.java
@@ -0,0 +1,22 @@
+/**
+ * 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.common.graph;
+
+public interface Visitable<T extends Visitable<?>> {
+  public void accept(T node);
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/graph/package-info.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/graph/package-info.java b/logical/src/main/java/org/apache/drill/common/graph/package-info.java
new file mode 100644
index 0000000..38138d0
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/graph/package-info.java
@@ -0,0 +1,21 @@
+/**
+ * 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.
+ */
+/**
+ * Connected-graph representation shared by logical and physical query graphs.
+ */
+package org.apache.drill.common.graph;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/FormatPluginConfig.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/FormatPluginConfig.java b/logical/src/main/java/org/apache/drill/common/logical/FormatPluginConfig.java
new file mode 100644
index 0000000..e7d3d1f
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/FormatPluginConfig.java
@@ -0,0 +1,40 @@
+/**
+ * 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.common.logical;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+/**
+ * Interface for defining a Drill format plugin.
+ *
+ * Format plugins are contained within storage plugins to describe particular
+ * data formats available in a given storage system. These formats are not
+ * necessarily tied to how the data is stored. One current use of this
+ * abstraction is describing different file formats like CSV and JSON that
+ * can be stored in a filesystem. Some storage systems like databases may only
+ * have a single format in which the data is actually stored. This interface
+ * enables flexibility for configuring the different data formats that will
+ * live under one storage system. The storage systems themselves are described
+ * in {@see StoragePluginConfig}s.
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property="type")
+public interface FormatPluginConfig {
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(FormatPluginConfig.class);
+
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/FormatPluginConfigBase.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/FormatPluginConfigBase.java b/logical/src/main/java/org/apache/drill/common/logical/FormatPluginConfigBase.java
new file mode 100644
index 0000000..50de963
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/FormatPluginConfigBase.java
@@ -0,0 +1,44 @@
+/**
+ * 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.common.logical;
+
+import java.util.Set;
+
+import org.apache.drill.common.scanner.persistence.ScanResult;
+
+
+public abstract class FormatPluginConfigBase implements FormatPluginConfig{
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(FormatPluginConfigBase.class);
+
+
+  /**
+   * scan for implementations of {@see FormatPlugin}.
+   *
+   * @param classpathScan - Drill configuration object, used to find the packages to scan
+   * @return - list of classes that implement the interface.
+   */
+  public static Set<Class<? extends FormatPluginConfig>> getSubTypes(final ScanResult classpathScan) {
+    final Set<Class<? extends FormatPluginConfig>> pluginClasses = classpathScan.getImplementations(FormatPluginConfig.class);
+    logger.debug("Found {} format plugin configuration classes: {}.", pluginClasses.size(), pluginClasses);
+    return pluginClasses;
+  }
+
+  @Override
+  public abstract boolean equals(Object o);
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/LogicalPlan.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/LogicalPlan.java b/logical/src/main/java/org/apache/drill/common/logical/LogicalPlan.java
new file mode 100644
index 0000000..8a4a5ab
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/LogicalPlan.java
@@ -0,0 +1,122 @@
+/**
+ * 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.common.logical;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.drill.common.config.DrillConfig;
+import org.apache.drill.common.config.LogicalPlanPersistence;
+import org.apache.drill.common.graph.Graph;
+import org.apache.drill.common.graph.GraphAlgos;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.SinkOperator;
+import org.apache.drill.common.logical.data.SourceOperator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@JsonPropertyOrder({ "head", "storage", "query" })
+public class LogicalPlan {
+  static final Logger logger = LoggerFactory.getLogger(LogicalPlan.class);
+
+  private final PlanProperties properties;
+  private final Map<String, StoragePluginConfig> storageEngineMap;
+  private final Graph<LogicalOperator, SinkOperator, SourceOperator> graph;
+
+
+  @JsonCreator
+  public LogicalPlan(@JsonProperty("head") PlanProperties head,
+      @JsonProperty("storage") Map<String, StoragePluginConfig> storageEngineMap,
+      @JsonProperty("query") List<LogicalOperator> operators) {
+    this.storageEngineMap = storageEngineMap != null ? storageEngineMap : new HashMap<String, StoragePluginConfig>();
+    this.properties = head;
+    this.graph = Graph.newGraph(operators, SinkOperator.class, SourceOperator.class);
+  }
+
+  @JsonProperty("query")
+  public List<LogicalOperator> getSortedOperators() {
+    return GraphAlgos.TopoSorter.sortLogical(graph);
+  }
+
+  public StoragePluginConfig getStorageEngineConfig(String name) {
+    return storageEngineMap.get(name);
+  }
+
+  @JsonIgnore
+  public Graph<LogicalOperator, SinkOperator, SourceOperator> getGraph() {
+    return graph;
+  }
+
+  @JsonProperty("head")
+  public PlanProperties getProperties() {
+    return properties;
+  }
+
+  @JsonProperty("storage")
+  public Map<String, StoragePluginConfig> getStorageEngines() {
+    return storageEngineMap;
+  }
+
+  public String toJsonString(LogicalPlanPersistence config) throws JsonProcessingException {
+    return config.getMapper().writeValueAsString(this);
+  }
+
+  public String toJsonStringSafe(LogicalPlanPersistence config){
+    try{
+      return toJsonString(config);
+    }catch(JsonProcessingException e){
+      logger.error("Failure while trying to get JSON representation of plan.", e);
+      return "Unable to generate plan.";
+    }
+  }
+
+  /** Parses a logical plan. */
+  public static LogicalPlan parse(LogicalPlanPersistence config, String planString) {
+    ObjectMapper mapper = config.getMapper();
+    try {
+      LogicalPlan plan = mapper.readValue(planString, LogicalPlan.class);
+      return plan;
+    } catch (IOException e) {
+
+      throw new RuntimeException(String.format("Failure while parsing plan: \n %s}", planString), e);
+    }
+  }
+
+  /** Converts a logical plan to a string. (Opposite of {@link #parse}.) */
+  public String unparse(LogicalPlanPersistence config) {
+    try {
+      return config.getMapper().writeValueAsString(this);
+    } catch (JsonProcessingException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public static LogicalPlanBuilder builder() {
+    return new LogicalPlanBuilder();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/LogicalPlanBuilder.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/LogicalPlanBuilder.java b/logical/src/main/java/org/apache/drill/common/logical/LogicalPlanBuilder.java
new file mode 100644
index 0000000..28f1402
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/LogicalPlanBuilder.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.common.logical;
+
+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 com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * A programmatic builder for logical plans.
+ */
+public class LogicalPlanBuilder {
+  private PlanProperties planProperties;
+  private ImmutableMap.Builder<String, StoragePluginConfig> storageEngines = ImmutableMap.builder();
+  private ImmutableList.Builder<LogicalOperator> operators = ImmutableList.builder();
+
+  public LogicalPlanBuilder planProperties(PlanProperties planProperties) {
+    this.planProperties = planProperties;
+    return this;
+  }
+
+  public LogicalPlanBuilder planProperties(PlanType type, int version, String generatorType, String generatorInfo, ResultMode mode){
+    this.planProperties = PlanProperties.builder().generator(generatorType, generatorInfo).type(type).version(version).resultMode(mode).build();
+    return this;
+  }
+
+  public LogicalPlanBuilder addStorageEngine(String name, StoragePluginConfig config) {
+    this.storageEngines.put(name, config);
+    return this;
+  }
+  public LogicalPlanBuilder addLogicalOperator(LogicalOperator operator) {
+    this.operators.add(operator);
+    return this;
+  }
+  public LogicalPlan build() {
+    return new LogicalPlan(this.planProperties, this.storageEngines.build(), this.operators.build());
+  }
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/PlanProperties.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/PlanProperties.java b/logical/src/main/java/org/apache/drill/common/logical/PlanProperties.java
new file mode 100644
index 0000000..ce9603e
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/PlanProperties.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * 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.common.logical;
+
+import org.apache.drill.common.JSONOptions;
+import org.apache.drill.common.logical.PlanProperties.Generator.ResultMode;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Logical plan meta properties.
+ */
+public class PlanProperties {
+  public static enum PlanType {APACHE_DRILL_LOGICAL, APACHE_DRILL_PHYSICAL}
+
+  public PlanType type;
+  public int version;
+  public Generator generator;
+  public ResultMode resultMode;
+  public JSONOptions options;
+  public int queue;
+
+//  @JsonInclude(Include.NON_NULL)
+  public static class Generator {
+    public String type;
+    public String info;
+
+    public static enum ResultMode {
+      EXEC, LOGICAL, PHYSICAL;
+    }
+
+    private Generator(@JsonProperty("type") String type, @JsonProperty("info") String info) {
+      this.type = type;
+      this.info = info;
+    }
+  }
+
+  private PlanProperties(@JsonProperty("version") int version,
+                         @JsonProperty("generator") Generator generator,
+                         @JsonProperty("type") PlanType type,
+                         @JsonProperty("mode") ResultMode resultMode,
+                         @JsonProperty("options") JSONOptions options,
+                         @JsonProperty("queue") int queue
+                         ) {
+    this.version = version;
+    this.queue = queue;
+    this.generator = generator;
+    this.type = type;
+    this.resultMode = resultMode == null ? ResultMode.EXEC : resultMode;
+    this.options = options;
+  }
+
+  public static PlanPropertiesBuilder builder() {
+    return new PlanPropertiesBuilder();
+  }
+
+  public static class PlanPropertiesBuilder {
+    private int version;
+    private Generator generator;
+    private PlanType type;
+    private ResultMode mode = ResultMode.EXEC;
+    private JSONOptions options;
+    private int queueNumber = 0;
+
+    public PlanPropertiesBuilder type(PlanType type) {
+      this.type = type;
+      return this;
+    }
+
+    public PlanPropertiesBuilder version(int version) {
+      this.version = version;
+      return this;
+    }
+
+    public PlanPropertiesBuilder generator(String type, String info) {
+      this.generator = new Generator(type, info);
+      return this;
+    }
+
+    public PlanPropertiesBuilder resultMode(ResultMode mode) {
+      this.mode = mode;
+      return this;
+    }
+
+    public PlanPropertiesBuilder queue(int queueNumber) {
+      this.queueNumber = queueNumber;
+      return this;
+    }
+
+    public PlanPropertiesBuilder options(JSONOptions options) {
+      this.options = options;
+      return this;
+    }
+
+    public PlanPropertiesBuilder generator(Generator generator) {
+      this.generator = generator;
+      return this;
+    }
+
+    public PlanProperties build() {
+      return new PlanProperties(version, generator, type, mode, options, queueNumber);
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/StoragePluginConfig.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/StoragePluginConfig.java b/logical/src/main/java/org/apache/drill/common/logical/StoragePluginConfig.java
new file mode 100644
index 0000000..a4a0f2b
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/StoragePluginConfig.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.common.logical;
+
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property="type")
+public abstract class StoragePluginConfig{
+
+  private boolean enabled = true;
+
+  public boolean isEnabled() {
+    return enabled;
+  }
+
+  public void setEnabled(boolean enabled) {
+    this.enabled = enabled;
+  }
+
+  @Override
+  public abstract boolean equals(Object o);
+
+  @Override
+  public abstract int hashCode();
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/StoragePluginConfigBase.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/StoragePluginConfigBase.java b/logical/src/main/java/org/apache/drill/common/logical/StoragePluginConfigBase.java
new file mode 100644
index 0000000..6075483
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/StoragePluginConfigBase.java
@@ -0,0 +1,37 @@
+/**
+ * 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.common.logical;
+
+import java.util.Set;
+
+import org.apache.drill.common.scanner.persistence.ScanResult;
+
+
+public abstract class StoragePluginConfigBase extends StoragePluginConfig {
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(StoragePluginConfigBase.class);
+
+  public static Set<Class<? extends StoragePluginConfig>> getSubTypes(final ScanResult classpathScan) {
+    final Set<Class<? extends StoragePluginConfig>> packages = classpathScan.getImplementations(StoragePluginConfig.class);
+    logger.debug("Found {} logical operator classes: {}.", packages.size(), packages);
+    return packages;
+  }
+
+  @Override
+  public abstract boolean equals(Object o);
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/UnexpectedOperatorType.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/UnexpectedOperatorType.java b/logical/src/main/java/org/apache/drill/common/logical/UnexpectedOperatorType.java
new file mode 100644
index 0000000..ea3f4b2
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/UnexpectedOperatorType.java
@@ -0,0 +1,35 @@
+/**
+ * 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.common.logical;
+
+
+public class UnexpectedOperatorType extends ValidationError{
+
+  public UnexpectedOperatorType(String message){
+    super(message);
+  }
+
+  public UnexpectedOperatorType(Object operator, String message) {
+    super(message + " Received node of type " + operator.getClass().getCanonicalName());
+  }
+
+
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/ValidationError.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/ValidationError.java b/logical/src/main/java/org/apache/drill/common/logical/ValidationError.java
new file mode 100644
index 0000000..54c9c82
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/ValidationError.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.common.logical;
+
+public class ValidationError extends RuntimeException{
+
+  public ValidationError() {
+    super();
+  }
+
+
+  public ValidationError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+    super(message, cause, enableSuppression, writableStackTrace);
+  }
+
+  public ValidationError(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public ValidationError(String message) {
+    super(message);
+  }
+
+  public ValidationError(Throwable cause) {
+    super(cause);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/AbstractBuilder.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/AbstractBuilder.java b/logical/src/main/java/org/apache/drill/common/logical/data/AbstractBuilder.java
new file mode 100644
index 0000000..b178cd9
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/AbstractBuilder.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.common.logical.data;
+
+import java.util.List;
+
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.expression.LogicalExpression;
+
+public abstract class AbstractBuilder<T extends LogicalOperator> {
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AbstractBuilder.class);
+
+  public abstract T build();
+
+  protected LogicalExpression[] aL(List<LogicalExpression> exprs){
+    return exprs.toArray(new LogicalExpression[exprs.size()]);
+  }
+
+  protected FieldReference[] aF(List<FieldReference> exprs){
+    return exprs.toArray(new FieldReference[exprs.size()]);
+  }
+
+  protected NamedExpression[] aN(List<NamedExpression> exprs){
+    return exprs.toArray(new NamedExpression[exprs.size()]);
+  }
+
+  protected Order.Ordering[] aO(List<Order.Ordering> orderings) {
+    return orderings.toArray(new Order.Ordering[orderings.size()]);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/AbstractSingleBuilder.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/AbstractSingleBuilder.java b/logical/src/main/java/org/apache/drill/common/logical/data/AbstractSingleBuilder.java
new file mode 100644
index 0000000..3ed947e
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/AbstractSingleBuilder.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.common.logical.data;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractSingleBuilder<T extends SingleInputOperator, X extends AbstractSingleBuilder<T, X>> extends AbstractBuilder<T> {
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AbstractSingleBuilder.class);
+
+  private LogicalOperator input;
+
+  @Override
+  public final T build(){
+    Preconditions.checkNotNull(input);
+    T out = internalBuild();
+    out.setInput(input);
+    return out;
+  }
+
+  public X setInput(LogicalOperator input){
+    this.input = input;
+    return (X) this;
+  }
+
+  public abstract T internalBuild();
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Filter.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Filter.java b/logical/src/main/java/org/apache/drill/common/logical/data/Filter.java
new file mode 100644
index 0000000..02737f8
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Filter.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.common.logical.data;
+
+import java.util.Iterator;
+
+import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.logical.data.visitors.LogicalVisitor;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.google.common.collect.Iterators;
+
+@JsonTypeName("filter")
+public class Filter extends SingleInputOperator {
+  private final LogicalExpression expr;
+
+  @JsonCreator
+  public Filter(@JsonProperty("expr") LogicalExpression expr) {
+    this.expr = expr;
+  }
+
+  public LogicalExpression getExpr() {
+    return expr;
+  }
+
+    @Override
+    public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+        return logicalVisitor.visitFilter(this, value);
+    }
+
+    @Override
+    public Iterator<LogicalOperator> iterator() {
+        return Iterators.singletonIterator(getInput());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Flatten.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Flatten.java b/logical/src/main/java/org/apache/drill/common/logical/data/Flatten.java
new file mode 100644
index 0000000..803a4b3
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Flatten.java
@@ -0,0 +1,67 @@
+/**
+ * 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.common.logical.data;
+
+import java.util.Iterator;
+
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.logical.data.visitors.LogicalVisitor;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.google.common.collect.Iterators;
+
+@JsonTypeName("flatten")
+public class Flatten extends SingleInputOperator {
+  private final FieldReference name;
+  private final LogicalExpression expr;
+  private final boolean drop;
+
+  @JsonCreator
+  public Flatten(@JsonProperty("name") FieldReference name, @JsonProperty("expr") LogicalExpression expr,
+      @JsonProperty("drop") boolean drop) {
+    this.name = name;
+    this.expr = expr;
+    this.drop = drop;
+  }
+
+  public FieldReference getName() {
+    return name;
+  }
+
+  public LogicalExpression getExpr() {
+    return expr;
+  }
+
+  public boolean isDrop() {
+    return drop;
+  }
+
+  @Override
+  public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+    return logicalVisitor.visitFlatten(this, value);
+  }
+
+  @Override
+  public Iterator<LogicalOperator> iterator() {
+    return Iterators.singletonIterator(getInput());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/GroupingAggregate.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/GroupingAggregate.java b/logical/src/main/java/org/apache/drill/common/logical/data/GroupingAggregate.java
new file mode 100644
index 0000000..2913a7e
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/GroupingAggregate.java
@@ -0,0 +1,101 @@
+/**
+ * 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.common.logical.data;
+
+import java.util.Iterator;
+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.visitors.LogicalVisitor;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+
+@JsonTypeName("groupingaggregate")
+public class GroupingAggregate extends SingleInputOperator{
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(GroupingAggregate.class);
+
+  private final NamedExpression[] keys;
+  private final NamedExpression[] exprs;
+
+  public GroupingAggregate(@JsonProperty("keys") NamedExpression[] keys, @JsonProperty("exprs") NamedExpression[] exprs) {
+    super();
+    this.keys = keys;
+    this.exprs = exprs;
+  }
+
+  @Override
+  public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+      return logicalVisitor.visitGroupingAggregate(this, value);
+  }
+
+  @Override
+  public Iterator<LogicalOperator> iterator() {
+    return Iterators.singletonIterator(getInput());
+  }
+
+  public static Builder builder(){
+    return new Builder();
+  }
+
+  public NamedExpression[] getKeys(){
+    return keys;
+  }
+
+  public NamedExpression[] getExprs(){
+    return exprs;
+  }
+
+  public static class Builder extends AbstractSingleBuilder<GroupingAggregate, Builder>{
+    private List<NamedExpression> keys = Lists.newArrayList();
+    private List<NamedExpression> exprs = Lists.newArrayList();
+
+    public Builder addKey(FieldReference ref, LogicalExpression expr){
+      keys.add(new NamedExpression(expr, ref));
+      return this;
+    }
+
+    public Builder addKey(NamedExpression expr){
+      keys.add(expr);
+      return this;
+    }
+
+    public Builder addExpr(NamedExpression expr){
+      exprs.add(expr);
+      return this;
+    }
+
+    public Builder addExpr(FieldReference ref, LogicalExpression expr){
+      exprs.add(new NamedExpression(expr, ref));
+      return this;
+    }
+
+    @Override
+    public GroupingAggregate internalBuild(){
+      GroupingAggregate ga =  new GroupingAggregate(aN(keys), aN(exprs));
+      return ga;
+    }
+
+  }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Join.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Join.java b/logical/src/main/java/org/apache/drill/common/logical/data/Join.java
new file mode 100644
index 0000000..2d7e6e1
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Join.java
@@ -0,0 +1,140 @@
+/**
+ * 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.common.logical.data;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.drill.common.exceptions.ExpressionParsingException;
+import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.logical.data.visitors.LogicalVisitor;
+import org.apache.calcite.rel.core.JoinRelType;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+
+@JsonTypeName("join")
+public class Join extends LogicalOperatorBase {
+  private final LogicalOperator left;
+  private final LogicalOperator right;
+  private final JoinRelType type;
+  private final JoinCondition[] conditions;
+
+  public static JoinRelType resolve(String val) {
+    for (JoinRelType jt : JoinRelType.values()) {
+      if (jt.name().equalsIgnoreCase(val)) {
+        return jt;
+      }
+    }
+    throw new ExpressionParsingException(String.format("Unable to determine join type for value '%s'.", val));
+  }
+
+  @JsonCreator
+  public Join(@JsonProperty("left") LogicalOperator left, @JsonProperty("right") LogicalOperator right,
+      @JsonProperty("conditions") JoinCondition[] conditions, @JsonProperty("type") String type) {
+    this(left, right, conditions, resolve(type));
+  }
+
+  @JsonCreator
+  public Join(@JsonProperty("left") LogicalOperator left, @JsonProperty("right") LogicalOperator right, @JsonProperty("conditions")JoinCondition[] conditions, @JsonProperty("type") JoinRelType type) {
+    super();
+    this.conditions = conditions;
+    this.left = left;
+    this.right = right;
+    left.registerAsSubscriber(this);
+    right.registerAsSubscriber(this);
+    this.type = type;
+
+  }
+
+  public LogicalOperator getLeft() {
+    return left;
+  }
+
+  public LogicalOperator getRight() {
+    return right;
+  }
+
+  public JoinCondition[] getConditions() {
+    return conditions;
+  }
+
+  @JsonIgnore
+  public JoinRelType getJoinType() {
+    return type;
+  }
+
+  public String getType() {
+    return type.name();
+  }
+
+  @Override
+  public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+    return logicalVisitor.visitJoin(this, value);
+  }
+
+  @Override
+  public Iterator<LogicalOperator> iterator() {
+    return Iterators.forArray(getLeft(), getRight());
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder extends AbstractBuilder<Join>{
+    private LogicalOperator left;
+    private LogicalOperator right;
+    private JoinRelType type;
+    private List<JoinCondition> conditions = Lists.newArrayList();
+
+    public Builder type(JoinRelType type) {
+      this.type = type;
+      return this;
+    }
+
+    public Builder left(LogicalOperator left) {
+      this.left = left;
+      return this;
+    }
+    public Builder right(LogicalOperator right) {
+      this.right = right;
+      return this;
+    }
+
+    public Builder addCondition(String relationship, LogicalExpression left, LogicalExpression right) {
+      conditions.add(new JoinCondition(relationship, left, right));
+      return this;
+    }
+
+    @Override
+    public Join build() {
+      Preconditions.checkNotNull(left);
+      Preconditions.checkNotNull(right);
+      Preconditions.checkNotNull(type);
+      return new Join(left, right, conditions.toArray(new JoinCondition[conditions.size()]), type);
+    }
+
+  }
+
+}


Mime
View raw message