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/12/30 16:05:30 UTC

[2/2] git commit: TAJO-458: Visit methods of LogicalPlanVisitor should take a query block as parameter. (hyunsik)

TAJO-458: Visit methods of LogicalPlanVisitor should take a query block as parameter. (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/c7990c72
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/c7990c72
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/c7990c72

Branch: refs/heads/master
Commit: c7990c724898cd136fe87d508a4b07f62ede3567
Parents: b6a5ff0
Author: Hyunsik Choi <hy...@apache.org>
Authored: Mon Dec 30 23:01:43 2013 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Mon Dec 30 23:01:43 2013 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |   3 +
 .../tajo/engine/planner/BaseAlgebraVisitor.java |  16 +-
 .../engine/planner/BasicLogicalPlanVisitor.java | 151 ++++++++++---------
 .../planner/ExplainLogicalPlanVisitor.java      |  94 ++++++------
 .../tajo/engine/planner/LogicalOptimizer.java   |  44 +++---
 .../engine/planner/LogicalPlanVerifier.java     |  76 +++++-----
 .../tajo/engine/planner/LogicalPlanVisitor.java |  86 ++++++-----
 .../apache/tajo/engine/planner/PlannerUtil.java |  18 +--
 .../engine/planner/global/GlobalPlanner.java    | 137 +++++++++--------
 .../tajo/engine/planner/logical/NodeType.java   |  30 ++--
 .../planner/rewrite/FilterPushDownRule.java     |  20 +--
 .../rewrite/PartitionedTableRewriter.java       |   8 +-
 .../planner/rewrite/ProjectionPushDownRule.java | 124 +++++++--------
 13 files changed, 413 insertions(+), 394 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 76b0acc..fc92fc0 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -110,6 +110,9 @@ Release 0.8.0 - unreleased
 
   IMPROVEMENTS
 
+    TAJO-458: Visit methods of LogicalPlanVisitor should take a query block
+    as parameter. (hyunsik)
+
     TAJO-456: Separate tajo-jdbc and tajo-client from tajo-core-backend. (hyunsik)
 
     TAJO-432: Add shuffle phase for column-partitioned table store. (Min Zhou via jihoon)

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/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 1aeef5f..8b13194 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
@@ -47,7 +47,7 @@ public class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisitor<CONTE
   public RESULT visit(CONTEXT ctx, Stack<OpType> stack, Expr expr) throws PlanningException {
     preHook(ctx, stack, expr);
 
-    RESULT current = null;
+    RESULT current;
 
     switch (expr.getType()) {
 
@@ -93,6 +93,9 @@ public class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisitor<CONTE
     case Relation:
       current = visitRelation(ctx, stack, (Relation) expr);
       break;
+    case ScalarSubQuery:
+      current = visitScalarSubQuery(ctx, stack, (ScalarSubQuery) expr);
+      break;
 
     case CreateTable:
       current = visitCreateTable(ctx, stack, (CreateTable) expr);
@@ -207,22 +210,23 @@ public class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisitor<CONTE
       current = visitGeneralSetFunction(ctx, stack, (GeneralSetFunctionExpr) expr);
       break;
 
+    case DataType:
+      current = visitDataType(ctx, stack, (DataTypeExpr) expr);
+      break;
     case Cast:
       current = visitCastExpr(ctx, stack, (CastExpr) expr);
       break;
-    case ScalarSubQuery:
-      current = visitScalarSubQuery(ctx, stack, (ScalarSubQuery) expr);
-      break;
     case Literal:
       current = visitLiteral(ctx, stack, (LiteralValue) expr);
       break;
     case NullLiteral:
       current = visitNullLiteral(ctx, stack, (NullLiteral) expr);
       break;
-    case DataType:
-      current = visitDataType(ctx, stack, (DataTypeExpr) expr);
+    case TimestampLiteral:
+      current = visitTimestampLiteral(ctx, stack, (TimestampLiteral) expr);
       break;
 
+
     default:
       throw new PlanningException("Cannot support this type algebra \"" + expr.getType() + "\"");
     }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/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 0cee8dd..9cbb0ad 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
@@ -28,7 +28,8 @@ public class BasicLogicalPlanVisitor<CONTEXT, RESULT> implements LogicalPlanVisi
    * The prehook is called before each node is visited.
    */
   @SuppressWarnings("unused")
-  public void preHook(LogicalPlan plan, LogicalNode node, Stack<LogicalNode> stack, CONTEXT data) throws PlanningException {
+  public void preHook(LogicalPlan plan, LogicalNode node, Stack<LogicalNode> stack, CONTEXT data)
+      throws PlanningException {
   }
 
   /**
@@ -39,73 +40,72 @@ public class BasicLogicalPlanVisitor<CONTEXT, RESULT> implements LogicalPlanVisi
       throws PlanningException {
   }
 
-  public CONTEXT visit(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block) throws PlanningException {
-    visitChild(context, plan, block.getRoot(), new Stack<LogicalNode>());
-    return context;
-  }
-
-  public CONTEXT visit(CONTEXT context, LogicalPlan plan, LogicalNode node) throws PlanningException {
-    visitChild(context, plan, node, new Stack<LogicalNode>());
+  public CONTEXT visit(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block)
+      throws PlanningException {
+    visit(context, plan, block, block.getRoot(), new Stack<LogicalNode>());
     return context;
   }
 
   /**
    * visit visits each logicalNode recursively.
    */
-  public RESULT visitChild(CONTEXT context, LogicalPlan plan, LogicalNode node, Stack<LogicalNode> stack)
+  public RESULT visit(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, LogicalNode node,
+                      Stack<LogicalNode> stack)
       throws PlanningException {
     RESULT current;
     switch (node.getType()) {
       case ROOT:
-        current = visitRoot(context, plan, (LogicalRootNode) node, stack);
+        current = visitRoot(context, plan, block, (LogicalRootNode) node, stack);
         break;
+      case EXPRS:
+        return null;
       case PROJECTION:
-        current = visitProjection(context, plan, (ProjectionNode) node, stack);
+        current = visitProjection(context, plan, block, (ProjectionNode) node, stack);
         break;
       case LIMIT:
-        current = visitLimit(context, plan, (LimitNode) node, stack);
+        current = visitLimit(context, plan, block, (LimitNode) node, stack);
         break;
       case SORT:
-        current = visitSort(context, plan, (SortNode) node, stack);
+        current = visitSort(context, plan, block, (SortNode) node, stack);
         break;
       case GROUP_BY:
-        current = visitGroupBy(context, plan, (GroupbyNode) node, stack);
+        current = visitGroupBy(context, plan, block, (GroupbyNode) node, stack);
         break;
       case SELECTION:
-        current = visitFilter(context, plan, (SelectionNode) node, stack);
+        current = visitFilter(context, plan, block, (SelectionNode) node, stack);
         break;
       case JOIN:
-        current = visitJoin(context, plan, (JoinNode) node, stack);
+        current = visitJoin(context, plan, block, (JoinNode) node, stack);
         break;
       case UNION:
-        current = visitUnion(context, plan, (UnionNode) node, stack);
+        current = visitUnion(context, plan, block, (UnionNode) node, stack);
         break;
       case EXCEPT:
-        current = visitExcept(context, plan, (ExceptNode) node, stack);
+        current = visitExcept(context, plan, block, (ExceptNode) node, stack);
         break;
       case INTERSECT:
-        current = visitIntersect(context, plan, (IntersectNode) node, stack);
+        current = visitIntersect(context, plan, block, (IntersectNode) node, stack);
         break;
       case TABLE_SUBQUERY:
-        current = visitTableSubQuery(context, plan, (TableSubQueryNode) node, stack);
+        current = visitTableSubQuery(context, plan, block, (TableSubQueryNode) node, stack);
         break;
       case SCAN:
-        current = visitScan(context, plan, (ScanNode) node, stack);
+        current = visitScan(context, plan, block, (ScanNode) node, stack);
         break;
       case PARTITIONS_SCAN:
-        current = visitScan(context, plan, (ScanNode) node, stack);
+        current = visitPartitionedTableScan(context, plan, block, (PartitionedTableScanNode) node, stack);
         break;
       case STORE:
-        current = visitStoreTable(context, plan, (StoreTableNode) node, stack);
+        current = visitStoreTable(context, plan, block, (StoreTableNode) node, stack);
         break;
       case INSERT:
-        current = visitInsert(context, plan, (InsertNode) node, stack);
+        current = visitInsert(context, plan, block, (InsertNode) node, stack);
         break;
       case CREATE_TABLE:
-        current = visitCreateTable(context, plan, (CreateTableNode) node, stack);
+        current = visitCreateTable(context, plan, block, (CreateTableNode) node, stack);
         break;
       case DROP_TABLE:
-        current = visitDropTable(context, plan, (DropTableNode) node, stack);
+        current = visitDropTable(context, plan, block, (DropTableNode) node, stack);
         break;
       default:
         throw new PlanningException("Unknown logical node type: " + node.getType());
@@ -115,144 +115,149 @@ public class BasicLogicalPlanVisitor<CONTEXT, RESULT> implements LogicalPlanVisi
   }
 
   @Override
-  public RESULT visitRoot(CONTEXT context, LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitRoot(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, LogicalRootNode node,
+                          Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getChild(), stack);
+    RESULT result = visit(context, plan, block, node.getChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitProjection(CONTEXT context, LogicalPlan plan, ProjectionNode node, Stack<LogicalNode> stack)
+  public RESULT visitProjection(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, ProjectionNode node,
+                                Stack<LogicalNode> stack)
       throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getChild(), stack);
+    RESULT result = visit(context, plan, block, node.getChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitLimit(CONTEXT context, LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitLimit(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, LimitNode node,
+                           Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getChild(), stack);
+    RESULT result = visit(context, plan, block, node.getChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitSort(CONTEXT context, LogicalPlan plan, SortNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitSort(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, SortNode node,
+                          Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getChild(), stack);
+    RESULT result = visit(context, plan, block, node.getChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitGroupBy(CONTEXT context, LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitGroupBy(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, GroupbyNode node,
+                             Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getChild(), stack);
+    RESULT result = visit(context, plan, block, node.getChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitFilter(CONTEXT context, LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitFilter(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, SelectionNode node,
+                            Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getChild(), stack);
+    RESULT result = visit(context, plan, block, node.getChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitJoin(CONTEXT context, LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitJoin(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, JoinNode node,
+                          Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getLeftChild(), stack);
-    visitChild(context, plan, node.getRightChild(), stack);
+    RESULT result = visit(context, plan, block, node.getLeftChild(), stack);
+    visit(context, plan, block, node.getRightChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitUnion(CONTEXT context, LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitUnion(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, UnionNode node,
+                           Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getLeftChild(), stack);
-    visitChild(context, plan, node.getRightChild(), stack);
+    RESULT result = visit(context, plan, block, node.getLeftChild(), stack);
+    visit(context, plan, block, node.getRightChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitExcept(CONTEXT context, LogicalPlan plan, ExceptNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitExcept(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, ExceptNode node,
+                            Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getLeftChild(), stack);
-    visitChild(context, plan, node.getRightChild(), stack);
+    RESULT result = visit(context, plan, block, node.getLeftChild(), stack);
+    visit(context, plan, block, node.getRightChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitIntersect(CONTEXT context, LogicalPlan plan, IntersectNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitIntersect(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, IntersectNode node,
+                               Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getLeftChild(), stack);
-    visitChild(context, plan, node.getRightChild(), stack);
+    RESULT result = visit(context, plan, block, node.getLeftChild(), stack);
+    visit(context, plan, block, node.getRightChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitTableSubQuery(CONTEXT context, LogicalPlan plan, TableSubQueryNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitTableSubQuery(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                   TableSubQueryNode node, Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getSubQuery(), stack);
+    RESULT result = visit(context, plan, plan.getBlock(node.getSubQuery()), node.getSubQuery(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitScan(CONTEXT context, LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitScan(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode node,
+                          Stack<LogicalNode> stack) throws PlanningException {
     return null;
   }
 
   @Override
-  public RESULT visitPartitionedTableScan(CONTEXT context, LogicalPlan plan, PartitionedTableScanNode node, Stack<LogicalNode> stack) throws PlanningException {
+  public RESULT visitPartitionedTableScan(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                          PartitionedTableScanNode node, Stack<LogicalNode> stack)
+      throws PlanningException {
     return null;
   }
 
   @Override
-  public RESULT visitStoreTable(CONTEXT context, LogicalPlan plan, StoreTableNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitStoreTable(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, StoreTableNode node,
+                                Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getChild(), stack);
+    RESULT result = visit(context, plan, block, node.getChild(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitInsert(CONTEXT context, LogicalPlan plan, InsertNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public RESULT visitInsert(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, InsertNode node,
+                            Stack<LogicalNode> stack) throws PlanningException {
     stack.push(node);
-    RESULT result = visitChild(context, plan, node.getSubQuery(), stack);
+    RESULT result = visit(context, plan, plan.getBlock(node.getSubQuery()), node.getSubQuery(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitCreateTable(CONTEXT context, LogicalPlan plan, CreateTableNode node, Stack<LogicalNode> stack) {
+  public RESULT visitCreateTable(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, CreateTableNode node,
+                                 Stack<LogicalNode> stack) {
     return null;
   }
 
   @Override
-  public RESULT visitDropTable(CONTEXT context, LogicalPlan plan, DropTableNode node, Stack<LogicalNode> stack) {
+  public RESULT visitDropTable(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, DropTableNode node,
+                               Stack<LogicalNode> stack) {
     return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/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 cd42b34..fd8a6e1 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
@@ -67,56 +67,58 @@ public class ExplainLogicalPlanVisitor extends BasicLogicalPlanVisitor<ExplainLo
   public Context getBlockPlanStrings(LogicalPlan plan, String block) throws PlanningException {
     Stack<LogicalNode> stack = new Stack<LogicalNode>();
     Context explainContext = new Context();
-    visitChild(explainContext, plan, plan.getBlock(block).getRoot(), stack);
+    visit(explainContext, plan, plan.getBlock(block), plan.getBlock(block).getRoot(), stack);
     return explainContext;
   }
 
   @Override
-  public LogicalNode visitRoot(Context context, LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack)
+  public LogicalNode visitRoot(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, LogicalRootNode node, Stack<LogicalNode> stack)
       throws PlanningException {
-    return visitChild(context, plan, node.getChild(), stack);
+    return visit(context, plan, block, node.getChild(), stack);
   }
 
   @Override
-  public LogicalNode visitProjection(Context context, LogicalPlan plan, ProjectionNode node, Stack<LogicalNode> stack)
+  public LogicalNode visitProjection(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                     ProjectionNode node, Stack<LogicalNode> stack)
       throws PlanningException {
-    return visitUnaryNode(context, plan, node, stack);
+    return visitUnaryNode(context, plan, block, node, stack);
   }
 
   @Override
-  public LogicalNode visitLimit(Context context, LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    return visitUnaryNode(context, plan, node, stack);
+  public LogicalNode visitLimit(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                LimitNode node, Stack<LogicalNode> stack) throws PlanningException {
+    return visitUnaryNode(context, plan, block, node, stack);
   }
 
   @Override
-  public LogicalNode visitSort(Context context, LogicalPlan plan, SortNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    return visitUnaryNode(context, plan, node, stack);
+  public LogicalNode visitSort(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, SortNode node,
+                               Stack<LogicalNode> stack) throws PlanningException {
+    return visitUnaryNode(context, plan, block, node, stack);
   }
 
   @Override
-  public LogicalNode visitGroupBy(Context context, LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    return visitUnaryNode(context, plan, node, stack);
+  public LogicalNode visitGroupBy(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, GroupbyNode node,
+                                  Stack<LogicalNode> stack) throws PlanningException {
+    return visitUnaryNode(context, plan, block, node, stack);
   }
 
-  private LogicalNode visitUnaryNode(Context context, LogicalPlan plan, UnaryNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  private LogicalNode visitUnaryNode(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                     UnaryNode node, Stack<LogicalNode> stack) throws PlanningException {
     context.depth++;
     stack.push(node);
-    visitChild(context, plan, node.getChild(), stack);
+    visit(context, plan, block, node.getChild(), stack);
     context.depth--;
     context.add(context.depth, node.getPlanString());
     return node;
   }
 
-  private LogicalNode visitBinaryNode(Context context, LogicalPlan plan, BinaryNode node, Stack<LogicalNode> stack)
+  private LogicalNode visitBinaryNode(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, BinaryNode node,
+                                      Stack<LogicalNode> stack)
       throws PlanningException {
     context.depth++;
     stack.push(node);
-    visitChild(context, plan, node.getLeftChild(), stack);
-    visitChild(context, plan, node.getRightChild(), stack);
+    visit(context, plan, block, node.getLeftChild(), stack);
+    visit(context, plan, block, node.getRightChild(), stack);
     stack.pop();
     context.depth--;
     context.add(context.depth, node.getPlanString());
@@ -124,41 +126,41 @@ public class ExplainLogicalPlanVisitor extends BasicLogicalPlanVisitor<ExplainLo
   }
 
   @Override
-  public LogicalNode visitFilter(Context context, LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    return visitUnaryNode(context, plan, node, stack);
+  public LogicalNode visitFilter(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, SelectionNode node,
+                                 Stack<LogicalNode> stack) throws PlanningException {
+    return visitUnaryNode(context, plan, block, node, stack);
   }
 
   @Override
-  public LogicalNode visitJoin(Context context, LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack) throws
-      PlanningException {
-    return visitBinaryNode(context, plan, node, stack);
+  public LogicalNode visitJoin(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, JoinNode node,
+                               Stack<LogicalNode> stack) throws PlanningException {
+    return visitBinaryNode(context, plan, block, node, stack);
   }
 
   @Override
-  public LogicalNode visitUnion(Context context, LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    return visitBinaryNode(context, plan, node, stack);
+  public LogicalNode visitUnion(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, UnionNode node,
+                                Stack<LogicalNode> stack) throws PlanningException {
+    return visitBinaryNode(context, plan, block, node, stack);
   }
 
   @Override
-  public LogicalNode visitExcept(Context context, LogicalPlan plan, ExceptNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    return visitBinaryNode(context, plan, node, stack);
+  public LogicalNode visitExcept(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, ExceptNode node,
+                                 Stack<LogicalNode> stack) throws PlanningException {
+    return visitBinaryNode(context, plan, block, node, stack);
   }
 
   @Override
-  public LogicalNode visitIntersect(Context context, LogicalPlan plan, IntersectNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    return visitBinaryNode(context, plan, node, stack);
+  public LogicalNode visitIntersect(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, IntersectNode node,
+                                    Stack<LogicalNode> stack) throws PlanningException {
+    return visitBinaryNode(context, plan, block, node, stack);
   }
 
   @Override
-  public LogicalNode visitTableSubQuery(Context context, LogicalPlan plan, TableSubQueryNode node,
-                                        Stack<LogicalNode> stack) throws PlanningException {
+  public LogicalNode visitTableSubQuery(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                        TableSubQueryNode node, Stack<LogicalNode> stack) throws PlanningException {
     context.depth++;
     stack.push(node);
-    super.visitTableSubQuery(context, plan, node, stack);
+    super.visitTableSubQuery(context, plan, block, node, stack);
     stack.pop();
     context.depth--;
     context.add(context.depth, node.getPlanString());
@@ -167,24 +169,24 @@ public class ExplainLogicalPlanVisitor extends BasicLogicalPlanVisitor<ExplainLo
   }
 
   @Override
-  public LogicalNode visitScan(Context context, LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public LogicalNode visitScan(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode node,
+                               Stack<LogicalNode> stack) throws PlanningException {
     context.add(context.depth, node.getPlanString());
     return node;
   }
 
   @Override
-  public LogicalNode visitStoreTable(Context context, LogicalPlan plan, StoreTableNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    return visitUnaryNode(context, plan, node, stack);
+  public LogicalNode visitStoreTable(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                     StoreTableNode node, Stack<LogicalNode> stack) throws PlanningException {
+    return visitUnaryNode(context, plan, block, node, stack);
   }
 
   @Override
-  public LogicalNode visitInsert(Context context, LogicalPlan plan, InsertNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public LogicalNode visitInsert(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, InsertNode node,
+                                 Stack<LogicalNode> stack) throws PlanningException {
     context.depth++;
     stack.push(node);
-    visitChild(context, plan, node.getSubQuery(), stack);
+    super.visitInsert(context, plan, block, node, stack);
     stack.pop();
     context.depth--;
     context.add(context.depth, node.getPlanString());

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalOptimizer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalOptimizer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalOptimizer.java
index 5f11f1a..acbace0 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalOptimizer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalOptimizer.java
@@ -97,18 +97,9 @@ public class LogicalOptimizer {
   }
 
   private static class JoinGraphContext {
-    LogicalPlan.QueryBlock block;
     JoinGraph joinGraph = new JoinGraph();
     Set<EvalNode> quals = Sets.newHashSet();
     Set<String> relationsForProduct = Sets.newHashSet();
-
-    public JoinGraphContext(LogicalPlan.QueryBlock block) {
-      this.block = block;
-    }
-
-    public LogicalPlan.QueryBlock getBlock() {
-      return block;
-    }
   }
 
   private static class JoinGraphBuilder extends BasicLogicalPlanVisitor<JoinGraphContext, LogicalNode> {
@@ -125,25 +116,25 @@ public class LogicalOptimizer {
      */
     public static JoinGraphContext buildJoinGraph(LogicalPlan plan, LogicalPlan.QueryBlock block)
         throws PlanningException {
-      JoinGraphContext joinGraphContext = new JoinGraphContext(block);
+      JoinGraphContext joinGraphContext = new JoinGraphContext();
       instance.visit(joinGraphContext, plan, block);
       return joinGraphContext;
     }
 
-    public LogicalNode visitFilter(JoinGraphContext context, LogicalPlan plan, SelectionNode node,
-                                   Stack<LogicalNode> stack) throws PlanningException {
-      super.visitFilter(context, plan, node, stack);
+    public LogicalNode visitFilter(JoinGraphContext context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                   SelectionNode node, Stack<LogicalNode> stack) throws PlanningException {
+      super.visitFilter(context, plan, block, node, stack);
       context.quals.addAll(Lists.newArrayList(AlgebraicUtil.toConjunctiveNormalFormArray(node.getQual())));
       return node;
     }
 
     @Override
-    public LogicalNode visitJoin(JoinGraphContext joinGraphContext, LogicalPlan plan, JoinNode joinNode,
-                                 Stack<LogicalNode> stack)
+    public LogicalNode visitJoin(JoinGraphContext joinGraphContext, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                 JoinNode joinNode, Stack<LogicalNode> stack)
         throws PlanningException {
-      super.visitJoin(joinGraphContext, plan, joinNode, stack);
+      super.visitJoin(joinGraphContext, plan, block, joinNode, stack);
       if (joinNode.hasJoinQual()) {
-        joinGraphContext.joinGraph.addJoin(plan, joinGraphContext.block, joinNode);
+        joinGraphContext.joinGraph.addJoin(plan, block, joinNode);
       } else {
         LogicalNode leftChild = joinNode.getLeftChild();
         LogicalNode rightChild = joinNode.getRightChild();
@@ -177,14 +168,14 @@ public class LogicalOptimizer {
     }
 
     @Override
-    public LogicalNode visitJoin(StringBuilder sb, LogicalPlan plan, JoinNode joinNode,
+    public LogicalNode visitJoin(StringBuilder sb, LogicalPlan plan, LogicalPlan.QueryBlock block, JoinNode joinNode,
                                  Stack<LogicalNode> stack)
         throws PlanningException {
       stack.push(joinNode);
       sb.append("(");
-      visitChild(sb, plan, joinNode.getLeftChild(), stack);
+      visit(sb, plan, block, joinNode.getLeftChild(), stack);
       sb.append(" ").append(getJoinNotation(joinNode.getJoinType())).append(" ");
-      visitChild(sb, plan, joinNode.getRightChild(), stack);
+      visit(sb, plan, block, joinNode.getRightChild(), stack);
       sb.append(")");
       stack.pop();
       return joinNode;
@@ -205,13 +196,14 @@ public class LogicalOptimizer {
     }
 
     @Override
-    public LogicalNode visitTableSubQuery(StringBuilder sb, LogicalPlan plan, TableSubQueryNode node,
-                                          Stack<LogicalNode> stack) {
+    public LogicalNode visitTableSubQuery(StringBuilder sb, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                          TableSubQueryNode node, Stack<LogicalNode> stack) {
       sb.append(node.getTableName());
       return node;
     }
 
-    public LogicalNode visitScan(StringBuilder sb, LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack) {
+    public LogicalNode visitScan(StringBuilder sb, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode node,
+                                 Stack<LogicalNode> stack) {
       sb.append(node.getTableName());
       return node;
     }
@@ -235,10 +227,10 @@ public class LogicalOptimizer {
     }
 
     @Override
-    public LogicalNode visitJoin(CostContext joinGraphContext, LogicalPlan plan, JoinNode joinNode,
-                                 Stack<LogicalNode> stack)
+    public LogicalNode visitJoin(CostContext joinGraphContext, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                 JoinNode joinNode, Stack<LogicalNode> stack)
         throws PlanningException {
-      super.visitJoin(joinGraphContext, plan, joinNode, stack);
+      super.visitJoin(joinGraphContext, plan, block, joinNode, stack);
 
       double filterFactor = 1;
       if (joinNode.hasJoinQual()) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java
index 6491b9b..e48b655 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java
@@ -37,9 +37,9 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitProjection(VerificationState state, LogicalPlan plan, ProjectionNode node,
-                                     Stack<LogicalNode> stack) throws PlanningException {
-    visitChild(state, plan, node.getChild(), stack);
+  public LogicalNode visitProjection(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                     ProjectionNode node, Stack<LogicalNode> stack) throws PlanningException {
+    visit(state, plan, block, node.getChild(), stack);
 
     for (Target target : node.getTargets()) {
       ExprsVerifier.verify(state, target.getEvalTree());
@@ -49,10 +49,10 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitLimit(VerificationState state, LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public LogicalNode visitLimit(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                LimitNode node, Stack<LogicalNode> stack) throws PlanningException {
 
-    visitChild(state, plan, node.getChild(), stack);
+    visit(state, plan, block, node.getChild(), stack);
     if (node.getFetchFirstNum() < 0) {
       state.addVerification("LIMIT must not be negative");
     }
@@ -61,9 +61,9 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitGroupBy(VerificationState state, LogicalPlan plan, GroupbyNode node,
-                                  Stack<LogicalNode> stack) throws PlanningException {
-    visitChild(state, plan, node.getChild(), stack);
+  public LogicalNode visitGroupBy(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                  GroupbyNode node, Stack<LogicalNode> stack) throws PlanningException {
+    visit(state, plan, block, node.getChild(), stack);
 
     if (node.hasTargets()) {
       for (Target target : node.getTargets()) {
@@ -78,18 +78,18 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitFilter(VerificationState state, LogicalPlan plan, SelectionNode node,
-                                 Stack<LogicalNode> stack) throws PlanningException {
-    visitChild(state, plan, node.getChild(), stack);
+  public LogicalNode visitFilter(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                 SelectionNode node, Stack<LogicalNode> stack) throws PlanningException {
+    visit(state, plan, block, node.getChild(), stack);
     ExprsVerifier.verify(state, node.getQual());
     return node;
   }
 
   @Override
-  public LogicalNode visitJoin(VerificationState state, LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    visitChild(state, plan, node.getLeftChild(), stack);
-    visitChild(state, plan, node.getRightChild(), stack);
+  public LogicalNode visitJoin(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block, JoinNode node,
+                               Stack<LogicalNode> stack) throws PlanningException {
+    visit(state, plan, block, node.getLeftChild(), stack);
+    visit(state, plan, block, node.getRightChild(), stack);
 
     if (node.hasJoinQual()) {
       ExprsVerifier.verify(state, node.getJoinQual());
@@ -122,33 +122,33 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitUnion(VerificationState state, LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack)
-      throws PlanningException {
-    visitChild(state, plan, node.getLeftChild(), stack);
-    visitChild(state, plan, node.getRightChild(), stack);
+  public LogicalNode visitUnion(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                UnionNode node, Stack<LogicalNode> stack) throws PlanningException {
+    visit(state, plan, block, node.getLeftChild(), stack);
+    visit(state, plan, block, node.getRightChild(), stack);
     verifySetStatement(state, node);
     return node;
   }
 
   @Override
-  public LogicalNode visitExcept(VerificationState state, LogicalPlan plan, ExceptNode node,
-                                 Stack<LogicalNode> stack) throws PlanningException {
-    visitChild(state, plan, node, stack);
+  public LogicalNode visitExcept(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                 ExceptNode node, Stack<LogicalNode> stack) throws PlanningException {
+    visit(state, plan, block, node, stack);
     verifySetStatement(state, node);
     return node;
   }
 
   @Override
-  public LogicalNode visitIntersect(VerificationState state, LogicalPlan plan, IntersectNode node,
-                                    Stack<LogicalNode> stack) throws PlanningException {
-    visitChild(state, plan, node.getLeftChild(), stack);
-    visitChild(state, plan, node.getRightChild(), stack);
+  public LogicalNode visitIntersect(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                    IntersectNode node, Stack<LogicalNode> stack) throws PlanningException {
+    visit(state, plan, block, node.getLeftChild(), stack);
+    visit(state, plan, block, node.getRightChild(), stack);
     verifySetStatement(state, node);
     return node;
   }
 
   @Override
-  public LogicalNode visitScan(VerificationState state, LogicalPlan plan, ScanNode node,
+  public LogicalNode visitScan(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode node,
                                Stack<LogicalNode> stack) throws PlanningException {
     if (node.hasTargets()) {
       for (Target target : node.getTargets()) {
@@ -163,9 +163,9 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitStoreTable(VerificationState state, LogicalPlan plan, StoreTableNode node,
-                                     Stack<LogicalNode> stack) throws PlanningException {
-    visitChild(state, plan, node.getChild(), stack);
+  public LogicalNode visitStoreTable(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                     StoreTableNode node, Stack<LogicalNode> stack) throws PlanningException {
+    visit(state, plan, block, node.getChild(), stack);
 
     if (node.isCreatedTable() && catalog.existsTable(node.getTableName())) {
       state.addVerification("relation \"" + node.getTableName() + "\" already exists");
@@ -175,9 +175,9 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitInsert(VerificationState state, LogicalPlan plan, InsertNode node,
-                                 Stack<LogicalNode> stack) throws PlanningException {
-    LogicalNode child = visitChild(state, plan, node.getSubQuery(), stack);
+  public LogicalNode visitInsert(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                 InsertNode node, Stack<LogicalNode> stack) throws PlanningException {
+    LogicalNode child = visit(state, plan, plan.getBlock(node.getSubQuery()), node.getSubQuery(), stack);
 
     if (node.hasTargetSchema()) {
       ensureDomains(state, node.getTargetSchema(), node.getSubQuery().getOutSchema());
@@ -204,8 +204,8 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitCreateTable(VerificationState state, LogicalPlan plan, CreateTableNode node,
-                                      Stack<LogicalNode> stack) {
+  public LogicalNode visitCreateTable(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                      CreateTableNode node, Stack<LogicalNode> stack) {
     if (catalog.existsTable(node.getTableName())) {
       state.addVerification("relation \"" + node.getTableName() + "\" already exists");
     }
@@ -214,8 +214,8 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitDropTable(VerificationState state, LogicalPlan plan, DropTableNode node,
-                                    Stack<LogicalNode> stack) {
+  public LogicalNode visitDropTable(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                    DropTableNode node, Stack<LogicalNode> stack) {
     if (!catalog.existsTable(node.getTableName())) {
       state.addVerification("table \"" + node.getTableName() + "\" does not exist");
     }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/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 c6fcefc..697a8c6 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,39 +22,55 @@ import org.apache.tajo.engine.planner.logical.*;
 
 import java.util.Stack;
 
-public interface LogicalPlanVisitor <CONTEXT, RESULT> {
-  RESULT visitRoot(CONTEXT context, LogicalPlan plan, LogicalRootNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitProjection(CONTEXT context, LogicalPlan plan, ProjectionNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitLimit(CONTEXT context, LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitSort(CONTEXT context, LogicalPlan plan, SortNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitGroupBy(CONTEXT context, LogicalPlan plan, GroupbyNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitFilter(CONTEXT context, LogicalPlan plan, SelectionNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitJoin(CONTEXT context, LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitUnion(CONTEXT context, LogicalPlan plan, UnionNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitExcept(CONTEXT context, LogicalPlan plan, ExceptNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitIntersect(CONTEXT context, LogicalPlan plan, IntersectNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitTableSubQuery(CONTEXT context, LogicalPlan plan, TableSubQueryNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitScan(CONTEXT context, LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitPartitionedTableScan(CONTEXT context, LogicalPlan plan, PartitionedTableScanNode node,
-                                   Stack<LogicalNode> stack) throws PlanningException;
-  RESULT visitStoreTable(CONTEXT context, LogicalPlan plan, StoreTableNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitInsert(CONTEXT context, LogicalPlan plan, InsertNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitCreateTable(CONTEXT context, LogicalPlan plan, CreateTableNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
-  RESULT visitDropTable(CONTEXT context, LogicalPlan plan, DropTableNode node, Stack<LogicalNode> stack)
-      throws PlanningException;
+public interface LogicalPlanVisitor<CONTEXT, RESULT> {
+  RESULT visitRoot(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, LogicalRootNode node,
+                   Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitProjection(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, ProjectionNode node,
+                         Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitLimit(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, LimitNode node,
+                    Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitSort(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, SortNode node,
+                   Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitGroupBy(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, GroupbyNode node,
+                      Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitFilter(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, SelectionNode node,
+                     Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitJoin(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, JoinNode node,
+                   Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitUnion(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, UnionNode node,
+                    Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitExcept(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, ExceptNode node,
+                     Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitIntersect(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, IntersectNode node,
+                        Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitTableSubQuery(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, TableSubQueryNode node,
+                            Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitScan(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode node,
+                   Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitPartitionedTableScan(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                   PartitionedTableScanNode node, Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitStoreTable(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, StoreTableNode node,
+                         Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitInsert(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, InsertNode node,
+                     Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitCreateTable(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, CreateTableNode node,
+                          Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitDropTable(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, DropTableNode node,
+                        Stack<LogicalNode> stack) throws PlanningException;
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
index d541680..3d604ef 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
@@ -23,6 +23,7 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.ObjectArrays;
 import com.google.common.collect.Sets;
 import org.apache.tajo.algebra.JoinType;
+import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.catalog.SortSpec;
@@ -74,7 +75,7 @@ public class PlannerUtil {
   public static Collection<String> getRelationLineageWithinQueryBlock(LogicalPlan plan, LogicalNode node)
       throws PlanningException {
     RelationFinderVisitor visitor = new RelationFinderVisitor();
-    visitor.visit(null, plan, node);
+    visitor.visit(null, plan, null, node, new Stack<LogicalNode>());
     return visitor.getFoundRelations();
   }
 
@@ -86,10 +87,10 @@ public class PlannerUtil {
     }
 
     @Override
-    public LogicalNode visitChild(Object context, LogicalPlan plan, LogicalNode node, Stack<LogicalNode> stack)
-        throws PlanningException {
+    public LogicalNode visit(Object context, LogicalPlan plan, @Nullable LogicalPlan.QueryBlock block, LogicalNode node,
+                             Stack<LogicalNode> stack) throws PlanningException {
       if (node.getType() != NodeType.TABLE_SUBQUERY) {
-        super.visitChild(context, plan, node, stack);
+        super.visit(context, plan, block, node, stack);
       }
 
       if (node instanceof RelationNode) {
@@ -137,12 +138,11 @@ public class PlannerUtil {
   public static void replaceNode(LogicalPlan plan, LogicalNode startNode, LogicalNode oldNode, LogicalNode newNode) {
     LogicalNodeReplaceVisitor replacer = new LogicalNodeReplaceVisitor(oldNode, newNode);
     try {
-      replacer.visit(null, plan, startNode);
+      replacer.visit(null, plan, null, startNode, new Stack<LogicalNode>());
     } catch (PlanningException e) {
       e.printStackTrace();
     }
   }
-
   public static class LogicalNodeReplaceVisitor extends BasicLogicalPlanVisitor<Object, LogicalNode> {
     private LogicalNode target;
     private LogicalNode tobeReplaced;
@@ -153,9 +153,9 @@ public class PlannerUtil {
     }
 
     @Override
-    public LogicalNode visitChild(Object context, LogicalPlan plan, LogicalNode node, Stack<LogicalNode> stack)
-        throws PlanningException {
-      super.visitChild(context, plan, node, stack);
+    public LogicalNode visit(Object context, LogicalPlan plan, @Nullable LogicalPlan.QueryBlock block, LogicalNode node,
+                                  Stack<LogicalNode> stack) throws PlanningException {
+      super.visit(context, plan, null, node, stack);
 
       if (node.deepEquals(target)) {
         LogicalNode parent = stack.peek();

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
index 5ab53d8..b7e1ddb 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
@@ -74,8 +74,8 @@ public class GlobalPlanner {
 
     LogicalNode inputPlan = PlannerUtil.clone(masterPlan.getLogicalPlan(),
         masterPlan.getLogicalPlan().getRootBlock().getRoot());
-    LogicalNode lastNode = planner.visitChild(globalPlanContext, masterPlan.getLogicalPlan(), inputPlan,
-        new Stack<LogicalNode>());
+    LogicalNode lastNode = planner.visit(globalPlanContext,
+        masterPlan.getLogicalPlan(), masterPlan.getLogicalPlan().getRootBlock(), inputPlan, new Stack<LogicalNode>());
 
     ExecutionBlock childExecBlock = globalPlanContext.execBlockMap.get(lastNode.getPID());
 
@@ -372,16 +372,16 @@ public class GlobalPlanner {
   public class DistributedPlannerVisitor extends BasicLogicalPlanVisitor<GlobalPlanContext, LogicalNode> {
 
     @Override
-    public LogicalNode visitRoot(GlobalPlanContext context, LogicalPlan plan, LogicalRootNode node,
-                                 Stack<LogicalNode> stack) throws PlanningException {
-      LogicalNode child = super.visitRoot(context, plan, node, stack);
+    public LogicalNode visitRoot(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                 LogicalRootNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode child = super.visitRoot(context, plan, block, node, stack);
       return child;
     }
 
     @Override
-    public LogicalNode visitProjection(GlobalPlanContext context, LogicalPlan plan, ProjectionNode node,
-                                       Stack<LogicalNode> stack) throws PlanningException {
-      LogicalNode child = super.visitProjection(context, plan, node, stack);
+    public LogicalNode visitProjection(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                       ProjectionNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode child = super.visitProjection(context, plan, block, node, stack);
 
       ExecutionBlock execBlock = context.execBlockMap.remove(child.getPID());
 
@@ -393,30 +393,30 @@ public class GlobalPlanner {
     }
 
     @Override
-    public LogicalNode visitLimit(GlobalPlanContext context, LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack)
-        throws PlanningException {
-      LogicalNode child = super.visitLimit(context, plan, node, stack);
+    public LogicalNode visitLimit(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                  LimitNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode child = super.visitLimit(context, plan, block, node, stack);
 
-      ExecutionBlock block;
-      block = context.execBlockMap.remove(child.getPID());
+      ExecutionBlock execBlock;
+      execBlock = context.execBlockMap.remove(child.getPID());
       if (child.getType() == NodeType.SORT) {
-        node.setChild(block.getPlan());
-        block.setPlan(node);
+        node.setChild(execBlock.getPlan());
+        execBlock.setPlan(node);
 
-        ExecutionBlock childBlock = context.plan.getChild(block, 0);
+        ExecutionBlock childBlock = context.plan.getChild(execBlock, 0);
         LimitNode childLimit = PlannerUtil.clone(context.plan.getLogicalPlan(), node);
         childLimit.setChild(childBlock.getPlan());
         childBlock.setPlan(childLimit);
 
-        DataChannel channel = context.plan.getChannel(childBlock, block);
+        DataChannel channel = context.plan.getChannel(childBlock, execBlock);
         channel.setPartitionNum(1);
-        context.execBlockMap.put(node.getPID(), block);
+        context.execBlockMap.put(node.getPID(), execBlock);
       } else {
-        node.setChild(block.getPlan());
-        block.setPlan(node);
+        node.setChild(execBlock.getPlan());
+        execBlock.setPlan(node);
 
         ExecutionBlock newExecBlock = context.plan.newExecutionBlock();
-        DataChannel newChannel = new DataChannel(block, newExecBlock, HASH_PARTITION, 1);
+        DataChannel newChannel = new DataChannel(execBlock, newExecBlock, HASH_PARTITION, 1);
         newChannel.setPartitionKey(new Column[]{});
         newChannel.setSchema(node.getOutSchema());
         newChannel.setStoreType(storeType);
@@ -434,10 +434,10 @@ public class GlobalPlanner {
     }
 
     @Override
-    public LogicalNode visitSort(GlobalPlanContext context, LogicalPlan plan, SortNode node, Stack<LogicalNode> stack)
-        throws PlanningException {
+    public LogicalNode visitSort(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                 SortNode node, Stack<LogicalNode> stack) throws PlanningException {
 
-      LogicalNode child = super.visitSort(context, plan, node, stack);
+      LogicalNode child = super.visitSort(context, plan, block, node, stack);
 
       ExecutionBlock childBlock = context.execBlockMap.remove(child.getPID());
       ExecutionBlock newExecBlock = buildSortPlan(context, childBlock, node);
@@ -447,9 +447,9 @@ public class GlobalPlanner {
     }
 
     @Override
-    public LogicalNode visitGroupBy(GlobalPlanContext context, LogicalPlan plan, GroupbyNode node,
-                                    Stack<LogicalNode> stack) throws PlanningException {
-      LogicalNode child = super.visitGroupBy(context, plan, node, stack);
+    public LogicalNode visitGroupBy(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                    GroupbyNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode child = super.visitGroupBy(context, plan, block, node, stack);
 
       ExecutionBlock childBlock = context.execBlockMap.remove(child.getPID());
       ExecutionBlock newExecBlock = buildGroupBy(context, childBlock, node);
@@ -459,9 +459,9 @@ public class GlobalPlanner {
     }
 
     @Override
-    public LogicalNode visitFilter(GlobalPlanContext context, LogicalPlan plan, SelectionNode node,
-                                   Stack<LogicalNode> stack) throws PlanningException {
-      LogicalNode child = super.visitFilter(context, plan, node, stack);
+    public LogicalNode visitFilter(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                   SelectionNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode child = super.visitFilter(context, plan, block, node, stack);
 
       ExecutionBlock execBlock = context.execBlockMap.remove(child.getPID());
       node.setChild(execBlock.getPlan());
@@ -473,10 +473,10 @@ public class GlobalPlanner {
     }
 
     @Override
-    public LogicalNode visitJoin(GlobalPlanContext context, LogicalPlan plan, JoinNode node, Stack<LogicalNode> stack)
-        throws PlanningException {
-      LogicalNode leftChild = visitChild(context, plan, node.getLeftChild(), stack);
-      LogicalNode rightChild = visitChild(context, plan, node.getRightChild(), stack);
+    public LogicalNode visitJoin(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                 JoinNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode leftChild = visit(context, plan, block, node.getLeftChild(), stack);
+      LogicalNode rightChild = visit(context, plan, block, node.getRightChild(), stack);
 
       ExecutionBlock leftChildBlock = context.execBlockMap.get(leftChild.getPID());
       ExecutionBlock rightChildBlock = context.execBlockMap.get(rightChild.getPID());
@@ -488,11 +488,11 @@ public class GlobalPlanner {
     }
 
     @Override
-    public LogicalNode visitUnion(GlobalPlanContext context, LogicalPlan plan, UnionNode node,
-                                  Stack<LogicalNode> stack) throws PlanningException {
+    public LogicalNode visitUnion(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock queryBlock,
+                                  UnionNode node, Stack<LogicalNode> stack) throws PlanningException {
       stack.push(node);
-      LogicalNode leftChild = visitChild(context, plan, node.getLeftChild(), stack);
-      LogicalNode rightChild = visitChild(context, plan, node.getRightChild(), stack);
+      LogicalNode leftChild = visit(context, plan, queryBlock, node.getLeftChild(), stack);
+      LogicalNode rightChild = visit(context, plan, queryBlock, node.getRightChild(), stack);
       stack.pop();
 
       List<ExecutionBlock> unionBlocks = Lists.newArrayList();
@@ -544,29 +544,40 @@ public class GlobalPlanner {
     }
 
     @Override
-    public LogicalNode visitExcept(GlobalPlanContext context, LogicalPlan plan, ExceptNode node,
-                                   Stack<LogicalNode> stack) throws PlanningException {
-      LogicalNode child = super.visitExcept(context, plan, node, stack);
+    public LogicalNode visitExcept(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock queryBlock,
+                                   ExceptNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode child = super.visitExcept(context, plan, queryBlock, node, stack);
       return handleUnaryNode(context, child, node);
     }
 
     @Override
-    public LogicalNode visitIntersect(GlobalPlanContext context, LogicalPlan plan, IntersectNode node,
-                                      Stack<LogicalNode> stack) throws PlanningException {
-      LogicalNode child = super.visitIntersect(context, plan, node, stack);
+    public LogicalNode visitIntersect(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock queryBlock,
+                                      IntersectNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode child = super.visitIntersect(context, plan, queryBlock, node, stack);
       return handleUnaryNode(context, child, node);
     }
 
     @Override
-    public LogicalNode visitTableSubQuery(GlobalPlanContext context, LogicalPlan plan, TableSubQueryNode node,
-                                          Stack<LogicalNode> stack) throws PlanningException {
-      LogicalNode child = super.visitTableSubQuery(context, plan, node, stack);
+    public LogicalNode visitTableSubQuery(GlobalPlanContext context, LogicalPlan plan,
+                                          LogicalPlan.QueryBlock queryBlock,
+                                          TableSubQueryNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode child = super.visitTableSubQuery(context, plan, queryBlock, node, stack);
       return handleUnaryNode(context, child, node);
     }
 
     @Override
-    public LogicalNode visitScan(GlobalPlanContext context, LogicalPlan plan, ScanNode node, Stack<LogicalNode> stack)
-        throws PlanningException {
+    public LogicalNode visitScan(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock queryBlock,
+                                 ScanNode node, Stack<LogicalNode> stack) throws PlanningException {
+      ExecutionBlock newExecBlock = context.plan.newExecutionBlock();
+      newExecBlock.setPlan(node);
+      context.execBlockMap.put(node.getPID(), newExecBlock);
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitPartitionedTableScan(GlobalPlanContext context, LogicalPlan plan,
+                                                 LogicalPlan.QueryBlock block, PartitionedTableScanNode node,
+                                                 Stack<LogicalNode> stack)throws PlanningException {
       ExecutionBlock newExecBlock = context.plan.newExecutionBlock();
       newExecBlock.setPlan(node);
       context.execBlockMap.put(node.getPID(), newExecBlock);
@@ -574,9 +585,9 @@ public class GlobalPlanner {
     }
 
     @Override
-    public LogicalNode visitStoreTable(GlobalPlanContext context, LogicalPlan plan, StoreTableNode node,
-                                       Stack<LogicalNode> stack) throws PlanningException {
-      LogicalNode child = super.visitStoreTable(context, plan, node, stack);
+    public LogicalNode visitStoreTable(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock queryBlock,
+                                       StoreTableNode node, Stack<LogicalNode> stack) throws PlanningException {
+      LogicalNode child = super.visitStoreTable(context, plan, queryBlock, node, stack);
 
       ExecutionBlock childBlock = context.execBlockMap.remove(child.getPID());
       ExecutionBlock newExecBlock = buildStorePlan(context, childBlock, node);
@@ -586,10 +597,10 @@ public class GlobalPlanner {
     }
 
     @Override
-    public LogicalNode visitInsert(GlobalPlanContext context, LogicalPlan plan, InsertNode node,
-                                   Stack<LogicalNode> stack)
+    public LogicalNode visitInsert(GlobalPlanContext context, LogicalPlan plan, LogicalPlan.QueryBlock queryBlock,
+                                   InsertNode node, Stack<LogicalNode> stack)
         throws PlanningException {
-      LogicalNode child = super.visitInsert(context, plan, node, stack);
+      LogicalNode child = super.visitInsert(context, plan, queryBlock, node, stack);
       ExecutionBlock execBlock = context.execBlockMap.remove(child.getPID());
       execBlock.setPlan(node);
       context.execBlockMap.put(node.getPID(), execBlock);
@@ -598,28 +609,24 @@ public class GlobalPlanner {
     }
   }
 
-  private class UnionsFinderContext {
-    List<UnionNode> unionList = new ArrayList<UnionNode>();
-  }
-
   @SuppressWarnings("unused")
-  private class ConsecutiveUnionFinder extends BasicLogicalPlanVisitor<UnionsFinderContext, LogicalNode> {
+  private class ConsecutiveUnionFinder extends BasicLogicalPlanVisitor<List<UnionNode>, LogicalNode> {
     @Override
-    public LogicalNode visitUnion(UnionsFinderContext context, LogicalPlan plan, UnionNode node,
-                                  Stack<LogicalNode> stack)
+    public LogicalNode visitUnion(List<UnionNode> unionNodeList, LogicalPlan plan, LogicalPlan.QueryBlock queryBlock,
+                                  UnionNode node, Stack<LogicalNode> stack)
         throws PlanningException {
       if (node.getType() == NodeType.UNION) {
-        context.unionList.add(node);
+        unionNodeList.add(node);
       }
 
       stack.push(node);
       TableSubQueryNode leftSubQuery = node.getLeftChild();
       TableSubQueryNode rightSubQuery = node.getRightChild();
       if (leftSubQuery.getSubQuery().getType() == NodeType.UNION) {
-        visitChild(context, plan, leftSubQuery, stack);
+        visit(unionNodeList, plan, queryBlock, leftSubQuery, stack);
       }
       if (rightSubQuery.getSubQuery().getType() == NodeType.UNION) {
-        visitChild(context, plan, rightSubQuery, stack);
+        visit(unionNodeList, plan, queryBlock, rightSubQuery, stack);
       }
       stack.pop();
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
index eaaf0c7..4c0dd11 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
@@ -27,26 +27,26 @@ import org.apache.tajo.engine.planner.InsertNode;
  * This indicates a logical node type.
  */
 public enum NodeType {
-  BST_INDEX_SCAN(IndexScanNode.class),
-  CREATE_TABLE(CreateTableNode.class),
-  DROP_TABLE(DropTableNode.class),
-  EXCEPT(ExceptNode.class),
+  ROOT(LogicalRootNode.class),
   EXPRS(EvalExprNode.class),
-  GROUP_BY(GroupbyNode.class),
-  INSERT(InsertNode.class),
-  INTERSECT(IntersectNode.class),
+  PROJECTION(ProjectionNode.class),
   LIMIT(LimitNode.class),
+  SORT(SortNode.class),
+  GROUP_BY(GroupbyNode.class),
+  SELECTION(SelectionNode.class),
   JOIN(JoinNode.class),
-  PARTITIONS_SCAN(PartitionedTableScanNode.class),
-  PROJECTION(ProjectionNode.class),
-  ROOT(LogicalRootNode.class),
+  UNION(UnionNode.class),
+  EXCEPT(ExceptNode.class),
+  INTERSECT(IntersectNode.class),
+  TABLE_SUBQUERY(TableSubQueryNode.class),
   SCAN(ScanNode.class),
-  SELECTION(SelectionNode.class),
+  PARTITIONS_SCAN(PartitionedTableScanNode.class),
+  BST_INDEX_SCAN(IndexScanNode.class),
   STORE(StoreTableNode.class),
-  SORT(SortNode.class),
-  UNION(UnionNode.class),
-  TABLE_SUBQUERY(TableSubQueryNode.class);
-
+  INSERT(InsertNode.class),
+  CREATE_TABLE(CreateTableNode.class),
+  DROP_TABLE(DropTableNode.class)
+  ;
 
   private final Class<? extends LogicalNode> baseClass;
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java
index 817e48a..44af891 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java
@@ -53,19 +53,19 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<Set<EvalNode>, L
   @Override
   public LogicalPlan rewrite(LogicalPlan plan) throws PlanningException {
     for (LogicalPlan.QueryBlock block : plan.getQueryBlocks()) {
-      this.visit(new HashSet<EvalNode>(), plan, block.getRoot());
+      this.visit(new HashSet<EvalNode>(), plan, block, block.getRoot(), new Stack<LogicalNode>());
     }
 
     return plan;
   }
 
   @Override
-  public LogicalNode visitFilter(Set<EvalNode> cnf, LogicalPlan plan, SelectionNode selNode, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public LogicalNode visitFilter(Set<EvalNode> cnf, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                 SelectionNode selNode, Stack<LogicalNode> stack) throws PlanningException {
     cnf.addAll(Sets.newHashSet(AlgebraicUtil.toConjunctiveNormalFormArray(selNode.getQual())));
 
     stack.push(selNode);
-    visitChild(cnf, plan, selNode.getChild(), stack);
+    visit(cnf, plan, block, selNode.getChild(), stack);
     stack.pop();
 
     // remove the selection operator if there is no search condition
@@ -88,8 +88,8 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<Set<EvalNode>, L
   }
 
   @Override
-  public LogicalNode visitJoin(Set<EvalNode> cnf, LogicalPlan plan, JoinNode joinNode, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public LogicalNode visitJoin(Set<EvalNode> cnf, LogicalPlan plan, LogicalPlan.QueryBlock block, JoinNode joinNode,
+                               Stack<LogicalNode> stack) throws PlanningException {
     LogicalNode left = joinNode.getRightChild();
     LogicalNode right = joinNode.getLeftChild();
 
@@ -194,8 +194,8 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<Set<EvalNode>, L
       cnf.addAll(Sets.newHashSet(AlgebraicUtil.toConjunctiveNormalFormArray(joinNode.getJoinQual())));
     }
 
-    visitChild(cnf, plan, left, stack);
-    visitChild(cnf, plan, right, stack);
+    visit(cnf, plan, block, left, stack);
+    visit(cnf, plan, block, right, stack);
 
     List<EvalNode> matched = Lists.newArrayList();
     for (EvalNode eval : cnf) {
@@ -227,8 +227,8 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<Set<EvalNode>, L
   }
 
   @Override
-  public LogicalNode visitScan(Set<EvalNode> cnf, LogicalPlan plan, ScanNode scanNode, Stack<LogicalNode> stack)
-      throws PlanningException {
+  public LogicalNode visitScan(Set<EvalNode> cnf, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode scanNode,
+                               Stack<LogicalNode> stack) throws PlanningException {
 
     List<EvalNode> matched = Lists.newArrayList();
     for (EvalNode eval : cnf) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/c7990c72/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/PartitionedTableRewriter.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/PartitionedTableRewriter.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/PartitionedTableRewriter.java
index 561424f..4a7a324 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/PartitionedTableRewriter.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/rewrite/PartitionedTableRewriter.java
@@ -88,7 +88,7 @@ public class PartitionedTableRewriter implements RewriteRule {
         }
       }
       if (containsPartitionedTables) {
-        rewriter.visitChild(block, plan, block.getRoot(), new Stack<LogicalNode>());
+        rewriter.visit(block, plan, block, block.getRoot(), new Stack<LogicalNode>());
       }
     }
     return plan;
@@ -346,10 +346,10 @@ public class PartitionedTableRewriter implements RewriteRule {
     }
   }
 
-  private final class Rewriter extends BasicLogicalPlanVisitor<LogicalPlan.QueryBlock, Object> {
+  private final class Rewriter extends BasicLogicalPlanVisitor<Object, Object> {
     @Override
-    public Object visitScan(LogicalPlan.QueryBlock block, LogicalPlan plan, ScanNode scanNode, Stack<LogicalNode> stack)
-        throws PlanningException {
+    public Object visitScan(Object object, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode scanNode,
+                            Stack<LogicalNode> stack) throws PlanningException {
 
       TableDesc table = scanNode.getTableDesc();
       if (!table.hasPartitions()) {