You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by ji...@apache.org on 2014/10/26 06:46:18 UTC
[19/33] TAJO-1125: Separate logical plan and optimizer into a maven
module.
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/NamedExprsManager.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/NamedExprsManager.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/NamedExprsManager.java
deleted file mode 100644
index 8666a5c..0000000
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/NamedExprsManager.java
+++ /dev/null
@@ -1,380 +0,0 @@
-/**
- * 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;
-
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import org.apache.tajo.algebra.ColumnReferenceExpr;
-import org.apache.tajo.algebra.Expr;
-import org.apache.tajo.algebra.NamedExpr;
-import org.apache.tajo.algebra.OpType;
-import org.apache.tajo.annotation.Nullable;
-import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.eval.EvalType;
-import org.apache.tajo.engine.eval.FieldEval;
-import org.apache.tajo.util.TUtil;
-
-import java.util.*;
-
-/**
- * NamedExprsManager manages an expressions used in a query block. All expressions used in a query block must be
- * added to NamedExprsManager. When an expression is added to NamedExprsManager, NamedExprsManager gives a reference
- * to the expression. If the expression already has an alias name, it gives the alias name as the reference
- * to the expression. If the expression does not have any alias, it gives a generated name as the reference to the
- * expression. Usually, predicates in WHERE clause, expressions in GROUP-BY, ORDER-BY, LIMIT clauses are not given
- * any alias name. Those reference names are used to identify an individual expression.
- *
- * NamedExprsManager only keeps unique expressions. Since expressions in a query block can be duplicated,
- * one or more reference names can point one expressions. Due to this process, it naturally removes duplicated
- * expression.
- *
- * As we mentioned above, one or more reference names can indicate one expression. Primary names are used for
- * representing expressions. A primary name of an expression indicates the reference obtained when
- * the expression is added firstly. All output schemas uses only primary names of expressions.
- *
- * Each expression that NamedExprsManager keeps has an boolean state to indicate whether the expression is evaluated
- * or not. The <code>evaluated</code> state means that upper logical operators can access this expression like a column
- * reference. For it, the reference name is used to access this expression like a column reference,
- * The evaluated state is set with an EvalNode which is an annotated expression.
- * {@link #getTarget(String)} returns EvalNodes by a reference name.
- */
-public class NamedExprsManager {
- /** a sequence id */
- private int sequenceId = 0;
-
- /** Map: Name -> ID. Two or more different names can indicates the same id. */
- private LinkedHashMap<String, Integer> nameToIdMap = Maps.newLinkedHashMap();
-
- /** Map; ID <-> EvalNode */
- private BiMap<Integer, EvalNode> idToEvalMap = HashBiMap.create();
-
- /** Map: ID -> Names */
- private LinkedHashMap<Integer, List<String>> idToNamesMap = Maps.newLinkedHashMap();
-
- /** Map: ID -> Expr */
- private BiMap<Integer, Expr> idToExprBiMap = HashBiMap.create();
-
- /** Map; Name -> Boolean (if it is resolved or not) */
- private LinkedHashMap<Integer, Boolean> evaluationStateMap = Maps.newLinkedHashMap();
-
- /** Map: Alias Name <-> Original Name */
- private BiMap<String, String> aliasedColumnMap = HashBiMap.create();
-
- private final LogicalPlan plan;
-
- private final LogicalPlan.QueryBlock block;
-
- public NamedExprsManager(LogicalPlan plan, LogicalPlan.QueryBlock block) {
- this.plan = plan;
- this.block = block;
- }
-
- private int getNextId() {
- return sequenceId++;
- }
-
- /**
- * Check whether the expression corresponding to a given name was evaluated.
- *
- * @param name The name of a certain expression to be checked
- * @return true if resolved. Otherwise, false.
- */
- public boolean isEvaluated(String name) {
- if (nameToIdMap.containsKey(name)) {
- int refId = nameToIdMap.get(name);
- return evaluationStateMap.containsKey(refId) && evaluationStateMap.get(refId);
- } else {
- return false;
- }
- }
-
- public boolean contains(String name) {
- return nameToIdMap.containsKey(name);
- }
-
- public boolean contains(Expr expr) {
- return idToExprBiMap.inverse().containsKey(expr);
- }
-
- private Expr getExpr(String name) {
- return idToExprBiMap.get(nameToIdMap.get(name));
- }
-
- public NamedExpr getNamedExpr(String name) {
- String normalized = name;
- return new NamedExpr(getExpr(name), normalized);
- }
-
- public boolean isAliased(String name) {
- return aliasedColumnMap.containsKey(name);
- }
-
- public String getAlias(String originalName) {
- return aliasedColumnMap.get(originalName);
- }
-
- public boolean isAliasedName(String aliasName) {
- return aliasedColumnMap.inverse().containsKey(aliasName);
- }
-
- public String getOriginalName(String aliasName) {
- return aliasedColumnMap.inverse().get(aliasName);
- }
-
- /**
- * Adds an expression and returns a reference name.
- */
- public String addExpr(Expr expr) throws PlanningException {
- if (idToExprBiMap.inverse().containsKey(expr)) {
- int refId = idToExprBiMap.inverse().get(expr);
- return idToNamesMap.get(refId).get(0);
- }
-
- if (block.isRegisteredConst(expr)) {
- return block.getConstReference(expr);
- }
-
- String generatedName = plan.generateUniqueColumnName(expr);
- return addExpr(expr, generatedName);
- }
-
- /**
- * Adds an expression with an alias name and returns a reference name.
- * It specifies the alias as an reference name.
- */
- public String addExpr(Expr expr, String alias) throws PlanningException {
-
- if (OpType.isLiteralType(expr.getType())) {
- return alias;
- }
-
- // if this name already exists, just returns the name.
- if (nameToIdMap.containsKey(alias)) {
- return alias;
- }
-
- // if the name is first
- int refId;
- if (idToExprBiMap.inverse().containsKey(expr)) {
- refId = idToExprBiMap.inverse().get(expr);
- } else {
- refId = getNextId();
- idToExprBiMap.put(refId, expr);
- }
-
- nameToIdMap.put(alias, refId);
- evaluationStateMap.put(refId, false);
-
- // add the entry to idToNames map
- TUtil.putToNestedList(idToNamesMap, refId, alias);
-
- return alias;
- }
-
- /**
- * Adds an expression and returns a reference name.
- * If an alias is given, it specifies the alias as an reference name.
- */
- public String addNamedExpr(NamedExpr namedExpr) throws PlanningException {
- if (namedExpr.hasAlias()) {
- return addExpr(namedExpr.getExpr(), namedExpr.getAlias());
- } else {
- return addExpr(namedExpr.getExpr());
- }
- }
-
- /**
- * Adds a list of expressions and returns a list of reference names.
- * If some NamedExpr has an alias, NamedExprsManager specifies the alias for the NamedExpr.
- */
- public String [] addNamedExprArray(@Nullable Collection<NamedExpr> namedExprs) throws PlanningException {
- if (namedExprs != null && namedExprs.size() > 0) {
- String [] names = new String[namedExprs.size()];
- int i = 0;
- for (NamedExpr target : namedExprs) {
- names[i++] = addNamedExpr(target);
- }
- return names;
- } else {
- return null;
- }
- }
-
- public Collection<NamedExpr> getAllNamedExprs() {
- List<NamedExpr> namedExprList = Lists.newArrayList();
- for (Map.Entry<Integer, Expr> entry: idToExprBiMap.entrySet()) {
- namedExprList.add(new NamedExpr(entry.getValue(), idToNamesMap.get(entry.getKey()).get(0)));
- }
- return namedExprList;
- }
-
- /**
- * It marks the expression identified by the reference name as <code>evaluated</code>.
- * In addition, it adds an EvanNode for the expression identified by the reference.
- *
- * @param referenceName The reference name to be marked as 'evaluated'.
- * @param evalNode EvalNode to be added.
- */
- public void markAsEvaluated(String referenceName, EvalNode evalNode) throws PlanningException {
- String normalized = referenceName;
-
- int refId = nameToIdMap.get(normalized);
- evaluationStateMap.put(refId, true);
- idToEvalMap.put(refId, evalNode);
-
- String originalName = checkAndGetIfAliasedColumn(normalized);
- if (originalName != null) {
- aliasedColumnMap.put(originalName, normalized);
- }
- }
-
- /**
- * It returns an original column name if it is aliased column reference.
- * Otherwise, it will return NULL.
- */
- public String checkAndGetIfAliasedColumn(String name) {
- Expr expr = getExpr(name);
- if (expr != null && expr.getType() == OpType.Column) {
- ColumnReferenceExpr column = (ColumnReferenceExpr) expr;
- if (!column.getCanonicalName().equals(name)) {
- return column.getCanonicalName();
- }
- }
- return null;
- }
-
- public Target getTarget(String name) {
- return getTarget(name, false);
- }
-
- /**
- * It checks if a given name is the primary name.
- *
- * @See {@link NamedExprsManager}
- * @see {@link NamedExprsManager#getPrimaryName}
- *
- * @param id The expression id
- * @param name The name to be checked if it is primary name.
- * @return The primary name
- */
- private boolean isPrimaryName(int id, String name) {
- return idToNamesMap.get(id).get(0).equals(name);
- }
-
- /**
- * One or more reference names can indicate one expression. Primary names are used for
- * representing expressions. A primary name of an expression indicates the reference obtained when
- * the expression is added firstly. All output schemas uses only primary names of expressions.
- *
- * @param id The expression id
- * @return The primary name
- */
- private String getPrimaryName(int id) {
- return idToNamesMap.get(id).get(0);
- }
-
- /**
- * get a Target instance. A target consists of a reference name and an EvalNode corresponding to the reference name.
- * According to evaluation state, it returns different EvalNodes.
- * If the expression corresponding to the reference name is evaluated, it just returns {@link FieldEval}
- * (i.e., a column reference). Otherwise, it returns the original EvalNode of the expression.
- *
- * @param referenceName The reference name to get EvalNode
- * @param unevaluatedForm If TRUE, it always return the annotated EvalNode of the expression.
- * @return
- */
- public Target getTarget(String referenceName, boolean unevaluatedForm) {
- String normalized = referenceName;
- int refId = nameToIdMap.get(normalized);
-
- if (!unevaluatedForm && evaluationStateMap.containsKey(refId) && evaluationStateMap.get(refId)) {
- EvalNode evalNode = idToEvalMap.get(refId);
-
- // If the expression is already evaluated, it should use the FieldEval to access a field value.
- // But, if this reference name is not primary name, it cannot use the reference name.
- // It changes the given reference name to the primary name.
- if (evalNode.getType() != EvalType.CONST && isEvaluated(normalized) && !isPrimaryName(refId, referenceName)) {
- return new Target(new FieldEval(getPrimaryName(refId),evalNode.getValueType()), referenceName);
- }
-
- EvalNode referredEval;
- if (evalNode.getType() == EvalType.CONST) {
- referredEval = evalNode;
- } else {
- referredEval = new FieldEval(idToNamesMap.get(refId).get(0), evalNode.getValueType());
- }
- return new Target(referredEval, referenceName);
-
- } else {
- if (idToEvalMap.containsKey(refId)) {
- return new Target(idToEvalMap.get(refId), referenceName);
- } else {
- return null;
- }
- }
- }
-
- public String toString() {
- return "unevaluated=" + nameToIdMap.size() + ", evaluated=" + idToEvalMap.size()
- + ", renamed=" + aliasedColumnMap.size();
- }
-
- /**
- * It returns an iterator for unevaluated NamedExprs.
- */
- public Iterator<NamedExpr> getIteratorForUnevaluatedExprs() {
- return new UnevaluatedIterator();
- }
-
- public class UnevaluatedIterator implements Iterator<NamedExpr> {
- private final Iterator<NamedExpr> iterator;
-
- public UnevaluatedIterator() {
- List<NamedExpr> unEvaluatedList = TUtil.newList();
- for (Integer refId: idToNamesMap.keySet()) {
- String name = idToNamesMap.get(refId).get(0);
- if (!isEvaluated(name)) {
- Expr expr = idToExprBiMap.get(refId);
- unEvaluatedList.add(new NamedExpr(expr, name));
- }
- }
- if (unEvaluatedList.size() == 0) {
- iterator = null;
- } else {
- iterator = unEvaluatedList.iterator();
- }
- }
-
- @Override
- public boolean hasNext() {
- return iterator != null && iterator.hasNext();
- }
-
- @Override
- public NamedExpr next() {
- return iterator.next();
- }
-
- @Override
- public void remove() {
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlanner.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlanner.java
index ebe47b4..d4c57db 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlanner.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlanner.java
@@ -22,7 +22,7 @@
package org.apache.tajo.engine.planner;
import org.apache.tajo.worker.TaskAttemptContext;
-import org.apache.tajo.engine.planner.logical.LogicalNode;
+import org.apache.tajo.plan.logical.LogicalNode;
import org.apache.tajo.engine.planner.physical.PhysicalExec;
import org.apache.tajo.exception.InternalException;
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java
index 485677a..f7f071f 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java
@@ -36,7 +36,6 @@ import org.apache.tajo.catalog.proto.CatalogProtos.SortSpecProto;
import org.apache.tajo.conf.TajoConf;
import org.apache.tajo.engine.planner.enforce.Enforcer;
import org.apache.tajo.engine.planner.global.DataChannel;
-import org.apache.tajo.engine.planner.logical.*;
import org.apache.tajo.engine.planner.physical.*;
import org.apache.tajo.engine.query.QueryContext;
import org.apache.tajo.exception.InternalException;
@@ -45,6 +44,9 @@ import org.apache.tajo.ipc.TajoWorkerProtocol.DistinctGroupbyEnforcer;
import org.apache.tajo.ipc.TajoWorkerProtocol.DistinctGroupbyEnforcer.DistinctAggregationAlgorithm;
import org.apache.tajo.ipc.TajoWorkerProtocol.DistinctGroupbyEnforcer.MultipleAggregationStage;
import org.apache.tajo.ipc.TajoWorkerProtocol.DistinctGroupbyEnforcer.SortSpecArray;
+import org.apache.tajo.plan.LogicalPlan;
+import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.plan.logical.*;
import org.apache.tajo.storage.StorageConstants;
import org.apache.tajo.storage.StorageManager;
import org.apache.tajo.storage.TupleComparator;
@@ -56,7 +58,6 @@ import org.apache.tajo.util.TUtil;
import org.apache.tajo.worker.TaskAttemptContext;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlanString.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlanString.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlanString.java
deleted file mode 100644
index 98f921b..0000000
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlanString.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * 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;
-
-import org.apache.tajo.engine.planner.logical.LogicalNode;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-public class PlanString {
- final StringBuilder title;
-
- final List<String> explanations = new ArrayList<String>();
- final List<String> details = new ArrayList<String>();
-
- StringBuilder currentExplanation;
- StringBuilder currentDetail;
-
- public PlanString(LogicalNode node) {
- this.title = new StringBuilder(node.getType().name() + "(" + node.getPID() + ")");
- }
-
- public PlanString(String title) {
- this.title = new StringBuilder(title);
- }
-
- public PlanString appendTitle(String str) {
- title.append(str);
- return this;
- }
-
- public PlanString addExplan(String explain) {
- flushCurrentExplanation();
- currentExplanation = new StringBuilder(explain);
- return this;
- }
-
- public PlanString appendExplain(String explain) {
- if (currentExplanation == null) {
- currentExplanation = new StringBuilder();
- }
- currentExplanation.append(explain);
- return this;
- }
-
- public PlanString addDetail(String detail) {
- flushCurrentDetail();
- currentDetail = new StringBuilder(detail);
- return this;
- }
-
- public PlanString appendDetail(String detail) {
- if (currentDetail == null) {
- currentDetail = new StringBuilder();
- }
- currentDetail.append(detail);
- return this;
-
- }
-
- public String getTitle() {
- return title.toString();
- }
-
- public List<String> getExplanations() {
- flushCurrentExplanation();
- return explanations;
- }
-
- public List<String> getDetails() {
- flushCurrentDetail();
- return details;
- }
-
- private void flushCurrentExplanation() {
- if (currentExplanation != null) {
- explanations.add(currentExplanation.toString());
- currentExplanation = null;
- }
- }
-
- private void flushCurrentDetail() {
- if (currentDetail != null) {
- details.add(currentDetail.toString());
- currentDetail = null;
- }
- }
-
- public String toString() {
- StringBuilder output = new StringBuilder();
- output.append(getTitle()).append("\n");
-
- for (String str : getExplanations()) {
- output.append(" => ").append(str).append("\n");
- }
-
- for (String str : getDetails()) {
- output.append(" => ").append(str).append("\n");
- }
- return output.toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
deleted file mode 100644
index 827be83..0000000
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
+++ /dev/null
@@ -1,888 +0,0 @@
-/**
- * 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;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.tajo.algebra.*;
-import org.apache.tajo.annotation.Nullable;
-import org.apache.tajo.catalog.Column;
-import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.catalog.SortSpec;
-import org.apache.tajo.catalog.TableDesc;
-import org.apache.tajo.catalog.proto.CatalogProtos;
-import org.apache.tajo.catalog.proto.CatalogProtos.FragmentProto;
-import org.apache.tajo.common.TajoDataTypes.DataType;
-import org.apache.tajo.conf.TajoConf;
-import org.apache.tajo.engine.eval.*;
-import org.apache.tajo.engine.exception.InvalidQueryException;
-import org.apache.tajo.engine.planner.logical.*;
-import org.apache.tajo.engine.utils.SchemaUtil;
-import org.apache.tajo.storage.StorageManager;
-import org.apache.tajo.storage.TupleComparator;
-import org.apache.tajo.storage.fragment.FileFragment;
-import org.apache.tajo.storage.fragment.FragmentConvertor;
-import org.apache.tajo.util.TUtil;
-
-import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class PlannerUtil {
-
- public static boolean checkIfDDLPlan(LogicalNode node) {
- LogicalNode baseNode = node;
- if (node instanceof LogicalRootNode) {
- baseNode = ((LogicalRootNode) node).getChild();
- }
-
- NodeType type = baseNode.getType();
-
- return
- type == NodeType.CREATE_DATABASE ||
- type == NodeType.DROP_DATABASE ||
- (type == NodeType.CREATE_TABLE && !((CreateTableNode) baseNode).hasSubQuery()) ||
- baseNode.getType() == NodeType.DROP_TABLE ||
- baseNode.getType() == NodeType.ALTER_TABLESPACE ||
- baseNode.getType() == NodeType.ALTER_TABLE ||
- baseNode.getType() == NodeType.TRUNCATE_TABLE;
- }
-
- /**
- * Checks whether the query is simple or not.
- * The simple query can be defined as 'select * from tb_name [LIMIT X]'.
- *
- * @param plan The logical plan
- * @return True if the query is a simple query.
- */
- public static boolean checkIfSimpleQuery(LogicalPlan plan) {
- LogicalRootNode rootNode = plan.getRootBlock().getRoot();
-
- // one block, without where clause, no group-by, no-sort, no-join
- boolean isOneQueryBlock = plan.getQueryBlocks().size() == 1;
- boolean simpleOperator = rootNode.getChild().getType() == NodeType.LIMIT
- || rootNode.getChild().getType() == NodeType.SCAN || rootNode.getChild().getType() == NodeType.PARTITIONS_SCAN;
- boolean noOrderBy = !plan.getRootBlock().hasNode(NodeType.SORT);
- boolean noGroupBy = !plan.getRootBlock().hasNode(NodeType.GROUP_BY);
- boolean noWhere = !plan.getRootBlock().hasNode(NodeType.SELECTION);
- boolean noJoin = !plan.getRootBlock().hasNode(NodeType.JOIN);
- boolean singleRelation =
- (plan.getRootBlock().hasNode(NodeType.SCAN) || plan.getRootBlock().hasNode(NodeType.PARTITIONS_SCAN)) &&
- PlannerUtil.getRelationLineage(plan.getRootBlock().getRoot()).length == 1;
-
- boolean noComplexComputation = false;
- if (singleRelation) {
- ScanNode scanNode = plan.getRootBlock().getNode(NodeType.SCAN);
- if (scanNode == null) {
- scanNode = plan.getRootBlock().getNode(NodeType.PARTITIONS_SCAN);
- }
- if (scanNode.hasTargets()) {
- // If the number of columns in the select clause is s different from table schema,
- // This query is not a simple query.
- if (scanNode.getTableDesc().hasPartition()) {
- // In the case of partitioned table, the actual number of columns is ScanNode.InSchema + partitioned columns
- int numPartitionColumns = scanNode.getTableDesc().getPartitionMethod().getExpressionSchema().size();
- if (scanNode.getTargets().length != scanNode.getInSchema().size() + numPartitionColumns) {
- return false;
- }
- } else {
- if (scanNode.getTargets().length != scanNode.getInSchema().size()) {
- return false;
- }
- }
- noComplexComputation = true;
- for (int i = 0; i < scanNode.getTargets().length; i++) {
- noComplexComputation =
- noComplexComputation && scanNode.getTargets()[i].getEvalTree().getType() == EvalType.FIELD;
- if (noComplexComputation) {
- noComplexComputation = noComplexComputation &&
- scanNode.getTargets()[i].getNamedColumn().equals(
- scanNode.getTableDesc().getLogicalSchema().getColumn(i));
- }
- if (!noComplexComputation) {
- return noComplexComputation;
- }
- }
- }
- }
-
- return !checkIfDDLPlan(rootNode) &&
- (simpleOperator && noComplexComputation && isOneQueryBlock &&
- noOrderBy && noGroupBy && noWhere && noJoin && singleRelation);
- }
-
- /**
- * Checks whether the query has 'from clause' or not.
- *
- * @param plan The logical plan
- * @return True if a query does not have 'from clause'.
- */
- public static boolean checkIfNonFromQuery(LogicalPlan plan) {
- LogicalNode node = plan.getRootBlock().getRoot();
-
- // one block, without where clause, no group-by, no-sort, no-join
- boolean isOneQueryBlock = plan.getQueryBlocks().size() == 1;
- boolean noRelation = !plan.getRootBlock().hasAlgebraicExpr(OpType.Relation);
-
- return !checkIfDDLPlan(node) && noRelation && isOneQueryBlock;
- }
-
- /**
- * Get all RelationNodes which are descendant of a given LogicalNode.
- *
- * @param from The LogicalNode to start visiting LogicalNodes.
- * @return an array of all descendant RelationNode of LogicalNode.
- */
- public static String[] getRelationLineage(LogicalNode from) {
- LogicalNode[] scans = findAllNodes(from, NodeType.SCAN, NodeType.PARTITIONS_SCAN);
- String[] tableNames = new String[scans.length];
- ScanNode scan;
- for (int i = 0; i < scans.length; i++) {
- scan = (ScanNode) scans[i];
- tableNames[i] = scan.getCanonicalName();
- }
- return tableNames;
- }
-
- /**
- * Get all RelationNodes which are descendant of a given LogicalNode.
- * The finding is restricted within a query block.
- *
- * @param from The LogicalNode to start visiting LogicalNodes.
- * @return an array of all descendant RelationNode of LogicalNode.
- */
- public static Collection<String> getRelationLineageWithinQueryBlock(LogicalPlan plan, LogicalNode from)
- throws PlanningException {
- RelationFinderVisitor visitor = new RelationFinderVisitor();
- visitor.visit(null, plan, null, from, new Stack<LogicalNode>());
- return visitor.getFoundRelations();
- }
-
- public static class RelationFinderVisitor extends BasicLogicalPlanVisitor<Object, LogicalNode> {
- private Set<String> foundRelNameSet = Sets.newHashSet();
-
- public Set<String> getFoundRelations() {
- return foundRelNameSet;
- }
-
- @Override
- public LogicalNode visit(Object context, LogicalPlan plan, @Nullable LogicalPlan.QueryBlock block, LogicalNode node,
- Stack<LogicalNode> stack) throws PlanningException {
- if (node.getType() != NodeType.TABLE_SUBQUERY) {
- super.visit(context, plan, block, node, stack);
- }
-
- if (node instanceof RelationNode) {
- foundRelNameSet.add(((RelationNode) node).getCanonicalName());
- }
-
- return node;
- }
- }
-
- /**
- * Delete the logical node from a plan.
- *
- * @param parent this node must be a parent node of one node to be removed.
- * @param tobeRemoved this node must be a child node of the parent.
- */
- public static LogicalNode deleteNode(LogicalNode parent, LogicalNode tobeRemoved) {
- Preconditions.checkArgument(tobeRemoved instanceof UnaryNode,
- "ERROR: the logical node to be removed must be unary node.");
-
- UnaryNode child = (UnaryNode) tobeRemoved;
- LogicalNode grandChild = child.getChild();
- if (parent instanceof UnaryNode) {
- UnaryNode unaryParent = (UnaryNode) parent;
-
- Preconditions.checkArgument(unaryParent.getChild() == child,
- "ERROR: both logical node must be parent and child nodes");
- unaryParent.setChild(grandChild);
-
- } else if (parent instanceof BinaryNode) {
- BinaryNode binaryParent = (BinaryNode) parent;
- if (binaryParent.getLeftChild().deepEquals(child)) {
- binaryParent.setLeftChild(grandChild);
- } else if (binaryParent.getRightChild().deepEquals(child)) {
- binaryParent.setRightChild(grandChild);
- } else {
- throw new IllegalStateException("ERROR: both logical node must be parent and child nodes");
- }
- } else {
- throw new InvalidQueryException("Unexpected logical plan: " + parent);
- }
- return child;
- }
-
- public static void replaceNode(LogicalPlan plan, LogicalNode startNode, LogicalNode oldNode, LogicalNode newNode) {
- LogicalNodeReplaceVisitor replacer = new LogicalNodeReplaceVisitor(oldNode, newNode);
- try {
- replacer.visit(new ReplacerContext(), plan, null, startNode, new Stack<LogicalNode>());
- } catch (PlanningException e) {
- e.printStackTrace();
- }
- }
-
- static class ReplacerContext {
- boolean updateSchemaFlag = false;
- }
-
- public static class LogicalNodeReplaceVisitor extends BasicLogicalPlanVisitor<ReplacerContext, LogicalNode> {
- private LogicalNode target;
- private LogicalNode tobeReplaced;
-
- public LogicalNodeReplaceVisitor(LogicalNode target, LogicalNode tobeReplaced) {
- this.target = target;
- this.tobeReplaced = tobeReplaced;
- }
-
- /**
- * If this node can have child, it returns TRUE. Otherwise, it returns FALSE.
- */
- private static boolean checkIfVisitable(LogicalNode node) {
- return node instanceof UnaryNode || node instanceof BinaryNode;
- }
-
- @Override
- public LogicalNode visit(ReplacerContext context, LogicalPlan plan, @Nullable LogicalPlan.QueryBlock block,
- LogicalNode node, Stack<LogicalNode> stack) throws PlanningException {
- LogicalNode left = null;
- LogicalNode right = null;
-
- if (node instanceof UnaryNode) {
- UnaryNode unaryNode = (UnaryNode) node;
- if (unaryNode.getChild().deepEquals(target)) {
- unaryNode.setChild(tobeReplaced);
- left = tobeReplaced;
- context.updateSchemaFlag = true;
- } else if (checkIfVisitable(unaryNode.getChild())) {
- left = visit(context, plan, null, unaryNode.getChild(), stack);
- }
- } else if (node instanceof BinaryNode) {
- BinaryNode binaryNode = (BinaryNode) node;
- if (binaryNode.getLeftChild().deepEquals(target)) {
- binaryNode.setLeftChild(tobeReplaced);
- left = tobeReplaced;
- context.updateSchemaFlag = true;
- } else if (checkIfVisitable(binaryNode.getLeftChild())) {
- left = visit(context, plan, null, binaryNode.getLeftChild(), stack);
- } else {
- left = binaryNode.getLeftChild();
- }
-
- if (binaryNode.getRightChild().deepEquals(target)) {
- binaryNode.setRightChild(tobeReplaced);
- right = tobeReplaced;
- context.updateSchemaFlag = true;
- } else if (checkIfVisitable(binaryNode.getRightChild())) {
- right = visit(context, plan, null, binaryNode.getRightChild(), stack);
- } else {
- right = binaryNode.getRightChild();
- }
- }
-
- // update schemas of nodes except for leaf node (i.e., RelationNode)
- if (context.updateSchemaFlag) {
- if (node instanceof Projectable) {
- if (node instanceof BinaryNode) {
- node.setInSchema(SchemaUtil.merge(left.getOutSchema(), right.getOutSchema()));
- } else {
- node.setInSchema(left.getOutSchema());
- }
- context.updateSchemaFlag = false;
- } else {
- node.setInSchema(left.getOutSchema());
- node.setOutSchema(left.getOutSchema());
- }
- }
- return node;
- }
-
- @Override
- public LogicalNode visitScan(ReplacerContext context, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode node,
- Stack<LogicalNode> stack) throws PlanningException {
- return node;
- }
-
- @Override
- public LogicalNode visitPartitionedTableScan(ReplacerContext context, LogicalPlan plan, LogicalPlan.
- QueryBlock block, PartitionedTableScanNode node, Stack<LogicalNode> stack)
-
- throws PlanningException {
- return node;
- }
- }
-
- public static void replaceNode(LogicalNode plan, LogicalNode newNode, NodeType type) {
- LogicalNode parent = findTopParentNode(plan, type);
- Preconditions.checkArgument(parent instanceof UnaryNode);
- Preconditions.checkArgument(!(newNode instanceof BinaryNode));
- UnaryNode parentNode = (UnaryNode) parent;
- LogicalNode child = parentNode.getChild();
- if (child instanceof UnaryNode) {
- ((UnaryNode) newNode).setChild(((UnaryNode) child).getChild());
- }
- parentNode.setChild(newNode);
- }
-
- /**
- * Find the top logical node matched to type from the given node
- *
- * @param node start node
- * @param type to find
- * @return a found logical node
- */
- public static <T extends LogicalNode> T findTopNode(LogicalNode node, NodeType type) {
- Preconditions.checkNotNull(node);
- Preconditions.checkNotNull(type);
-
- LogicalNodeFinder finder = new LogicalNodeFinder(type);
- node.preOrder(finder);
-
- if (finder.getFoundNodes().size() == 0) {
- return null;
- }
- return (T) finder.getFoundNodes().get(0);
- }
-
- /**
- * Find the most bottom logical node matched to type from the given node
- *
- * @param node start node
- * @param type to find
- * @return a found logical node
- */
- public static <T extends LogicalNode> T findMostBottomNode(LogicalNode node, NodeType type) {
- Preconditions.checkNotNull(node);
- Preconditions.checkNotNull(type);
-
- LogicalNodeFinder finder = new LogicalNodeFinder(type);
- node.preOrder(finder);
-
- if (finder.getFoundNodes().size() == 0) {
- return null;
- }
- return (T) finder.getFoundNodes().get(finder.getFoundNodes().size() - 1);
- }
-
- /**
- * Find the all logical node matched to type from the given node
- *
- * @param node start node
- * @param type to find
- * @return a found logical node
- */
- public static LogicalNode[] findAllNodes(LogicalNode node, NodeType... type) {
- Preconditions.checkNotNull(node);
- Preconditions.checkNotNull(type);
-
- LogicalNodeFinder finder = new LogicalNodeFinder(type);
- node.postOrder(finder);
-
- if (finder.getFoundNodes().size() == 0) {
- return new LogicalNode[]{};
- }
- List<LogicalNode> founds = finder.getFoundNodes();
- return founds.toArray(new LogicalNode[founds.size()]);
- }
-
- /**
- * Find a parent node of a given-typed operator.
- *
- * @param node start node
- * @param type to find
- * @return the parent node of a found logical node
- */
- public static <T extends LogicalNode> T findTopParentNode(LogicalNode node, NodeType type) {
- Preconditions.checkNotNull(node);
- Preconditions.checkNotNull(type);
-
- ParentNodeFinder finder = new ParentNodeFinder(type);
- node.postOrder(finder);
-
- if (finder.getFoundNodes().size() == 0) {
- return null;
- }
- return (T) finder.getFoundNodes().get(0);
- }
-
- private static class LogicalNodeFinder implements LogicalNodeVisitor {
- private List<LogicalNode> list = new ArrayList<LogicalNode>();
- private final NodeType[] tofind;
- private boolean topmost = false;
- private boolean finished = false;
-
- public LogicalNodeFinder(NodeType... type) {
- this.tofind = type;
- }
-
- public LogicalNodeFinder(NodeType[] type, boolean topmost) {
- this(type);
- this.topmost = topmost;
- }
-
- @Override
- public void visit(LogicalNode node) {
- if (!finished) {
- for (NodeType type : tofind) {
- if (node.getType() == type) {
- list.add(node);
- }
- if (topmost && list.size() > 0) {
- finished = true;
- }
- }
- }
- }
-
- public List<LogicalNode> getFoundNodes() {
- return list;
- }
-
- public LogicalNode[] getFoundNodeArray() {
- return list.toArray(new LogicalNode[list.size()]);
- }
- }
-
- private static class ParentNodeFinder implements LogicalNodeVisitor {
- private List<LogicalNode> list = new ArrayList<LogicalNode>();
- private NodeType tofind;
-
- public ParentNodeFinder(NodeType type) {
- this.tofind = type;
- }
-
- @Override
- public void visit(LogicalNode node) {
- if (node instanceof UnaryNode) {
- UnaryNode unary = (UnaryNode) node;
- if (unary.getChild().getType() == tofind) {
- list.add(node);
- }
- } else if (node instanceof BinaryNode) {
- BinaryNode bin = (BinaryNode) node;
- if (bin.getLeftChild().getType() == tofind ||
- bin.getRightChild().getType() == tofind) {
- list.add(node);
- }
- }
- }
-
- public List<LogicalNode> getFoundNodes() {
- return list;
- }
- }
-
- /**
- * fill targets with FieldEvals from a given schema
- *
- * @param schema to be transformed to targets
- * @param targets to be filled
- */
- public static void schemaToTargets(Schema schema, Target[] targets) {
- FieldEval eval;
- for (int i = 0; i < schema.size(); i++) {
- eval = new FieldEval(schema.getColumn(i));
- targets[i] = new Target(eval);
- }
- }
-
- public static Target[] schemaToTargets(Schema schema) {
- Target[] targets = new Target[schema.size()];
-
- FieldEval eval;
- for (int i = 0; i < schema.size(); i++) {
- eval = new FieldEval(schema.getColumn(i));
- targets[i] = new Target(eval);
- }
- return targets;
- }
-
- public static Target[] schemaToTargetsWithGeneratedFields(Schema schema) {
- List<Target> targets = TUtil.newList();
-
- FieldEval eval;
- for (int i = 0; i < schema.size(); i++) {
- eval = new FieldEval(schema.getColumn(i));
- targets.add(new Target(eval));
- }
- return targets.toArray(new Target[targets.size()]);
- }
-
- public static SortSpec[] schemaToSortSpecs(Schema schema) {
- return columnsToSortSpecs(schema.toArray());
- }
-
- public static SortSpec[] columnsToSortSpecs(Column[] columns) {
- SortSpec[] specs = new SortSpec[columns.length];
-
- for (int i = 0; i < columns.length; i++) {
- specs[i] = new SortSpec(columns[i], true, false);
- }
-
- return specs;
- }
-
- public static SortSpec[] columnsToSortSpecs(Collection<Column> columns) {
- return columnsToSortSpecs(columns.toArray(new Column[columns.size()]));
- }
-
- public static Schema sortSpecsToSchema(SortSpec[] sortSpecs) {
- Schema schema = new Schema();
- for (SortSpec spec : sortSpecs) {
- schema.addColumn(spec.getSortKey());
- }
-
- return schema;
- }
-
- public static SortSpec[][] getSortKeysFromJoinQual(EvalNode joinQual, Schema outer, Schema inner) {
- // It is used for the merge join executor. The merge join only considers the equi-join.
- // So, theta-join flag must be false.
- List<Column[]> joinKeyPairs = getJoinKeyPairs(joinQual, outer, inner, false);
- SortSpec[] outerSortSpec = new SortSpec[joinKeyPairs.size()];
- SortSpec[] innerSortSpec = new SortSpec[joinKeyPairs.size()];
-
- for (int i = 0; i < joinKeyPairs.size(); i++) {
- outerSortSpec[i] = new SortSpec(joinKeyPairs.get(i)[0]);
- innerSortSpec[i] = new SortSpec(joinKeyPairs.get(i)[1]);
- }
-
- return new SortSpec[][]{outerSortSpec, innerSortSpec};
- }
-
- public static TupleComparator[] getComparatorsFromJoinQual(EvalNode joinQual, Schema leftSchema, Schema rightSchema) {
- SortSpec[][] sortSpecs = getSortKeysFromJoinQual(joinQual, leftSchema, rightSchema);
- TupleComparator[] comparators = new TupleComparator[2];
- comparators[0] = new TupleComparator(leftSchema, sortSpecs[0]);
- comparators[1] = new TupleComparator(rightSchema, sortSpecs[1]);
- return comparators;
- }
-
- /**
- * @return the first array contains left table's columns, and the second array contains right table's columns.
- */
- public static Column[][] joinJoinKeyForEachTable(EvalNode joinQual, Schema leftSchema,
- Schema rightSchema, boolean includeThetaJoin) {
- List<Column[]> joinKeys = getJoinKeyPairs(joinQual, leftSchema, rightSchema, includeThetaJoin);
- Column[] leftColumns = new Column[joinKeys.size()];
- Column[] rightColumns = new Column[joinKeys.size()];
- for (int i = 0; i < joinKeys.size(); i++) {
- leftColumns[i] = joinKeys.get(i)[0];
- rightColumns[i] = joinKeys.get(i)[1];
- }
-
- return new Column[][]{leftColumns, rightColumns};
- }
-
- public static List<Column[]> getJoinKeyPairs(EvalNode joinQual, Schema leftSchema, Schema rightSchema,
- boolean includeThetaJoin) {
- JoinKeyPairFinder finder = new JoinKeyPairFinder(includeThetaJoin, leftSchema, rightSchema);
- joinQual.preOrder(finder);
- return finder.getPairs();
- }
-
- public static class JoinKeyPairFinder implements EvalNodeVisitor {
- private boolean includeThetaJoin;
- private final List<Column[]> pairs = Lists.newArrayList();
- private Schema[] schemas = new Schema[2];
-
- public JoinKeyPairFinder(boolean includeThetaJoin, Schema outer, Schema inner) {
- this.includeThetaJoin = includeThetaJoin;
- schemas[0] = outer;
- schemas[1] = inner;
- }
-
- @Override
- public void visit(EvalNode node) {
- if (EvalTreeUtil.isJoinQual(node, includeThetaJoin)) {
- BinaryEval binaryEval = (BinaryEval) node;
- Column[] pair = new Column[2];
-
- for (int i = 0; i <= 1; i++) { // access left, right sub expression
- Column column = EvalTreeUtil.findAllColumnRefs(binaryEval.getChild(i)).get(0);
- for (int j = 0; j < schemas.length; j++) {
- // check whether the column is for either outer or inner
- // 0 is outer, and 1 is inner
- if (schemas[j].contains(column.getQualifiedName())) {
- pair[j] = column;
- }
- }
- }
-
- if (pair[0] == null || pair[1] == null) {
- throw new IllegalStateException("Wrong join key: " + node);
- }
- pairs.add(pair);
- }
- }
-
- public List<Column[]> getPairs() {
- return this.pairs;
- }
- }
-
- public static Schema targetToSchema(Collection<Target> targets) {
- return targetToSchema(targets.toArray(new Target[targets.size()]));
- }
-
- public static Schema targetToSchema(Target[] targets) {
- Schema schema = new Schema();
- for (Target t : targets) {
- DataType type = t.getEvalTree().getValueType();
- String name;
- if (t.hasAlias()) {
- name = t.getAlias();
- } else {
- name = t.getEvalTree().getName();
- }
- if (!schema.containsByQualifiedName(name)) {
- schema.addColumn(name, type);
- }
- }
-
- return schema;
- }
-
- /**
- * It removes all table names from FieldEvals in targets
- *
- * @param sourceTargets The targets to be stripped
- * @return The stripped targets
- */
- public static Target[] stripTarget(Target[] sourceTargets) {
- Target[] copy = new Target[sourceTargets.length];
- for (int i = 0; i < sourceTargets.length; i++) {
- try {
- copy[i] = (Target) sourceTargets[i].clone();
- } catch (CloneNotSupportedException e) {
- throw new InternalError(e.getMessage());
- }
- if (copy[i].getEvalTree().getType() == EvalType.FIELD) {
- FieldEval fieldEval = copy[i].getEvalTree();
- if (fieldEval.getColumnRef().hasQualifier()) {
- fieldEval.replaceColumnRef(fieldEval.getColumnName());
- }
- }
- }
-
- return copy;
- }
-
- public static <T extends LogicalNode> T clone(LogicalPlan plan, LogicalNode node) {
- try {
- T copy = (T) node.clone();
- if (plan == null) {
- copy.setPID(-1);
- } else {
- copy.setPID(plan.newPID());
- if (node instanceof DistinctGroupbyNode) {
- DistinctGroupbyNode dNode = (DistinctGroupbyNode)copy;
- for (GroupbyNode eachNode: dNode.getGroupByNodes()) {
- eachNode.setPID(plan.newPID());
- }
- }
- }
- return copy;
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e);
- }
- }
-
- public static boolean isCommutativeJoin(JoinType joinType) {
- return joinType == JoinType.INNER;
- }
-
- public static boolean existsAggregationFunction(Expr expr) throws PlanningException {
- AggregationFunctionFinder finder = new AggregationFunctionFinder();
- AggFunctionFoundResult result = new AggFunctionFoundResult();
- finder.visit(result, new Stack<Expr>(), expr);
- return result.generalSetFunction;
- }
-
- public static boolean existsDistinctAggregationFunction(Expr expr) throws PlanningException {
- AggregationFunctionFinder finder = new AggregationFunctionFinder();
- AggFunctionFoundResult result = new AggFunctionFoundResult();
- finder.visit(result, new Stack<Expr>(), expr);
- return result.distinctSetFunction;
- }
-
- static class AggFunctionFoundResult {
- boolean generalSetFunction;
- boolean distinctSetFunction;
- }
-
- static class AggregationFunctionFinder extends SimpleAlgebraVisitor<AggFunctionFoundResult, Object> {
- @Override
- public Object visitCountRowsFunction(AggFunctionFoundResult ctx, Stack<Expr> stack, CountRowsFunctionExpr expr)
- throws PlanningException {
- ctx.generalSetFunction = true;
- return super.visitCountRowsFunction(ctx, stack, expr);
- }
-
- @Override
- public Object visitGeneralSetFunction(AggFunctionFoundResult ctx, Stack<Expr> stack, GeneralSetFunctionExpr expr)
- throws PlanningException {
- ctx.generalSetFunction = true;
- ctx.distinctSetFunction = expr.isDistinct();
- return super.visitGeneralSetFunction(ctx, stack, expr);
- }
- }
-
- public static Collection<String> toQualifiedFieldNames(Collection<String> fieldNames, String qualifier) {
- List<String> names = TUtil.newList();
- for (String n : fieldNames) {
- String[] parts = n.split("\\.");
- if (parts.length == 1) {
- names.add(qualifier + "." + parts[0]);
- } else {
- names.add(qualifier + "." + parts[1]);
- }
- }
- return names;
- }
-
- public static SortSpec[] convertSortSpecs(Collection<CatalogProtos.SortSpecProto> sortSpecProtos) {
- SortSpec[] sortSpecs = new SortSpec[sortSpecProtos.size()];
- int i = 0;
- for (CatalogProtos.SortSpecProto proto : sortSpecProtos) {
- sortSpecs[i++] = new SortSpec(proto);
- }
- return sortSpecs;
- }
-
- /**
- * Generate an explain string of a LogicalNode and its descendant nodes.
- *
- * @param node The LogicalNode instance to be started
- * @return A pretty print explain string
- */
- public static String buildExplainString(LogicalNode node) {
- ExplainLogicalPlanVisitor explain = new ExplainLogicalPlanVisitor();
-
- StringBuilder explains = new StringBuilder();
- try {
- ExplainLogicalPlanVisitor.Context explainContext = explain.getBlockPlanStrings(null, node);
- while (!explainContext.explains.empty()) {
- explains.append(
- ExplainLogicalPlanVisitor.printDepthString(explainContext.getMaxDepth(), explainContext.explains.pop()));
- }
- } catch (PlanningException e) {
- throw new RuntimeException(e);
- }
-
- return explains.toString();
- }
-
- /**
- * Listing table data file which is not empty.
- * If the table is a partitioned table, return file list which has same partition key.
- * @param tajoConf
- * @param tableDesc
- * @param fileIndex
- * @param numResultFiles
- * @return
- * @throws IOException
- */
- public static FragmentProto[] getNonZeroLengthDataFiles(TajoConf tajoConf,TableDesc tableDesc,
- int fileIndex, int numResultFiles) throws IOException {
- FileSystem fs = tableDesc.getPath().getFileSystem(tajoConf);
-
- List<FileStatus> nonZeroLengthFiles = new ArrayList<FileStatus>();
- if (fs.exists(tableDesc.getPath())) {
- getNonZeroLengthDataFiles(fs, tableDesc.getPath(), nonZeroLengthFiles, fileIndex, numResultFiles,
- new AtomicInteger(0));
- }
-
- List<FileFragment> fragments = new ArrayList<FileFragment>();
-
- //In the case of partitioned table, return same partition key data files.
- int numPartitionColumns = 0;
- if (tableDesc.hasPartition()) {
- numPartitionColumns = tableDesc.getPartitionMethod().getExpressionSchema().getColumns().size();
- }
- String[] previousPartitionPathNames = null;
- for (FileStatus eachFile: nonZeroLengthFiles) {
- FileFragment fileFragment = new FileFragment(tableDesc.getName(), eachFile.getPath(), 0, eachFile.getLen(), null);
-
- if (numPartitionColumns > 0) {
- // finding partition key;
- Path filePath = fileFragment.getPath();
- Path parentPath = filePath;
- String[] parentPathNames = new String[numPartitionColumns];
- for (int i = 0; i < numPartitionColumns; i++) {
- parentPath = parentPath.getParent();
- parentPathNames[numPartitionColumns - i - 1] = parentPath.getName();
- }
-
- // If current partitionKey == previousPartitionKey, add to result.
- if (previousPartitionPathNames == null) {
- fragments.add(fileFragment);
- } else if (previousPartitionPathNames != null && Arrays.equals(previousPartitionPathNames, parentPathNames)) {
- fragments.add(fileFragment);
- } else {
- break;
- }
- previousPartitionPathNames = parentPathNames;
- } else {
- fragments.add(fileFragment);
- }
- }
- return FragmentConvertor.toFragmentProtoArray(fragments.toArray(new FileFragment[]{}));
- }
-
- private static void getNonZeroLengthDataFiles(FileSystem fs, Path path, List<FileStatus> result,
- int startFileIndex, int numResultFiles,
- AtomicInteger currentFileIndex) throws IOException {
- if (fs.isDirectory(path)) {
- FileStatus[] files = fs.listStatus(path, StorageManager.hiddenFileFilter);
- if (files != null && files.length > 0) {
- for (FileStatus eachFile : files) {
- if (result.size() >= numResultFiles) {
- return;
- }
- if (eachFile.isDirectory()) {
- getNonZeroLengthDataFiles(fs, eachFile.getPath(), result, startFileIndex, numResultFiles,
- currentFileIndex);
- } else if (eachFile.isFile() && eachFile.getLen() > 0) {
- if (currentFileIndex.get() >= startFileIndex) {
- result.add(eachFile);
- }
- currentFileIndex.incrementAndGet();
- }
- }
- }
- } else {
- FileStatus fileStatus = fs.getFileStatus(path);
- if (fileStatus != null && fileStatus.getLen() > 0) {
- if (currentFileIndex.get() >= startFileIndex) {
- result.add(fileStatus);
- }
- currentFileIndex.incrementAndGet();
- if (result.size() >= numResultFiles) {
- return;
- }
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlanningException.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlanningException.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlanningException.java
deleted file mode 100644
index 4fa88ee..0000000
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlanningException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * 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;
-
-public class PlanningException extends Exception {
- public PlanningException(String message) {
- super(message);
- }
-
- public PlanningException(Exception e) {
- super(e);
- }
-}
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
deleted file mode 100644
index f6d5540..0000000
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/**
- * 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;
-
-import org.apache.tajo.TajoConstants;
-import org.apache.tajo.algebra.*;
-import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.CatalogUtil;
-import org.apache.tajo.catalog.TableDesc;
-import org.apache.tajo.catalog.proto.CatalogProtos;
-import org.apache.tajo.engine.query.QueryContext;
-import org.apache.tajo.util.TUtil;
-
-import java.util.Set;
-import java.util.Stack;
-
-public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <PreLogicalPlanVerifier.Context, Expr> {
- private CatalogService catalog;
-
- public PreLogicalPlanVerifier(CatalogService catalog) {
- this.catalog = catalog;
- }
-
- public static class Context {
- QueryContext queryContext;
- VerificationState state;
-
- public Context(QueryContext queryContext, VerificationState state) {
- this.queryContext = queryContext;
- this.state = state;
- }
- }
-
- public VerificationState verify(QueryContext queryContext, VerificationState state, Expr expr) throws PlanningException {
- Context context = new Context(queryContext, state);
- visit(context, new Stack<Expr>(), expr);
- return context.state;
- }
-
- public Expr visitProjection(Context context, Stack<Expr> stack, Projection expr) throws PlanningException {
- super.visitProjection(context, stack, expr);
-
- Set<String> names = TUtil.newHashSet();
- Expr [] distinctValues = null;
-
- for (NamedExpr namedExpr : expr.getNamedExprs()) {
-
- if (namedExpr.hasAlias()) {
- if (names.contains(namedExpr.getAlias())) {
- context.state.addVerification(String.format("column name \"%s\" specified more than once",
- namedExpr.getAlias()));
- } else {
- names.add(namedExpr.getAlias());
- }
- }
-
- Set<GeneralSetFunctionExpr> exprs = ExprFinder.finds(namedExpr.getExpr(), OpType.GeneralSetFunction);
-
- // Currently, avg functions with distinct aggregation are not supported.
- // This code does not allow users to use avg functions with distinct aggregation.
- if (distinctValues != null) {
- for (GeneralSetFunctionExpr setFunction : exprs) {
- if (setFunction.getSignature().equalsIgnoreCase("avg")) {
- if (setFunction.isDistinct()) {
- throw new PlanningException("avg(distinct) function is not supported yet.");
- } else {
- throw new PlanningException("avg() function with distinct aggregation functions is not supported yet.");
- }
- }
- }
- }
- }
- return expr;
- }
-
- @Override
- public Expr visitLimit(Context context, Stack<Expr> stack, Limit expr) throws PlanningException {
- stack.push(expr);
-
- if (ExprFinder.finds(expr.getFetchFirstNum(), OpType.Column).size() > 0) {
- context.state.addVerification("argument of LIMIT must not contain variables");
- }
-
- visit(context, stack, expr.getFetchFirstNum());
- Expr result = visit(context, stack, expr.getChild());
- stack.pop();
- return result;
- }
-
- @Override
- public Expr visitGroupBy(Context context, Stack<Expr> stack, Aggregation expr) throws PlanningException {
- super.visitGroupBy(context, stack, expr);
-
- // Enforcer only ordinary grouping set.
- for (Aggregation.GroupElement groupingElement : expr.getGroupSet()) {
- if (groupingElement.getType() != Aggregation.GroupType.OrdinaryGroup) {
- context.state.addVerification(groupingElement.getType() + " is not supported yet");
- }
- }
-
- Projection projection = null;
- for (Expr parent : stack) {
- if (parent.getType() == OpType.Projection) {
- projection = (Projection) parent;
- break;
- }
- }
-
- if (projection == null) {
- throw new PlanningException("No Projection");
- }
-
- return expr;
- }
-
- @Override
- public Expr visitRelation(Context context, Stack<Expr> stack, Relation expr) throws PlanningException {
- assertRelationExistence(context, expr.getName());
- return expr;
- }
-
- private boolean assertRelationExistence(Context context, String tableName) {
- String qualifiedName;
-
- if (CatalogUtil.isFQTableName(tableName)) {
- qualifiedName = tableName;
- } else {
- qualifiedName = CatalogUtil.buildFQName(context.queryContext.getCurrentDatabase(), tableName);
- }
-
- if (!catalog.existsTable(qualifiedName)) {
- context.state.addVerification(String.format("relation \"%s\" does not exist", qualifiedName));
- return false;
- }
- return true;
- }
-
- private boolean assertRelationNoExistence(Context context, String tableName) {
- String qualifiedName;
-
- if (CatalogUtil.isFQTableName(tableName)) {
- qualifiedName = tableName;
- } else {
- qualifiedName = CatalogUtil.buildFQName(context.queryContext.getCurrentDatabase(), tableName);
- }
- if(qualifiedName == null) {
- System.out.println("A");
- }
- if (catalog.existsTable(qualifiedName)) {
- context.state.addVerification(String.format("relation \"%s\" already exists", qualifiedName));
- return false;
- }
- return true;
- }
-
- private boolean assertUnsupportedStoreType(VerificationState state, String name) {
- if (name != null && name.equals(CatalogProtos.StoreType.RAW.name())) {
- state.addVerification(String.format("Unsupported store type :%s", name));
- return false;
- }
- return true;
- }
-
- private boolean assertDatabaseExistence(VerificationState state, String name) {
- if (!catalog.existDatabase(name)) {
- state.addVerification(String.format("database \"%s\" does not exist", name));
- return false;
- }
- return true;
- }
-
- private boolean assertDatabaseNoExistence(VerificationState state, String name) {
- if (catalog.existDatabase(name)) {
- state.addVerification(String.format("database \"%s\" already exists", name));
- return false;
- }
- return true;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Data Definition Language Section
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
- @Override
- public Expr visitCreateDatabase(Context context, Stack<Expr> stack, CreateDatabase expr)
- throws PlanningException {
- super.visitCreateDatabase(context, stack, expr);
- if (!expr.isIfNotExists()) {
- assertDatabaseNoExistence(context.state, expr.getDatabaseName());
- }
- return expr;
- }
-
- @Override
- public Expr visitDropDatabase(Context context, Stack<Expr> stack, DropDatabase expr) throws PlanningException {
- super.visitDropDatabase(context, stack, expr);
- if (!expr.isIfExists()) {
- assertDatabaseExistence(context.state, expr.getDatabaseName());
- }
- return expr;
- }
-
- @Override
- public Expr visitCreateTable(Context context, Stack<Expr> stack, CreateTable expr) throws PlanningException {
- super.visitCreateTable(context, stack, expr);
- if (!expr.isIfNotExists()) {
- assertRelationNoExistence(context, expr.getTableName());
- }
- assertUnsupportedStoreType(context.state, expr.getStorageType());
- return expr;
- }
-
- @Override
- public Expr visitDropTable(Context context, Stack<Expr> stack, DropTable expr) throws PlanningException {
- super.visitDropTable(context, stack, expr);
- if (!expr.isIfExists()) {
- assertRelationExistence(context, expr.getTableName());
- }
- return expr;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Insert or Update Section
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- public Expr visitInsert(Context context, Stack<Expr> stack, Insert expr) throws PlanningException {
- Expr child = super.visitInsert(context, stack, expr);
-
- if (expr.hasTableName()) {
- assertRelationExistence(context, expr.getTableName());
- }
-
- if (child != null && child.getType() == OpType.Projection) {
- Projection projection = (Projection) child;
- int projectColumnNum = projection.getNamedExprs().length;
-
- if (expr.hasTargetColumns()) {
- int targetColumnNum = expr.getTargetColumns().length;
-
- if (targetColumnNum > projectColumnNum) {
- context.state.addVerification("INSERT has more target columns than expressions");
- } else if (targetColumnNum < projectColumnNum) {
- context.state.addVerification("INSERT has more expressions than target columns");
- }
- } else {
- if (expr.hasTableName()) {
- String qualifiedName = expr.getTableName();
- if (TajoConstants.EMPTY_STRING.equals(CatalogUtil.extractQualifier(expr.getTableName()))) {
- qualifiedName = CatalogUtil.buildFQName(context.queryContext.getCurrentDatabase(),
- expr.getTableName());
- }
-
- TableDesc table = catalog.getTableDesc(qualifiedName);
- if (table == null) {
- context.state.addVerification(String.format("relation \"%s\" does not exist", qualifiedName));
- return null;
- }
- if (table.hasPartition()) {
- int columnSize = table.getSchema().getColumns().size();
- columnSize += table.getPartitionMethod().getExpressionSchema().getColumns().size();
- if (projectColumnNum < columnSize) {
- context.state.addVerification("INSERT has smaller expressions than target columns");
- } else if (projectColumnNum > columnSize) {
- context.state.addVerification("INSERT has more expressions than target columns");
- }
- }
- }
- }
- }
-
- return expr;
- }
-}
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/Projector.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/Projector.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/Projector.java
index d8499d0..7c2e81f 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/Projector.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/Projector.java
@@ -20,14 +20,16 @@ package org.apache.tajo.engine.planner;
import org.apache.tajo.SessionVars;
import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.plan.Target;
+import org.apache.tajo.plan.expr.EvalNode;
import org.apache.tajo.storage.Tuple;
import org.apache.tajo.worker.TaskAttemptContext;
public class Projector {
private final TaskAttemptContext context;
private final Schema inSchema;
- private final Target [] targets;
+ private final Target[] targets;
// for projection
private final int targetNum;
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/SimpleAlgebraVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/SimpleAlgebraVisitor.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/SimpleAlgebraVisitor.java
deleted file mode 100644
index 8b34189..0000000
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/SimpleAlgebraVisitor.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/**
- * 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;
-
-import org.apache.tajo.algebra.*;
-
-import java.util.Stack;
-
-/**
- * <code>SimpleAlgebraVisitor</code> provides a simple and fewer visit methods. It makes building concrete class easier.
- */
-public abstract class SimpleAlgebraVisitor<CONTEXT, RESULT> extends BaseAlgebraVisitor<CONTEXT, RESULT> {
-
- public RESULT visit(CONTEXT ctx, Stack<Expr> stack, Expr expr) throws PlanningException {
- RESULT result = null;
- if (expr instanceof UnaryOperator) {
- preHook(ctx, stack, expr);
- result = visitUnaryOperator(ctx, stack, (UnaryOperator) expr);
- postHook(ctx, stack, expr, result);
- } else if (expr instanceof BinaryOperator) {
- preHook(ctx, stack, expr);
- result = visitBinaryOperator(ctx, stack, (BinaryOperator) expr);
- postHook(ctx, stack, expr, result);
- } else {
- result = super.visit(ctx, stack, expr);
- }
-
- return result;
- }
-
- public RESULT visitUnaryOperator(CONTEXT ctx, Stack<Expr> stack, UnaryOperator expr) throws PlanningException {
- stack.push(expr);
- RESULT result = visit(ctx, stack, expr.getChild());
- stack.pop();
- return result;
- }
-
- public RESULT visitBinaryOperator(CONTEXT ctx, Stack<Expr> stack, BinaryOperator expr) throws PlanningException {
- stack.push(expr);
- visit(ctx, stack, expr.getLeft());
- RESULT result = visit(ctx, stack, expr.getRight());
- stack.pop();
- return result;
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Relational Operator Section
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- @Override
- public RESULT visitProjection(CONTEXT ctx, Stack<Expr> stack, Projection expr) throws PlanningException {
- return super.visitProjection(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitLimit(CONTEXT ctx, Stack<Expr> stack, Limit expr) throws PlanningException {
- return super.visitLimit(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitSort(CONTEXT ctx, Stack<Expr> stack, Sort expr) throws PlanningException {
- return super.visitSort(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitHaving(CONTEXT ctx, Stack<Expr> stack, Having expr) throws PlanningException {
- return super.visitHaving(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitGroupBy(CONTEXT ctx, Stack<Expr> stack, Aggregation expr) throws PlanningException {
- return super.visitGroupBy(ctx, stack, expr);
- }
-
- public RESULT visitFilter(CONTEXT ctx, Stack<Expr> stack, Selection expr) throws PlanningException {
- return super.visitFilter(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitJoin(CONTEXT ctx, Stack<Expr> stack, Join expr) throws PlanningException {
- return super.visitJoin(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitTableSubQuery(CONTEXT ctx, Stack<Expr> stack, TablePrimarySubQuery expr) throws PlanningException {
- return super.visitTableSubQuery(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitRelationList(CONTEXT ctx, Stack<Expr> stack, RelationList expr) throws PlanningException {
- return super.visitRelationList(ctx, stack, expr);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Data Definition Language Section
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- @Override
- public RESULT visitCreateTable(CONTEXT ctx, Stack<Expr> stack, CreateTable expr) throws PlanningException {
- return super.visitCreateTable(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitDropTable(CONTEXT ctx, Stack<Expr> stack, DropTable expr) throws PlanningException {
- return super.visitDropTable(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitAlterTable(CONTEXT ctx, Stack<Expr> stack, AlterTable expr) throws PlanningException {
- return super.visitAlterTable(ctx, stack, expr);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Insert or Update Section
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- @Override
- public RESULT visitInsert(CONTEXT ctx, Stack<Expr> stack, Insert expr) throws PlanningException {
- return super.visitInsert(ctx, stack, expr);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Other Predicates Section
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- @Override
- public RESULT visitBetween(CONTEXT ctx, Stack<Expr> stack, BetweenPredicate expr) throws PlanningException {
- return super.visitBetween(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitCaseWhen(CONTEXT ctx, Stack<Expr> stack, CaseWhenPredicate expr) throws PlanningException {
- return super.visitCaseWhen(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitValueListExpr(CONTEXT ctx, Stack<Expr> stack, ValueListExpr expr) throws PlanningException {
- return super.visitValueListExpr(ctx, stack, expr);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Functions and General Set Function Section
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- @Override
- public RESULT visitFunction(CONTEXT ctx, Stack<Expr> stack, FunctionExpr expr) throws PlanningException {
- return super.visitFunction(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitCountRowsFunction(CONTEXT ctx, Stack<Expr> stack, CountRowsFunctionExpr expr)
- throws PlanningException {
- return super.visitCountRowsFunction(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitGeneralSetFunction(CONTEXT ctx, Stack<Expr> stack, GeneralSetFunctionExpr expr)
- throws PlanningException {
- return super.visitGeneralSetFunction(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitWindowFunction(CONTEXT ctx, Stack<Expr> stack, WindowFunctionExpr expr) throws PlanningException {
- return super.visitWindowFunction(ctx, stack, expr);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Literal Section
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- @Override
- public RESULT visitDataType(CONTEXT ctx, Stack<Expr> stack, DataTypeExpr expr) throws PlanningException {
- return super.visitDataType(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitLiteral(CONTEXT ctx, Stack<Expr> stack, LiteralValue expr) throws PlanningException {
- return super.visitLiteral(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitNullLiteral(CONTEXT ctx, Stack<Expr> stack, NullLiteral expr) throws PlanningException {
- return super.visitNullLiteral(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitTimestampLiteral(CONTEXT ctx, Stack<Expr> stack, TimestampLiteral expr) throws PlanningException {
- return super.visitTimestampLiteral(ctx, stack, expr);
- }
-
- @Override
- public RESULT visitTimeLiteral(CONTEXT ctx, Stack<Expr> stack, TimeLiteral expr) throws PlanningException {
- return super.visitTimeLiteral(ctx, stack, expr);
- }
-}
http://git-wip-us.apache.org/repos/asf/tajo/blob/b143f991/tajo-core/src/main/java/org/apache/tajo/engine/planner/Target.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/Target.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/Target.java
deleted file mode 100644
index 6a16d3c..0000000
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/Target.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/**
- * 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;
-
-import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.Column;
-import org.apache.tajo.common.TajoDataTypes.DataType;
-import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.eval.FieldEval;
-import org.apache.tajo.engine.json.CoreGsonHelper;
-import org.apache.tajo.json.GsonObject;
-import org.apache.tajo.util.TUtil;
-
-/**
- * A Target contains how to evaluate an expression and its alias name.
- */
-public class Target implements Cloneable, GsonObject {
- @Expose private EvalNode expr;
- @Expose private Column column;
- @Expose private String alias = null;
-
- public Target(FieldEval fieldEval) {
- this.expr = fieldEval;
- this.column = fieldEval.getColumnRef();
- }
-
- public Target(final EvalNode eval, final String alias) {
- this.expr = eval;
- // force lower case
- String normalized = alias;
-
- // If an expr is a column reference and its alias is equivalent to column name, ignore a given alias.
- if (eval instanceof FieldEval && eval.getName().equals(normalized)) {
- column = ((FieldEval) eval).getColumnRef();
- } else {
- column = new Column(normalized, eval.getValueType());
- setAlias(alias);
- }
- }
-
- public String getCanonicalName() {
- return !hasAlias() ? column.getQualifiedName() : alias;
- }
-
- public final void setExpr(EvalNode expr) {
- this.expr = expr;
- }
-
- public final void setAlias(String alias) {
- this.alias = alias;
- this.column = new Column(alias, expr.getValueType());
- }
-
- public final String getAlias() {
- return alias;
- }
-
- public final boolean hasAlias() {
- return alias != null;
- }
-
- public DataType getDataType() {
- return column.getDataType();
- }
-
- public <T extends EvalNode> T getEvalTree() {
- return (T) this.expr;
- }
-
- public Column getNamedColumn() {
- return this.column;
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder(expr.toString());
- if(hasAlias()) {
- sb.append(" as ").append(alias);
- }
- return sb.toString();
- }
-
- public boolean equals(Object obj) {
- if(obj instanceof Target) {
- Target other = (Target) obj;
-
- boolean b1 = expr.equals(other.expr);
- boolean b2 = column.equals(other.column);
- boolean b3 = TUtil.checkEquals(alias, other.alias);
-
- return b1 && b2 && b3;
- } else {
- return false;
- }
- }
-
- public int hashCode() {
- return this.expr.getName().hashCode();
- }
-
- @Override
- public Object clone() throws CloneNotSupportedException {
- Target target = (Target) super.clone();
- target.expr = (EvalNode) expr.clone();
- target.column = column;
- target.alias = alias != null ? alias : null;
-
- return target;
- }
-
- public String toJson() {
- return CoreGsonHelper.toJson(this, Target.class);
- }
-}