You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2014/04/18 11:19:56 UTC
[34/51] [partial] TAJO-752: Escalate sub modules in tajo-core into
the top-level modules. (hyunsik)
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/BinaryNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/BinaryNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/BinaryNode.java
new file mode 100644
index 0000000..8aaeb58
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/BinaryNode.java
@@ -0,0 +1,77 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.json.GsonObject;
+
+public abstract class BinaryNode extends LogicalNode implements Cloneable, GsonObject {
+ @Expose LogicalNode leftChild = null;
+ @Expose LogicalNode rightChild = null;
+
+ public BinaryNode(int pid, NodeType nodeType) {
+ super(pid, nodeType);
+ }
+
+ public <T extends LogicalNode> T getLeftChild() {
+ return (T) this.leftChild;
+ }
+
+ public void setLeftChild(LogicalNode op) {
+ this.leftChild = op;
+ }
+
+ public <T extends LogicalNode> T getRightChild() {
+ return (T) this.rightChild;
+ }
+
+ public void setRightChild(LogicalNode op) {
+ this.rightChild = op;
+ }
+
+ public boolean deepEquals(Object o) {
+ if (o instanceof BinaryNode) {
+ BinaryNode b = (BinaryNode) o;
+ return equals(o) &&
+ leftChild.deepEquals(b.leftChild) && rightChild.deepEquals(b.rightChild);
+ }
+ return false;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ BinaryNode binNode = (BinaryNode) super.clone();
+ binNode.leftChild = (LogicalNode) leftChild.clone();
+ binNode.rightChild = (LogicalNode) rightChild.clone();
+
+ return binNode;
+ }
+
+ public void preOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ leftChild.postOrder(visitor);
+ rightChild.postOrder(visitor);
+ }
+
+ public void postOrder(LogicalNodeVisitor visitor) {
+ leftChild.postOrder(visitor);
+ rightChild.postOrder(visitor);
+ visitor.visit(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/CreateDatabaseNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/CreateDatabaseNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/CreateDatabaseNode.java
new file mode 100644
index 0000000..9dc73e2
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/CreateDatabaseNode.java
@@ -0,0 +1,87 @@
+/*
+ * 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.tajo.engine.planner.logical;
+
+import com.google.common.base.Objects;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.engine.planner.PlanString;
+
+public class CreateDatabaseNode extends LogicalNode implements Cloneable {
+ private String databaseName;
+ private boolean ifNotExists;
+
+ public CreateDatabaseNode(int pid) {
+ super(pid, NodeType.CREATE_DATABASE);
+ }
+
+ public void init(String databaseName, boolean ifNotExists) {
+ this.databaseName = databaseName;
+ this.ifNotExists = ifNotExists;
+ }
+
+ public String getDatabaseName() {
+ return this.databaseName;
+ }
+
+ public boolean isIfNotExists() {
+ return ifNotExists;
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ return new PlanString(this).appendTitle(ifNotExists ? " IF NOT EXISTS " : " ").appendTitle(databaseName);
+ }
+
+ public int hashCode() {
+ return Objects.hashCode(databaseName, ifNotExists);
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof CreateDatabaseNode) {
+ CreateDatabaseNode other = (CreateDatabaseNode) obj;
+ return super.equals(other) && this.databaseName.equals(other.databaseName) && ifNotExists == other.ifNotExists;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ CreateDatabaseNode newNode = (CreateDatabaseNode) super.clone();
+ newNode.databaseName = databaseName;
+ newNode.ifNotExists = ifNotExists;
+ return newNode;
+ }
+
+ @Override
+ public String toString() {
+ return "CREATE DATABASE " + (ifNotExists ? " IF NOT EXISTS " : "")
+ + CatalogUtil.denormalizeIdentifier(databaseName);
+ }
+
+ @Override
+ public void preOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public void postOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
new file mode 100644
index 0000000..c70fb10
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
@@ -0,0 +1,145 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.catalog.Options;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.util.TUtil;
+
+public class CreateTableNode extends StoreTableNode implements Cloneable {
+ @Expose private Schema schema;
+ @Expose private Path path;
+ @Expose private boolean external;
+ @Expose private boolean ifNotExists;
+
+ public CreateTableNode(int pid) {
+ super(pid, NodeType.CREATE_TABLE);
+ }
+
+ public void setTableSchema(Schema schema) {
+ this.schema = schema;
+ }
+
+ public Schema getTableSchema() {
+ return this.schema;
+ }
+
+ public Schema getLogicalSchema() {
+ if (hasPartition()) {
+ Schema logicalSchema = new Schema(schema);
+ logicalSchema.addColumns(getPartitionMethod().getExpressionSchema());
+ return logicalSchema;
+ } else {
+ return schema;
+ }
+ }
+
+ public boolean hasPath() {
+ return this.path != null;
+ }
+
+ public void setPath(Path path) {
+ this.path = path;
+ }
+
+ public Path getPath() {
+ return this.path;
+ }
+
+ public boolean isExternal() {
+ return external;
+ }
+
+ public void setExternal(boolean external) {
+ this.external = external;
+ }
+
+ public boolean hasSubQuery() {
+ return child != null;
+ }
+
+ public void setIfNotExists(boolean ifNotExists) {
+ this.ifNotExists = ifNotExists;
+ }
+
+ public boolean isIfNotExists() {
+ return ifNotExists;
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ return new PlanString(this);
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ Objects.hashCode(schema, path, external, ifNotExists) * 31;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof CreateTableNode) {
+ CreateTableNode other = (CreateTableNode) obj;
+ return super.equals(other)
+ && this.schema.equals(other.schema)
+ && this.external == other.external
+ && TUtil.checkEquals(path, other.path)
+ && ifNotExists == other.ifNotExists;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ CreateTableNode createTableNode = (CreateTableNode) super.clone();
+ createTableNode.tableName = tableName;
+ createTableNode.schema = (Schema) schema.clone();
+ createTableNode.storageType = storageType;
+ createTableNode.external = external;
+ createTableNode.path = path != null ? new Path(path.toString()) : null;
+ createTableNode.options = (Options) (options != null ? options.clone() : null);
+ createTableNode.ifNotExists = ifNotExists;
+ return createTableNode;
+ }
+
+ public String toString() {
+ return "CreateTable (table=" + tableName + ", external=" + external + ", storeType=" + storageType +
+ ", ifNotExists=" + ifNotExists +")";
+ }
+
+ @Override
+ public void preOrder(LogicalNodeVisitor visitor) {
+ if (hasSubQuery()) {
+ child.preOrder(visitor);
+ }
+ visitor.visit(this);
+ }
+
+ @Override
+ public void postOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ if (hasSubQuery()) {
+ child.preOrder(visitor);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/DropDatabaseNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/DropDatabaseNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/DropDatabaseNode.java
new file mode 100644
index 0000000..1578759
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/DropDatabaseNode.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.tajo.engine.planner.logical;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.engine.planner.PlanString;
+
+public class DropDatabaseNode extends LogicalNode implements Cloneable {
+ @Expose private String databaseName;
+ @Expose private boolean ifExists;
+
+ public DropDatabaseNode(int pid) {
+ super(pid, NodeType.DROP_DATABASE);
+ }
+
+ public void init(String databaseName, boolean ifExists) {
+ this.databaseName = databaseName;
+ this.ifExists = ifExists;
+ }
+
+ public String getDatabaseName() {
+ return this.databaseName;
+ }
+
+ public boolean isIfExists() {
+ return ifExists;
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ return new PlanString(this).appendTitle(ifExists ? " IF EXISTS " : " ").appendTitle(databaseName);
+ }
+
+ public int hashCode() {
+ return Objects.hashCode(databaseName, ifExists);
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof DropDatabaseNode) {
+ DropDatabaseNode other = (DropDatabaseNode) obj;
+ return super.equals(other) && this.databaseName.equals(other.databaseName) && ifExists == other.ifExists;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ DropDatabaseNode dropTableNode = (DropDatabaseNode) super.clone();
+ dropTableNode.databaseName = databaseName;
+ return dropTableNode;
+ }
+
+ @Override
+ public String toString() {
+ return "DROP DATABASE " + (ifExists ? "IF EXISTS ":"") + databaseName;
+ }
+
+ @Override
+ public void preOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public void postOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
new file mode 100644
index 0000000..ac68a9c
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
@@ -0,0 +1,95 @@
+/*
+ * 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.tajo.engine.planner.logical;
+
+import com.google.common.base.Objects;
+import org.apache.tajo.engine.planner.PlanString;
+
+public class DropTableNode extends LogicalNode implements Cloneable {
+ private String tableName;
+ private boolean ifExists;
+ private boolean purge;
+
+ public DropTableNode(int pid) {
+ super(pid, NodeType.DROP_TABLE);
+ }
+
+ public void init(String tableName, boolean ifExists, boolean purge) {
+ this.tableName = tableName;
+ this.ifExists = ifExists;
+ this.purge = purge;
+ }
+
+ public String getTableName() {
+ return this.tableName;
+ }
+
+ public boolean isIfExists() {
+ return this.ifExists;
+ }
+
+ public boolean isPurge() {
+ return this.purge;
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ return new PlanString(this).appendTitle(ifExists ? " IF EXISTS" : "").appendTitle(purge ? " PURGE" : "");
+ }
+
+ public int hashCode() {
+ return Objects.hashCode(tableName, ifExists, purge);
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof DropTableNode) {
+ DropTableNode other = (DropTableNode) obj;
+ return super.equals(other) &&
+ this.tableName.equals(other.tableName) &&
+ this.ifExists == other.ifExists &&
+ this.purge == other.purge;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ DropTableNode dropTableNode = (DropTableNode) super.clone();
+ dropTableNode.tableName = tableName;
+ dropTableNode.ifExists = ifExists;
+ dropTableNode.purge = purge;
+ return dropTableNode;
+ }
+
+ @Override
+ public String toString() {
+ return "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + tableName + (purge ? " PURGE" : "");
+ }
+
+ @Override
+ public void preOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public void postOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/EvalExprNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/EvalExprNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/EvalExprNode.java
new file mode 100644
index 0000000..6ea3f40
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/EvalExprNode.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ *
+ */
+package org.apache.tajo.engine.planner.logical;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.util.TUtil;
+
+public class EvalExprNode extends LogicalNode implements Projectable {
+ @Expose private Target[] exprs;
+
+ public EvalExprNode(int pid) {
+ super(pid, NodeType.EXPRS);
+ }
+
+ @Override
+ public boolean hasTargets() {
+ return true;
+ }
+
+ @Override
+ public void setTargets(Target[] targets) {
+ this.exprs = targets;
+ }
+
+ @Override
+ public Target[] getTargets() {
+ return exprs;
+ }
+
+ public Target[] getExprs() {
+ return this.exprs;
+ }
+
+ @Override
+ public String toString() {
+ return "EvalExprNode (" + TUtil.arrayToString(exprs) + ")";
+ }
+
+ public boolean equals(Object object) {
+ if (object instanceof EvalExprNode) {
+ EvalExprNode other = (EvalExprNode) object;
+ return TUtil.checkEquals(this.exprs, other.exprs);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void preOrder(LogicalNodeVisitor visitor) {
+ // nothing
+ }
+
+ @Override
+ public void postOrder(LogicalNodeVisitor visitor) {
+ // nothing
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ExceptNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ExceptNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ExceptNode.java
new file mode 100644
index 0000000..1540e1c
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ExceptNode.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ *
+ */
+package org.apache.tajo.engine.planner.logical;
+
+import org.apache.tajo.engine.planner.PlanString;
+
+public class ExceptNode extends BinaryNode {
+
+ public ExceptNode(int pid) {
+ super(pid, NodeType.EXCEPT);
+ }
+
+ public void init(LogicalNode left, LogicalNode right) {
+ setLeftChild(left);
+ setRightChild(right);
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ PlanString planStr = new PlanString(this);
+ planStr.appendTitle(" (L - " + ((TableSubQueryNode)getLeftChild()).getTableName());
+ planStr.appendTitle(", R - " + ((TableSubQueryNode)getRightChild()).getTableName());
+ planStr.appendTitle(")");
+ return planStr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
new file mode 100644
index 0000000..bafe0c6
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
@@ -0,0 +1,198 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Column;
+import org.apache.tajo.engine.eval.AggregationFunctionCallEval;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.engine.planner.PlannerUtil;
+import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.util.TUtil;
+
+public class GroupbyNode extends UnaryNode implements Projectable, Cloneable {
+ /** Grouping key sets */
+ @Expose private Column [] groupingColumns;
+ /** Aggregation Functions */
+ @Expose private AggregationFunctionCallEval [] aggrFunctions;
+ /**
+ * It's a list of targets. The grouping columns should be followed by aggregation functions.
+ * aggrFunctions keep actual aggregation functions, but it only contains field references.
+ * */
+ @Expose private Target [] targets;
+ @Expose private boolean hasDistinct = false;
+
+ public GroupbyNode(int pid) {
+ super(pid, NodeType.GROUP_BY);
+ }
+
+ public final boolean isEmptyGrouping() {
+ return groupingColumns == null || groupingColumns.length == 0;
+ }
+
+ public void setGroupingColumns(Column [] groupingColumns) {
+ this.groupingColumns = groupingColumns;
+ }
+
+ public final Column [] getGroupingColumns() {
+ return this.groupingColumns;
+ }
+
+ public final boolean isDistinct() {
+ return hasDistinct;
+ }
+
+ public void setDistinct(boolean distinct) {
+ hasDistinct = distinct;
+ }
+
+ public boolean hasAggFunctions() {
+ return this.aggrFunctions != null;
+ }
+
+ public AggregationFunctionCallEval [] getAggFunctions() {
+ return this.aggrFunctions;
+ }
+
+ public void setAggFunctions(AggregationFunctionCallEval[] evals) {
+ this.aggrFunctions = evals;
+ }
+
+ @Override
+ public boolean hasTargets() {
+ return this.targets != null;
+ }
+
+ @Override
+ public void setTargets(Target[] targets) {
+ this.targets = targets;
+ setOutSchema(PlannerUtil.targetToSchema(targets));
+ }
+
+ @Override
+ public Target[] getTargets() {
+ return this.targets;
+ }
+
+ public void setChild(LogicalNode subNode) {
+ super.setChild(subNode);
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("GroupBy (");
+ if (groupingColumns != null || groupingColumns.length > 0) {
+ sb.append("grouping set=").append(TUtil.arrayToString(groupingColumns));
+ sb.append(", ");
+ }
+ if (hasAggFunctions()) {
+ sb.append("funcs=").append(TUtil.arrayToString(aggrFunctions));
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof GroupbyNode) {
+ GroupbyNode other = (GroupbyNode) obj;
+ boolean eq = super.equals(other);
+ eq = eq && TUtil.checkEquals(groupingColumns, other.groupingColumns);
+ eq = eq && TUtil.checkEquals(aggrFunctions, other.aggrFunctions);
+ eq = eq && TUtil.checkEquals(targets, other.targets);
+ return eq;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ GroupbyNode grp = (GroupbyNode) super.clone();
+ if (groupingColumns != null) {
+ grp.groupingColumns = new Column[groupingColumns.length];
+ for (int i = 0; i < groupingColumns.length; i++) {
+ grp.groupingColumns[i] = groupingColumns[i];
+ }
+ }
+
+ if (aggrFunctions != null) {
+ grp.aggrFunctions = new AggregationFunctionCallEval[aggrFunctions.length];
+ for (int i = 0; i < aggrFunctions.length; i++) {
+ grp.aggrFunctions[i] = (AggregationFunctionCallEval) aggrFunctions[i].clone();
+ }
+ }
+
+ if (targets != null) {
+ grp.targets = new Target[targets.length];
+ for (int i = 0; i < targets.length; i++) {
+ grp.targets[i] = (Target) targets[i].clone();
+ }
+ }
+
+ return grp;
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ PlanString planStr = new PlanString(this);
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("(");
+ Column [] groupingColumns = this.groupingColumns;
+ for (int j = 0; j < groupingColumns.length; j++) {
+ sb.append(groupingColumns[j].getSimpleName());
+ if(j < groupingColumns.length - 1) {
+ sb.append(",");
+ }
+ }
+
+ sb.append(")");
+
+ planStr.appendTitle(sb.toString());
+
+ // there can be no aggregation functions
+ if (hasAggFunctions()) {
+ sb = new StringBuilder();
+ sb.append("(");
+
+ for (int j = 0; j < aggrFunctions.length; j++) {
+ sb.append(aggrFunctions[j]);
+ if(j < aggrFunctions.length - 1) {
+ sb.append(",");
+ }
+ }
+ sb.append(")");
+ planStr.appendExplain("exprs: ").appendExplain(sb.toString());
+ }
+
+ sb = new StringBuilder("target list: ");
+ for (int i = 0; i < targets.length; i++) {
+ sb.append(targets[i]);
+ if( i < targets.length - 1) {
+ sb.append(", ");
+ }
+ }
+ planStr.addExplan(sb.toString());
+
+ planStr.addDetail("out schema:").appendDetail(getOutSchema().toString());
+ planStr.addDetail("in schema:").appendDetail(getInSchema().toString());
+
+ return planStr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/HavingNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/HavingNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/HavingNode.java
new file mode 100644
index 0000000..6c45868
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/HavingNode.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.tajo.engine.planner.logical;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.engine.planner.PlanString;
+
+public class HavingNode extends UnaryNode implements Cloneable {
+ @Expose private EvalNode qual;
+
+ public HavingNode(int pid) {
+ super(pid, NodeType.HAVING);
+ }
+
+ public EvalNode getQual() {
+ return this.qual;
+ }
+
+ public void setQual(EvalNode qual) {
+ this.qual = qual;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof HavingNode) {
+ HavingNode other = (HavingNode) obj;
+ return super.equals(other)
+ && this.qual.equals(other.qual);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ HavingNode selNode = (HavingNode) super.clone();
+ selNode.qual = (EvalNode) this.qual.clone();
+
+ return selNode;
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ return new PlanString(this).appendTitle(" (").appendTitle(qual.toString()).appendTitle(")");
+ }
+
+ public String toString() {
+ return "Having (filter=" + qual + ")";
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/IndexScanNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/IndexScanNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/IndexScanNode.java
new file mode 100644
index 0000000..bff0b31
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/IndexScanNode.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.tajo.engine.planner.logical;
+
+import com.google.gson.Gson;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.catalog.SortSpec;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.engine.json.CoreGsonHelper;
+
+public class IndexScanNode extends ScanNode {
+ @Expose private SortSpec [] sortKeys;
+ @Expose private Schema keySchema = null;
+ @Expose private Datum[] datum = null;
+
+ public IndexScanNode(int pid, ScanNode scanNode ,
+ Schema keySchema , Datum[] datum, SortSpec[] sortKeys ) {
+ super(pid);
+ init(scanNode.getTableDesc());
+ setQual(scanNode.getQual());
+ setInSchema(scanNode.getInSchema());
+ setTargets(scanNode.getTargets());
+ setType(NodeType.BST_INDEX_SCAN);
+ this.sortKeys = sortKeys;
+ this.keySchema = keySchema;
+ this.datum = datum;
+ }
+
+ public SortSpec[] getSortKeys() {
+ return this.sortKeys;
+ }
+
+ public Schema getKeySchema() {
+ return this.keySchema;
+ }
+
+ public Datum[] getDatum() {
+ return this.datum;
+ }
+
+ public void setSortKeys(SortSpec[] sortKeys) {
+ this.sortKeys = sortKeys;
+ }
+
+ public void setKeySchema( Schema keySchema ) {
+ this.keySchema = keySchema;
+ }
+
+ @Override
+ public String toString() {
+ Gson gson = CoreGsonHelper.getInstance();
+ StringBuilder builder = new StringBuilder();
+ builder.append("IndexScanNode : {\n");
+ builder.append(" \"keySchema\" : \"" + gson.toJson(this.keySchema) + "\"\n");
+ builder.append(" \"sortKeys\" : \"" + gson.toJson(this.sortKeys) + " \"\n");
+ builder.append(" \"datums\" : \"" + gson.toJson(this.datum) + "\"\n");
+ builder.append(" <<\"superClass\" : " + super.toString());
+ builder.append(">>}");
+ builder.append("}");
+ return builder.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof IndexScanNode) {
+ IndexScanNode other = (IndexScanNode) obj;
+
+ boolean eq = super.equals(other);
+ eq = eq && this.sortKeys.length == other.sortKeys.length;
+ if(eq) {
+ for(int i = 0 ; i < this.sortKeys.length ; i ++) {
+ eq = eq && this.sortKeys[i].getSortKey().equals(
+ other.sortKeys[i].getSortKey());
+ eq = eq && this.sortKeys[i].isAscending()
+ == other.sortKeys[i].isAscending();
+ eq = eq && this.sortKeys[i].isNullFirst()
+ == other.sortKeys[i].isNullFirst();
+ }
+ }
+ if(eq) {
+ for(int i = 0 ; i < this.datum.length ; i ++ ) {
+ eq = eq && this.datum[i].equals(other.datum[i]);
+ }
+ }
+ return eq;
+ }
+ return false;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ IndexScanNode indexNode = (IndexScanNode) super.clone();
+ indexNode.keySchema = (Schema) this.keySchema.clone();
+ indexNode.sortKeys = new SortSpec[this.sortKeys.length];
+ for(int i = 0 ; i < sortKeys.length ; i ++ )
+ indexNode.sortKeys[i] = (SortSpec) this.sortKeys[i].clone();
+ indexNode.datum = new Datum[this.datum.length];
+ for(int i = 0 ; i < datum.length ; i ++ ) {
+ indexNode.datum[i] = this.datum[i];
+ }
+ return indexNode;
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/InsertNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/InsertNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/InsertNode.java
new file mode 100644
index 0000000..f5e87ef
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/InsertNode.java
@@ -0,0 +1,182 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import com.google.gson.annotations.Expose;
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.util.TUtil;
+
+public class InsertNode extends StoreTableNode implements Cloneable {
+ @Expose private boolean overwrite;
+ @Expose private Schema tableSchema;
+
+ /** a target schema of a target table */
+ @Expose private Schema targetSchema;
+ /** a output schema of select clause */
+ @Expose private Schema projectedSchema;
+ @Expose private Path path;
+
+ public InsertNode(int pid) {
+ super(pid, NodeType.INSERT);
+ }
+
+ public void setTargetTable(TableDesc desc) {
+ setTableName(desc.getName());
+ if (desc.hasPartition()) {
+ tableSchema = desc.getLogicalSchema();
+ } else {
+ tableSchema = desc.getSchema();
+ }
+ setPath(desc.getPath());
+ setOptions(desc.getMeta().getOptions());
+ setStorageType(desc.getMeta().getStoreType());
+
+ if (desc.hasPartition()) {
+ this.setPartitionMethod(desc.getPartitionMethod());
+ }
+ }
+
+ public void setTargetLocation(Path path) {
+ this.path = path;
+ }
+
+ public void setSubQuery(LogicalNode subQuery) {
+ this.setChild(subQuery);
+ this.setInSchema(subQuery.getOutSchema());
+ this.setOutSchema(subQuery.getOutSchema());
+ }
+
+ public boolean isOverwrite() {
+ return overwrite;
+ }
+
+ public void setOverwrite(boolean overwrite) {
+ this.overwrite = overwrite;
+ }
+
+ public Schema getTableSchema() {
+ return tableSchema;
+ }
+
+ public void setTableSchema(Schema tableSchema) {
+ this.tableSchema = tableSchema;
+ }
+
+ public boolean hasTargetSchema() {
+ return this.targetSchema != null;
+ }
+
+ public Schema getTargetSchema() {
+ return this.targetSchema;
+ }
+
+ public void setTargetSchema(Schema schema) {
+ this.targetSchema = schema;
+ }
+
+ public Schema getProjectedSchema() {
+ return this.projectedSchema;
+ }
+
+ public void setProjectedSchema(Schema projected) {
+ this.projectedSchema = projected;
+ }
+
+ public boolean hasPath() {
+ return this.path != null;
+ }
+
+ public void setPath(Path path) {
+ this.path = path;
+ }
+
+ public Path getPath() {
+ return this.path;
+ }
+
+ public boolean hasStorageType() {
+ return this.storageType != null;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof InsertNode) {
+ InsertNode other = (InsertNode) obj;
+ return super.equals(other)
+ && this.overwrite == other.overwrite
+ && TUtil.checkEquals(this.tableSchema, other.tableSchema)
+ && TUtil.checkEquals(this.targetSchema, other.targetSchema)
+ && TUtil.checkEquals(path, other.path);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ InsertNode insertNode = (InsertNode) super.clone();
+ insertNode.overwrite = overwrite;
+ insertNode.tableSchema = new Schema(tableSchema);
+ insertNode.targetSchema = targetSchema != null ? new Schema(targetSchema) : null;
+ insertNode.path = path != null ? new Path(path.toString()) : null;
+ return insertNode;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Insert (overwrite=").append(overwrite);
+ if (hasTargetTable()) {
+ sb.append(",table=").append(tableName);
+ }
+ if (hasPath()) {
+ sb.append(", location=").append(path);
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ @Override
+ public void preOrder(LogicalNodeVisitor visitor) {
+ getChild().preOrder(visitor);
+ visitor.visit(this);
+ }
+
+ @Override
+ public void postOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ getChild().postOrder(visitor);
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ PlanString planString = new PlanString(this);
+ planString.appendTitle(" INTO ");
+ if (hasTargetTable()) {
+ planString.appendTitle(getTableName());
+ if (hasTargetSchema()) {
+ planString.addExplan(getTargetSchema().toString());
+ }
+ } else {
+ planString.addExplan("LOCATION " + path);
+ }
+ return planString;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/IntersectNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/IntersectNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/IntersectNode.java
new file mode 100644
index 0000000..4bcfd24
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/IntersectNode.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.tajo.engine.planner.logical;
+
+import org.apache.tajo.engine.planner.PlanString;
+
+public class IntersectNode extends BinaryNode {
+ public IntersectNode(int pid) {
+ super(pid, NodeType.INTERSECT);
+ }
+
+ public void init(LogicalNode left, LogicalNode right) {
+ setLeftChild(left);
+ setRightChild(right);
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ PlanString planStr = new PlanString(this);
+ planStr.appendTitle(" (L - " + ((TableSubQueryNode)getLeftChild()).getTableName());
+ planStr.appendTitle(", R - " + ((TableSubQueryNode)getRightChild()).getTableName());
+ planStr.appendTitle(")");
+ return planStr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/JoinNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/JoinNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/JoinNode.java
new file mode 100644
index 0000000..915c66d
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/JoinNode.java
@@ -0,0 +1,165 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ *
+ */
+package org.apache.tajo.engine.planner.logical;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.algebra.JoinType;
+import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.engine.planner.PlannerUtil;
+import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.util.TUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JoinNode extends BinaryNode implements Projectable, Cloneable {
+ @Expose private JoinType joinType;
+ @Expose private EvalNode joinQual;
+ @Expose private Target[] targets;
+
+ @Expose private boolean candidateBroadcast = false;
+ @Expose private List<LogicalNode> broadcastTargets = new ArrayList<LogicalNode>();
+
+ public JoinNode(int pid) {
+ super(pid, NodeType.JOIN);
+ }
+
+ public void init(JoinType joinType, LogicalNode left, LogicalNode right) {
+ this.joinType = joinType;
+ setLeftChild(left);
+ setRightChild(right);
+ }
+
+ public boolean isCandidateBroadcast() {
+ return candidateBroadcast;
+ }
+
+ public void setCandidateBroadcast(boolean candidateBroadcast) {
+ this.candidateBroadcast = candidateBroadcast;
+ }
+
+ public List<LogicalNode> getBroadcastTargets() {
+ return broadcastTargets;
+ }
+
+ public void setBroadcastTargets(List<LogicalNode> broadcastTargets) {
+ this.broadcastTargets = broadcastTargets;
+ }
+
+ public JoinType getJoinType() {
+ return this.joinType;
+ }
+
+ public void setJoinType(JoinType joinType) {
+ this.joinType = joinType;
+ }
+
+ public void setJoinQual(EvalNode joinQual) {
+ this.joinQual = joinQual;
+ }
+
+ public boolean hasJoinQual() {
+ return this.joinQual != null;
+ }
+
+ public EvalNode getJoinQual() {
+ return this.joinQual;
+ }
+
+ @Override
+ public boolean hasTargets() {
+ return this.targets != null;
+ }
+
+ @Override
+ public Target[] getTargets() {
+ return this.targets;
+ }
+
+ @Override
+ public void setTargets(Target[] targets) {
+ this.targets = targets;
+ this.setOutSchema(PlannerUtil.targetToSchema(targets));
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ PlanString planStr = new PlanString(this).appendTitle("(").appendTitle(joinType.name()).appendTitle(")");
+ if (hasJoinQual()) {
+ planStr.addExplan("Join Cond: " + joinQual.toString());
+ }
+
+ if (hasTargets()) {
+ planStr.addExplan("target list: ");
+ boolean first = true;
+ for (Target target : targets) {
+ if (!first) {
+ planStr.appendExplain(", ");
+ }
+ planStr.appendExplain(target.toString());
+ first = false;
+ }
+ }
+
+ planStr.addDetail("out schema: " + getOutSchema());
+ planStr.addDetail("in schema: " + getInSchema());
+
+ return planStr;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof JoinNode) {
+ JoinNode other = (JoinNode) obj;
+ boolean eq = this.joinType.equals(other.joinType);
+ eq &= TUtil.checkEquals(this.targets, other.targets);
+ eq &= TUtil.checkEquals(joinQual, other.joinQual);
+ return eq && leftChild.equals(other.leftChild) && rightChild.equals(other.rightChild);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ JoinNode join = (JoinNode) super.clone();
+ join.joinType = this.joinType;
+ join.joinQual = this.joinQual == null ? null : (EvalNode) this.joinQual.clone();
+ if (hasTargets()) {
+ join.targets = new Target[targets.length];
+ for (int i = 0; i < targets.length; i++) {
+ join.targets[i] = (Target) targets[i].clone();
+ }
+ }
+ return join;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Join (type").append(joinType);
+ if (hasJoinQual()) {
+ sb.append(",filter=").append(joinQual);
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LimitNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LimitNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LimitNode.java
new file mode 100644
index 0000000..7f5b258
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LimitNode.java
@@ -0,0 +1,65 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.engine.planner.PlanString;
+
+public final class LimitNode extends UnaryNode implements Cloneable {
+ @Expose private long fetchFirstNum;
+
+ public LimitNode(int pid) {
+ super(pid, NodeType.LIMIT);
+ }
+
+ public void setFetchFirst(long num) {
+ this.fetchFirstNum = num;
+ }
+
+ public long getFetchFirstNum() {
+ return fetchFirstNum;
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ return new PlanString(this).appendTitle(" " + fetchFirstNum);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof LimitNode) {
+ LimitNode other = (LimitNode) obj;
+ return super.equals(other)
+ && fetchFirstNum == other.fetchFirstNum;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ LimitNode newLimitNode = (LimitNode) super.clone();
+ newLimitNode.fetchFirstNum = fetchFirstNum;
+ return newLimitNode;
+ }
+
+ public String toString() {
+ return "Limit (fetch first=" + fetchFirstNum + ")";
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNode.java
new file mode 100644
index 0000000..f62caa4
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNode.java
@@ -0,0 +1,128 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.json.CoreGsonHelper;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.engine.planner.PlannerUtil;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.util.TUtil;
+
+public abstract class LogicalNode implements Cloneable, GsonObject {
+ @Expose private int pid;
+ @Expose private NodeType type;
+ @Expose private Schema inputSchema;
+ @Expose private Schema outputSchema;
+
+ @Expose private double cost = 0;
+
+ protected LogicalNode(int pid, NodeType type) {
+ this.pid = pid;
+ this.type = type;
+ }
+
+ public int getPID() {
+ return pid;
+ }
+
+ public void setPID(int pid) {
+ this.pid = pid;
+ }
+
+ public NodeType getType() {
+ return this.type;
+ }
+
+ public void setType(NodeType type) {
+ this.type = type;
+ }
+
+ public double getCost() {
+ return this.cost;
+ }
+
+ public void setCost(double cost) {
+ this.cost = cost;
+ }
+
+ public void setInSchema(Schema inSchema) {
+ this.inputSchema = inSchema;
+ }
+
+ public Schema getInSchema() {
+ return this.inputSchema;
+ }
+
+ public void setOutSchema(Schema outSchema) {
+ this.outputSchema = outSchema;
+ }
+
+ public Schema getOutSchema() {
+ return this.outputSchema;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof LogicalNode) {
+ LogicalNode other = (LogicalNode) obj;
+
+ boolean eq = this.type == other.type;
+ eq = eq && TUtil.checkEquals(this.inputSchema, other.inputSchema);
+ eq = eq && TUtil.checkEquals(this.outputSchema, other.outputSchema);
+ eq = eq && this.cost == other.cost;
+
+ return eq;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean deepEquals(Object o) {
+ return equals(o);
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ LogicalNode node = (LogicalNode)super.clone();
+ node.pid = pid;
+ node.type = type;
+ node.inputSchema = (Schema) (inputSchema != null ? inputSchema.clone() : null);
+ node.outputSchema = (Schema) (outputSchema != null ? outputSchema.clone() : null);
+ return node;
+ }
+
+ @Override
+ public String toJson() {
+ return CoreGsonHelper.toJson(this, LogicalNode.class);
+ }
+
+ public abstract void preOrder(LogicalNodeVisitor visitor);
+ public abstract void postOrder(LogicalNodeVisitor visitor);
+
+ public abstract PlanString getPlanString();
+
+ public String toString() {
+ return PlannerUtil.buildExplainString(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNodeVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNodeVisitor.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNodeVisitor.java
new file mode 100644
index 0000000..5b0c1c2
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalNodeVisitor.java
@@ -0,0 +1,27 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+
+public interface LogicalNodeVisitor {
+ void visit(LogicalNode node);
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalRootNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalRootNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalRootNode.java
new file mode 100644
index 0000000..bacf14f
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/LogicalRootNode.java
@@ -0,0 +1,41 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import org.apache.tajo.engine.planner.PlanString;
+
+public class LogicalRootNode extends UnaryNode implements Cloneable {
+ public LogicalRootNode(int pid) {
+ super(pid, NodeType.ROOT);
+ }
+
+ public String toString() {
+ return "Logical Plan Root\n\n" + getChild().toString();
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ return new PlanString(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
new file mode 100644
index 0000000..f498231
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.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.tajo.engine.planner.logical;
+
+
+import org.apache.tajo.engine.planner.AlterTablespaceNode;
+
+/**
+ * This indicates a logical node type.
+ */
+public enum NodeType {
+ ROOT(LogicalRootNode.class),
+ EXPRS(EvalExprNode.class),
+ PROJECTION(ProjectionNode.class),
+ LIMIT(LimitNode.class),
+ SORT(SortNode.class),
+ HAVING(HavingNode.class),
+ GROUP_BY(GroupbyNode.class),
+ SELECTION(SelectionNode.class),
+ JOIN(JoinNode.class),
+ UNION(UnionNode.class),
+ EXCEPT(ExceptNode.class),
+ INTERSECT(IntersectNode.class),
+ TABLE_SUBQUERY(TableSubQueryNode.class),
+ SCAN(ScanNode.class),
+ PARTITIONS_SCAN(PartitionedTableScanNode.class),
+ BST_INDEX_SCAN(IndexScanNode.class),
+ STORE(StoreTableNode.class),
+ INSERT(InsertNode.class),
+
+ CREATE_DATABASE(CreateDatabaseNode.class),
+ DROP_DATABASE(DropDatabaseNode.class),
+ CREATE_TABLE(CreateTableNode.class),
+ DROP_TABLE(DropTableNode.class),
+ ALTER_TABLESPACE (AlterTablespaceNode.class),
+ ALTER_TABLE (AlterTableNode.class);
+
+ private final Class<? extends LogicalNode> baseClass;
+
+ NodeType(Class<? extends LogicalNode> baseClass) {
+ this.baseClass = baseClass;
+ }
+
+ public Class<? extends LogicalNode> getBaseClass() {
+ return this.baseClass;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/PartitionedTableScanNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/PartitionedTableScanNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/PartitionedTableScanNode.java
new file mode 100644
index 0000000..45cc578
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/PartitionedTableScanNode.java
@@ -0,0 +1,155 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.util.TUtil;
+
+public class PartitionedTableScanNode extends ScanNode {
+ @Expose Path [] inputPaths;
+
+ public PartitionedTableScanNode(int pid) {
+ super(pid, NodeType.PARTITIONS_SCAN);
+ }
+
+ public void init(ScanNode scanNode, Path[] inputPaths) {
+ tableDesc = scanNode.tableDesc;
+ setInSchema(scanNode.getInSchema());
+ setOutSchema(scanNode.getOutSchema());
+ this.qual = scanNode.qual;
+ this.targets = scanNode.targets;
+ this.inputPaths = inputPaths;
+ }
+
+ public void setInputPaths(Path [] paths) {
+ this.inputPaths = paths;
+ }
+
+ public Path [] getInputPaths() {
+ return inputPaths;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Partitions Scan (table=").append(getTableName());
+ if (hasAlias()) {
+ sb.append(", alias=").append(alias);
+ }
+ if (hasQual()) {
+ sb.append(", filter=").append(qual);
+ }
+ sb.append(", path=").append(getTableDesc().getPath()).append(")");
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.tableDesc, this.qual, this.targets);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PartitionedTableScanNode) {
+ PartitionedTableScanNode other = (PartitionedTableScanNode) obj;
+
+ boolean eq = super.equals(other);
+ eq = eq && TUtil.checkEquals(this.tableDesc, other.tableDesc);
+ eq = eq && TUtil.checkEquals(this.qual, other.qual);
+ eq = eq && TUtil.checkEquals(this.targets, other.targets);
+ eq = eq && TUtil.checkEquals(this.inputPaths, other.inputPaths);
+
+ return eq;
+ }
+
+ return false;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ PartitionedTableScanNode unionScan = (PartitionedTableScanNode) super.clone();
+
+ unionScan.tableDesc = (TableDesc) this.tableDesc.clone();
+
+ if (hasQual()) {
+ unionScan.qual = (EvalNode) this.qual.clone();
+ }
+
+ if (hasTargets()) {
+ unionScan.targets = new Target[targets.length];
+ for (int i = 0; i < targets.length; i++) {
+ unionScan.targets[i] = (Target) targets[i].clone();
+ }
+ }
+
+ unionScan.inputPaths = inputPaths;
+
+ return unionScan;
+ }
+
+ @Override
+ public void preOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ public void postOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ PlanString planStr = new PlanString(this).appendTitle(" on " + getTableName());
+ if (hasAlias()) {
+ planStr.appendTitle(" as ").appendTitle(alias);
+ }
+
+ if (hasQual()) {
+ planStr.addExplan("filter: ").appendExplain(this.qual.toString());
+ }
+
+ if (hasTargets()) {
+ planStr.addExplan("target list: ");
+ boolean first = true;
+ for (Target target : targets) {
+ if (!first) {
+ planStr.appendExplain(", ");
+ }
+ planStr.appendExplain(target.toString());
+ first = false;
+ }
+ }
+
+ planStr.addDetail("out schema: ").appendDetail(getOutSchema().toString());
+ planStr.addDetail("in schema: ").appendDetail(getInSchema().toString());
+
+ if (inputPaths != null) {
+ planStr.addExplan("num of filtered paths: ").appendExplain(""+ inputPaths.length);
+ int i = 0;
+ for (Path path : inputPaths) {
+ planStr.addDetail((i++) + ": ").appendDetail(path.toString());
+ }
+ }
+
+ return planStr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/PersistentStoreNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/PersistentStoreNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/PersistentStoreNode.java
new file mode 100644
index 0000000..9d2acf6
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/PersistentStoreNode.java
@@ -0,0 +1,90 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Options;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.util.TUtil;
+
+import static org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
+
+
+/**
+ * <code>PersistentStoreNode</code> an expression for a persistent data store step.
+ * This includes some basic information for materializing data.
+ */
+public abstract class PersistentStoreNode extends UnaryNode implements Cloneable {
+ @Expose protected StoreType storageType = StoreType.CSV;
+ @Expose protected Options options;
+
+ protected PersistentStoreNode(int pid, NodeType nodeType) {
+ super(pid, nodeType);
+ }
+
+ public void setStorageType(StoreType storageType) {
+ this.storageType = storageType;
+ }
+
+ public StoreType getStorageType() {
+ return this.storageType;
+ }
+
+ public boolean hasOptions() {
+ return this.options != null;
+ }
+
+ public Options getOptions() {
+ return this.options;
+ }
+
+ public void setOptions(Options options) {
+ this.options = options;
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ PlanString planStr = new PlanString(this);
+ planStr.addExplan("Store type: " + storageType);
+
+ return planStr;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PersistentStoreNode) {
+ PersistentStoreNode other = (PersistentStoreNode) obj;
+ boolean eq = super.equals(other);
+ eq = eq && this.storageType.equals(other.storageType);
+ eq = eq && TUtil.checkEquals(options, other.options);
+ return eq;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ PersistentStoreNode store = (PersistentStoreNode) super.clone();
+ store.storageType = storageType != null ? storageType : null;
+ store.options = options != null ? (Options) options.clone() : null;
+ return store;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/Projectable.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/Projectable.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/Projectable.java
new file mode 100644
index 0000000..1e4bdc5
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/Projectable.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.planner.logical;
+
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.planner.Target;
+
+/**
+ * Projectable is an interface for a LogicalNode which has a list of targets.
+ * What a logical node has a list of targets means that the node evaluated a list of expressions.
+ * For example, {@link org.apache.tajo.engine.planner.logical.ScanNode},
+ * {@link org.apache.tajo.engine.planner.logical.JoinNode},
+ * {@link org.apache.tajo.engine.planner.logical.GroupbyNode}, and
+ * {@link org.apache.tajo.engine.planner.logical.ProjectionNode} are all <i>Projectable</i> nodes.
+ * The expression evaluation occurs only at those projectable nodes.
+ */
+public interface Projectable {
+
+ /**
+ * Get a PlanNode Id
+ * @return PlanNodeId
+ */
+ int getPID();
+
+ /**
+ * check if this node has a target list
+ * @return TRUE if this node has a target list. Otherwise, FALSE.
+ */
+ boolean hasTargets();
+
+ /**
+ * Set a target list
+ *
+ * @param targets The array of targets
+ */
+ void setTargets(Target[] targets);
+
+ /**
+ * Get a list of targets
+ *
+ * @return The array of targets
+ */
+ Target [] getTargets();
+
+ /**
+ * Get an input schema
+ * @return The input schema
+ */
+ public Schema getInSchema();
+
+ /**
+ * Get an output schema
+ *
+ * @return The output schema
+ */
+ public Schema getOutSchema();
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ProjectionNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ProjectionNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ProjectionNode.java
new file mode 100644
index 0000000..e9fd803
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ProjectionNode.java
@@ -0,0 +1,114 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.engine.planner.PlannerUtil;
+import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.util.TUtil;
+
+public class ProjectionNode extends UnaryNode implements Projectable {
+ /**
+ * the targets are always filled even if the query is 'select *'
+ */
+ @Expose private Target [] targets;
+ @Expose private boolean distinct = false;
+
+ public ProjectionNode(int pid) {
+ super(pid, NodeType.PROJECTION);
+ }
+
+ public boolean hasTargets() {
+ return this.targets != null;
+ }
+
+ @Override
+ public void setTargets(Target[] targets) {
+ this.targets = targets;
+ this.setOutSchema(PlannerUtil.targetToSchema(targets));
+ }
+
+ @Override
+ public Target [] getTargets() {
+ return this.targets;
+ }
+
+ public void setChild(LogicalNode subNode) {
+ super.setChild(subNode);
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Projection (distinct=").append(distinct);
+ if (targets != null) {
+ sb.append(", exprs=").append(TUtil.arrayToString(targets)).append(")");
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ProjectionNode) {
+ ProjectionNode other = (ProjectionNode) obj;
+
+ boolean b1 = super.equals(other);
+ boolean b2 = TUtil.checkEquals(targets, other.targets);
+ return b1 && b2;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ ProjectionNode projNode = (ProjectionNode) super.clone();
+ projNode.targets = targets.clone();
+
+ return projNode;
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ PlanString planStr = new PlanString(this);
+
+ if (distinct) {
+ planStr.appendTitle(" (distinct)");
+ }
+
+
+ StringBuilder sb = new StringBuilder("Targets: ");
+ if (targets != null) {
+ for (int i = 0; i < targets.length; i++) {
+ sb.append(targets[i]);
+ if (i < targets.length - 1) {
+ sb.append(", ");
+ }
+ }
+ }
+ planStr.addExplan(sb.toString());
+ if (getOutSchema() != null) {
+ planStr.addExplan("out schema: " + getOutSchema().toString());
+ }
+ if (getInSchema() != null) {
+ planStr.addExplan("in schema: " + getInSchema().toString());
+ }
+
+ return planStr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/RelationNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/RelationNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/RelationNode.java
new file mode 100644
index 0000000..83c16cd
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/RelationNode.java
@@ -0,0 +1,49 @@
+/**
+ * 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.tajo.engine.planner.logical;
+
+import org.apache.tajo.catalog.Schema;
+
+/**
+ * It provides a logical view of a relation. Regarding a table, the main difference between a logical view and a
+ * physical view is as follows:
+ *
+ * <ul>
+ * <li>In logical view, each column in the table has qualified name by table alias name. In addition, the schema of
+ * logical view will includes partition columns if we use column-partitioned tables.</li>
+ * <li>In contrast, in physical view: each column in the table has qualified name by the original table.</li>
+ * </ul>
+ */
+public abstract class RelationNode extends LogicalNode {
+
+ protected RelationNode(int pid, NodeType nodeType) {
+ super(pid, nodeType);
+ assert(nodeType == NodeType.SCAN || nodeType == NodeType.PARTITIONS_SCAN || nodeType == NodeType.TABLE_SUBQUERY);
+ }
+
+ public abstract boolean hasAlias();
+
+ public abstract String getAlias();
+
+ public abstract String getTableName();
+
+ public abstract String getCanonicalName();
+
+ public abstract Schema getTableSchema();
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
new file mode 100644
index 0000000..27782a2
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.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.tajo.engine.planner.logical;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.engine.planner.PlanString;
+import org.apache.tajo.engine.planner.PlannerUtil;
+import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.engine.utils.SchemaUtil;
+import org.apache.tajo.util.TUtil;
+
+public class ScanNode extends RelationNode implements Projectable, Cloneable {
+ @Expose protected TableDesc tableDesc;
+ @Expose protected String alias;
+ @Expose protected Schema logicalSchema;
+ @Expose protected EvalNode qual;
+ @Expose protected Target[] targets;
+ @Expose protected boolean broadcastTable;
+
+ protected ScanNode(int pid, NodeType nodeType) {
+ super(pid, nodeType);
+ }
+
+ public ScanNode(int pid) {
+ super(pid, NodeType.SCAN);
+ }
+
+ public void init(TableDesc desc) {
+ this.tableDesc = desc;
+ this.setInSchema(tableDesc.getSchema());
+ this.setOutSchema(tableDesc.getSchema());
+ logicalSchema = SchemaUtil.getQualifiedLogicalSchema(tableDesc, null);
+ }
+
+ public void init(TableDesc desc, String alias) {
+ this.tableDesc = desc;
+ this.alias = alias;
+
+ if (!CatalogUtil.isFQTableName(this.tableDesc.getName())) {
+ throw new IllegalArgumentException("the name in TableDesc must be qualified, but it is \"" +
+ desc.getName() + "\"");
+ }
+
+ String databaseName = CatalogUtil.extractQualifier(this.tableDesc.getName());
+ String qualifiedAlias = CatalogUtil.buildFQName(databaseName, alias);
+ this.setInSchema(tableDesc.getSchema());
+ this.getInSchema().setQualifier(qualifiedAlias);
+ this.setOutSchema(new Schema(getInSchema()));
+ logicalSchema = SchemaUtil.getQualifiedLogicalSchema(tableDesc, qualifiedAlias);
+ }
+
+ public String getTableName() {
+ return tableDesc.getName();
+ }
+
+ @Override
+ public boolean hasAlias() {
+ return alias != null;
+ }
+
+ @Override
+ public String getAlias() {
+ return alias;
+ }
+
+ public void setBroadcastTable(boolean broadcastTable) {
+ this.broadcastTable = broadcastTable;
+ }
+
+ public boolean isBroadcastTable() {
+ return broadcastTable;
+ }
+
+ public String getCanonicalName() {
+ if (CatalogUtil.isFQTableName(this.tableDesc.getName())) {
+ String databaseName = CatalogUtil.extractQualifier(this.tableDesc.getName());
+ return hasAlias() ? CatalogUtil.buildFQName(databaseName, alias) : tableDesc.getName();
+ } else {
+ return hasAlias() ? alias : tableDesc.getName();
+ }
+ }
+
+ public Schema getTableSchema() {
+ return logicalSchema;
+ }
+
+ public Schema getPhysicalSchema() {
+ return getInSchema();
+ }
+
+ public boolean hasQual() {
+ return qual != null;
+ }
+
+ public EvalNode getQual() {
+ return this.qual;
+ }
+
+ public void setQual(EvalNode evalTree) {
+ this.qual = evalTree;
+ }
+
+ @Override
+ public boolean hasTargets() {
+ return this.targets != null;
+ }
+
+ @Override
+ public void setTargets(Target [] targets) {
+ this.targets = targets;
+ setOutSchema(PlannerUtil.targetToSchema(targets));
+ }
+
+ @Override
+ public Target [] getTargets() {
+ return this.targets;
+ }
+
+ public TableDesc getTableDesc() {
+ return tableDesc;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Scan (table=").append(getTableName());
+ if (hasAlias()) {
+ sb.append(", alias=").append(alias);
+ }
+ if (hasQual()) {
+ sb.append(", filter=").append(qual);
+ }
+ sb.append(", path=").append(getTableDesc().getPath()).append(")");
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.tableDesc, this.qual, this.targets);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ScanNode) {
+ ScanNode other = (ScanNode) obj;
+
+ boolean eq = super.equals(other);
+ eq = eq && TUtil.checkEquals(this.tableDesc, other.tableDesc);
+ eq = eq && TUtil.checkEquals(this.qual, other.qual);
+ eq = eq && TUtil.checkEquals(this.targets, other.targets);
+
+ return eq;
+ }
+
+ return false;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ ScanNode scanNode = (ScanNode) super.clone();
+
+ scanNode.tableDesc = (TableDesc) this.tableDesc.clone();
+
+ if (hasQual()) {
+ scanNode.qual = (EvalNode) this.qual.clone();
+ }
+
+ if (hasTargets()) {
+ scanNode.targets = new Target[targets.length];
+ for (int i = 0; i < targets.length; i++) {
+ scanNode.targets[i] = (Target) targets[i].clone();
+ }
+ }
+
+ return scanNode;
+ }
+
+ @Override
+ public void preOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ public void postOrder(LogicalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public PlanString getPlanString() {
+ PlanString planStr = new PlanString(this).appendTitle(" on ").appendTitle(getTableName());
+ if (hasAlias()) {
+ planStr.appendTitle(" as ").appendTitle(alias);
+ }
+
+ if (hasQual()) {
+ planStr.addExplan("filter: ").appendExplain(this.qual.toString());
+ }
+
+ if (hasTargets()) {
+ planStr.addExplan("target list: ");
+ boolean first = true;
+ for (Target target : targets) {
+ if (!first) {
+ planStr.appendExplain(", ");
+ }
+ planStr.appendExplain(target.toString());
+ first = false;
+ }
+ }
+
+ planStr.addDetail("out schema: ").appendDetail(getOutSchema().toString());
+ planStr.addDetail("in schema: ").appendDetail(getInSchema().toString());
+
+ return planStr;
+ }
+}