You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by ja...@apache.org on 2015/11/13 03:38:02 UTC
[32/45] drill git commit: DRILL-3987: (MOVE) Move logical expressions
and operators out of common. Move to new drill-logical model.
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/JoinCondition.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/JoinCondition.java b/logical/src/main/java/org/apache/drill/common/logical/data/JoinCondition.java
new file mode 100644
index 0000000..611e70b
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/JoinCondition.java
@@ -0,0 +1,55 @@
+/**
+ * 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 org.apache.drill.common.expression.LogicalExpression;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class JoinCondition {
+ private final String relationship;
+ private final LogicalExpression left;
+ private final LogicalExpression right;
+
+ @JsonCreator
+ public JoinCondition(@JsonProperty("relationship") String relationship,
+ @JsonProperty("left") LogicalExpression left, @JsonProperty("right") LogicalExpression right) {
+ super();
+ this.relationship = relationship;
+ this.left = left;
+ this.right = right;
+ }
+
+ public String getRelationship() {
+ return relationship;
+ }
+
+ public LogicalExpression getLeft() {
+ return left;
+ }
+
+ public LogicalExpression getRight() {
+ return right;
+ }
+
+ public JoinCondition flip(){
+ return new JoinCondition(relationship, right, left);
+ }
+
+}
\ 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/data/Limit.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Limit.java b/logical/src/main/java/org/apache/drill/common/logical/data/Limit.java
new file mode 100644
index 0000000..56ae8d9
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Limit.java
@@ -0,0 +1,79 @@
+/**
+ * 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.logical.data.visitors.LogicalVisitor;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Iterators;
+
+@JsonTypeName("limit")
+public class Limit extends SingleInputOperator {
+
+ private final Integer first;
+ private final Integer last;
+
+ @JsonCreator
+ public Limit(@JsonProperty("first") Integer first, @JsonProperty("last") Integer last) {
+ super();
+ this.first = first;
+ this.last = last;
+ }
+
+ public Integer getFirst() {
+ return first;
+ }
+
+ public Integer getLast() {
+ return last;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitLimit(this, value);
+ }
+
+ @Override
+ public NodeBuilder nodeBuilder() {
+ return new LimitNodeBuilder(); //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public Iterator<LogicalOperator> iterator() {
+ return Iterators.singletonIterator(getInput());
+ }
+
+ public static class LimitNodeBuilder implements NodeBuilder<Limit> {
+
+ @Override
+ public ObjectNode convert(ObjectMapper mapper, Limit operator, Integer inputId) {
+ ObjectNode limitNode = mapper.createObjectNode();
+ limitNode.put("op", "limit");
+ limitNode.put("input", inputId);
+ limitNode.put("first", operator.first);
+ limitNode.put("last", operator.last);
+ return limitNode;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/LogicalOperator.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/LogicalOperator.java b/logical/src/main/java/org/apache/drill/common/logical/data/LogicalOperator.java
new file mode 100644
index 0000000..3343d4e
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/LogicalOperator.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.data;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.drill.common.graph.GraphValue;
+import org.apache.drill.common.logical.ValidationError;
+import org.apache.drill.common.logical.data.visitors.LogicalVisitor;
+
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+@JsonPropertyOrder({"@id", "memo", "input"}) // op will always be first since it is wrapped.
+@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "op")
+public interface LogicalOperator extends GraphValue<LogicalOperator> {
+
+ public void setupAndValidate(List<LogicalOperator> operators, Collection<ValidationError> errors);
+
+ /**
+ * Provides capability to build a set of output based on traversing a query graph tree.
+ *
+ * @param logicalVisitor
+ * @return
+ */
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E;
+
+ public void registerAsSubscriber(LogicalOperator operator);
+
+ NodeBuilder nodeBuilder();
+
+ public interface NodeBuilder<T extends LogicalOperator> {
+ ObjectNode convert(ObjectMapper mapper, T operator, Integer inputId);
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/LogicalOperatorBase.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/LogicalOperatorBase.java b/logical/src/main/java/org/apache/drill/common/logical/data/LogicalOperatorBase.java
new file mode 100644
index 0000000..a213c8d
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/LogicalOperatorBase.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.common.logical.data;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.drill.common.graph.GraphVisitor;
+import org.apache.drill.common.logical.ValidationError;
+import org.apache.drill.common.scanner.persistence.ScanResult;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+
+public abstract class LogicalOperatorBase implements LogicalOperator{
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(LogicalOperatorBase.class);
+
+ private List<LogicalOperator> children = new ArrayList<LogicalOperator>();
+
+ private String memo;
+
+ @Override
+ public final int hashCode() {
+ return super.hashCode();
+ }
+
+ @Override
+ public void setupAndValidate(List<LogicalOperator> operators, Collection<ValidationError> errors) {
+ // TODO: remove this and implement individually.
+ }
+
+ @Override
+ public NodeBuilder nodeBuilder() {
+ // FIXME: Implement this on all logical operators
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public void accept(GraphVisitor<LogicalOperator> visitor) {
+ if (visitor.enter(this)) {
+ visitor.leave(this);
+ }
+ }
+
+ @Override
+ public void registerAsSubscriber(LogicalOperator operator) {
+ if (operator == null) {
+ throw new IllegalArgumentException("You attempted to register a null operators.");
+ }
+ children.add(operator);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + " [memo=" + memo + "]";
+ }
+
+ @JsonInclude(Include.NON_EMPTY)
+ @JsonProperty("memo")
+ public String getMemo() {
+ return memo;
+ }
+
+ public void setMemo(String memo) {
+ this.memo = memo;
+ }
+
+ public static Set<Class<? extends LogicalOperator>> getSubTypes(final ScanResult classpathScan) {
+ final Set<Class<? extends LogicalOperator>> ops = classpathScan.getImplementations(LogicalOperator.class);
+ logger.debug("Found {} logical operator classes: {}.", ops.size(), ops);
+ return ops;
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/NamedExpression.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/NamedExpression.java b/logical/src/main/java/org/apache/drill/common/logical/data/NamedExpression.java
new file mode 100644
index 0000000..a166c25
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/NamedExpression.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.common.logical.data;
+
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.expression.LogicalExpression;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonPropertyOrder({"ref", "expr"})
+public class NamedExpression {
+ private final LogicalExpression expr;
+ private final FieldReference ref;
+
+ @JsonCreator
+ public NamedExpression(@JsonProperty("expr") LogicalExpression expr, @JsonProperty("ref") FieldReference ref) {
+ super();
+ this.expr = expr;
+ this.ref = ref;
+ }
+
+ public LogicalExpression getExpr() {
+ return expr;
+ }
+
+ public FieldReference getRef() {
+ return ref;
+ }
+
+ @Override
+ public String toString() {
+ return "NamedExpression [expr=" + expr + ", ref=" + ref + "]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Order.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Order.java b/logical/src/main/java/org/apache/drill/common/logical/data/Order.java
new file mode 100644
index 0000000..fca6010
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Order.java
@@ -0,0 +1,252 @@
+/**
+ * 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.DrillRuntimeException;
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.logical.data.visitors.LogicalVisitor;
+import org.apache.calcite.rel.RelFieldCollation;
+import org.apache.calcite.rel.RelFieldCollation.Direction;
+import org.apache.calcite.rel.RelFieldCollation.NullDirection;
+
+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.collect.Iterators;
+import com.google.common.collect.Lists;
+
+@JsonTypeName("order")
+public class Order extends SingleInputOperator {
+
+ private final Ordering[] orderings;
+ private final FieldReference within;
+
+ @JsonCreator
+ public Order(@JsonProperty("within") FieldReference within, @JsonProperty("orderings") Ordering... orderings) {
+ this.orderings = orderings;
+ this.within = within;
+ }
+
+ public Ordering[] getOrderings() {
+ return orderings;
+ }
+
+ public FieldReference getWithin() {
+ return within;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitOrder(this, value);
+ }
+
+ @Override
+ public Iterator<LogicalOperator> iterator() {
+ return Iterators.singletonIterator(getInput());
+ }
+
+
+ /**
+ * Representation of a SQL <sort specification>.
+ */
+ public static class Ordering {
+
+ private final LogicalExpression expr;
+ /** Net <ordering specification>. */
+ private final Direction direction;
+ /** Net <null ordering> */
+ private final NullDirection nullOrdering;
+
+ /**
+ * Constructs a sort specification.
+ * @param expr ...
+ * @param strOrderingSpec the <ordering specification> as string;
+ * allowed values: {@code "ASC"}, {@code "DESC"}, {@code null};
+ * null specifies default <ordering specification>
+ * ({@code "ASC"} / {@link Direction#ASCENDING})
+ * @param strNullOrdering the <null ordering> as string;
+ * allowed values: {@code "FIRST"}, {@code "LAST"},
+ * {@code "UNSPECIFIED"}, {@code null};
+ * null specifies default <null ordering>
+ * (omitted / {@link NullDirection#UNSPECIFIED}, interpreted later)
+ */
+ @JsonCreator
+ public Ordering( @JsonProperty("expr") LogicalExpression expr,
+ @JsonProperty("order") String strOrderingSpec,
+ @JsonProperty("nullDirection") String strNullOrdering ) {
+ this.expr = expr;
+ this.direction = getOrderingSpecFromString( strOrderingSpec );
+ this.nullOrdering = getNullOrderingFromString( strNullOrdering );
+ }
+
+ public Ordering(Direction direction, LogicalExpression e, NullDirection nullOrdering) {
+ this.expr = e;
+ this.direction = direction;
+ this.nullOrdering = nullOrdering;
+ }
+
+ public Ordering(Direction direction, LogicalExpression e) {
+ this(direction, e, NullDirection.FIRST);
+ }
+
+ private static Direction getOrderingSpecFromString( String strDirection ) {
+ final Direction direction;
+ if ( null == strDirection
+ || Direction.ASCENDING.shortString.equals( strDirection ) ) {
+ direction = Direction.ASCENDING;
+ }
+ else if ( Direction.DESCENDING.shortString.equals( strDirection ) ) {
+ direction = Direction.DESCENDING;
+ }
+ else {
+ throw new DrillRuntimeException(
+ "Unknown <ordering specification> string (not \"ASC\", \"DESC\", "
+ + "or null): \"" + strDirection + "\"" );
+ }
+ return direction;
+ }
+
+ private static NullDirection getNullOrderingFromString( String strNullOrdering ) {
+ final RelFieldCollation.NullDirection nullOrdering;
+ if ( null == strNullOrdering ) {
+ nullOrdering = NullDirection.UNSPECIFIED;
+ }
+ else {
+ try {
+ nullOrdering = NullDirection.valueOf( strNullOrdering );
+ }
+ catch ( IllegalArgumentException e ) {
+ throw new DrillRuntimeException(
+ "Internal error: Unknown <null ordering> string (not "
+ + "\"" + NullDirection.FIRST.name() + "\", "
+ + "\"" + NullDirection.LAST.name() + "\", or "
+ + "\"" + NullDirection.UNSPECIFIED.name() + "\" or null): "
+ + "\"" + strNullOrdering + "\"" );
+ }
+ }
+ return nullOrdering;
+ }
+
+ @Override
+ public String toString() {
+ return
+ super.toString()
+ + "[ "
+ + " expr = " + expr
+ + ", direction = " + direction
+ + ", nullOrdering = " + nullOrdering
+ + "] ";
+ }
+
+ @JsonIgnore
+ public Direction getDirection() {
+ return direction;
+ }
+
+ public LogicalExpression getExpr() {
+ return expr;
+ }
+
+ public String getOrder() {
+ switch (direction) {
+ case ASCENDING:
+ return Direction.ASCENDING.shortString;
+ case DESCENDING:
+ return Direction.DESCENDING.shortString;
+ default:
+ throw new DrillRuntimeException(
+ "Unexpected " + Direction.class.getName() + " value other than "
+ + Direction.ASCENDING + " or " + Direction.DESCENDING + ": "
+ + direction );
+ }
+ }
+
+ public NullDirection getNullDirection() {
+ return nullOrdering;
+ }
+
+ /**
+ * Reports whether NULL sorts high or low in this ordering.
+ *
+ * @return
+ * {@code true} if NULL sorts higher than any other value;
+ * {@code false} if NULL sorts lower than any other value
+ */
+ public boolean nullsSortHigh() {
+ final boolean nullsHigh;
+
+ switch (nullOrdering) {
+
+ case UNSPECIFIED:
+ // Default: NULL sorts high: like NULLS LAST if ASC, FIRST if DESC.
+ nullsHigh = true;
+ break;
+
+ case FIRST:
+ // FIRST: NULL sorts low with ASC, high with DESC.
+ nullsHigh = Direction.DESCENDING == getDirection();
+ break;
+
+ case LAST:
+ // LAST: NULL sorts high with ASC, low with DESC.
+ nullsHigh = Direction.ASCENDING == getDirection();
+ break;
+
+ default:
+ throw new DrillRuntimeException(
+ "Unexpected " + NullDirection.class.getName() + " value other than "
+ + NullDirection.FIRST + ", " + NullDirection.LAST + " or " + NullDirection.UNSPECIFIED + ": "
+ + nullOrdering );
+ }
+
+ return nullsHigh;
+ }
+
+ }
+
+ public static Builder builder(){
+ return new Builder();
+ }
+
+ public static class Builder extends AbstractSingleBuilder<Order, Builder>{
+ private List<Ordering> orderings = Lists.newArrayList();
+ private FieldReference within;
+
+ public Builder setWithin(FieldReference within){
+ this.within = within;
+ return this;
+ }
+
+ public Builder addOrdering(Direction direction, LogicalExpression e, NullDirection collation){
+ orderings.add(new Ordering(direction, e, collation));
+ return this;
+ }
+
+ @Override
+ public Order internalBuild() {
+ return new Order(within, orderings.toArray(new Ordering[orderings.size()]));
+ }
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Project.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Project.java b/logical/src/main/java/org/apache/drill/common/logical/data/Project.java
new file mode 100644
index 0000000..4345c80
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Project.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.common.logical.data;
+
+import java.util.List;
+
+import org.apache.drill.common.exceptions.ExpressionParsingException;
+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.Lists;
+
+@JsonTypeName("project")
+public class Project extends SingleInputOperator {
+
+ private final NamedExpression[] selections;
+
+ @JsonCreator
+ public Project(@JsonProperty("projections") NamedExpression[] selections) {
+ this.selections = selections;
+ if (selections == null || selections.length == 0) {
+ throw new ExpressionParsingException(
+ "Project did not provide any projection selections. At least one projection must be provided.");
+// for (int i = 0; i < selections.length; i++) {
+// PathSegment segment = selections[i].getRef().getRootSegment();
+// CharSequence path = segment.getNameSegment().getPath();
+// if (!segment.isNamed() || !path.equals("output"))
+// throw new ExpressionParsingException(
+// String
+// .format(
+// "Outputs for projections always have to start with named path of output. First segment was named '%s' or was named [%s]",
+// path, segment.isNamed()));
+//
+// }
+ }
+ }
+
+ @JsonProperty("projections")
+ public NamedExpression[] getSelections() {
+ return selections;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitProject(this, value);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder extends AbstractSingleBuilder<Project, Builder> {
+
+ private List<NamedExpression> exprs = Lists.newArrayList();
+
+ 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 Project internalBuild() {
+ return new Project(aN(exprs));
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/RunningAggregate.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/RunningAggregate.java b/logical/src/main/java/org/apache/drill/common/logical/data/RunningAggregate.java
new file mode 100644
index 0000000..e280627
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/RunningAggregate.java
@@ -0,0 +1,63 @@
+/**
+ * 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.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("runningaggregate")
+public class RunningAggregate extends SingleInputOperator{
+
+ private final FieldReference within;
+ private final NamedExpression[] aggregations;
+
+ @JsonCreator
+ public RunningAggregate(@JsonProperty("within") FieldReference within, @JsonProperty("aggregations") NamedExpression[] aggregations) {
+ super();
+ this.within = within;
+ this.aggregations = aggregations;
+ }
+
+ public FieldReference getWithin() {
+ return within;
+ }
+
+ public NamedExpression[] getAggregations() {
+ return aggregations;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitRunningAggregate(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/Scan.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Scan.java b/logical/src/main/java/org/apache/drill/common/logical/data/Scan.java
new file mode 100644
index 0000000..68eabbb
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Scan.java
@@ -0,0 +1,78 @@
+/**
+ * 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 org.apache.drill.common.JSONOptions;
+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;
+
+@JsonTypeName("scan")
+public class Scan extends SourceOperator {
+ private final String storageEngine;
+ private final JSONOptions selection;
+
+ @JsonCreator
+ public Scan(@JsonProperty("storageengine") String storageEngine, @JsonProperty("selection") JSONOptions selection) {
+ super();
+ this.storageEngine = storageEngine;
+ this.selection = selection;
+ }
+
+ @JsonProperty("storageengine")
+ public String getStorageEngine() {
+ return storageEngine;
+ }
+
+ public JSONOptions getSelection() {
+ return selection;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitScan(this, value);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder extends AbstractBuilder<Scan>{
+ private String storageEngine;
+ private JSONOptions selection;
+
+ public Builder storageEngine(String storageEngine) {
+ this.storageEngine = storageEngine;
+ return this;
+ }
+
+ public Builder selection(JSONOptions selection) {
+ this.selection = selection;
+ return this;
+ }
+
+ @Override
+ public Scan build() {
+ return new Scan(storageEngine, selection);
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Sequence.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Sequence.java b/logical/src/main/java/org/apache/drill/common/logical/data/Sequence.java
new file mode 100644
index 0000000..f04b09c
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Sequence.java
@@ -0,0 +1,187 @@
+/**
+ * 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.io.IOException;
+import java.util.Iterator;
+
+import org.apache.drill.common.logical.data.Sequence.De;
+import org.apache.drill.common.logical.data.visitors.LogicalVisitor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.ObjectIdGenerator;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+import com.fasterxml.jackson.core.JsonLocation;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.google.common.collect.Iterators;
+
+/**
+ * Describes a list of operators where each operator only has one input and that
+ * input is the operator that came before.
+ *
+ */
+@JsonDeserialize(using = De.class)
+@JsonTypeName("sequence")
+public class Sequence extends LogicalOperatorBase {
+ static final Logger logger = LoggerFactory.getLogger(Sequence.class);
+
+ private Sequence() {}
+
+ public boolean openTop;
+ public LogicalOperator input;
+ @JsonProperty("do")
+ public LogicalOperator[] stream;
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitSequence(this, value);
+ }
+
+ @Override
+ public Iterator<LogicalOperator> iterator() {
+ return Iterators.singletonIterator(stream[stream.length - 1]);
+ }
+
+ public static class De extends StdDeserializer<LogicalOperator> {
+
+ protected De() {
+ super(Sequence.class);
+ }
+
+ @Override
+ public LogicalOperator deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
+ JsonProcessingException {
+ ObjectIdGenerator<Integer> idGenerator = new ObjectIdGenerators.IntSequenceGenerator();
+ JsonLocation start = jp.getCurrentLocation();
+ JsonToken t = jp.getCurrentToken();
+ LogicalOperator parent = null;
+ LogicalOperator first = null;
+ LogicalOperator prev = null;
+ Integer id = null;
+
+ while (true) {
+ String fieldName = jp.getText();
+ t = jp.nextToken();
+ switch (fieldName) { // switch on field names.
+ case "@id":
+ id = _parseIntPrimitive(jp, ctxt);
+ break;
+ case "input":
+ JavaType tp = ctxt.constructType(LogicalOperator.class);
+ JsonDeserializer<Object> d = ctxt.findRootValueDeserializer(tp);
+ parent = (LogicalOperator) d.deserialize(jp, ctxt);
+ break;
+
+ case "do":
+ if (!jp.isExpectedStartArrayToken()) {
+ throwE(
+ jp,
+ "The do parameter of sequence should be an array of SimpleOperators. Expected a JsonToken.START_ARRAY token but received a "
+ + t.name() + "token.");
+ }
+
+ int pos = 0;
+ while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
+ // logger.debug("Reading sequence child {}.", pos);
+ JsonLocation l = jp.getCurrentLocation(); // get current location
+ // first so we can
+ // correctly reference the
+ // start of the object in
+ // the case that the type
+ // is wrong.
+ LogicalOperator o = jp.readValueAs(LogicalOperator.class);
+
+ if (pos == 0) {
+ if (!(o instanceof SingleInputOperator) && !(o instanceof SourceOperator)) {
+ throwE(
+ l,
+ "The first operator in a sequence must be either a ZeroInput or SingleInput operator. The provided first operator was not. It was of type "
+ + o.getClass().getName());
+ }
+ first = o;
+ } else {
+ if (!(o instanceof SingleInputOperator)) {
+ throwE(l, "All operators after the first must be single input operators. The operator at position "
+ + pos + " was not. It was of type " + o.getClass().getName());
+ }
+ SingleInputOperator now = (SingleInputOperator) o;
+ now.setInput(prev);
+ }
+ prev = o;
+
+ pos++;
+ }
+ break;
+ default:
+ throwE(jp, "Unknown field name provided for Sequence: " + jp.getText());
+ }
+
+ t = jp.nextToken();
+ if (t == JsonToken.END_OBJECT) {
+ break;
+ }
+ }
+
+ if (first == null) {
+ throwE(start, "A sequence must include at least one operator.");
+ }
+ if ((parent == null && first instanceof SingleInputOperator)
+ || (parent != null && first instanceof SourceOperator)) {
+ throwE(start,
+ "A sequence must either start with a ZeroInputOperator or have a provided input. It cannot have both or neither.");
+ }
+
+ if (parent != null && first instanceof SingleInputOperator) {
+ ((SingleInputOperator) first).setInput(parent);
+ }
+
+ // set input reference.
+ if (id != null) {
+
+ ReadableObjectId rid = ctxt.findObjectId(id, idGenerator);
+ rid.bindItem(prev);
+ // logger.debug("Binding id {} to item {}.", rid.id, rid.item);
+
+ }
+
+ return first;
+ }
+
+ }
+
+ private static void throwE(JsonLocation l, String e) throws JsonParseException {
+ throw new JsonParseException(e, l);
+ }
+
+ private static void throwE(JsonParser jp, String e) throws JsonParseException {
+ throw new JsonParseException(e, jp.getCurrentLocation());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/SingleInputOperator.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/SingleInputOperator.java b/logical/src/main/java/org/apache/drill/common/logical/data/SingleInputOperator.java
new file mode 100644
index 0000000..e46cb6b
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/SingleInputOperator.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.logical.UnexpectedOperatorType;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.Iterators;
+
+/**
+ * SimpleOperator is an operator that has one inputs at most.
+ */
+public abstract class SingleInputOperator extends LogicalOperatorBase {
+
+ private LogicalOperator input;
+
+ @JsonProperty("input")
+ public LogicalOperator getInput() {
+ return input;
+ }
+
+ @JsonProperty(value="input", required=true)
+ public void setInput(LogicalOperator input) {
+ if (input instanceof SinkOperator) {
+ throw new UnexpectedOperatorType("You have set the input of a sink node of type ["+input.getClass().getSimpleName()+ "] as the input for another node of type ["+this.getClass().getSimpleName()+ "]. This is invalid.");
+ }
+ this.input = input;
+ input.registerAsSubscriber(this);
+ }
+
+ @Override
+ public Iterator<LogicalOperator> iterator() {
+ return Iterators.singletonIterator(input);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/SinkOperator.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/SinkOperator.java b/logical/src/main/java/org/apache/drill/common/logical/data/SinkOperator.java
new file mode 100644
index 0000000..2ca4006
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/SinkOperator.java
@@ -0,0 +1,30 @@
+/**
+ * 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;
+
+
+/**
+ * An operator that cannot be subscribed to.
+ */
+public abstract class SinkOperator extends SingleInputOperator{
+
+ @Override
+ public void registerAsSubscriber(LogicalOperator operator) {
+ throw new UnsupportedOperationException("You can not subscribe to a sink operator such as " + this.getClass().getSimpleName());
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/SourceOperator.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/SourceOperator.java b/logical/src/main/java/org/apache/drill/common/logical/data/SourceOperator.java
new file mode 100644
index 0000000..d4f8246
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/SourceOperator.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.data;
+
+import java.util.Iterator;
+
+import com.google.common.collect.Iterators;
+
+
+/**
+ * An operator that produces data without any parents. (zero input operator)
+ */
+public abstract class SourceOperator extends LogicalOperatorBase{
+
+ @Override
+ public Iterator<LogicalOperator> iterator() {
+ return Iterators.emptyIterator();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Store.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Store.java b/logical/src/main/java/org/apache/drill/common/logical/data/Store.java
new file mode 100644
index 0000000..8f99eed
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Store.java
@@ -0,0 +1,85 @@
+/**
+ * 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.JSONOptions;
+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("store")
+public class Store extends SinkOperator{
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Store.class);
+
+ private final String storageEngine;
+ private final JSONOptions target;
+
+ @JsonCreator
+ public Store(@JsonProperty("storageengine") String storageEngine, @JsonProperty("target") JSONOptions target) {
+ super();
+ this.storageEngine = storageEngine;
+ this.target = target;
+ }
+
+ public String getStorageEngine() {
+ return storageEngine;
+ }
+
+ public JSONOptions getTarget() {
+ return target;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitStore(this, value);
+ }
+
+ @Override
+ public Iterator<LogicalOperator> iterator() {
+ return Iterators.singletonIterator(getInput());
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder extends AbstractSingleBuilder<Store, Builder>{
+ private String storageEngine;
+ private JSONOptions target;
+
+ public Builder storageEngine(String storageEngine) {
+ this.storageEngine = storageEngine;
+ return this;
+ }
+
+ public Builder target(JSONOptions target) {
+ this.target = target;
+ return this;
+ }
+
+ @Override
+ public Store internalBuild() {
+ return new Store(storageEngine, target);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Transform.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Transform.java b/logical/src/main/java/org/apache/drill/common/logical/data/Transform.java
new file mode 100644
index 0000000..129ae2c
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Transform.java
@@ -0,0 +1,54 @@
+/**
+ * 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.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("transform")
+public class Transform extends SingleInputOperator {
+
+ private final NamedExpression[] transforms;
+
+ @JsonCreator
+ public Transform(@JsonProperty("transforms") NamedExpression[] transforms) {
+ super();
+ this.transforms = transforms;
+ }
+
+ public NamedExpression[] getTransforms() {
+ return transforms;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitTransform(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/Union.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Union.java b/logical/src/main/java/org/apache/drill/common/logical/data/Union.java
new file mode 100644
index 0000000..113ffe0
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Union.java
@@ -0,0 +1,94 @@
+/**
+ * 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.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;
+import com.google.common.collect.Lists;
+
+@JsonTypeName("union")
+public class Union extends LogicalOperatorBase {
+ private final LogicalOperator[] inputs;
+ private final boolean distinct;
+
+// @JsonCreator
+// public Union(@JsonProperty("inputs") LogicalOperator[] inputs){
+// this(inputs, false);
+// }
+
+ @JsonCreator
+ public Union(@JsonProperty("inputs") LogicalOperator[] inputs, @JsonProperty("distinct") Boolean distinct){
+ this.inputs = inputs;
+ for (LogicalOperator o : inputs) {
+ o.registerAsSubscriber(this);
+ }
+ this.distinct = distinct == null ? false : distinct;
+ }
+
+ public LogicalOperator[] getInputs() {
+ return inputs;
+ }
+
+ public boolean isDistinct() {
+ return distinct;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitUnion(this, value);
+ }
+
+ @Override
+ public Iterator<LogicalOperator> iterator() {
+ return Iterators.forArray(inputs);
+ }
+
+
+ public static Builder builder(){
+ return new Builder();
+ }
+
+ public static class Builder extends AbstractBuilder<Union>{
+ private List<LogicalOperator> inputs = Lists.newArrayList();
+ private boolean distinct;
+
+ public Builder addInput(LogicalOperator o){
+ inputs.add(o);
+ return this;
+ }
+
+ public Builder setDistinct(boolean distinct){
+ this.distinct = distinct;
+ return this;
+ }
+
+ @Override
+ public Union build() {
+ return new Union(inputs.toArray(new LogicalOperator[inputs.size()]), distinct);
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Values.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Values.java b/logical/src/main/java/org/apache/drill/common/logical/data/Values.java
new file mode 100644
index 0000000..9276e55
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Values.java
@@ -0,0 +1,69 @@
+/**
+ * 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 org.apache.drill.common.JSONOptions;
+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.fasterxml.jackson.core.JsonLocation;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.base.Preconditions;
+
+@JsonTypeName("values")
+public class Values extends SourceOperator {
+
+ private final JSONOptions content;
+
+ @JsonCreator
+ public Values(@JsonProperty("content") JSONOptions content){
+ super();
+ this.content = content;
+ Preconditions.checkNotNull(content, "content attribute is required for source operator 'constant'.");
+ }
+
+ public JSONOptions getContent() {
+ return content;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitValues(this, value);
+ }
+
+ public static Builder builder(){
+ return new Builder();
+ }
+
+ public static class Builder extends AbstractBuilder<Values>{
+ private JSONOptions content;
+
+ public Builder content(JsonNode n){
+ content = new JSONOptions(n, JsonLocation.NA);
+ return this;
+ }
+
+ @Override
+ public Values build() {
+ return new Values(content);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Window.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Window.java b/logical/src/main/java/org/apache/drill/common/logical/data/Window.java
new file mode 100644
index 0000000..0f550dc
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Window.java
@@ -0,0 +1,120 @@
+/**
+ * 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.collect.Iterators;
+import com.google.common.collect.Lists;
+import org.apache.drill.common.expression.FieldReference;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.logical.data.visitors.LogicalVisitor;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+@JsonTypeName("window")
+public class Window extends SingleInputOperator {
+ private final NamedExpression[] withins;
+ private final NamedExpression[] aggregations;
+ private final Order.Ordering[] orderings;
+ private final long start;
+ private final long end;
+
+
+ @JsonCreator
+ public Window(@JsonProperty("withins") NamedExpression[] withins,
+ @JsonProperty("aggregations") NamedExpression[] aggregations,
+ @JsonProperty("orderings") Order.Ordering[] orderings,
+ @JsonProperty("start") Long start,
+ @JsonProperty("end") Long end) {
+ super();
+ this.withins = withins;
+ this.start = start == null ? Long.MIN_VALUE : start;
+ this.end = end == null ? Long.MIN_VALUE : end;
+ this.aggregations = aggregations;
+ this.orderings = orderings;
+ }
+
+ public NamedExpression[] getWithins() {
+ return withins;
+ }
+
+ public long getStart() {
+ return start;
+ }
+
+ public long getEnd() {
+ return end;
+ }
+
+ public NamedExpression[] getAggregations() {
+ return aggregations;
+ }
+
+ public Order.Ordering[] getOrderings() {
+ return orderings;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitWindow(this, value);
+ }
+
+ @Override
+ public Iterator<LogicalOperator> iterator() {
+ return Iterators.singletonIterator(getInput());
+ }
+
+ public static class Builder extends AbstractSingleBuilder<Window, Builder>{
+ private List<NamedExpression> aggregations = Lists.newArrayList();
+ private List<NamedExpression> withins = Lists.newArrayList();
+ private List<Order.Ordering> orderings = Lists.newArrayList();
+ private long start = Long.MIN_VALUE;
+ private long end = Long.MIN_VALUE;
+
+
+ public Builder addAggregation(FieldReference ref, LogicalExpression expr){
+ aggregations.add(new NamedExpression(expr, ref));
+ return this;
+ }
+
+ public Builder addWithin(FieldReference within, LogicalExpression expr) {
+ withins.add(new NamedExpression(expr, within));
+ return this;
+ }
+
+ public Window internalBuild() {
+ //TODO withins can actually be empty: over(), over(order by <expression>), ...
+ checkState(!withins.isEmpty(), "Withins in window must not be empty.");
+ checkState(!aggregations.isEmpty(), "Aggregations in window must not be empty.");
+ return new Window(aN(withins), aN(aggregations), aO(orderings), start, end);
+ }
+
+ public Builder addOrdering(Order.Ordering ordering) {
+ orderings.add(ordering);
+ return this;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/Writer.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/Writer.java b/logical/src/main/java/org/apache/drill/common/logical/data/Writer.java
new file mode 100644
index 0000000..6e51df7
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/Writer.java
@@ -0,0 +1,61 @@
+/**
+ * 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 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;
+
+@JsonTypeName("writer")
+public class Writer extends SingleInputOperator {
+
+ // TODO: Hack - Make the type generic until "common" and "java-exec" modules are merged (DRILL-507).
+ private final Object createTableEntry;
+
+ @JsonCreator
+ public Writer(@JsonProperty("createTableEntry") Object createTableEntry) {
+ this.createTableEntry = createTableEntry;
+ }
+
+ @Override
+ public <T, X, E extends Throwable> T accept(LogicalVisitor<T, X, E> logicalVisitor, X value) throws E {
+ return logicalVisitor.visitWriter(this, value);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder extends AbstractSingleBuilder<Writer, Builder> {
+
+ // TODO: Hack - Make the type generic until "common" and "java-exec" modules are merged (DRILL-507).
+ private Object createTableEntry;
+
+ public Builder setCreateTableEntry(Object createTableEntry) {
+ this.createTableEntry = createTableEntry;
+ return this;
+ }
+
+ @Override
+ public Writer internalBuild() {
+ return new Writer(createTableEntry);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/package-info.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/package-info.java b/logical/src/main/java/org/apache/drill/common/logical/data/package-info.java
new file mode 100644
index 0000000..fc76c0d
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/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.
+ */
+/**
+ * Logical operators in a query graph.
+ */
+package org.apache.drill.common.logical.data;
\ 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/data/visitors/AbstractLogicalVisitor.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/visitors/AbstractLogicalVisitor.java b/logical/src/main/java/org/apache/drill/common/logical/data/visitors/AbstractLogicalVisitor.java
new file mode 100644
index 0000000..165ee66
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/visitors/AbstractLogicalVisitor.java
@@ -0,0 +1,126 @@
+/**
+ * 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.visitors;
+
+import org.apache.drill.common.logical.data.Values;
+import org.apache.drill.common.logical.data.Filter;
+import org.apache.drill.common.logical.data.Flatten;
+import org.apache.drill.common.logical.data.GroupingAggregate;
+import org.apache.drill.common.logical.data.Join;
+import org.apache.drill.common.logical.data.Limit;
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.Order;
+import org.apache.drill.common.logical.data.Project;
+import org.apache.drill.common.logical.data.RunningAggregate;
+import org.apache.drill.common.logical.data.Scan;
+import org.apache.drill.common.logical.data.Sequence;
+import org.apache.drill.common.logical.data.Store;
+import org.apache.drill.common.logical.data.Transform;
+import org.apache.drill.common.logical.data.Union;
+import org.apache.drill.common.logical.data.Window;
+import org.apache.drill.common.logical.data.Writer;
+
+
+public abstract class AbstractLogicalVisitor<T, X, E extends Throwable> implements LogicalVisitor<T, X, E> {
+
+ public T visitOp(LogicalOperator op, X value) throws E{
+ throw new UnsupportedOperationException(String.format(
+ "The LogicalVisitor of type %s does not currently support visiting the PhysicalOperator type %s.", this
+ .getClass().getCanonicalName(), op.getClass().getCanonicalName()));
+ }
+
+ @Override
+ public T visitScan(Scan scan, X value) throws E {
+ return visitOp(scan, value);
+ }
+
+ @Override
+ public T visitStore(Store store, X value) throws E {
+ return visitOp(store, value);
+ }
+
+ @Override
+ public T visitFilter(Filter filter, X value) throws E {
+ return visitOp(filter, value);
+ }
+
+ @Override
+ public T visitFlatten(Flatten flatten, X value) throws E {
+ return visitOp(flatten, value);
+ }
+
+ @Override
+ public T visitProject(Project project, X value) throws E {
+ return visitOp(project, value);
+ }
+
+ @Override
+ public T visitOrder(Order order, X value) throws E {
+ return visitOp(order, value);
+ }
+
+ @Override
+ public T visitJoin(Join join, X value) throws E {
+ return visitOp(join, value);
+ }
+
+ @Override
+ public T visitLimit(Limit limit, X value) throws E {
+ return visitOp(limit, value);
+ }
+
+ @Override
+ public T visitRunningAggregate(RunningAggregate runningAggregate, X value) throws E {
+ return visitOp(runningAggregate, value);
+ }
+
+ @Override
+ public T visitGroupingAggregate(GroupingAggregate groupBy, X value) throws E {
+ return visitOp(groupBy, value);
+ }
+
+ @Override
+ public T visitSequence(Sequence sequence, X value) throws E {
+ return visitOp(sequence, value);
+ }
+
+ @Override
+ public T visitTransform(Transform transform, X value) throws E {
+ return visitOp(transform, value);
+ }
+
+ @Override
+ public T visitUnion(Union union, X value) throws E {
+ return visitOp(union, value);
+ }
+
+ @Override
+ public T visitWindow(Window window, X value) throws E {
+ return visitOp(window, value);
+ }
+
+ @Override
+ public T visitValues(Values constant, X value) throws E {
+ return visitOp(constant, value);
+ }
+
+ @Override
+ public T visitWriter(Writer writer, X value) throws E {
+ return visitOp(writer, value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/visitors/LogicalVisitor.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/visitors/LogicalVisitor.java b/logical/src/main/java/org/apache/drill/common/logical/data/visitors/LogicalVisitor.java
new file mode 100644
index 0000000..1e07dc6
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/visitors/LogicalVisitor.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.common.logical.data.visitors;
+
+
+import org.apache.drill.common.logical.data.Values;
+import org.apache.drill.common.logical.data.Filter;
+import org.apache.drill.common.logical.data.Flatten;
+import org.apache.drill.common.logical.data.GroupingAggregate;
+import org.apache.drill.common.logical.data.Join;
+import org.apache.drill.common.logical.data.Limit;
+import org.apache.drill.common.logical.data.Order;
+import org.apache.drill.common.logical.data.Project;
+import org.apache.drill.common.logical.data.RunningAggregate;
+import org.apache.drill.common.logical.data.Scan;
+import org.apache.drill.common.logical.data.Sequence;
+import org.apache.drill.common.logical.data.Store;
+import org.apache.drill.common.logical.data.Transform;
+import org.apache.drill.common.logical.data.Union;
+import org.apache.drill.common.logical.data.Window;
+import org.apache.drill.common.logical.data.Window;
+import org.apache.drill.common.logical.data.Writer;
+
+/**
+ * Visitor class designed to traversal of a operator tree. Basis for a number of operator manipulations including fragmentation and materialization.
+ * @param <RETURN> The class associated with the return of each visit method.
+ * @param <EXTRA> The class object associated with additional data required for a particular operator modification.
+ * @param <EXCEP> An optional exception class that can be thrown when a portion of a modification or traversal fails. Must extend Throwable. In the case where the visitor does not throw any caught exception, this can be set as RuntimeException.
+ */
+public interface LogicalVisitor<RETURN, EXTRA, EXCEP extends Throwable> {
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(LogicalVisitor.class);
+
+
+ public RETURN visitScan(Scan scan, EXTRA value) throws EXCEP;
+ public RETURN visitStore(Store store, EXTRA value) throws EXCEP;
+ public RETURN visitGroupingAggregate(GroupingAggregate groupBy, EXTRA value) throws EXCEP;
+ public RETURN visitFilter(Filter filter, EXTRA value) throws EXCEP;
+ public RETURN visitFlatten(Flatten flatten, EXTRA value) throws EXCEP;
+
+ public RETURN visitProject(Project project, EXTRA value) throws EXCEP;
+ public RETURN visitValues(Values constant, EXTRA value) throws EXCEP;
+ public RETURN visitOrder(Order order, EXTRA value) throws EXCEP;
+ public RETURN visitJoin(Join join, EXTRA value) throws EXCEP;
+ public RETURN visitLimit(Limit limit, EXTRA value) throws EXCEP;
+ public RETURN visitRunningAggregate(RunningAggregate runningAggregate, EXTRA value) throws EXCEP;
+ public RETURN visitSequence(Sequence sequence, EXTRA value) throws EXCEP;
+ public RETURN visitTransform(Transform transform, EXTRA value) throws EXCEP;
+ public RETURN visitUnion(Union union, EXTRA value) throws EXCEP;
+ public RETURN visitWindow(Window window, EXTRA value) throws EXCEP;
+ public RETURN visitWriter(Writer writer, EXTRA value) throws EXCEP;
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/data/visitors/package-info.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/data/visitors/package-info.java b/logical/src/main/java/org/apache/drill/common/logical/data/visitors/package-info.java
new file mode 100644
index 0000000..9b82bb3
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/data/visitors/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.
+ */
+/**
+ * Visitors for Drill logical plan graphs.
+ */
+package org.apache.drill.common.logical.data.visitors;
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/main/java/org/apache/drill/common/logical/package-info.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/logical/package-info.java b/logical/src/main/java/org/apache/drill/common/logical/package-info.java
new file mode 100644
index 0000000..1f88f06
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/logical/package-info.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.
+ */
+/**
+ * Storage plugin interfaces and logical plan representation.
+ *
+ * This package includes the interface for storage and format plugins for Drill
+ * as well as the top level class for representing a Drill logical plan and a
+ * builder for constructing plans.
+ */
+package org.apache.drill.common.logical;
\ 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/util/AbstractDynamicBean.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/util/AbstractDynamicBean.java b/logical/src/main/java/org/apache/drill/common/util/AbstractDynamicBean.java
new file mode 100644
index 0000000..07a3620
--- /dev/null
+++ b/logical/src/main/java/org/apache/drill/common/util/AbstractDynamicBean.java
@@ -0,0 +1,81 @@
+/**
+ * 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.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.drill.common.exceptions.LogicalPlanParsingException;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.core.JsonParser.Feature;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Captures all properties and turns them into an object node for late bind conversion.
+ */
+public abstract class AbstractDynamicBean {
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AbstractDynamicBean.class);
+
+ private static volatile ObjectMapper MAPPER;
+
+ private ObjectNode objectNode = new ObjectNode(null);
+
+ @JsonAnySetter
+ public void _anySetter(String name, JsonNode value){
+ objectNode.put(name, value);
+ }
+
+ @JsonAnyGetter
+ public Map<String,JsonNode> _anyGetter() {
+ Map<String, JsonNode> unknowns = new HashMap<String, JsonNode>();
+
+ for(Iterator<Entry<String, JsonNode>> i = objectNode.fields(); i.hasNext(); ){
+ Entry<String, JsonNode> e = i.next();
+ unknowns.put(e.getKey(), e.getValue());
+ }
+ return unknowns;
+ }
+
+ public <T> T getWith(Class<T> c){
+ try {
+ return getMapper().treeToValue(objectNode, c);
+ } catch (JsonProcessingException e) {
+ throw new LogicalPlanParsingException(String.format("Failure while trying to convert late bound json type to type of %s.", c.getCanonicalName()), e);
+ }
+ }
+
+
+ private static synchronized ObjectMapper getMapper(){
+ if(MAPPER == null){
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
+ mapper.configure(Feature.ALLOW_COMMENTS, true);
+ MAPPER = mapper;
+ }
+ return MAPPER;
+ }
+}
http://git-wip-us.apache.org/repos/asf/drill/blob/44dea433/logical/src/test/java/org/apache/drill/common/expression/PathSegmentTests.java
----------------------------------------------------------------------
diff --git a/logical/src/test/java/org/apache/drill/common/expression/PathSegmentTests.java b/logical/src/test/java/org/apache/drill/common/expression/PathSegmentTests.java
new file mode 100644
index 0000000..97cd578
--- /dev/null
+++ b/logical/src/test/java/org/apache/drill/common/expression/PathSegmentTests.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.expression;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.drill.test.DrillTest;
+import org.junit.Test;
+
+public class PathSegmentTests extends DrillTest {
+ protected PathSegment makeArraySegment(final int len, final PathSegment tail) {
+ PathSegment node = tail;
+ for (int i = 0; i < len; i++) {
+ node = new PathSegment.ArraySegment(node);
+ }
+ return node;
+ }
+
+ @Test
+ public void testIfMultiLevelCloneWorks() {
+ final int levels = 10;
+ final PathSegment segment = new PathSegment.NameSegment("test", makeArraySegment(levels, null));
+ final PathSegment clone = segment.clone();
+ assertEquals("result of clone & original segments must be identical", segment, clone);
+
+ final PathSegment tail = new PathSegment.NameSegment("tail");
+ final PathSegment newSegment = new PathSegment.NameSegment("test", makeArraySegment(levels, tail));
+ final PathSegment newClone = segment.cloneWithNewChild(tail);
+ assertEquals("result of cloneWithChild & original segment must be identical", newSegment, newClone);
+ }
+}