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 2013/09/21 04:02:44 UTC
[1/2] TAJO-46: The "having" clause does not work properly. (hyunsik)
Updated Branches:
refs/heads/master bd1619de0 -> e595384ba
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java
index dd91500..21730db 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java
@@ -185,10 +185,6 @@ public class ProjectionPushDownRule extends BasicLogicalPlanVisitor<ProjectionPu
throws PlanningException {
Set<Column> currentRequired = new HashSet<Column>(context.upperRequired);
- if (node.hasHavingCondition()) {
- currentRequired.addAll(EvalTreeUtil.findDistinctRefColumns(node.getHavingCondition()));
- }
-
for (Target target : node.getTargets()) {
currentRequired.addAll(EvalTreeUtil.findDistinctRefColumns(target.getEvalTree()));
}
@@ -271,7 +267,7 @@ public class ProjectionPushDownRule extends BasicLogicalPlanVisitor<ProjectionPu
Stack<LogicalNode> newStack = new Stack<LogicalNode>();
newStack.push(node);
PushDownContext newContext = new PushDownContext(subBlock);
- if (subBlock.getProjection() != null && subBlock.getProjection().isAllProjected()
+ if (subBlock.hasProjection() && subBlock.getProjection().isAllProjected()
&& context.upperRequired.size() == 0) {
newContext.targetListManager = new TargetListManager(plan, subBlock.getProjectionNode().getTargets());
} else {
@@ -366,7 +362,9 @@ public class ProjectionPushDownRule extends BasicLogicalPlanVisitor<ProjectionPu
Projectable projectable = (Projectable) node;
if (last) {
Preconditions.checkState(targetListManager.isAllResolved(), "Not all targets are evaluated");
- projectable.setTargets(targetListManager.getTargets());
+ if (node.getType() != NodeType.GROUP_BY) {
+ projectable.setTargets(targetListManager.getTargets());
+ }
node.setOutSchema(targetListManager.getUpdatedSchema());
} else {
// Preparing targets regardless of that the node has targets or not.
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalPlanner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalPlanner.java
index ff885aa..b853ed8 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalPlanner.java
@@ -62,7 +62,7 @@ public class GlobalPlanner {
public void build(MasterPlan masterPlan)
throws IOException, PlanningException {
- NewPlanner planner = new NewPlanner();
+ DistributedPlannerVisitor planner = new DistributedPlannerVisitor();
GlobalPlanContext globalPlanContext = new GlobalPlanContext();
globalPlanContext.plan = masterPlan;
LOG.info(masterPlan.getLogicalPlan());
@@ -112,39 +112,39 @@ public class GlobalPlanner {
return new ScanNode(desc);
}
- public class NewPlanner extends BasicLogicalPlanVisitor<GlobalPlanContext> {
+ public class DistributedPlannerVisitor extends BasicLogicalPlanVisitor<GlobalPlanContext> {
@Override
public LogicalNode visitRoot(LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack,
- GlobalPlanContext data) throws PlanningException {
- super.visitRoot(plan, node, stack, data);
+ GlobalPlanContext context) throws PlanningException {
+ super.visitRoot(plan, node, stack, context);
- if (data.lastRepartionableNode != null && data.lastRepartionableNode.getType() != NodeType.UNION) {
- data.topMostLeftExecBlock = addChannel(data.plan, data.lastRepartionableNode, node, data.topmost, data.topMostLeftExecBlock);
- } else if (data.lastRepartionableNode != null && data.lastRepartionableNode.getType() == NodeType.UNION) {
+ if (context.lastRepartionableNode != null && context.lastRepartionableNode.getType() != NodeType.UNION) {
+ context.topMostLeftExecBlock = addChannel(context.plan, context.lastRepartionableNode, node, context.topmost, context.topMostLeftExecBlock);
+ } else if (context.lastRepartionableNode != null && context.lastRepartionableNode.getType() == NodeType.UNION) {
} else {
- ExecutionBlock execBlock = data.plan.newExecutionBlock();
+ ExecutionBlock execBlock = context.plan.newExecutionBlock();
execBlock.setPlan(node);
- data.topMostLeftExecBlock = execBlock;
+ context.topMostLeftExecBlock = execBlock;
}
- data.topmost = node;
+ context.topmost = node;
return node;
}
@Override
public LogicalNode visitProjection(LogicalPlan plan, ProjectionNode node, Stack<LogicalNode> stack,
- GlobalPlanContext data) throws PlanningException {
- super.visitProjection(plan, node, stack, data);
- data.topmost = node;
+ GlobalPlanContext context) throws PlanningException {
+ super.visitProjection(plan, node, stack, context);
+ context.topmost = node;
return node;
}
@Override
- public LogicalNode visitLimit(LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack, GlobalPlanContext data) throws PlanningException {
- super.visitLimit(plan, node, stack, data);
- data.topmost = node;
+ public LogicalNode visitLimit(LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack, GlobalPlanContext context) throws PlanningException {
+ super.visitLimit(plan, node, stack, context);
+ context.topmost = node;
return node;
}
@@ -160,6 +160,7 @@ public class GlobalPlanner {
GroupbyNode groupByNode = (GroupbyNode) lastDistNode;
GroupbyNode firstGroupBy = PlannerUtil.transformGroupbyTo2P(groupByNode);
+ firstGroupBy.setHavingCondition(null);
if (firstGroupBy.getChild().getType() == NodeType.TABLE_SUBQUERY &&
((TableSubQueryNode)firstGroupBy.getChild()).getSubQuery().getType() == NodeType.UNION) {
@@ -310,113 +311,121 @@ public class GlobalPlanner {
}
@Override
- public LogicalNode visitSort(LogicalPlan plan, SortNode node, Stack<LogicalNode> stack, GlobalPlanContext data)
+ public LogicalNode visitSort(LogicalPlan plan, SortNode node, Stack<LogicalNode> stack, GlobalPlanContext context)
throws PlanningException {
- super.visitSort(plan, node, stack, data);
+ super.visitSort(plan, node, stack, context);
- if (data.lastRepartionableNode != null) {
- data.topMostLeftExecBlock = addChannel(data.plan, data.lastRepartionableNode, node, data.topmost, data.topMostLeftExecBlock);
+ if (context.lastRepartionableNode != null) {
+ context.topMostLeftExecBlock = addChannel(context.plan, context.lastRepartionableNode, node, context.topmost,
+ context.topMostLeftExecBlock);
}
- data.topmost = node;
- data.lastRepartionableNode = node;
+ context.topmost = node;
+ context.lastRepartionableNode = node;
return node;
}
@Override
- public LogicalNode visitGroupBy(LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack, GlobalPlanContext data) throws PlanningException {
- super.visitGroupBy(plan, node, stack, data);
+ public LogicalNode visitGroupBy(LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack,
+ GlobalPlanContext context) throws PlanningException {
+ super.visitGroupBy(plan, node, stack, context);
- if (data.lastRepartionableNode != null) {
- data.topMostLeftExecBlock = addChannel(data.plan, data.lastRepartionableNode, node, data.topmost, data.topMostLeftExecBlock);
+ if (context.lastRepartionableNode != null) {
+ context.topMostLeftExecBlock = addChannel(context.plan, context.lastRepartionableNode, node, context.topmost,
+ context.topMostLeftExecBlock);
}
- data.topmost = node;
- data.lastRepartionableNode = node;
+ context.topmost = node;
+ context.lastRepartionableNode = node;
return node;
}
@Override
- public LogicalNode visitFilter(LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack, GlobalPlanContext data) throws PlanningException {
- super.visitFilter(plan, node, stack, data);
- data.topmost = node;
+ public LogicalNode visitFilter(LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack,
+ GlobalPlanContext context) throws PlanningException {
+ super.visitFilter(plan, node, stack, context);
+ context.topmost = node;
return node;
}
@Override
- public LogicalNode visitJoin(LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack, GlobalPlanContext data) throws PlanningException {
- super.visitJoin(plan, node, stack, data);
+ public LogicalNode visitJoin(LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack, GlobalPlanContext context)
+ throws PlanningException {
+ super.visitJoin(plan, node, stack, context);
- if (data.lastRepartionableNode != null) {
- data.topMostLeftExecBlock = addChannel(data.plan, data.lastRepartionableNode, node, data.topmost, data.topMostLeftExecBlock);
+ if (context.lastRepartionableNode != null) {
+ context.topMostLeftExecBlock = addChannel(context.plan, context.lastRepartionableNode, node, context.topmost,
+ context.topMostLeftExecBlock);
}
- data.topmost = node;
- data.lastRepartionableNode = node;
+ context.topmost = node;
+ context.lastRepartionableNode = node;
return node;
}
@Override
- public LogicalNode visitUnion(LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack, GlobalPlanContext data) throws PlanningException {
- super.visitUnion(plan, node, stack, data);
+ public LogicalNode visitUnion(LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack,
+ GlobalPlanContext context) throws PlanningException {
+ super.visitUnion(plan, node, stack, context);
- if (data.lastRepartionableNode != null && data.lastRepartionableNode.getType() != NodeType.UNION) {
- data.topMostLeftExecBlock = addChannel(data.plan, data.lastRepartionableNode, node, data.topmost,
- data.topMostLeftExecBlock);
+ if (context.lastRepartionableNode != null && context.lastRepartionableNode.getType() != NodeType.UNION) {
+ context.topMostLeftExecBlock = addChannel(context.plan, context.lastRepartionableNode, node, context.topmost,
+ context.topMostLeftExecBlock);
}
- data.topmost = node;
- data.lastRepartionableNode = node;
+ context.topmost = node;
+ context.lastRepartionableNode = node;
return node;
}
@Override
public LogicalNode visitExcept(LogicalPlan plan, ExceptNode node, Stack<LogicalNode> stack,
- GlobalPlanContext data) throws PlanningException {
- super.visitExcept(plan, node, stack, data);
- data.topmost = node;
+ GlobalPlanContext context) throws PlanningException {
+ super.visitExcept(plan, node, stack, context);
+ context.topmost = node;
return node;
}
@Override
public LogicalNode visitIntersect(LogicalPlan plan, IntersectNode node, Stack<LogicalNode> stack,
- GlobalPlanContext data) throws PlanningException {
- super.visitIntersect(plan, node, stack, data);
- data.topmost = node;
+ GlobalPlanContext context) throws PlanningException {
+ super.visitIntersect(plan, node, stack, context);
+ context.topmost = node;
return node;
}
@Override
public LogicalNode visitTableSubQuery(LogicalPlan plan, TableSubQueryNode node, Stack<LogicalNode> stack,
- GlobalPlanContext data) throws PlanningException {
- super.visitTableSubQuery(plan, node, stack, data);
- data.topmost = node;
+ GlobalPlanContext context) throws PlanningException {
+ super.visitTableSubQuery(plan, node, stack, context);
+ context.topmost = node;
return node;
}
@Override
- public LogicalNode visitScan(LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack, GlobalPlanContext data)
+ public LogicalNode visitScan(LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack, GlobalPlanContext context)
throws PlanningException {
- data.topmost = node;
+ context.topmost = node;
return node;
}
@Override
public LogicalNode visitStoreTable(LogicalPlan plan, StoreTableNode node, Stack<LogicalNode> stack,
- GlobalPlanContext data) throws PlanningException {
- super.visitStoreTable(plan, node, stack, data);
- data.topmost = node;
+ GlobalPlanContext context) throws PlanningException {
+ super.visitStoreTable(plan, node, stack, context);
+ context.topmost = node;
return node;
}
@Override
- public LogicalNode visitInsert(LogicalPlan plan, InsertNode node, Stack<LogicalNode> stack, GlobalPlanContext data)
+ public LogicalNode visitInsert(LogicalPlan plan, InsertNode node, Stack<LogicalNode> stack,
+ GlobalPlanContext context)
throws PlanningException {
- super.visitInsert(plan, node, stack, data);
- data.topmost = node;
+ super.visitInsert(plan, node, stack, context);
+ context.topmost = node;
return node;
}
}
@@ -426,20 +435,21 @@ public class GlobalPlanner {
}
private class ConsecutiveUnionFinder extends BasicLogicalPlanVisitor<UnionsFinderContext> {
- public LogicalNode visitUnion(LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack, UnionsFinderContext data)
+ public LogicalNode visitUnion(LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack,
+ UnionsFinderContext context)
throws PlanningException {
if (node.getType() == NodeType.UNION) {
- data.unionList.add(node);
+ context.unionList.add(node);
}
stack.push(node);
TableSubQueryNode leftSubQuery = node.getLeftChild();
TableSubQueryNode rightSubQuery = node.getRightChild();
if (leftSubQuery.getSubQuery().getType() == NodeType.UNION) {
- visitChild(plan, leftSubQuery, stack, data);
+ visitChild(plan, leftSubQuery, stack, context);
}
if (rightSubQuery.getSubQuery().getType() == NodeType.UNION) {
- visitChild(plan, rightSubQuery, stack, data);
+ visitChild(plan, rightSubQuery, stack, context);
}
stack.pop();
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
index a11cdbf..e4d9108 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
@@ -18,16 +18,17 @@
package org.apache.tajo.engine.query;
-import org.apache.tajo.client.ResultSetUtil;
+import org.apache.tajo.IntegrationTest;
+import org.apache.tajo.TpchTestBase;
+import org.apache.tajo.util.TUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
-import org.apache.tajo.IntegrationTest;
-import org.apache.tajo.TpchTestBase;
import java.io.IOException;
import java.sql.ResultSet;
+import java.util.Map;
import static org.junit.Assert.*;
@@ -91,6 +92,40 @@ public class TestGroupByQuery {
}
}
+ @Test
+ public final void testHavingWithNamedTarget() throws Exception {
+ ResultSet res = tpch.execute("select l_orderkey, avg(l_partkey) total, sum(l_linenumber) as num from lineitem group by l_orderkey having total >= 2 or num = 3");
+ Map<Integer, Double> result = TUtil.newHashMap();
+ result.put(3, 2.5d);
+ result.put(2, 2.0d);
+ result.put(1, 1.0d);
+
+ for (int i = 0; i < 3; i++) {
+ assertTrue(res.next());
+ assertTrue(result.containsKey(res.getInt("l_orderkey")));
+ assertTrue(result.get(res.getInt("l_orderkey")) == res.getDouble("total"));
+ }
+ assertFalse(res.next());
+ res.close();
+ }
+
+
+ @Test
+ public final void testHavingWithAggFunction() throws Exception {
+ ResultSet res = tpch.execute("select l_orderkey, avg(l_partkey) total, sum(l_linenumber) as num from lineitem group by l_orderkey having avg(l_partkey) = 2.5 or num = 1");
+ Map<Integer, Double> result = TUtil.newHashMap();
+ result.put(3, 2.5d);
+ result.put(2, 2.0d);
+
+ for (int i = 0; i < 2; i++) {
+ assertTrue(res.next());
+ assertTrue(result.containsKey(res.getInt("l_orderkey")));
+ assertTrue(result.get(res.getInt("l_orderkey")) == res.getDouble("total"));
+ }
+ assertFalse(res.next());
+ res.close();
+ }
+
//@Test
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java
index 1e89ce5..3ab644a 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java
@@ -90,17 +90,17 @@ public class TestGlobalPlanner {
@Test
public void testSelectDistinct() throws Exception {
- MasterPlan masterPlan = buildPlan("select distinct l_orderkey from lineitem");
+ buildPlan("select distinct l_orderkey from lineitem");
}
@Test
public void testSortAfterGroupBy() throws Exception {
- MasterPlan masterPlan = buildPlan("select max(l_quantity) as max_quantity, l_orderkey from lineitem group by l_orderkey order by max_quantity");
+ buildPlan("select max(l_quantity) as max_quantity, l_orderkey from lineitem group by l_orderkey order by max_quantity");
}
@Test
public void testSortLimit() throws Exception {
- MasterPlan masterPlan = buildPlan("select max(l_quantity) as max_quantity, l_orderkey from lineitem group by l_orderkey order by max_quantity limit 3");
+ buildPlan("select max(l_quantity) as max_quantity, l_orderkey from lineitem group by l_orderkey order by max_quantity limit 3");
}
@Test
[2/2] git commit: TAJO-46: The "having" clause does not work
properly. (hyunsik)
Posted by hy...@apache.org.
TAJO-46: The "having" clause does not work properly. (hyunsik)
Project: http://git-wip-us.apache.org/repos/asf/incubator-tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tajo/commit/e595384b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/e595384b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/e595384b
Branch: refs/heads/master
Commit: e595384bace80341c23575a554cd21a95fb19738
Parents: bd1619d
Author: Hyunsik Choi <hy...@apache.org>
Authored: Sat Sep 21 11:01:50 2013 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Sat Sep 21 11:01:50 2013 +0900
----------------------------------------------------------------------
CHANGES.txt | 5 +-
.../org/apache/tajo/algebra/LiteralValue.java | 1 +
.../java/org/apache/tajo/algebra/Target.java | 7 +-
.../main/java/org/apache/tajo/util/TUtil.java | 22 ++
.../tajo/engine/eval/BasicEvalNodeVisitor.java | 280 +++++++++++++++++++
.../apache/tajo/engine/eval/CaseWhenEval.java | 36 ++-
.../tajo/engine/eval/EvalNodeVisitor.java | 1 +
.../tajo/engine/eval/EvalNodeVisitor2.java | 61 ++++
.../apache/tajo/engine/eval/EvalTreeUtil.java | 37 ++-
.../org/apache/tajo/engine/eval/EvalType.java | 4 +-
.../org/apache/tajo/engine/eval/InEval.java | 4 +-
.../org/apache/tajo/engine/eval/NotEval.java | 7 +-
.../apache/tajo/engine/eval/RowConstant.java | 89 ------
.../tajo/engine/eval/RowConstantEval.java | 89 ++++++
.../tajo/engine/parser/HiveConverter.java | 16 +-
.../apache/tajo/engine/parser/SQLAnalyzer.java | 4 +-
.../tajo/engine/planner/AlgebraVisitor.java | 31 +-
.../tajo/engine/planner/BaseAlgebraVisitor.java | 13 +-
.../engine/planner/BasicLogicalPlanVisitor.java | 62 ++--
.../planner/ExplainLogicalPlanVisitor.java | 8 +-
.../apache/tajo/engine/planner/LogicalPlan.java | 88 ++++--
.../tajo/engine/planner/LogicalPlanVisitor.java | 30 +-
.../tajo/engine/planner/LogicalPlanner.java | 32 ++-
.../engine/planner/PhysicalPlannerImpl.java | 52 ++--
.../org/apache/tajo/engine/planner/Target.java | 2 +-
.../engine/planner/logical/GroupbyNode.java | 34 ++-
.../planner/physical/AggregationExec.java | 23 +-
.../planner/physical/HashAggregateExec.java | 30 +-
.../planner/rewrite/ProjectionPushDownRule.java | 10 +-
.../org/apache/tajo/master/GlobalPlanner.java | 140 +++++-----
.../tajo/engine/query/TestGroupByQuery.java | 41 ++-
.../apache/tajo/master/TestGlobalPlanner.java | 6 +-
32 files changed, 924 insertions(+), 341 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 32d7713..af1a245 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -25,7 +25,8 @@ Release 0.2.0 - unreleased
IMPROVEMENTS
- TAJO-183: Creating too many TableMetaProto objects might lead a potential memory leak. (jihoon)
+ TAJO-183: Creating too many TableMetaProto objects might lead a potential
+ memory leak. (jihoon)
TAJO-184: Refactor GlobalPlanner and global plan data structure. (hyunsik)
@@ -142,6 +143,8 @@ Release 0.2.0 - unreleased
BUG FIXES
+ TAJO-46: The "having" clause does not work properly. (hyunsik)
+
TAJO-186: Improve column resolving method. (hyunsik)
TAJO-168: infinite loop occurs when QueryMaster is stopping. (jinho)
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java
index 02445f0..d713d00 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java
@@ -23,6 +23,7 @@ public class LiteralValue extends Expr {
private LiteralType valueType;
public static enum LiteralType {
+ Boolean,
String,
Unsigned_Integer,
Unsigned_Float,
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-algebra/src/main/java/org/apache/tajo/algebra/Target.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/Target.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/Target.java
index 2de5057..9172d6c 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/Target.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/Target.java
@@ -26,7 +26,12 @@ public class Target extends Expr {
public Target(Expr expr) {
super(OpType.Target);
- this.expr = expr;
+ this.expr = expr;
+ }
+
+ public Target(Expr expr, String alias) {
+ this(expr);
+ setAlias(alias);
}
public Expr getExpr() {
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java b/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
index 373292b..3931709 100644
--- a/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
+++ b/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
@@ -67,6 +67,20 @@ public class TUtil {
return result;
}
+ public static <T> T[] concatAll(T[] first, T[]... rest) {
+ int totalLength = first.length;
+ for (T[] array : rest) {
+ totalLength += array.length;
+ }
+ T[] result = Arrays.copyOf(first, totalLength);
+ int offset = first.length;
+ for (T[] array : rest) {
+ System.arraycopy(array, 0, result, offset, array.length);
+ offset += array.length;
+ }
+ return result;
+ }
+
public static <T> Set<T> newHashSet() {
return new HashSet<T>();
}
@@ -135,6 +149,14 @@ public class TUtil {
return reference;
}
+ public static <KEY1, VALUE> void putToNestedList(Map<KEY1, List<VALUE>> map, KEY1 k1, VALUE value) {
+ if (map.containsKey(k1)) {
+ map.get(k1).add(value);
+ } else {
+ map.put(k1, TUtil.newList(value));
+ }
+ }
+
public static <KEY1, KEY2, VALUE> void putToNestedMap(Map<KEY1, Map<KEY2, VALUE>> map, KEY1 k1, KEY2 k2,
VALUE value) {
if (map.containsKey(k1)) {
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
new file mode 100644
index 0000000..8d6e250
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
@@ -0,0 +1,280 @@
+/**
+ * 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.eval;
+
+import java.util.Stack;
+
+public class BasicEvalNodeVisitor<CONTEXT, RESULT> implements EvalNodeVisitor2<CONTEXT, RESULT> {
+ @Override
+ public RESULT visitChild(CONTEXT context, Stack<EvalNode> stack, EvalNode evalNode) {
+ RESULT result;
+ switch (evalNode.getType()) {
+ // Column and Value reference expressions
+ case CONST:
+ result = visitConst(context, stack, (ConstEval) evalNode);
+ break;
+ case ROW_CONSTANT:
+ result = visitRowConstant(context, stack, (RowConstantEval) evalNode);
+ break;
+ case FIELD:
+ result = visitField(context, stack, (FieldEval) evalNode);
+ break;
+
+ // Arithmetic expression
+ case PLUS:
+ result = visitPlus(context, stack, (BinaryEval) evalNode);
+ break;
+ case MINUS:
+ result = visitMinus(context, stack, (BinaryEval) evalNode);
+ break;
+ case MULTIPLY:
+ result = visitMultiply(context, stack, (BinaryEval) evalNode);
+ break;
+ case DIVIDE:
+ result = visitDivide(context, stack, (BinaryEval) evalNode);
+ break;
+ case MODULAR:
+ result = visitModular(context, stack, (BinaryEval) evalNode);
+ break;
+
+ // Logical Predicates
+ case AND:
+ result = visitAnd(context, stack, (BinaryEval) evalNode);
+ break;
+ case OR:
+ result = visitOr(context, stack, (BinaryEval) evalNode);
+ break;
+ case NOT:
+ result = visitNot(context, stack, (NotEval) evalNode);
+ break;
+
+ // Comparison Predicates
+ case EQUAL:
+ result = visitEqual(context, stack, (BinaryEval) evalNode);
+ break;
+ case NOT_EQUAL:
+ result = visitNotEqual(context, stack, (BinaryEval) evalNode);
+ break;
+ case LTH:
+ result = visitLessThan(context, stack, (BinaryEval) evalNode);
+ break;
+ case LEQ:
+ result = visitLessThanOrEqual(context, stack, (BinaryEval) evalNode);
+ break;
+ case GTH:
+ result = visitGreaterThan(context, stack, (BinaryEval) evalNode);
+ break;
+ case GEQ:
+ result = visitGreaterThanOrEqual(context, stack, (BinaryEval) evalNode);
+ break;
+
+ // Other Predicates
+ case IS_NULL:
+ result = visitIsNull(context, stack, (IsNullEval) evalNode);
+ break;
+ case CASE:
+ result = visitCaseWhen(context, stack, (CaseWhenEval) evalNode);
+ break;
+ case IF_THEN:
+ result = visitIfThen(context, stack, (CaseWhenEval.IfThenEval) evalNode);
+ break;
+ case IN:
+ result = visitInPredicate(context, stack, (InEval) evalNode);
+ break;
+ case LIKE:
+ result = visitLike(context, stack, (LikeEval) evalNode);
+ break;
+
+ // Functions
+ case FUNCTION:
+ result = visitFuncCall(context, stack, (FuncCallEval) evalNode);
+ break;
+ case AGG_FUNCTION:
+ result = visitAggrFuncCall(context, stack, (AggFuncCallEval) evalNode);
+ break;
+
+ default:
+ throw new InvalidEvalException("Unknown EvalNode: " + evalNode);
+ }
+
+ return result;
+ }
+
+ private RESULT visitDefaultBinaryEval(CONTEXT context, Stack<EvalNode> stack, BinaryEval binaryEval) {
+ stack.push(binaryEval);
+ RESULT result = visitChild(context, stack, binaryEval.getLeftExpr());
+ visitChild(context, stack, binaryEval.getRightExpr());
+ stack.pop();
+ return result;
+ }
+
+ private RESULT visitDefaultFunctionEval(CONTEXT context, Stack<EvalNode> stack, FuncEval functionEval) {
+ RESULT result = null;
+ stack.push(functionEval);
+ for (EvalNode arg : functionEval.getArgs()) {
+ result = visitChild(context, stack, arg);
+ }
+ stack.pop();
+ return result;
+ }
+
+ @Override
+ public RESULT visitConst(CONTEXT context, Stack<EvalNode> stack, ConstEval evalNode) {
+ return null;
+ }
+
+ @Override
+ public RESULT visitRowConstant(CONTEXT context, Stack<EvalNode> stack, RowConstantEval evalNode) {
+ return null;
+ }
+
+ @Override
+ public RESULT visitField(CONTEXT context, Stack<EvalNode> stack, FieldEval evalNode) {
+ return null;
+ }
+
+ @Override
+ public RESULT visitPlus(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitMinus(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitMultiply(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitDivide(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitModular(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitAnd(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitOr(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitNot(CONTEXT context, Stack<EvalNode> stack, NotEval evalNode) {
+ RESULT result;
+ stack.push(evalNode);
+ if (evalNode.getChild() instanceof NotEval) {
+ result = visitChild(context, stack, evalNode);
+ } else {
+ result = visitChild(context, stack, evalNode.getLeftExpr());
+ visitChild(context, stack, evalNode.getRightExpr());
+ }
+ stack.pop();
+
+ return result;
+ }
+
+ @Override
+ public RESULT visitEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitNotEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitLessThan(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitLessThanOrEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitGreaterThan(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitGreaterThanOrEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitIsNull(CONTEXT context, Stack<EvalNode> stack, IsNullEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitCaseWhen(CONTEXT context, Stack<EvalNode> stack, CaseWhenEval evalNode) {
+ RESULT result = null;
+ stack.push(evalNode);
+ for (CaseWhenEval.IfThenEval ifThenEval : evalNode.getIfThenEvals()) {
+ result = visitIfThen(context, stack, ifThenEval);
+ }
+ if (evalNode.hasElse()) {
+ result = visitChild(context, stack, evalNode.getElse());
+ }
+ stack.pop();
+ return result;
+ }
+
+ @Override
+ public RESULT visitIfThen(CONTEXT context, Stack<EvalNode> stack, CaseWhenEval.IfThenEval evalNode) {
+ RESULT result;
+ stack.push(evalNode);
+ result = visitChild(context, stack, evalNode.getConditionExpr());
+ visitChild(context, stack, evalNode.getResultExpr());
+ stack.pop();
+ return result;
+ }
+
+ @Override
+ public RESULT visitInPredicate(CONTEXT context, Stack<EvalNode> stack, InEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitLike(CONTEXT context, Stack<EvalNode> stack, LikeEval evalNode) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitFuncCall(CONTEXT context, Stack<EvalNode> stack, FuncCallEval evalNode) {
+ return visitDefaultFunctionEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitAggrFuncCall(CONTEXT context, Stack<EvalNode> stack, AggFuncCallEval evalNode) {
+ return visitDefaultFunctionEval(context, stack, evalNode);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
index 1cb24d2..e2ab0b9 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
@@ -34,7 +34,7 @@ import org.apache.tajo.util.TUtil;
import java.util.List;
public class CaseWhenEval extends EvalNode implements GsonObject {
- @Expose private List<WhenEval> whens = Lists.newArrayList();
+ @Expose private List<IfThenEval> whens = Lists.newArrayList();
@Expose private EvalNode elseResult;
public CaseWhenEval() {
@@ -42,7 +42,19 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
}
public void addWhen(EvalNode condition, EvalNode result) {
- whens.add(new WhenEval(condition, result));
+ whens.add(new IfThenEval(condition, result));
+ }
+
+ public List<IfThenEval> getIfThenEvals() {
+ return whens;
+ }
+
+ public boolean hasElse() {
+ return this.elseResult != null;
+ }
+
+ public EvalNode getElse() {
+ return elseResult;
}
public void setElseResult(EvalNode elseResult) {
@@ -93,7 +105,7 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
@Override
public String toString() {
StringBuilder sb = new StringBuilder("CASE\n");
- for (WhenEval when : whens) {
+ for (IfThenEval when : whens) {
sb.append(when).append("\n");
}
@@ -105,7 +117,7 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
@Override
public void preOrder(EvalNodeVisitor visitor) {
visitor.visit(this);
- for (WhenEval when : whens) {
+ for (IfThenEval when : whens) {
when.preOrder(visitor);
}
if (elseResult != null) { // without else clause
@@ -115,7 +127,7 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
@Override
public void postOrder(EvalNodeVisitor visitor) {
- for (WhenEval when : whens) {
+ for (IfThenEval when : whens) {
when.postOrder(visitor);
}
if (elseResult != null) { // without else clause
@@ -140,12 +152,12 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
}
}
- public static class WhenEval extends EvalNode implements GsonObject {
+ public static class IfThenEval extends EvalNode implements GsonObject {
@Expose private EvalNode condition;
@Expose private EvalNode result;
- public WhenEval(EvalNode condition, EvalNode result) {
- super(EvalType.WHEN);
+ public IfThenEval(EvalNode condition, EvalNode result) {
+ super(EvalType.IF_THEN);
this.condition = condition;
this.result = result;
}
@@ -185,8 +197,8 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
@Override
public boolean equals(Object object) {
- if (object instanceof WhenEval) {
- WhenEval other = (WhenEval) object;
+ if (object instanceof IfThenEval) {
+ IfThenEval other = (IfThenEval) object;
return condition.equals(other.condition) &&
result.equals(other.result);
} else {
@@ -201,7 +213,7 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
@Override
public String toJson() {
- return CoreGsonHelper.toJson(WhenEval.this, WhenEval.class);
+ return CoreGsonHelper.toJson(IfThenEval.this, IfThenEval.class);
}
private class WhenContext implements EvalContext {
@@ -237,7 +249,7 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
EvalContext [] contexts;
EvalContext elseCtx;
- CaseContext(List<WhenEval> whens, EvalContext elseCtx) {
+ CaseContext(List<IfThenEval> whens, EvalContext elseCtx) {
contexts = new EvalContext[whens.size()];
for (int i = 0; i < whens.size(); i++) {
contexts[i] = whens.get(i).newContext();
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor.java
index 2cac5da..1680b31 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor.java
@@ -18,6 +18,7 @@
package org.apache.tajo.engine.eval;
+@Deprecated
public interface EvalNodeVisitor {
public void visit(EvalNode node);
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
new file mode 100644
index 0000000..abb6b51
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.eval;
+
+import java.util.Stack;
+
+public interface EvalNodeVisitor2<CONTEXT, RESULT> {
+ RESULT visitChild(CONTEXT context, Stack<EvalNode> stack, EvalNode evalNode);
+
+ // Column and Value reference expressions
+ RESULT visitConst(CONTEXT context, Stack<EvalNode> stack, ConstEval evalNode);
+ RESULT visitRowConstant(CONTEXT context, Stack<EvalNode> stack, RowConstantEval evalNode);
+ RESULT visitField(CONTEXT context, Stack<EvalNode> stack, FieldEval evalNode);
+
+ // Arithmetic expression
+ RESULT visitPlus(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitMinus(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitMultiply(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitDivide(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitModular(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+
+ // Logical Predicates
+ RESULT visitAnd(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitOr(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitNot(CONTEXT context, Stack<EvalNode> stack, NotEval evalNode);
+
+ // Comparison Predicates
+ RESULT visitEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitNotEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitLessThan(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitLessThanOrEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitGreaterThan(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+ RESULT visitGreaterThanOrEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+
+ // Other Predicates
+ RESULT visitIsNull(CONTEXT context, Stack<EvalNode> stack, IsNullEval evalNode);
+ RESULT visitCaseWhen(CONTEXT context, Stack<EvalNode> stack, CaseWhenEval evalNode);
+ RESULT visitIfThen(CONTEXT context, Stack<EvalNode> stack, CaseWhenEval.IfThenEval evalNode);
+ RESULT visitInPredicate(CONTEXT context, Stack<EvalNode> stack, InEval evalNode);
+ RESULT visitLike(CONTEXT context, Stack<EvalNode> stack, LikeEval evalNode);
+
+ // Functions
+ RESULT visitFuncCall(CONTEXT context, Stack<EvalNode> stack, FuncCallEval evalNode);
+ RESULT visitAggrFuncCall(CONTEXT context, Stack<EvalNode> stack, AggFuncCallEval evalNode);
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
index e6bd733..6be0996 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
@@ -35,6 +35,39 @@ public class EvalTreeUtil {
String newName) {
node.postOrder(new ChangeColumnRefVisitor(oldName, newName));
}
+
+ public static void replace(EvalNode expr, EvalNode targetExpr, EvalNode tobeReplaced) {
+ EvalReplaceVisitor replacer = new EvalReplaceVisitor(targetExpr, tobeReplaced);
+ replacer.visitChild(null, new Stack<EvalNode>(), expr);
+ }
+
+ public static class EvalReplaceVisitor extends BasicEvalNodeVisitor<EvalNode, EvalNode> {
+ private EvalNode target;
+ private EvalNode tobeReplaced;
+
+ public EvalReplaceVisitor(EvalNode target, EvalNode tobeReplaced) {
+ this.target = target;
+ this.tobeReplaced = tobeReplaced;
+ }
+
+ @Override
+ public EvalNode visitChild(EvalNode context, Stack<EvalNode> stack, EvalNode evalNode) {
+ super.visitChild(context, stack, evalNode);
+
+ if (evalNode.equals(target)) {
+ EvalNode parent = stack.peek();
+
+ if (parent.getLeftExpr().equals(evalNode)) {
+ parent.setLeftExpr(tobeReplaced);
+ }
+ if (parent.getRightExpr().equals(evalNode)) {
+ parent.setRightExpr(tobeReplaced);
+ }
+ }
+
+ return evalNode;
+ }
+ }
public static Set<Column> findDistinctRefColumns(EvalNode node) {
DistinctColumnRefFinder finder = new DistinctColumnRefFinder();
@@ -214,10 +247,6 @@ public class EvalTreeUtil {
expr.getLeftExpr().getType() == EvalType.FIELD &&
expr.getRightExpr().getType() == EvalType.FIELD;
}
-
- public static boolean isLogicalOperator(EvalNode expr) {
- return expr.getType() == EvalType.AND || expr.getType() == EvalType.OR;
- }
public static class ChangeColumnRefVisitor implements EvalNodeVisitor {
private final String findColumn;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
index a3fcf40..2e6742f 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
@@ -45,13 +45,13 @@ public enum EvalType {
// Predicate
LIKE(LikeEval.class),
CASE(CaseWhenEval.class),
- WHEN(CaseWhenEval.WhenEval.class),
+ IF_THEN(CaseWhenEval.IfThenEval.class),
IN(InEval.class),
// Value or Reference
FIELD(FieldEval.class),
CONST(ConstEval.class),
- ROW_CONSTANT(RowConstant.class);
+ ROW_CONSTANT(RowConstantEval.class);
private Class<? extends EvalNode> baseClass;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/InEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/InEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/InEval.java
index 6b04948..60dea3b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/InEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/InEval.java
@@ -36,7 +36,7 @@ public class InEval extends BinaryEval {
private Integer fieldId = null;
Datum [] values;
- public InEval(FieldEval columnRef, RowConstant valueList, boolean not) {
+ public InEval(FieldEval columnRef, RowConstantEval valueList, boolean not) {
super(EvalType.IN, columnRef, valueList);
this.not = not;
}
@@ -65,7 +65,7 @@ public class InEval extends BinaryEval {
InEvalCtx isNullCtx = (InEvalCtx) ctx;
if (fieldId == null) {
fieldId = schema.getColumnId(((FieldEval)leftExpr).getColumnRef().getQualifiedName());
- values = ((RowConstant)rightExpr).getValues();
+ values = ((RowConstantEval)rightExpr).getValues();
}
boolean isIncluded = false;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/NotEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/NotEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/NotEval.java
index 296850c..9fe4679 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/NotEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/NotEval.java
@@ -35,8 +35,7 @@ public class NotEval extends EvalNode implements Cloneable {
public NotEval(EvalNode subExpr) {
super(EvalType.NOT);
- Preconditions.checkArgument(
- subExpr instanceof BinaryEval || subExpr instanceof NotEval);
+ Preconditions.checkArgument(subExpr instanceof BinaryEval || subExpr instanceof NotEval);
this.subExpr = subExpr;
}
@@ -47,6 +46,10 @@ public class NotEval extends EvalNode implements Cloneable {
return newCtx;
}
+ public EvalNode getChild() {
+ return subExpr;
+ }
+
@Override
public DataType [] getValueType() {
return RES_TYPE;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/RowConstant.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/RowConstant.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/RowConstant.java
deleted file mode 100644
index 4e473ed..0000000
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/RowConstant.java
+++ /dev/null
@@ -1,89 +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.eval;
-
-import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.CatalogUtil;
-import org.apache.tajo.common.TajoDataTypes;
-import org.apache.tajo.datum.ArrayDatum;
-import org.apache.tajo.datum.Datum;
-import org.apache.tajo.util.TUtil;
-
-public class RowConstant extends EvalNode {
- @Expose ArrayDatum values;
-
- public RowConstant(Datum [] values) {
- super(EvalType.ROW_CONSTANT);
- this.values = new ArrayDatum(values);
- }
-
- @Override
- public EvalContext newContext() {
- return null;
- }
-
- @Override
- public TajoDataTypes.DataType[] getValueType() {
- return new TajoDataTypes.DataType[] {CatalogUtil.newDataTypeWithoutLen(values.get(0).type())};
- }
-
- @Override
- public String getName() {
- return "ROW";
- }
-
- @Override
- public Datum terminate(EvalContext ctx) {
- return values;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof RowConstant) {
- RowConstant other = (RowConstant) obj;
- return TUtil.checkEquals(values, other.values);
- }
-
- return false;
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder("(");
- for (int i = 0; i < values.toArray().length; i++) {
- if (i != 0) {
- sb.append(",");
- }
- sb.append(values.get(i).toString());
- }
- sb.append(")");
- return sb.toString();
- }
-
- public Datum [] getValues() {
- return values.toArray();
- }
-
- public void preOrder(EvalNodeVisitor visitor) {
- visitor.visit(this);
- }
-
- public void postOrder(EvalNodeVisitor visitor) {
- visitor.visit(this);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/RowConstantEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/RowConstantEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/RowConstantEval.java
new file mode 100644
index 0000000..ecda8ae
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/RowConstantEval.java
@@ -0,0 +1,89 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.ArrayDatum;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.util.TUtil;
+
+public class RowConstantEval extends EvalNode {
+ @Expose ArrayDatum values;
+
+ public RowConstantEval(Datum[] values) {
+ super(EvalType.ROW_CONSTANT);
+ this.values = new ArrayDatum(values);
+ }
+
+ @Override
+ public EvalContext newContext() {
+ return null;
+ }
+
+ @Override
+ public TajoDataTypes.DataType[] getValueType() {
+ return new TajoDataTypes.DataType[] {CatalogUtil.newDataTypeWithoutLen(values.get(0).type())};
+ }
+
+ @Override
+ public String getName() {
+ return "ROW";
+ }
+
+ @Override
+ public Datum terminate(EvalContext ctx) {
+ return values;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof RowConstantEval) {
+ RowConstantEval other = (RowConstantEval) obj;
+ return TUtil.checkEquals(values, other.values);
+ }
+
+ return false;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("(");
+ for (int i = 0; i < values.toArray().length; i++) {
+ if (i != 0) {
+ sb.append(",");
+ }
+ sb.append(values.get(i).toString());
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public Datum [] getValues() {
+ return values.toArray();
+ }
+
+ public void preOrder(EvalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ public void postOrder(EvalNodeVisitor visitor) {
+ visitor.visit(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveConverter.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveConverter.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveConverter.java
index e373d76..8429759 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveConverter.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveConverter.java
@@ -117,7 +117,9 @@ public class HiveConverter extends HiveParserBaseVisitor<Expr>{
if(ctx.havingClause() != null) {
Expr havingCondition = visitHavingClause(ctx.havingClause());
- aggregation.setHavingCondition(havingCondition);
+ Having having = new Having(havingCondition);
+ having.setChild(current);
+ current = having;
}
}
@@ -213,8 +215,10 @@ public class HiveConverter extends HiveParserBaseVisitor<Expr>{
current = aggregation;
if(ctx.havingClause() != null) {
- Expr havingCondition = visitHavingClause(ctx.havingClause());
- aggregation.setHavingCondition(havingCondition);
+ Expr havingCondition = visitHavingClause(ctx.havingClause());
+ Having having = new Having(havingCondition);
+ having.setChild(current);
+ current = having;
}
}
@@ -325,8 +329,10 @@ public class HiveConverter extends HiveParserBaseVisitor<Expr>{
current = aggregation;
if(ctx.havingClause() != null) {
- Expr havingCondition = visitHavingClause(ctx.havingClause());
- aggregation.setHavingCondition(havingCondition);
+ Expr havingCondition = visitHavingClause(ctx.havingClause());
+ Having having = new Having(havingCondition);
+ having.setChild(current);
+ current = having;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
index 60025f4..97c66b5 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
@@ -172,7 +172,9 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
if (ctx.table_expression().having_clause() != null) {
Expr havingCondition = visitBoolean_value_expression(
ctx.table_expression().having_clause().boolean_value_expression());
- aggregation.setHavingCondition(havingCondition);
+ Having having = new Having(havingCondition);
+ having.setChild(current);
+ current = having;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
index 78422b0..633609a 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
@@ -22,19 +22,20 @@ import org.apache.tajo.algebra.*;
import java.util.Stack;
-public interface AlgebraVisitor<T1, T2> {
- T2 visitProjection(T1 ctx, Stack<OpType> stack, Projection expr) throws PlanningException;
- T2 visitLimit(T1 ctx, Stack<OpType> stack, Limit expr) throws PlanningException;
- T2 visitSort(T1 ctx, Stack<OpType> stack, Sort expr) throws PlanningException;
- T2 visitGroupBy(T1 ctx, Stack<OpType> stack, Aggregation expr) throws PlanningException;
- T2 visitJoin(T1 ctx, Stack<OpType> stack, Join expr) throws PlanningException;
- T2 visitFilter(T1 ctx, Stack<OpType> stack, Selection expr) throws PlanningException;
- T2 visitUnion(T1 ctx, Stack<OpType> stack, SetOperation expr) throws PlanningException;
- T2 visitExcept(T1 ctx, Stack<OpType> stack, SetOperation expr) throws PlanningException;
- T2 visitIntersect(T1 ctx, Stack<OpType> stack, SetOperation expr) throws PlanningException;
- T2 visitRelationList(T1 ctx, Stack<OpType> stack, RelationList expr) throws PlanningException;
- T2 visitTableSubQuery(T1 ctx, Stack<OpType> stack, TableSubQuery expr) throws PlanningException;
- T2 visitRelation(T1 ctx, Stack<OpType> stack, Relation expr) throws PlanningException;
- T2 visitCreateTable(T1 ctx, Stack<OpType> stack, CreateTable expr) throws PlanningException;
- T2 visitDropTable(T1 ctx, Stack<OpType> stack, DropTable expr) throws PlanningException;
+public interface AlgebraVisitor<CONTEXT, RESULT> {
+ RESULT visitProjection(CONTEXT ctx, Stack<OpType> stack, Projection expr) throws PlanningException;
+ RESULT visitLimit(CONTEXT ctx, Stack<OpType> stack, Limit expr) throws PlanningException;
+ RESULT visitSort(CONTEXT ctx, Stack<OpType> stack, Sort expr) throws PlanningException;
+ RESULT visitHaving(CONTEXT ctx, Stack<OpType> stack, Having expr) throws PlanningException;
+ RESULT visitGroupBy(CONTEXT ctx, Stack<OpType> stack, Aggregation expr) throws PlanningException;
+ RESULT visitJoin(CONTEXT ctx, Stack<OpType> stack, Join expr) throws PlanningException;
+ RESULT visitFilter(CONTEXT ctx, Stack<OpType> stack, Selection expr) throws PlanningException;
+ RESULT visitUnion(CONTEXT ctx, Stack<OpType> stack, SetOperation expr) throws PlanningException;
+ RESULT visitExcept(CONTEXT ctx, Stack<OpType> stack, SetOperation expr) throws PlanningException;
+ RESULT visitIntersect(CONTEXT ctx, Stack<OpType> stack, SetOperation expr) throws PlanningException;
+ RESULT visitRelationList(CONTEXT ctx, Stack<OpType> stack, RelationList expr) throws PlanningException;
+ RESULT visitTableSubQuery(CONTEXT ctx, Stack<OpType> stack, TableSubQuery expr) throws PlanningException;
+ RESULT visitRelation(CONTEXT ctx, Stack<OpType> stack, Relation expr) throws PlanningException;
+ RESULT visitCreateTable(CONTEXT ctx, Stack<OpType> stack, CreateTable expr) throws PlanningException;
+ RESULT visitDropTable(CONTEXT ctx, Stack<OpType> stack, DropTable expr) throws PlanningException;
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
index 16df8f8..06ab38c 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
@@ -58,6 +58,9 @@ public abstract class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisi
case Sort:
current = visitSort(ctx, stack, (Sort) expr);
break;
+ case Having:
+ current = visitHaving(ctx, stack, (Having) expr);
+ break;
case Aggregation:
current = visitGroupBy(ctx, stack, (Aggregation) expr);
break;
@@ -135,6 +138,14 @@ public abstract class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisi
}
@Override
+ public RESULT visitHaving(CONTEXT ctx, Stack<OpType> stack, Having expr) throws PlanningException {
+ stack.push(expr.getType());
+ RESULT child = visitChild(ctx, stack, expr.getChild());
+ stack.pop();
+ return child;
+ }
+
+ @Override
public RESULT visitGroupBy(CONTEXT ctx, Stack<OpType> stack, Aggregation expr) throws PlanningException {
stack.push(expr.getType());
RESULT child = visitChild(ctx, stack, expr.getChild());
@@ -215,7 +226,7 @@ public abstract class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisi
stack.push(expr.getType());
RESULT child = null;
if (expr.hasSubQuery()) {
- child = visitChild(ctx, stack, expr.getSubQuery());
+ child = visitChild(ctx, stack, expr.getSubQuery());
}
stack.pop();
return child;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java
index b58b05e..0a564d9 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java
@@ -93,127 +93,127 @@ public class BasicLogicalPlanVisitor<T> implements LogicalPlanVisitor<T> {
}
@Override
- public LogicalNode visitRoot(LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitRoot(LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getChild(), stack, data);
+ visitChild(plan, node.getChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitProjection(LogicalPlan plan, ProjectionNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitProjection(LogicalPlan plan, ProjectionNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getChild(), stack, data);
+ visitChild(plan, node.getChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitLimit(LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitLimit(LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getChild(), stack, data);
+ visitChild(plan, node.getChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitSort(LogicalPlan plan, SortNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitSort(LogicalPlan plan, SortNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getChild(), stack, data);
+ visitChild(plan, node.getChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitGroupBy(LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitGroupBy(LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getChild(), stack, data);
+ visitChild(plan, node.getChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitFilter(LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitFilter(LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getChild(), stack, data);
+ visitChild(plan, node.getChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitJoin(LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitJoin(LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getLeftChild(), stack, data);
- visitChild(plan, node.getRightChild(), stack, data);
+ visitChild(plan, node.getLeftChild(), stack, context);
+ visitChild(plan, node.getRightChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitUnion(LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitUnion(LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getLeftChild(), stack, data);
- visitChild(plan, node.getRightChild(), stack, data);
+ visitChild(plan, node.getLeftChild(), stack, context);
+ visitChild(plan, node.getRightChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitExcept(LogicalPlan plan, ExceptNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitExcept(LogicalPlan plan, ExceptNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getLeftChild(), stack, data);
- visitChild(plan, node.getRightChild(), stack, data);
+ visitChild(plan, node.getLeftChild(), stack, context);
+ visitChild(plan, node.getRightChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitIntersect(LogicalPlan plan, IntersectNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitIntersect(LogicalPlan plan, IntersectNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getLeftChild(), stack, data);
- visitChild(plan, node.getRightChild(), stack, data);
+ visitChild(plan, node.getLeftChild(), stack, context);
+ visitChild(plan, node.getRightChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitTableSubQuery(LogicalPlan plan, TableSubQueryNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitTableSubQuery(LogicalPlan plan, TableSubQueryNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getSubQuery(), stack, data);
+ visitChild(plan, node.getSubQuery(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitScan(LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitScan(LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
return node;
}
@Override
- public LogicalNode visitStoreTable(LogicalPlan plan, StoreTableNode node, Stack<LogicalNode> stack, T data)
+ public LogicalNode visitStoreTable(LogicalPlan plan, StoreTableNode node, Stack<LogicalNode> stack, T context)
throws PlanningException {
stack.push(node);
- visitChild(plan, node.getChild(), stack, data);
+ visitChild(plan, node.getChild(), stack, context);
stack.pop();
return node;
}
@Override
- public LogicalNode visitInsert(LogicalPlan plan, InsertNode node, Stack<LogicalNode> stack, T data) throws PlanningException {
+ public LogicalNode visitInsert(LogicalPlan plan, InsertNode node, Stack<LogicalNode> stack, T context) throws PlanningException {
stack.push(node);
- visitChild(plan, node.getSubQuery(), stack, data);
+ visitChild(plan, node.getSubQuery(), stack, context);
stack.pop();
return node;
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java
index d572494..ce07d77 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java
@@ -72,11 +72,12 @@ public class ExplainLogicalPlanVisitor extends BasicLogicalPlanVisitor<ExplainLo
}
@Override
- public LogicalNode visitRoot(LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack, Context data)
+ public LogicalNode visitRoot(LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack, Context context)
throws PlanningException {
- return visitChild(plan, node.getChild(), stack, data);
+ return visitChild(plan, node.getChild(), stack, context);
}
+ @Override
public LogicalNode visitProjection(LogicalPlan plan, ProjectionNode node, Stack<LogicalNode> stack,
Context context) throws PlanningException {
return visitUnaryNode(plan, node, stack, context);
@@ -88,11 +89,13 @@ public class ExplainLogicalPlanVisitor extends BasicLogicalPlanVisitor<ExplainLo
return visitUnaryNode(plan, node, stack, context);
}
+ @Override
public LogicalNode visitSort(LogicalPlan plan, SortNode node, Stack<LogicalNode> stack,
Context context) throws PlanningException {
return visitUnaryNode(plan, node, stack, context);
}
+ @Override
public LogicalNode visitGroupBy(LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack,
Context context) throws PlanningException {
return visitUnaryNode(plan, node, stack, context);
@@ -120,6 +123,7 @@ public class ExplainLogicalPlanVisitor extends BasicLogicalPlanVisitor<ExplainLo
return node;
}
+ @Override
public LogicalNode visitFilter(LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack,
Context context) throws PlanningException {
return visitUnaryNode(plan, node, stack, context);
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
index d81165f..fb1f729 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
@@ -18,15 +18,11 @@
package org.apache.tajo.engine.planner;
-import org.apache.tajo.algebra.ColumnReferenceExpr;
-import org.apache.tajo.algebra.OpType;
-import org.apache.tajo.algebra.Projection;
+import org.apache.tajo.algebra.*;
import org.apache.tajo.annotation.NotThreadSafe;
import org.apache.tajo.catalog.Column;
import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.eval.EvalTreeUtil;
-import org.apache.tajo.engine.eval.EvalType;
+import org.apache.tajo.engine.eval.*;
import org.apache.tajo.engine.planner.graph.SimpleDirectedGraph;
import org.apache.tajo.engine.planner.logical.*;
import org.apache.tajo.util.TUtil;
@@ -320,15 +316,15 @@ public class LogicalPlan {
private LogicalNode rootNode;
private NodeType rootType;
private Map<String, RelationNode> relations = new HashMap<String, RelationNode>();
- private Projection projection;
+ private Map<OpType, List<Expr>> algebraicExprs = TUtil.newHashMap();
// changing states
private LogicalNode latestNode;
private boolean resolvedGrouping = true;
private boolean hasGrouping;
private Projectable projectionNode;
- private SelectionNode selectionNode;
private GroupbyNode groupingNode;
+ private SelectionNode selectionNode;
private StoreTableNode storeTableNode;
private InsertNode insertNode;
private Schema schema;
@@ -404,12 +400,40 @@ public class LogicalPlan {
return (T) this.latestNode;
}
- public void setProjection(Projection projection) {
- this.projection = projection;
+ public void setAlgebraicExpr(Expr expr) {
+ TUtil.putToNestedList(algebraicExprs, expr.getType(), expr);
+ }
+
+ public boolean hasAlgebraicExpr(OpType opType) {
+ return algebraicExprs.containsKey(opType);
+ }
+
+ public <T extends Expr> List<T> getAlgebraicExpr(OpType opType) {
+ return (List<T>) algebraicExprs.get(opType);
+ }
+
+ public <T extends Expr> T getSingletonExpr(OpType opType) {
+ if (hasAlgebraicExpr(opType)) {
+ return (T) algebraicExprs.get(opType).get(0);
+ } else {
+ return null;
+ }
+ }
+
+ public boolean hasProjection() {
+ return hasAlgebraicExpr(OpType.Projection);
}
public Projection getProjection() {
- return this.projection;
+ return getSingletonExpr(OpType.Projection);
+ }
+
+ public boolean hasHaving() {
+ return hasAlgebraicExpr(OpType.Having);
+ }
+
+ public Having getHaving() {
+ return getSingletonExpr(OpType.Having);
}
public void setProjectionNode(Projectable node) {
@@ -424,7 +448,7 @@ public class LogicalPlan {
return this.resolvedGrouping;
}
- public void needToResolveGrouping() {
+ public void resolveGroupingRequired() {
this.resolvedGrouping = true;
}
@@ -434,18 +458,18 @@ public class LogicalPlan {
}
public boolean hasGrouping() {
- return hasGrouping || hasGroupingNode();
+ return hasGrouping || hasGroupbyNode();
}
- public boolean hasGroupingNode() {
+ public boolean hasGroupbyNode() {
return this.groupingNode != null;
}
- public void setGroupingNode(GroupbyNode groupingNode) {
+ public void setGroupbyNode(GroupbyNode groupingNode) {
this.groupingNode = groupingNode;
}
- public GroupbyNode getGroupingNode() {
+ public GroupbyNode getGroupbyNode() {
return this.groupingNode;
}
@@ -502,7 +526,8 @@ public class LogicalPlan {
break;
case GROUP_BY:
- needToResolveGrouping();
+ resolveGroupingRequired();
+ setGroupbyNode((GroupbyNode) node);
break;
case SELECTION:
@@ -574,7 +599,7 @@ public class LogicalPlan {
}
public void fillTarget(int idx) throws VerifyException {
- targetListManager.update(idx, planner.createTarget(LogicalPlan.this, this, projection.getTargets()[idx]));
+ targetListManager.update(idx, planner.createTarget(LogicalPlan.this, this, getProjection().getTargets()[idx]));
}
public boolean checkIfTargetCanBeEvaluated(int targetId, LogicalNode node) {
@@ -607,7 +632,7 @@ public class LogicalPlan {
public void checkAndResolveTargets(LogicalNode node) throws PlanningException {
// If all columns are projected and do not include any expression
- if (projection.isAllProjected() && node instanceof RelationNode) {
+ if (getProjection().isAllProjected() && node instanceof RelationNode) {
initTargetList(PlannerUtil.schemaToTargets(node.getOutSchema()));
resolveAllTargetList();
@@ -682,8 +707,31 @@ public class LogicalPlan {
}
} else if (node instanceof GroupbyNode) {
// Set the current targets to the GroupByNode because the GroupByNode is the last projection operator.
- ((Projectable)node).setTargets(getCurrentTargets());
+ GroupbyNode groupbyNode = (GroupbyNode) node;
+ groupbyNode.setTargets(getCurrentTargets());
node.setOutSchema(updateSchema());
+
+ // if a having condition is given,
+ if (hasHaving()) {
+ EvalNode havingCondition = planner.createEvalTree(LogicalPlan.this, this, getHaving().getQual());
+ List<AggFuncCallEval> aggrFunctions = EvalTreeUtil.findDistinctAggFunction(havingCondition);
+
+ if (aggrFunctions.size() == 0) {
+ groupbyNode.setHavingCondition(havingCondition);
+ } else {
+ Target [] addedTargets = new Target[aggrFunctions.size()];
+ for (int i = 0; i < aggrFunctions.size(); i++) {
+ Target aggrFunctionTarget = new Target(aggrFunctions.get(i), newAnonymousColumnName());
+ addedTargets[i] = aggrFunctionTarget;
+ EvalTreeUtil.replace(havingCondition, aggrFunctions.get(i),
+ new FieldEval(aggrFunctionTarget.getColumnSchema()));
+ }
+ Target [] updatedTargets = TUtil.concat(groupbyNode.getTargets(), addedTargets);
+ groupbyNode.setTargets(updatedTargets);
+ groupbyNode.setHavingCondition(havingCondition);
+ groupbyNode.setHavingSchema(PlannerUtil.targetToSchema(groupbyNode.getTargets()));
+ }
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java
index ca5a8f0..d0a1cf6 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java
@@ -22,33 +22,33 @@ import org.apache.tajo.engine.planner.logical.*;
import java.util.Stack;
-public interface LogicalPlanVisitor <T> {
- LogicalNode visitRoot(LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack, T data)
+public interface LogicalPlanVisitor <CONTEXT> {
+ LogicalNode visitRoot(LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitProjection(LogicalPlan plan, ProjectionNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitProjection(LogicalPlan plan, ProjectionNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitLimit(LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitLimit(LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitSort(LogicalPlan plan, SortNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitSort(LogicalPlan plan, SortNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitGroupBy(LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitGroupBy(LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitFilter(LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitFilter(LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitJoin(LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitJoin(LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitUnion(LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitUnion(LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitExcept(LogicalPlan plan, ExceptNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitExcept(LogicalPlan plan, ExceptNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitIntersect(LogicalPlan plan, IntersectNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitIntersect(LogicalPlan plan, IntersectNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitTableSubQuery(LogicalPlan plan, TableSubQueryNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitTableSubQuery(LogicalPlan plan, TableSubQueryNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitScan(LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitScan(LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitStoreTable(LogicalPlan plan, StoreTableNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitStoreTable(LogicalPlan plan, StoreTableNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
- LogicalNode visitInsert(LogicalPlan plan, InsertNode node, Stack<LogicalNode> stack, T data)
+ LogicalNode visitInsert(LogicalPlan plan, InsertNode node, Stack<LogicalNode> stack, CONTEXT context)
throws PlanningException;
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
index ed5b54e..17f3634 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
@@ -87,7 +87,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
public LogicalPlan createPlan(Expr expr) throws PlanningException {
LogicalPlan plan = new LogicalPlan(this);
- LogicalNode subroot = null;
+ LogicalNode subroot;
Stack<OpType> stack = new Stack<OpType>();
@@ -106,6 +106,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
public void preHook(PlanContext context, Stack<OpType> stack, Expr expr) {
context.block = checkIfNewBlockOrGet(context.plan, context.block.getName());
+ context.block.setAlgebraicExpr(expr);
}
public LogicalNode postHook(PlanContext context, Stack<OpType> stack, Expr expr, LogicalNode current)
@@ -441,7 +442,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
// 4. Set Child Plan and Update Input Schemes Phase
groupingNode.setChild(child);
- block.setGroupingNode(groupingNode);
+ block.setGroupbyNode(groupingNode);
groupingNode.setInSchema(child.getOutSchema());
// 5. Update Output Schema and Targets for Upper Plan
@@ -452,7 +453,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
List<Column[]> cuboids = generateCuboids(annotateGroupingColumn(plan, block.getName(),
groupElements[0].getColumns(), null));
UnionNode topUnion = createGroupByUnion(plan, block, child, cuboids, 0);
- block.needToResolveGrouping();
+ block.resolveGroupingRequired();
block.getTargetListManager().resolveAll();
return topUnion;
@@ -573,7 +574,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
// 2. Build Child Plans:
stack.push(OpType.Sort);
LogicalNode child = visitChild(context, stack, sort.getChild());
- child = insertGroupingIfUnresolved(plan, block, child, stack);
+ child = insertGroupbyNodeIfUnresolved(block, child, stack);
stack.pop();
// 3. Build this plan:
@@ -630,7 +631,6 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
LogicalPlan plan = context.plan;
QueryBlock block = context.block;
- block.setProjection(projection);
if (!projection.isAllProjected()) {
block.targetListManager = new TargetListManager(plan, projection);
}
@@ -649,7 +649,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
// 2: Build Child Plans
stack.push(OpType.Projection);
LogicalNode child = visitChild(context, stack, projection.getChild());
- child = insertGroupingIfUnresolved(plan, block, child, stack);
+ child = insertGroupbyNodeIfUnresolved(block, child, stack);
stack.pop();
// All targets must be evaluable before the projection.
@@ -689,8 +689,8 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
* Insert a group-by operator before a sort or a projection operator.
* It is used only when a group-by clause is not given.
*/
- private LogicalNode insertGroupingIfUnresolved(LogicalPlan plan, QueryBlock block,
- LogicalNode child, Stack<OpType> stack) throws PlanningException {
+ private LogicalNode insertGroupbyNodeIfUnresolved(QueryBlock block,
+ LogicalNode child, Stack<OpType> stack) throws PlanningException {
if (!block.isGroupingResolved()) {
GroupbyNode groupbyNode = new GroupbyNode(new Column[] {});
@@ -921,6 +921,8 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
case Literal:
LiteralValue literal = (LiteralValue) expr;
switch (literal.getValueType()) {
+ case Boolean:
+ return new ConstEval(DatumFactory.createBool(literal.getValue()));
case String:
return new ConstEval(DatumFactory.createText(literal.getValue()));
case Unsigned_Integer:
@@ -941,7 +943,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
constEvals[i] = (ConstEval) createEvalTree(plan, block, valueList.getValues()[i]);
values[i] = constEvals[i].getValue();
}
- return new RowConstant(values);
+ return new RowConstantEval(values);
}
// unary expression
@@ -960,8 +962,8 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
InPredicate inPredicate = (InPredicate) expr;
FieldEval predicand =
new FieldEval(plan.resolveColumn(block, null, (ColumnReferenceExpr) inPredicate.getPredicand()));
- RowConstant rowConstant = (RowConstant) createEvalTree(plan, block, inPredicate.getInValue());
- return new InEval(predicand, rowConstant, inPredicate.isNot());
+ RowConstantEval rowConstantEval = (RowConstantEval) createEvalTree(plan, block, inPredicate.getInValue());
+ return new InEval(predicand, rowConstantEval, inPredicate.isNot());
}
case Is:
@@ -1021,7 +1023,9 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
}
FunctionDesc funcDesc = catalog.getFunction(setFunction.getSignature(), paramTypes);
- block.setHasGrouping();
+ if (!block.hasGroupbyNode()) {
+ block.setHasGrouping();
+ }
try {
return new AggFuncCallEval(funcDesc, (AggFunction) funcDesc.newInstance(), givenArgs);
} catch (InternalException e) {
@@ -1055,7 +1059,9 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
return new FuncCallEval(funcDesc,
(GeneralFunction) funcDesc.newInstance(), givenArgs);
else {
- block.setHasGrouping();
+ if (!block.hasGroupbyNode()) {
+ block.setHasGrouping();
+ }
return new AggFuncCallEval(funcDesc,
(AggFunction) funcDesc.newInstance(), givenArgs);
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java
index e6a0e51..b118852 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PhysicalPlannerImpl.java
@@ -92,8 +92,8 @@ public class PhysicalPlannerImpl implements PhysicalPlanner {
}
private PhysicalExec createPlanRecursive(TaskAttemptContext ctx, LogicalNode logicalNode) throws IOException {
- PhysicalExec outer;
- PhysicalExec inner;
+ PhysicalExec leftExec;
+ PhysicalExec rightExec;
switch (logicalNode.getType()) {
@@ -107,60 +107,60 @@ public class PhysicalPlannerImpl implements PhysicalPlanner {
case STORE:
StoreTableNode storeNode = (StoreTableNode) logicalNode;
- outer = createPlanRecursive(ctx, storeNode.getChild());
- return createStorePlan(ctx, storeNode, outer);
+ leftExec = createPlanRecursive(ctx, storeNode.getChild());
+ return createStorePlan(ctx, storeNode, leftExec);
case SELECTION:
SelectionNode selNode = (SelectionNode) logicalNode;
- outer = createPlanRecursive(ctx, selNode.getChild());
- return new SelectionExec(ctx, selNode, outer);
+ leftExec = createPlanRecursive(ctx, selNode.getChild());
+ return new SelectionExec(ctx, selNode, leftExec);
case PROJECTION:
ProjectionNode prjNode = (ProjectionNode) logicalNode;
- outer = createPlanRecursive(ctx, prjNode.getChild());
- return new ProjectionExec(ctx, prjNode, outer);
+ leftExec = createPlanRecursive(ctx, prjNode.getChild());
+ return new ProjectionExec(ctx, prjNode, leftExec);
case TABLE_SUBQUERY: {
TableSubQueryNode subQueryNode = (TableSubQueryNode) logicalNode;
- outer = createPlanRecursive(ctx, subQueryNode.getSubQuery());
- return outer;
+ leftExec = createPlanRecursive(ctx, subQueryNode.getSubQuery());
+ return leftExec;
} case SCAN:
- outer = createScanPlan(ctx, (ScanNode) logicalNode);
- return outer;
+ leftExec = createScanPlan(ctx, (ScanNode) logicalNode);
+ return leftExec;
case GROUP_BY:
GroupbyNode grpNode = (GroupbyNode) logicalNode;
- outer = createPlanRecursive(ctx, grpNode.getChild());
- return createGroupByPlan(ctx, grpNode, outer);
+ leftExec = createPlanRecursive(ctx, grpNode.getChild());
+ return createGroupByPlan(ctx, grpNode, leftExec);
case SORT:
SortNode sortNode = (SortNode) logicalNode;
- outer = createPlanRecursive(ctx, sortNode.getChild());
- return createSortPlan(ctx, sortNode, outer);
+ leftExec = createPlanRecursive(ctx, sortNode.getChild());
+ return createSortPlan(ctx, sortNode, leftExec);
case JOIN:
JoinNode joinNode = (JoinNode) logicalNode;
- outer = createPlanRecursive(ctx, joinNode.getLeftChild());
- inner = createPlanRecursive(ctx, joinNode.getRightChild());
- return createJoinPlan(ctx, joinNode, outer, inner);
+ leftExec = createPlanRecursive(ctx, joinNode.getLeftChild());
+ rightExec = createPlanRecursive(ctx, joinNode.getRightChild());
+ return createJoinPlan(ctx, joinNode, leftExec, rightExec);
case UNION:
UnionNode unionNode = (UnionNode) logicalNode;
- outer = createPlanRecursive(ctx, unionNode.getLeftChild());
- inner = createPlanRecursive(ctx, unionNode.getRightChild());
- return new UnionExec(ctx, outer, inner);
+ leftExec = createPlanRecursive(ctx, unionNode.getLeftChild());
+ rightExec = createPlanRecursive(ctx, unionNode.getRightChild());
+ return new UnionExec(ctx, leftExec, rightExec);
case LIMIT:
LimitNode limitNode = (LimitNode) logicalNode;
- outer = createPlanRecursive(ctx, limitNode.getChild());
+ leftExec = createPlanRecursive(ctx, limitNode.getChild());
return new LimitExec(ctx, limitNode.getInSchema(),
- limitNode.getOutSchema(), outer, limitNode);
+ limitNode.getOutSchema(), leftExec, limitNode);
case BST_INDEX_SCAN:
IndexScanNode indexScanNode = (IndexScanNode) logicalNode;
- outer = createIndexScanExec(ctx, indexScanNode);
- return outer;
+ leftExec = createIndexScanExec(ctx, indexScanNode);
+ return leftExec;
default:
return null;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java
index 670cbfb..7e2bc16 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Target.java
@@ -82,7 +82,7 @@ public class Target implements Cloneable, GsonObject {
public String toString() {
StringBuilder sb = new StringBuilder(expr.toString());
if(hasAlias()) {
- sb.append(", alias=").append(alias);
+ sb.append(" as ").append(alias);
}
return sb.toString();
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
index 34da374..5c4e28e 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/GroupbyNode.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.planner.logical;
import com.google.gson.annotations.Expose;
import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.Schema;
import org.apache.tajo.engine.eval.EvalNode;
import org.apache.tajo.engine.planner.PlanString;
import org.apache.tajo.engine.planner.Target;
@@ -27,6 +28,7 @@ import org.apache.tajo.util.TUtil;
public class GroupbyNode extends UnaryNode implements Projectable, Cloneable {
@Expose private Column [] columns;
+ @Expose private Schema havingSchema;
@Expose private EvalNode havingCondition = null;
@Expose private Target [] targets;
@@ -65,6 +67,14 @@ public class GroupbyNode extends UnaryNode implements Projectable, Cloneable {
this.havingCondition = evalTree;
}
+ public final void setHavingSchema(Schema schema) {
+ this.havingSchema = schema;
+ }
+
+ public Schema getHavingSchema() {
+ return this.havingSchema;
+ }
+
@Override
public boolean hasTargets() {
return this.targets != null;
@@ -153,16 +163,7 @@ public class GroupbyNode extends UnaryNode implements Projectable, Cloneable {
public PlanString getPlanString() {
PlanString planStr = new PlanString("Aggregation");
- StringBuilder sb = new StringBuilder("Targets: ");
- for (int i = 0; i < targets.length; i++) {
- sb.append(targets[i]);
- if( i < targets.length - 1) {
- sb.append(",");
- }
- }
- planStr.addExplan(sb.toString());
-
- sb = new StringBuilder("Groups: ");
+ StringBuilder sb = new StringBuilder();
sb.append("(");
Column [] groupingColumns = columns;
for (int j = 0; j < groupingColumns.length; j++) {
@@ -174,7 +175,20 @@ public class GroupbyNode extends UnaryNode implements Projectable, Cloneable {
sb.append(")");
+ planStr.appendTitle(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/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/AggregationExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/AggregationExec.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/AggregationExec.java
index a00fa41..fb4a3b9 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/AggregationExec.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/AggregationExec.java
@@ -21,6 +21,7 @@ package org.apache.tajo.engine.planner.physical;
import com.google.common.collect.Sets;
import org.apache.tajo.TaskAttemptContext;
import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.Schema;
import org.apache.tajo.datum.DatumFactory;
import org.apache.tajo.engine.eval.ConstEval;
import org.apache.tajo.engine.eval.EvalContext;
@@ -33,21 +34,33 @@ import java.io.IOException;
import java.util.Set;
public abstract class AggregationExec extends UnaryPhysicalExec {
- protected GroupbyNode annotation;
-
- @SuppressWarnings("unused")
- protected final EvalNode havingQual;
+ protected GroupbyNode plan;
protected Set<Column> nonNullGroupingFields;
protected int keylist [];
protected int measureList[];
protected final EvalNode evals [];
protected EvalContext evalContexts [];
+ protected Schema evalSchema;
+
+ protected EvalNode havingQual;
+ protected EvalContext havingContext;
public AggregationExec(final TaskAttemptContext context, GroupbyNode plan,
PhysicalExec child) throws IOException {
super(context, plan.getInSchema(), plan.getOutSchema(), child);
- this.havingQual = plan.getHavingCondition();
+ this.plan = plan;
+
+ if (plan.hasHavingCondition()) {
+ this.havingQual = plan.getHavingCondition();
+ this.havingContext = plan.getHavingCondition().newContext();
+ }
+
+ if (plan.getHavingSchema() != null) {
+ this.evalSchema = plan.getHavingSchema();
+ } else {
+ this.evalSchema = plan.getOutSchema();
+ }
nonNullGroupingFields = Sets.newHashSet();
// keylist will contain a list of IDs of grouping column
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e595384b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/HashAggregateExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/HashAggregateExec.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/HashAggregateExec.java
index 427e6f4..019db82 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/HashAggregateExec.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/physical/HashAggregateExec.java
@@ -47,12 +47,13 @@ public class HashAggregateExec extends AggregationExec {
PhysicalExec subOp) throws IOException {
super(ctx, annotation, subOp);
tupleSlots = new HashMap<Tuple, EvalContext[]>(10000);
- this.tuple = new VTuple(outSchema.getColumnNum());
+ this.tuple = new VTuple(evalSchema.getColumnNum());
}
private void compute() throws IOException {
Tuple tuple;
Tuple keyTuple;
+ int targetLength = plan.getTargets().length;
while((tuple = child.next()) != null && !context.isStopped()) {
keyTuple = new VTuple(keylist.length);
// build one key tuple
@@ -66,8 +67,8 @@ public class HashAggregateExec extends AggregationExec {
evals[measureList[i]].eval(tmpTuple[measureList[i]], inSchema, tuple);
}
} else { // if the key occurs firstly
- EvalContext evalCtx [] = new EvalContext[outSchema.getColumnNum()];
- for(int i = 0; i < outSchema.getColumnNum(); i++) {
+ EvalContext evalCtx [] = new EvalContext[targetLength];
+ for(int i = 0; i < targetLength; i++) {
evalCtx[i] = evals[i].newContext();
evals[i].eval(evalCtx[i], inSchema, tuple);
}
@@ -83,14 +84,31 @@ public class HashAggregateExec extends AggregationExec {
iterator = tupleSlots.entrySet().iterator();
computed = true;
}
-
- if(iterator.hasNext()) {
- EvalContext [] ctx = iterator.next().getValue();
+
+ EvalContext [] ctx;
+ if (havingQual == null) {
+ if (iterator.hasNext()) {
+ ctx = iterator.next().getValue();
+
for (int i = 0; i < ctx.length; i++) {
tuple.put(i, evals[i].terminate(ctx[i]));
}
+
return tuple;
+ } else {
+ return null;
+ }
} else {
+ while(iterator.hasNext()) {
+ ctx = iterator.next().getValue();
+ for (int i = 0; i < ctx.length; i++) {
+ tuple.put(i, evals[i].terminate(ctx[i]));
+ }
+ havingQual.eval(havingContext, evalSchema, tuple);
+ if (havingQual.terminate(havingContext).asBool()) {
+ return tuple;
+ }
+ }
return null;
}
}