tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hyun...@apache.org
Subject [3/3] git commit: TAJO-539: Change some EvalNode::eval to directly return a Datum value.
Date Sat, 25 Jan 2014 06:35:03 GMT
TAJO-539: Change some EvalNode::eval to directly return a Datum value.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tajo/commit/e23e78cc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/e23e78cc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/e23e78cc

Branch: refs/heads/master
Commit: e23e78ccd4c740fd93d2629e5b523c3f4b29c199
Parents: 0386268
Author: Hyunsik Choi <hyunsik@apache.org>
Authored: Sat Jan 25 15:34:35 2014 +0900
Committer: Hyunsik Choi <hyunsik@apache.org>
Committed: Sat Jan 25 15:34:45 2014 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |   3 +
 .../eval/AggregationFunctionCallEval.java       |  41 ++---
 .../apache/tajo/engine/eval/AlgebraicUtil.java  |   4 +-
 .../tajo/engine/eval/BetweenPredicateEval.java  |  85 +++------
 .../org/apache/tajo/engine/eval/BinaryEval.java |  28 +--
 .../apache/tajo/engine/eval/CaseWhenEval.java   |  73 ++------
 .../org/apache/tajo/engine/eval/CastEval.java   |  25 +--
 .../org/apache/tajo/engine/eval/ConstEval.java  |  18 +-
 .../apache/tajo/engine/eval/EvalContext.java    |  22 ---
 .../org/apache/tajo/engine/eval/EvalNode.java   |   6 +-
 .../apache/tajo/engine/eval/EvalTreeUtil.java   |   5 +-
 .../org/apache/tajo/engine/eval/FieldEval.java  |  22 +--
 .../apache/tajo/engine/eval/FunctionEval.java   |  20 +--
 .../tajo/engine/eval/GeneralFunctionEval.java   |  20 +--
 .../org/apache/tajo/engine/eval/InEval.java     |  29 +--
 .../org/apache/tajo/engine/eval/IsNullEval.java |  30 +---
 .../org/apache/tajo/engine/eval/NotEval.java    |  20 +--
 .../tajo/engine/eval/PartialBinaryExpr.java     |  14 +-
 .../engine/eval/PatternMatchPredicateEval.java  |  30 +---
 .../tajo/engine/eval/RowConstantEval.java       |  20 +--
 .../org/apache/tajo/engine/eval/SignedEval.java |  21 +--
 .../tajo/engine/planner/ExprsVerifier.java      |  13 +-
 .../engine/planner/LogicalPlanVerifier.java     |  11 --
 .../tajo/engine/planner/LogicalPlanner.java     | 165 ++++++++++-------
 .../apache/tajo/engine/planner/PlannerUtil.java |  96 +---------
 .../engine/planner/PreLogicalPlanVerifier.java  |  69 +++++++-
 .../apache/tajo/engine/planner/Projector.java   |  20 +--
 .../engine/planner/global/GlobalPlanner.java    | 177 +++++++++++++------
 .../engine/planner/logical/GroupbyNode.java     |  70 ++++++--
 .../planner/physical/AggregationExec.java       |  64 ++-----
 .../engine/planner/physical/BNLJoinExec.java    |  19 +-
 .../planner/physical/BSTIndexScanExec.java      |  24 +--
 .../engine/planner/physical/EvalExprExec.java   |  15 +-
 .../planner/physical/HashAggregateExec.java     |  65 +++----
 .../planner/physical/HashFullOuterJoinExec.java |  20 +--
 .../engine/planner/physical/HashJoinExec.java   |  13 +-
 .../planner/physical/HashLeftAntiJoinExec.java  |   9 +-
 .../planner/physical/HashLeftOuterJoinExec.java |  21 +--
 .../planner/physical/HashLeftSemiJoinExec.java  |   6 +-
 .../engine/planner/physical/HavingExec.java     |  13 +-
 .../physical/MergeFullOuterJoinExec.java        |  29 +--
 .../engine/planner/physical/MergeJoinExec.java  |  14 +-
 .../engine/planner/physical/NLJoinExec.java     |  16 +-
 .../planner/physical/NLLeftOuterJoinExec.java   |  17 +-
 .../engine/planner/physical/ProjectionExec.java |  10 +-
 .../physical/RightOuterMergeJoinExec.java       |  23 +--
 .../engine/planner/physical/SelectionExec.java  |   8 +-
 .../engine/planner/physical/SeqScanExec.java    |  42 ++---
 .../planner/physical/SortAggregateExec.java     |  94 ++++++----
 .../rewrite/PartitionedTableRewriter.java       |   7 +-
 .../planner/rewrite/ProjectionPushDownRule.java |  77 +++++---
 .../org/apache/tajo/engine/utils/TupleUtil.java |   7 +-
 .../org/apache/tajo/master/GlobalEngine.java    |   2 +-
 .../apache/tajo/engine/eval/ExprTestBase.java   |   5 +-
 .../apache/tajo/engine/eval/TestEvalTree.java   | 144 ++++-----------
 .../tajo/engine/eval/TestEvalTreeUtil.java      |  34 ++--
 .../tajo/engine/planner/TestLogicalPlanner.java |   2 +-
 .../tajo/engine/planner/TestPlannerUtil.java    |  22 ---
 .../planner/physical/TestPhysicalPlanner.java   |  24 +--
 59 files changed, 774 insertions(+), 1229 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index f4fa4e3..c04b2d4 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -125,6 +125,9 @@ Release 0.8.0 - unreleased
 
   IMPROVEMENTS
 
+    TAJO-539: Change some EvalNode::eval to directly return a Datum value.
+    (hyunsik)
+
     TAJO-543: InsertNode and CreateTableNode should play their roles. (hyunsik)
 
     TAJO-409: Add explored and explained annotations to Tajo function system.

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggregationFunctionCallEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggregationFunctionCallEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggregationFunctionCallEval.java
index 290ff45..10eadce 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggregationFunctionCallEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AggregationFunctionCallEval.java
@@ -21,10 +21,10 @@ package org.apache.tajo.engine.eval;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.engine.function.AggFunction;
-import org.apache.tajo.engine.function.FunctionContext;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
+import org.apache.tajo.engine.function.AggFunction;
+import org.apache.tajo.engine.function.FunctionContext;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.VTuple;
 
@@ -38,40 +38,38 @@ public class AggregationFunctionCallEval extends FunctionEval implements Cloneab
     this.instance = instance;
   }
 
-  @Override
-  public EvalContext newContext() {
-    return new AggFunctionCtx(argEvals, instance.newContext());
+  public FunctionContext newContext() {
+    return instance.newContext();
   }
 
-  @Override
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    AggFunctionCtx localCtx = (AggFunctionCtx) ctx;
+  public void merge(FunctionContext context, Schema schema, Tuple tuple) {
     if (params == null) {
       this.params = new VTuple(argEvals.length);
     }
 
     if (argEvals != null) {
-      params.clear();
-
       for (int i = 0; i < argEvals.length; i++) {
-        argEvals[i].eval(localCtx.argCtxs[i], schema, tuple);
-        params.put(i, argEvals[i].terminate(localCtx.argCtxs[i]));
+        params.put(i, argEvals[i].eval(schema, tuple));
       }
     }
 
     if (firstPhase) {
-      instance.eval(localCtx.funcCtx, params);
+      instance.eval(context, params);
     } else {
-      instance.merge(localCtx.funcCtx, params);
+      instance.merge(context, params);
     }
   }
 
   @Override
-  public Datum terminate(EvalContext ctx) {
+  public Datum eval(Schema schema, Tuple tuple) {
+    throw new UnsupportedOperationException("Cannot execute eval() of aggregation function");
+  }
+
+  public Datum terminate(FunctionContext context) {
     if (firstPhase) {
-      return instance.getPartialResult(((AggFunctionCtx)ctx).funcCtx);
+      return instance.getPartialResult(context);
     } else {
-      return instance.terminate(((AggFunctionCtx)ctx).funcCtx);
+      return instance.terminate(context);
     }
   }
 
@@ -91,13 +89,4 @@ public class AggregationFunctionCallEval extends FunctionEval implements Cloneab
   public void setFirstPhase() {
     this.firstPhase = true;
   }
-
-  protected class AggFunctionCtx extends FuncCallCtx {
-    FunctionContext funcCtx;
-
-    AggFunctionCtx(EvalNode [] argEvals, FunctionContext funcCtx) {
-      super(argEvals);
-      this.funcCtx = funcCtx;
-    }
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
index 70ae712..6bb0160 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
@@ -157,9 +157,7 @@ public class AlgebraicUtil {
       right = eliminateConstantExprs(right);
 
       if (left.getType() == EvalType.CONST && right.getType() == EvalType.CONST) {
-        EvalContext exprCtx = expr.newContext();
-        expr.eval(exprCtx, null, null);
-        return new ConstEval(expr.terminate(exprCtx));
+        return new ConstEval(expr.eval(null, null));
       } else {
         return new BinaryEval(expr.getType(), left, right);
       }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
index 0215928..61dc02b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
@@ -47,7 +47,7 @@ public class BetweenPredicateEval extends EvalNode {
   }
 
   private static interface Checker {
-    void eval(BetweenContext context, Schema schema, Tuple param);
+    Datum eval(Schema schema, Tuple param);
   }
 
   private static class ConstantChecker implements Checker {
@@ -69,16 +69,14 @@ public class BetweenPredicateEval extends EvalNode {
     }
 
     @Override
-    public void eval(BetweenContext context, Schema schema, Tuple param) {
-      predicand.eval(context.predicandContext, schema, param);
-      Datum predicandValue = predicand.terminate(context.predicandContext);
+    public Datum eval(Schema schema, Tuple param) {
+      Datum predicandValue = predicand.eval(schema, param);
 
-      if (!(predicandValue instanceof NullDatum)) {
-        context.result =
-            DatumFactory.createBool(not ^ (predicandValue.greaterThanEqual(begin).asBool()
+      if (!predicandValue.isNull()) {
+        return DatumFactory.createBool(not ^ (predicandValue.greaterThanEqual(begin).asBool()
                 && predicandValue.lessThanEqual(end).asBool()));
       } else {
-        context.result = NullDatum.get();
+        return NullDatum.get();
       }
     }
   }
@@ -97,20 +95,17 @@ public class BetweenPredicateEval extends EvalNode {
     }
 
     @Override
-    public void eval(BetweenContext context, Schema schema, Tuple param) {
-      predicand.eval(context.predicandContext, schema, param);
-      Datum predicandValue = predicand.terminate(context.predicandContext);
-      begin.eval(context.beginContext, schema, param);
-      Datum beginValue = begin.terminate(context.beginContext);
-      end.eval(context.endContext, schema, param);
-      Datum endValue = begin.terminate(context.endContext);
-
-      if (!(predicandValue instanceof NullDatum || beginValue instanceof NullDatum || endValue instanceof NullDatum)) {
-        context.result =
+    public Datum eval(Schema schema, Tuple param) {
+      Datum predicandValue = predicand.eval(schema, param);
+      Datum beginValue = begin.eval(schema, param);
+      Datum endValue = end.eval(schema, param);
+
+      if (!(predicandValue.isNull() || beginValue.isNull() || endValue.isNull())) {
+        return
             DatumFactory.createBool(not ^ (predicandValue.greaterThanEqual(beginValue).asBool()
                 && predicandValue.lessThanEqual(endValue).asBool()));
       } else {
-        context.result = NullDatum.get();
+        return NullDatum.get();
       }
     }
   }
@@ -129,31 +124,23 @@ public class BetweenPredicateEval extends EvalNode {
     }
 
     @Override
-    public void eval(BetweenContext context, Schema schema, Tuple param) {
-      predicand.eval(context.predicandContext, schema, param);
-      Datum predicandValue = predicand.terminate(context.predicandContext);
-      begin.eval(context.beginContext, schema, param);
-      Datum beginValue = begin.terminate(context.beginContext);
-      end.eval(context.endContext, schema, param);
-      Datum endValue = begin.terminate(context.endContext);
-
-      if (!(predicandValue instanceof NullDatum || beginValue instanceof NullDatum || endValue instanceof NullDatum)) {
-        context.result = DatumFactory.createBool( not ^
+    public Datum eval(Schema schema, Tuple param) {
+      Datum predicandValue = predicand.eval(schema, param);
+      Datum beginValue = begin.eval(schema, param);
+      Datum endValue = end.eval(schema, param);
+
+      if (!(predicandValue.isNull()|| beginValue.isNull() || endValue.isNull())) {
+        return DatumFactory.createBool( not ^
             (predicandValue.greaterThanEqual(beginValue).asBool() && predicandValue.lessThanEqual(endValue).asBool()) ||
             (predicandValue.lessThanEqual(beginValue).asBool() && predicandValue.greaterThanEqual(endValue).asBool())
         );
       } else {
-        context.result = NullDatum.get();
+        return NullDatum.get();
       }
     }
   }
 
   @Override
-  public EvalContext newContext() {
-    return new BetweenContext();
-  }
-
-  @Override
   public TajoDataTypes.DataType getValueType() {
     return RES_TYPE;
   }
@@ -169,14 +156,14 @@ public class BetweenPredicateEval extends EvalNode {
   }
 
   @Override
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
+  public Datum eval(Schema schema, Tuple tuple) {
     if (checker == null) {
       if (begin.getType() == EvalType.CONST && end.getType() == EvalType.CONST) {
-        Datum beginValue = begin.terminate(null);
-        Datum endValue = end.terminate(null);
+        Datum beginValue = ((ConstEval)begin).getValue();
+        Datum endValue = ((ConstEval)end).getValue();
 
         if (symmetric || beginValue.compareTo(endValue) <= 0) {
-          checker = new ConstantChecker(not, predicand, begin.terminate(null), end.terminate(null));
+          checker = new ConstantChecker(not, predicand, beginValue, endValue);
         } else {
           checker = new AsymmetricChecker(not, predicand, begin, end);
         }
@@ -189,12 +176,7 @@ public class BetweenPredicateEval extends EvalNode {
       }
     }
 
-    checker.eval((BetweenContext) ctx, schema, tuple);
-  }
-
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    return ((BetweenContext)ctx).result;
+    return checker.eval(schema, tuple);
   }
 
   @Override
@@ -207,19 +189,6 @@ public class BetweenPredicateEval extends EvalNode {
     return false;
   }
 
-  private class BetweenContext implements EvalContext {
-    private EvalContext predicandContext;
-    private EvalContext beginContext;
-    private EvalContext endContext;
-    private Datum result;
-
-    BetweenContext() {
-      predicandContext = predicand.newContext();
-      beginContext = begin.newContext();
-      endContext = end.newContext();
-    }
-  }
-
   @Deprecated
   public void preOrder(EvalNodeVisitor visitor) {
     visitor.visit(this);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
index ba21b4a..d362927 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
@@ -34,11 +34,6 @@ import static org.apache.tajo.common.TajoDataTypes.Type;
 public class BinaryEval extends EvalNode implements Cloneable {
   @Expose private DataType returnType = null;
 
-  private class BinaryEvalCtx implements EvalContext {
-    EvalContext left;
-    EvalContext right;
-  }
-
   /**
    * @param type
    */
@@ -75,15 +70,6 @@ public class BinaryEval extends EvalNode implements Cloneable {
     this(expr.type, expr.leftExpr, expr.rightExpr);
   }
 
-  @Override
-  public EvalContext newContext() {
-    BinaryEvalCtx newCtx =  new BinaryEvalCtx();
-    newCtx.left = leftExpr.newContext();
-    newCtx.right = rightExpr.newContext();
-
-    return newCtx;
-  }
-
   /**
    * This is verified by ExprsVerifier.checkArithmeticOperand().
    */
@@ -134,17 +120,9 @@ public class BinaryEval extends EvalNode implements Cloneable {
   }
 
   @Override
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    BinaryEvalCtx binCtx = (BinaryEvalCtx) ctx;
-    leftExpr.eval(binCtx == null ? null : binCtx.left, schema, tuple);
-    rightExpr.eval(binCtx == null ? null : binCtx.right, schema, tuple);
-  }
-
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    BinaryEvalCtx binCtx = (BinaryEvalCtx) ctx;
-    Datum lhs = leftExpr.terminate(binCtx.left);
-    Datum rhs = rightExpr.terminate(binCtx.right);
+  public Datum eval(Schema schema, Tuple tuple) {
+    Datum lhs = leftExpr.eval(schema, tuple);
+    Datum rhs = rightExpr.eval(schema, tuple);
 
     switch(type) {
     case AND:

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/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 9bbf4b4..d08bfd3 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
@@ -25,7 +25,7 @@ import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
-import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.storage.Tuple;
@@ -62,11 +62,6 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
   }
 
   @Override
-  public EvalContext newContext() {
-    return new CaseContext(whens, elseResult != null ? elseResult.newContext() : null);
-  }
-
-  @Override
   public DataType getValueType() {
     return whens.get(0).getResultExpr().getValueType();
   }
@@ -76,30 +71,18 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
     return "?";
   }
 
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    CaseContext caseCtx = (CaseContext) ctx;
+  public Datum eval(Schema schema, Tuple tuple) {
     for (int i = 0; i < whens.size(); i++) {
-      whens.get(i).eval(caseCtx.contexts[i], schema, tuple);
+      if (whens.get(i).checkIfCondition(schema, tuple)) {
+        return whens.get(i).eval(schema, tuple);
+      }
     }
 
     if (elseResult != null) { // without else clause
-      elseResult.eval(caseCtx.elseCtx, schema, tuple);
+      return elseResult.eval(schema, tuple);
     }
-  }
 
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    CaseContext caseCtx = (CaseContext) ctx;
-    for (int i = 0; i < whens.size(); i++) {
-      if (whens.get(i).terminate(caseCtx.contexts[i]).asBool()) {
-        return whens.get(i).getThenResult(caseCtx.contexts[i]);
-      }
-    }
-    if (elseResult != null) { // without else clause
-      return elseResult.terminate(caseCtx.elseCtx);
-    } else {
-      return DatumFactory.createNullDatum();
-    }
+    return NullDatum.get();
   }
 
   @Override
@@ -163,11 +146,6 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
     }
 
     @Override
-    public EvalContext newContext() {
-      return new WhenContext(condition.newContext(), result.newContext());
-    }
-
-    @Override
     public DataType getValueType() {
       return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.BOOLEAN);
     }
@@ -177,14 +155,12 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
       return "when?";
     }
 
-    public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-      condition.eval(((WhenContext) ctx).condCtx, schema, tuple);
-      result.eval(((WhenContext) ctx).resultCtx, schema, tuple);
+    public boolean checkIfCondition(Schema schema, Tuple tuple) {
+      return condition.eval(schema, tuple).isTrue();
     }
 
-    @Override
-    public Datum terminate(EvalContext ctx) {
-      return condition.terminate(((WhenContext) ctx).condCtx);
+    public Datum eval(Schema schema, Tuple tuple) {
+      return result.eval(schema, tuple);
     }
 
     public EvalNode getConditionExpr() {
@@ -215,20 +191,6 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
       return CoreGsonHelper.toJson(IfThenEval.this, IfThenEval.class);
     }
 
-    private class WhenContext implements EvalContext {
-      EvalContext condCtx;
-      EvalContext resultCtx;
-
-      public WhenContext(EvalContext condCtx, EvalContext resultCtx) {
-        this.condCtx = condCtx;
-        this.resultCtx = resultCtx;
-      }
-    }
-
-    public Datum getThenResult(EvalContext ctx) {
-      return result.terminate(((WhenContext) ctx).resultCtx);
-    }
-
     @Override
     public void preOrder(EvalNodeVisitor visitor) {
       visitor.visit(this);
@@ -243,17 +205,4 @@ public class CaseWhenEval extends EvalNode implements GsonObject {
       visitor.visit(this);
     }
   }
-
-  private class CaseContext implements EvalContext {
-    EvalContext [] contexts;
-    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();
-      }
-      this.elseCtx = elseCtx;
-    }
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java
index 033800d..9ff3df1 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java
@@ -41,13 +41,6 @@ public class CastEval extends EvalNode {
   }
 
   @Override
-  public EvalContext newContext() {
-    CastContext castContext = new CastContext();
-    castContext.childCtx = operand.newContext();
-    return castContext;
-  }
-
-  @Override
   public DataType getValueType() {
     return target;
   }
@@ -57,15 +50,8 @@ public class CastEval extends EvalNode {
     return target.getType().name();
   }
 
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    CastContext castContext = (CastContext) ctx;
-    operand.eval(castContext.childCtx , schema, tuple);
-  }
-
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    CastContext castContext = (CastContext) ctx;
-    Datum operandDatum = operand.terminate(castContext.childCtx);
+  public Datum eval(Schema schema, Tuple tuple) {
+    Datum operandDatum = operand.eval(schema, tuple);
     if (operandDatum.isNull()) {
       return operandDatum;
     }
@@ -97,8 +83,7 @@ public class CastEval extends EvalNode {
       case BLOB:
         return DatumFactory.createBlob(operandDatum.asByteArray());
       default:
-        throw new InvalidCastException("Cannot cast " + operand.getValueType().getType() + " to "
-            + target.getType());
+      throw new InvalidCastException("Cannot cast " + operand.getValueType().getType() + " to " + target.getType());
     }
   }
 
@@ -127,8 +112,4 @@ public class CastEval extends EvalNode {
     operand.postOrder(visitor);
     visitor.visit(this);
   }
-
-  static class CastContext implements EvalContext {
-    EvalContext childCtx;
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
index 6d7f67f..2cb530d 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
@@ -21,8 +21,10 @@ package org.apache.tajo.engine.eval;
 import com.google.common.base.Objects;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
+import org.apache.tajo.storage.Tuple;
 
 public class ConstEval extends EvalNode implements Comparable<ConstEval>, Cloneable {
 	@Expose Datum datum = null;
@@ -32,17 +34,6 @@ public class ConstEval extends EvalNode implements Comparable<ConstEval>, Clonea
 		this.datum = datum;
 	}
 
-  @Override
-  public EvalContext newContext() {
-    return null;
-  }
-
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    return this.datum;
-  }
-
-
   public Datum getValue() {
     return this.datum;
   }
@@ -52,6 +43,11 @@ public class ConstEval extends EvalNode implements Comparable<ConstEval>, Clonea
 	}
 
   @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    return datum;
+  }
+
+  @Override
 	public DataType getValueType() {
     return CatalogUtil.newSimpleDataType(datum.type());
 	}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalContext.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalContext.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalContext.java
deleted file mode 100644
index 00007ce..0000000
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalContext.java
+++ /dev/null
@@ -1,22 +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;
-
-public interface EvalContext {
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
index 2e797fb..5578043 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
@@ -40,8 +40,6 @@ public abstract class EvalNode implements Cloneable, GsonObject {
 		this.leftExpr = left;
 		this.rightExpr = right;
 	}
-
-  public abstract EvalContext newContext();
 	
 	public EvalType getType() {
 		return this.type;
@@ -86,9 +84,7 @@ public abstract class EvalNode implements Cloneable, GsonObject {
     return CoreGsonHelper.toJson(this, EvalNode.class);
 	}
 	
-	public void eval(EvalContext ctx, Schema schema, Tuple tuple) {}
-
-  public abstract <T extends Datum> T terminate(EvalContext ctx);
+	public abstract <T extends Datum> T eval(Schema schema, Tuple tuple);
 
   @Deprecated
 	public void preOrder(EvalNodeVisitor visitor) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/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 4044217..da05739 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
@@ -18,7 +18,6 @@
 
 package org.apache.tajo.engine.eval;
 
-import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import org.apache.tajo.catalog.Column;
@@ -277,10 +276,10 @@ public class EvalTreeUtil {
     }
   }
 
-  public static List<AggregationFunctionCallEval> findDistinctAggFunction(EvalNode expr) {
+  public static Set<AggregationFunctionCallEval> findDistinctAggFunction(EvalNode expr) {
     AllAggFunctionFinder finder = new AllAggFunctionFinder();
     expr.postOrder(finder);
-    return Lists.newArrayList(finder.getAggregationFunction());
+    return finder.getAggregationFunction();
   }
 
   public static class AllAggFunctionFinder implements EvalNodeVisitor {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
index dd29a3b..dc9b35b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
@@ -40,32 +40,14 @@ public class FieldEval extends EvalNode implements Cloneable {
 	}
 
 	@Override
-	public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
+	public Datum eval(Schema schema, Tuple tuple) {
 	  if (fieldId == -1) {
 	    fieldId = schema.getColumnId(column.getQualifiedName());
       if (fieldId == -1) {
         throw new IllegalStateException("No Such Column Reference: " + column + ", schema: " + schema);
       }
 	  }
-    FieldEvalContext fieldCtx = (FieldEvalContext) ctx;
-	  fieldCtx.datum = tuple.get(fieldId);
-	}
-
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    return ((FieldEvalContext)ctx).datum;
-  }
-
-  @Override
-  public EvalContext newContext() {
-    return new FieldEvalContext();
-  }
-
-  private static class FieldEvalContext implements EvalContext {
-    private Datum datum;
-
-    public FieldEvalContext() {
-    }
+	  return tuple.get(fieldId);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
index c4906d7..0555bde 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
@@ -64,12 +64,6 @@ public abstract class FunctionEval extends EvalNode implements Cloneable {
   public boolean isDistinct() {
     return funcDesc.getFuncType() == DISTINCT_AGGREGATION || funcDesc.getFuncType() == DISTINCT_UDA;
   }
-
-  @Override
-  public EvalContext newContext() {
-    FuncCallCtx newCtx = new FuncCallCtx(argEvals);
-    return newCtx;
-  }
 	
 	public EvalNode [] getArgs() {
 	  return this.argEvals;
@@ -84,9 +78,7 @@ public abstract class FunctionEval extends EvalNode implements Cloneable {
 	}
 
 	@Override
-	public abstract void eval(EvalContext ctx, Schema schema, Tuple tuple);
-
-  public abstract Datum terminate(EvalContext ctx);
+	public abstract Datum eval(Schema schema, Tuple tuple);
 
 	@Override
 	public String getName() {
@@ -149,14 +141,4 @@ public abstract class FunctionEval extends EvalNode implements Cloneable {
 	  }
 	  visitor.visit(this);
 	}
-
-  protected class FuncCallCtx implements EvalContext {
-    EvalContext [] argCtxs;
-    FuncCallCtx(EvalNode [] argEvals) {
-      argCtxs = new EvalContext[argEvals.length];
-      for (int i = 0; i < argEvals.length; i++) {
-        argCtxs[i] = argEvals[i].newContext();
-      }
-    }
-  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/GeneralFunctionEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/GeneralFunctionEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/GeneralFunctionEval.java
index aeb68aa..9446d70 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/GeneralFunctionEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/GeneralFunctionEval.java
@@ -22,17 +22,15 @@ import com.google.common.base.Objects;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.engine.function.GeneralFunction;
 import org.apache.tajo.datum.Datum;
+import org.apache.tajo.engine.function.GeneralFunction;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.VTuple;
 import org.apache.tajo.util.TUtil;
 
 public class GeneralFunctionEval extends FunctionEval {
   @Expose protected GeneralFunction instance;
-  private Tuple tuple;
   private Tuple params = null;
-  private Schema schema;
 
 	public GeneralFunctionEval(FunctionDesc desc, GeneralFunction instance, EvalNode[] givenArgs) {
 		super(EvalType.FUNCTION, desc, givenArgs);
@@ -44,27 +42,19 @@ public class GeneralFunctionEval extends FunctionEval {
     * @see nta.query.executor.eval.Expr#evalVal(Tuple)
     */
 	@Override
-	public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    this.schema = schema;
-    this.tuple = tuple;
-	}
-
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    FuncCallCtx localCtx = (FuncCallCtx) ctx;
+	public Datum eval(Schema schema, Tuple tuple) {
     if (this.params == null) {
       params = new VTuple(argEvals.length);
     }
-
     if(argEvals != null) {
       params.clear();
       for(int i=0;i < argEvals.length; i++) {
-        argEvals[i].eval(localCtx.argCtxs[i], schema, tuple);
-        params.put(i, argEvals[i].terminate(localCtx.argCtxs[i]));
+        params.put(i, argEvals[i].eval(schema, tuple));
       }
     }
+
     return instance.eval(params);
-  }
+	}
 	
 	@Override
 	public boolean equals(Object obj) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/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 e113326..189e9dd 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
@@ -25,7 +25,6 @@ import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
-import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.storage.Tuple;
 
 public class InEval extends BinaryEval {
@@ -45,11 +44,6 @@ public class InEval extends BinaryEval {
   }
 
   @Override
-  public EvalContext newContext() {
-    return new InEvalCtx();
-  }
-
-  @Override
   public TajoDataTypes.DataType getValueType() {
     return RES_TYPE;
   }
@@ -60,37 +54,27 @@ public class InEval extends BinaryEval {
   }
 
   @Override
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    InEvalCtx isNullCtx = (InEvalCtx) ctx;
+  public Datum eval(Schema schema, Tuple tuple) {
     if (fieldId == null) {
       fieldId = schema.getColumnId(((FieldEval)leftExpr).getColumnRef().getQualifiedName());
       values = ((RowConstantEval)rightExpr).getValues();
     }
 
-    boolean isIncluded = false;
-
     Datum value = tuple.get(fieldId);
 
     if (value.isNull()) {
-      isNullCtx.isNull = true;
-      return;
+      return value;
     }
 
+    boolean isIncluded = false;
     for (Datum datum : values) {
       if (value.equalsTo(datum).asBool()) {
         isIncluded = true;
         break;
       }
     }
-    isNullCtx.result = isIncluded;
-  }
 
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    if (((InEvalCtx)ctx).isNull) {
-      return NullDatum.get();
-    }
-    return DatumFactory.createBool(not ^ ((InEvalCtx)ctx).result);
+    return DatumFactory.createBool(not ^ isIncluded);
   }
 
   @Override
@@ -105,9 +89,4 @@ public class InEval extends BinaryEval {
   public String toString() {
     return leftExpr + " IN (" + rightExpr + ")";
   }
-
-  private class InEvalCtx implements EvalContext {
-    boolean isNull;
-    boolean result;
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/IsNullEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/IsNullEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/IsNullEval.java
index 8bb4d95..5704aa5 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/IsNullEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/IsNullEval.java
@@ -23,7 +23,6 @@ import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.TajoDataTypes.DataType;
-import org.apache.tajo.datum.BooleanDatum;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
 import org.apache.tajo.storage.Tuple;
@@ -42,13 +41,6 @@ public class IsNullEval extends BinaryEval {
   }
 
   @Override
-  public EvalContext newContext() {
-    IsNullEvalCtx context = new IsNullEvalCtx();
-    context.predicandContext = leftExpr.newContext();
-    return context;
-  }
-
-  @Override
   public DataType getValueType() {
     return RES_TYPE;
   }
@@ -64,16 +56,9 @@ public class IsNullEval extends BinaryEval {
   }
 
   @Override
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    IsNullEvalCtx isNullCtx = (IsNullEvalCtx) ctx;
-    leftExpr.eval(isNullCtx.predicandContext, schema, tuple);
-    Datum result = leftExpr.terminate(((IsNullEvalCtx)ctx).predicandContext);
-    ((IsNullEvalCtx) ctx).result = DatumFactory.createBool(isNot ^ (result.type() == TajoDataTypes.Type.NULL_TYPE));
-  }
-
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    return ((IsNullEvalCtx)ctx).result;
+  public Datum eval(Schema schema, Tuple tuple) {
+    boolean isNull = leftExpr.eval(schema, tuple).isNull();
+    return DatumFactory.createBool(isNot ^ isNull);
   }
 
   public boolean isNot() {
@@ -96,13 +81,4 @@ public class IsNullEval extends BinaryEval {
 
     return isNullEval;
   }
-
-  private class IsNullEvalCtx implements EvalContext {
-    EvalContext predicandContext;
-    BooleanDatum result;
-
-    IsNullEvalCtx() {
-      this.result = DatumFactory.createBool(false);
-    }
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/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 677708d..1a16af4 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
@@ -36,13 +36,6 @@ public class NotEval extends EvalNode implements Cloneable {
     this.childEval = childEval;
   }
 
-  @Override
-  public EvalContext newContext() {
-    NotEvalCtx newCtx = new NotEvalCtx();
-    newCtx.childExprCtx = childEval.newContext();
-    return newCtx;
-  }
-
   public EvalNode getChild() {
     return childEval;
   }
@@ -58,13 +51,8 @@ public class NotEval extends EvalNode implements Cloneable {
   }
 
   @Override
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    childEval.eval(((NotEvalCtx) ctx).childExprCtx, schema, tuple);
-  }
-
-  @Override
-  public Datum terminate(EvalContext ctx) {
-    Datum datum = childEval.terminate(((NotEvalCtx) ctx).childExprCtx);
+  public Datum eval(Schema schema, Tuple tuple) {
+    Datum datum = childEval.eval(schema, tuple);
     return !datum.isNull() ? DatumFactory.createBool(!datum.asBool()) : datum;
   }
 
@@ -101,8 +89,4 @@ public class NotEval extends EvalNode implements Cloneable {
     eval.childEval = (EvalNode) this.childEval.clone();
     return eval;
   }
-
-  private class NotEvalCtx implements EvalContext {
-    EvalContext childExprCtx;
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PartialBinaryExpr.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PartialBinaryExpr.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PartialBinaryExpr.java
index 73a68cd..0f4411d 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PartialBinaryExpr.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PartialBinaryExpr.java
@@ -34,11 +34,6 @@ public class PartialBinaryExpr extends EvalNode {
   }
 
   @Override
-  public EvalContext newContext() {
-    return null;
-  }
-
-  @Override
   public DataType getValueType() {
     return null;
   }
@@ -49,20 +44,13 @@ public class PartialBinaryExpr extends EvalNode {
   }
 
   @Override
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
+  public Datum eval(Schema schema, Tuple tuple) {
     throw new InvalidEvalException(
         "ERROR: the partial binary expression cannot be evluated: "
             + this.toString() );
   }
 
   @Override
-  public Datum terminate(EvalContext ctx) {
-    throw new InvalidEvalException(
-        "ERROR: the partial binary expression cannot be terminated: "
-            + this.toString() );
-  }
-
-  @Override
   public boolean equals(Object obj) {
     if (obj instanceof PartialBinaryExpr) {
       PartialBinaryExpr other = (PartialBinaryExpr) obj;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
index 568af0c..8d78b0b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
@@ -39,8 +39,6 @@ public abstract class PatternMatchPredicateEval extends BinaryEval {
   @Expose protected boolean caseInsensitive;
 
   // transient variables
-  private EvalContext leftContext;
-  private boolean isNullResult = false;
   protected Pattern compiled;
 
   public PatternMatchPredicateEval(EvalType evalType, boolean not, EvalNode predicand, ConstEval pattern,
@@ -68,29 +66,17 @@ public abstract class PatternMatchPredicateEval extends BinaryEval {
   }
 
   @Override
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    if (leftContext == null) {
-      leftContext = leftExpr.newContext();
+  public Datum eval(Schema schema, Tuple tuple) {
+    if (this.compiled == null) {
       compile(this.pattern);
     }
 
-    leftExpr.eval(leftContext, schema, tuple);
-    Datum predicand = leftExpr.terminate(leftContext);
-    isNullResult = predicand instanceof NullDatum;
-    boolean matched = compiled.matcher(predicand.asChars()).matches();
-    ((PatternMatchPredicateContext)ctx).result = matched ^ not;
-  }
-
-  public Datum terminate(EvalContext ctx) {
-    return !isNullResult ?
-        DatumFactory.createBool(((PatternMatchPredicateContext)ctx).result) : NullDatum.get();
-  }
-
-  public EvalContext newContext() {
-    return new PatternMatchPredicateContext();
-  }
+    Datum predicand = leftExpr.eval(schema, tuple);
+    if (predicand.isNull()) {
+      return NullDatum.get();
+    }
 
-  private class PatternMatchPredicateContext implements EvalContext {
-    public boolean result = false;
+    boolean matched = compiled.matcher(predicand.asChars()).matches();
+    return DatumFactory.createBool(matched ^ not);
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/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
index 1fc6a21..646a627 100644
--- 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
@@ -20,7 +20,10 @@ package org.apache.tajo.engine.eval;
 
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.util.TUtil;
 
 import static org.apache.tajo.common.TajoDataTypes.DataType;
@@ -34,11 +37,6 @@ public class RowConstantEval extends EvalNode {
   }
 
   @Override
-  public EvalContext newContext() {
-    return null;
-  }
-
-  @Override
   public DataType getValueType() {
     return CatalogUtil.newSimpleDataType(values[0].type());
   }
@@ -49,8 +47,12 @@ public class RowConstantEval extends EvalNode {
   }
 
   @Override
-  public Datum terminate(EvalContext ctx) {
-    return null;
+  public Datum eval(Schema schema, Tuple tuple) {
+    return NullDatum.get();
+  }
+
+  public Datum [] getValues() {
+    return values;
   }
 
   @Override
@@ -67,10 +69,6 @@ public class RowConstantEval extends EvalNode {
     return TUtil.arrayToString(values);
   }
 
-  public Datum [] getValues() {
-    return values;
-  }
-
   public void preOrder(EvalNodeVisitor visitor) {
     visitor.visit(this);
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/SignedEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/SignedEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/SignedEval.java
index b0ba813..e0f50c1 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/SignedEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/SignedEval.java
@@ -21,6 +21,7 @@ package org.apache.tajo.engine.eval;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.NumericDatum;
 import org.apache.tajo.storage.Tuple;
 
@@ -34,13 +35,6 @@ public class SignedEval extends EvalNode implements Cloneable {
     this.childEval = childEval;
   }
 
-  @Override
-  public EvalContext newContext() {
-    SignedEvalCtx newCtx = new SignedEvalCtx();
-    newCtx.childExprCtx = childEval.newContext();
-    return newCtx;
-  }
-
   public boolean isNegative() {
     return negative;
   }
@@ -60,13 +54,8 @@ public class SignedEval extends EvalNode implements Cloneable {
   }
 
   @Override
-  public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
-    childEval.eval(((SignedEvalCtx) ctx).childExprCtx, schema, tuple);
-  }
-
-  @Override
-  public NumericDatum terminate(EvalContext ctx) {
-    NumericDatum result = childEval.terminate(((SignedEvalCtx) ctx).childExprCtx);
+  public Datum eval(Schema schema, Tuple tuple) {
+    NumericDatum result = childEval.eval(schema, tuple);
     if (negative) {
       result.inverseSign();
     }
@@ -107,8 +96,4 @@ public class SignedEval extends EvalNode implements Cloneable {
     eval.childEval = (EvalNode) this.childEval.clone();
     return eval;
   }
-
-  private class SignedEvalCtx implements EvalContext {
-    EvalContext childExprCtx;
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprsVerifier.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprsVerifier.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprsVerifier.java
index a665730..c473ac1 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprsVerifier.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprsVerifier.java
@@ -46,6 +46,10 @@ public class ExprsVerifier extends BasicEvalNodeVisitor<VerificationState, EvalN
       return true;
     }
 
+    if (checkDateTime(dataType1) && checkDateTime(dataType2)) {
+      return true;
+    }
+
     return false;
   }
 
@@ -109,8 +113,7 @@ public class ExprsVerifier extends BasicEvalNodeVisitor<VerificationState, EvalN
   private static void checkArithmeticOperand(VerificationState state, BinaryEval evalNode) {
     EvalNode leftExpr = evalNode.getLeftExpr();
     EvalNode rightExpr = evalNode.getRightExpr();
-    if (!(checkNumericType(leftExpr.getValueType())
-        && checkNumericType(rightExpr.getValueType()))) {
+    if (!(checkNumericType(leftExpr.getValueType()) && checkNumericType(rightExpr.getValueType()))) {
       state.addVerification("No operator matches the given name and argument type(s): " + evalNode.toString());
     }
   }
@@ -125,6 +128,12 @@ public class ExprsVerifier extends BasicEvalNodeVisitor<VerificationState, EvalN
     return Type.CHAR.getNumber() < typeNumber && typeNumber <= Type.TEXT.getNumber();
   }
 
+  private static boolean checkDateTime(DataType dataType) {
+    int typeNumber = dataType.getType().getNumber();
+    return (Type.DATE.getNumber() < typeNumber && typeNumber <= Type.INTERVAL.getNumber()) ||
+        (Type.TIMEZ.getNumber() < typeNumber && typeNumber <= Type.TIMESTAMPZ.getNumber());
+  }
+
   @Override
   public EvalNode visitPlus(VerificationState state, BinaryEval evalNode, Stack<EvalNode> stack) {
     super.visitDivide(state, evalNode, stack);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/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 ac76f57..9c58b7d 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
@@ -64,13 +64,6 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   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()) {
-        ExprsVerifier.verify(state, target.getEvalTree());
-      }
-    }
-
     return node;
   }
 
@@ -172,10 +165,6 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
                                  InsertNode node, Stack<LogicalNode> stack) throws PlanningException {
     LogicalNode child = visit(state, plan, block, node.getChild(), stack);
 
-//    if (node.hasTargetSchema()) {
-//      ensureDomains(state, node.getTargetSchema(), node.getChild().getOutSchema());
-//    }
-
     return child;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/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 8995226..066a3bb 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
@@ -19,7 +19,6 @@
 package org.apache.tajo.engine.planner;
 
 import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
@@ -36,16 +35,15 @@ import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.engine.eval.*;
-import org.apache.tajo.engine.exception.InvalidQueryException;
 import org.apache.tajo.engine.exception.VerifyException;
 import org.apache.tajo.engine.planner.LogicalPlan.QueryBlock;
 import org.apache.tajo.engine.planner.logical.*;
+import org.apache.tajo.engine.planner.rewrite.ProjectionPushDownRule;
 import org.apache.tajo.engine.utils.SchemaUtil;
 import org.apache.tajo.util.TUtil;
 
 import java.util.*;
 
-import static org.apache.tajo.algebra.Aggregation.GroupType;
 import static org.apache.tajo.algebra.CreateTable.ColumnPartition;
 import static org.apache.tajo.algebra.CreateTable.PartitionType;
 import static org.apache.tajo.engine.planner.ExprNormalizer.ExprNormalizedResult;
@@ -225,6 +223,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     // It sets raw targets, all of them are raw expressions instead of references.
     setRawTargets(context, targets, referenceNames, projection);
 
+    verifyProjectedFields(block, projectionNode);
     return projectionNode;
   }
 
@@ -333,6 +332,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
   private Target [] buildTargets(LogicalPlan plan, QueryBlock block, String[] referenceNames)
       throws PlanningException {
     Target [] targets = new Target[referenceNames.length];
+
     for (int i = 0; i < referenceNames.length; i++) {
       if (block.namedExprsMgr.isResolved(referenceNames[i])) {
         targets[i] = block.namedExprsMgr.getTarget(referenceNames[i]);
@@ -346,6 +346,44 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     return targets;
   }
 
+  private static void verifyProjectedFields(QueryBlock block, Projectable projectable) throws PlanningException {
+    if (projectable instanceof ProjectionNode && block.hasNode(NodeType.GROUP_BY)) {
+      for (Target target : projectable.getTargets()) {
+        Set<Column> columns = EvalTreeUtil.findDistinctRefColumns(target.getEvalTree());
+        for (Column c : columns) {
+          if (!projectable.getInSchema().contains(c)) {
+            throw new PlanningException(c.getQualifiedName()
+                + " must appear in the GROUP BY clause or be used in an aggregate function");
+          }
+        }
+      }
+    } else  if (projectable instanceof GroupbyNode) {
+      GroupbyNode groupbyNode = (GroupbyNode) projectable;
+      for (Column c : groupbyNode.getGroupingColumns()) {
+        if (!projectable.getInSchema().contains(c)) {
+          throw new PlanningException("Cannot get such a field: " + c);
+        }
+      }
+      for (AggregationFunctionCallEval f : groupbyNode.getAggFunctions()) {
+        Set<Column> columns = EvalTreeUtil.findDistinctRefColumns(f);
+        for (Column c : columns) {
+          if (!projectable.getInSchema().contains(c)) {
+            throw new PlanningException("Cannot get such a field: " + c);
+          }
+        }
+      }
+    } else {
+      for (Target target : projectable.getTargets()) {
+        Set<Column> columns = EvalTreeUtil.findDistinctRefColumns(target.getEvalTree());
+        for (Column c : columns) {
+          if (!projectable.getInSchema().contains(c)) {
+            throw new PlanningException("Cannot get such a field: " + c);
+          }
+        }
+      }
+    }
+  }
+
   /**
    * Insert a group-by operator before a sort or a projection operator.
    * It is used only when a group-by clause is not given.
@@ -358,22 +396,26 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     GroupbyNode groupbyNode = new GroupbyNode(plan.newPID());
     groupbyNode.setGroupingColumns(new Column[] {});
 
-    Set<Target> evaluatedTargets = new LinkedHashSet<Target>();
+    Set<String> aggEvalNames = new LinkedHashSet<String>();
+    Set<AggregationFunctionCallEval> aggEvals = new LinkedHashSet<AggregationFunctionCallEval>();
     boolean includeDistinctFunction = false;
     for (Iterator<NamedExpr> it = block.namedExprsMgr.getUnresolvedExprs(); it.hasNext();) {
       NamedExpr rawTarget = it.next();
       try {
         includeDistinctFunction = PlannerUtil.existsDistinctAggregationFunction(rawTarget.getExpr());
         EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, context.queryBlock, rawTarget.getExpr());
-        if (EvalTreeUtil.findDistinctAggFunction(evalNode).size() > 0) {
+        if (evalNode.getType() == EvalType.AGG_FUNCTION) {
+          aggEvalNames.add(rawTarget.getAlias());
+          aggEvals.add((AggregationFunctionCallEval) evalNode);
           block.namedExprsMgr.resolveExpr(rawTarget.getAlias(), evalNode);
-          evaluatedTargets.add(new Target(evalNode, rawTarget.getAlias()));
         }
       } catch (VerifyException ve) {
       }
     }
     groupbyNode.setDistinct(includeDistinctFunction);
-    groupbyNode.setTargets(evaluatedTargets.toArray(new Target[evaluatedTargets.size()]));
+    groupbyNode.setAggFunctions(aggEvals.toArray(new AggregationFunctionCallEval[aggEvals.size()]));
+    Target [] targets = ProjectionPushDownRule.buildGroupByTarget(groupbyNode, aggEvalNames.toArray(new String[aggEvalNames.size()]));
+    groupbyNode.setTargets(targets);
     groupbyNode.setChild(child);
     groupbyNode.setInSchema(child.getOutSchema());
 
@@ -429,7 +471,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     limitNode.setInSchema(child.getOutSchema());
     limitNode.setOutSchema(child.getOutSchema());
 
-    limitNode.setFetchFirst(firstFetNum.terminate(null).asInt8());
+    limitNode.setFetchFirst(firstFetNum.eval(null, null).asInt8());
 
     return limitNode;
   }
@@ -558,53 +600,64 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     groupingNode.setChild(child);
     groupingNode.setInSchema(child.getOutSchema());
 
+    // Set grouping sets
+    Column [] groupingColumns = new Column[aggregation.getGroupSet()[0].getGroupingSets().length];
+    for (int i = 0; i < groupingColumns.length; i++) {
+      if (block.namedExprsMgr.isResolved(groupingKeyRefNames[i])) {
+        groupingColumns[i] = block.namedExprsMgr.getTarget(groupingKeyRefNames[i]).getNamedColumn();
+      } else {
+        throw new PlanningException("Each grouping column expression must be a scalar expression.");
+      }
+    }
+    groupingNode.setGroupingColumns(groupingColumns);
+
+    ////////////////////////////////////////////////////////
+    // Visit and Build Child Plan
+    ////////////////////////////////////////////////////////
 
     // create EvalNodes and check if each EvalNode can be evaluated here.
-    Set<Target> evaluatedTargets = new LinkedHashSet<Target>();
+    List<String> aggEvalNames = TUtil.newList();
+    List<AggregationFunctionCallEval> aggEvalNodes = TUtil.newList();
     boolean includeDistinctFunction = false;
-    for (NamedExpr rawTarget : block.namedExprsMgr.getAllNamedExprs()) {
+    for (Iterator<NamedExpr> iterator = block.namedExprsMgr.getUnresolvedExprs(); iterator.hasNext();) {
+      NamedExpr namedExpr = iterator.next();
       try {
-        includeDistinctFunction = PlannerUtil.existsDistinctAggregationFunction(rawTarget.getExpr());
-        EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, context.queryBlock, rawTarget.getExpr());
-        if (EvalTreeUtil.findDistinctAggFunction(evalNode).size() > 0) {
-          block.namedExprsMgr.resolveExpr(rawTarget.getAlias(), evalNode);
-          evaluatedTargets.add(new Target(evalNode, rawTarget.getAlias()));
+        includeDistinctFunction |= PlannerUtil.existsDistinctAggregationFunction(namedExpr.getExpr());
+        EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, context.queryBlock, namedExpr.getExpr());
+        if (evalNode.getType() == EvalType.AGG_FUNCTION) {
+          block.namedExprsMgr.resolveExpr(namedExpr.getAlias(), evalNode);
+          aggEvalNames.add(namedExpr.getAlias());
+          aggEvalNodes.add((AggregationFunctionCallEval) evalNode);
         }
       } catch (VerifyException ve) {
       }
     }
-    // If there is at least one distinct aggregation function
+    // if there is at least one distinct aggregation function
     groupingNode.setDistinct(includeDistinctFunction);
+    groupingNode.setAggFunctions(aggEvalNodes.toArray(new AggregationFunctionCallEval[aggEvalNodes.size()]));
 
+    Target [] targets = new Target[groupingKeyNum + aggEvalNames.size()];
 
-    // Set grouping sets
-    List<Target> targets = new ArrayList<Target>();
-    Aggregation.GroupElement [] groupElements = aggregation.getGroupSet();
-
-    // Currently, single ordinary grouping set is only available.
-    if (groupElements[0].getType() == GroupType.OrdinaryGroup) {
-      Column [] groupingColumns = new Column[aggregation.getGroupSet()[0].getGroupingSets().length];
-      for (int i = 0; i < groupingColumns.length; i++) {
-        if (block.namedExprsMgr.isResolved(groupingKeyRefNames[i])) {
-          groupingColumns[i] = block.namedExprsMgr.getTarget(groupingKeyRefNames[i]).getNamedColumn();
-        } else {
-          throw new PlanningException("Each grouping column expression must be a scalar expression.");
-        }
-      }
+    // In target, grouping columns will be followed by aggregation evals.
+    //
+    // col1, col2, col3,   sum(..),  agv(..)
+    // ^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^
+    //  grouping keys      aggregation evals
 
-      for (Column column : groupingColumns) {
-        if (child.getOutSchema().contains(column)) {
-          targets.add(new Target(new FieldEval(child.getOutSchema().getColumn(column))));
-        }
-      }
-      groupingNode.setGroupingColumns(groupingColumns);
-    } else {
-      throw new InvalidQueryException("Not support grouping");
+    // Build grouping keys
+    for (int i = 0; i < groupingKeyNum; i++) {
+      Target target = new Target(new FieldEval(groupingNode.getGroupingColumns()[i]));
+      targets[i] = target;
     }
 
-    targets.addAll(evaluatedTargets);
-    groupingNode.setTargets(targets.toArray(new Target[targets.size()]));
+    for (int i = 0, targetIdx = groupingKeyNum; i < aggEvalNodes.size(); i++, targetIdx++) {
+      targets[targetIdx] = block.namedExprsMgr.getTarget(aggEvalNames.get(i));
+    }
+
+    groupingNode.setTargets(targets);
     block.unsetAggregationRequire();
+
+    verifyProjectedFields(block, groupingNode);
     return groupingNode;
   }
 
@@ -892,6 +945,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
 
     scanNode.setTargets(targets.toArray(new Target[targets.size()]));
 
+    verifyProjectedFields(block, scanNode);
     return scanNode;
   }
 
@@ -1487,25 +1541,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
   ===============================================================================================*/
 
   public static boolean checkIfBeEvaluatedAtGroupBy(EvalNode evalNode, GroupbyNode groupbyNode) {
-    Set<Column> columnRefs = EvalTreeUtil.findDistinctRefColumns(evalNode);
-
-    if (!groupbyNode.getInSchema().containsAll(columnRefs)) {
-      return false;
-    }
-
-    Set<String> tableIds = Sets.newHashSet();
-    // getting distinct table references
-    for (Column col : columnRefs) {
-      if (!tableIds.contains(col.getQualifier())) {
-        tableIds.add(col.getQualifier());
-      }
-    }
-
-    if (tableIds.size() > 1) {
-      return false;
-    }
-
-    return true;
+    return checkIfBeEvaluateAtThis(evalNode, groupbyNode) && evalNode.getType() == EvalType.AGG_FUNCTION;
   }
 
   public static boolean checkIfBeEvaluatedAtJoin(QueryBlock block, EvalNode evalNode, JoinNode joinNode,
@@ -1524,11 +1560,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     // at the topmost join operator.
     // TODO - It's also valid that case-when is evalauted at the topmost outer operator.
     //        But, how can we know there is no further outer join operator after this node?
-    if (checkCaseWhenWithOuterJoin(block, evalNode, isTopMostJoin)) {
-      return true;
-    } else {
-      return false;
-    }
+    return checkCaseWhenWithOuterJoin(block, evalNode, isTopMostJoin);
   }
 
   private static boolean checkCaseWhenWithOuterJoin(QueryBlock block, EvalNode evalNode, boolean isTopMostJoin) {
@@ -1564,9 +1596,6 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
 
   public static boolean checkIfBeEvaluateAtThis(EvalNode evalNode, LogicalNode node) {
     Set<Column> columnRefs = EvalTreeUtil.findDistinctRefColumns(evalNode);
-    if (!node.getInSchema().containsAll(columnRefs)) {
-      return false;
-    }
-    return true;
+    return node.getInSchema().containsAll(columnRefs);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/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 ae5f4fc..663954e 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
@@ -20,9 +20,11 @@ package org.apache.tajo.engine.planner;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
-import com.google.common.collect.ObjectArrays;
 import com.google.common.collect.Sets;
-import org.apache.tajo.algebra.*;
+import org.apache.tajo.algebra.CountRowsFunctionExpr;
+import org.apache.tajo.algebra.Expr;
+import org.apache.tajo.algebra.GeneralSetFunctionExpr;
+import org.apache.tajo.algebra.JoinType;
 import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
@@ -30,8 +32,8 @@ import org.apache.tajo.catalog.SortSpec;
 import org.apache.tajo.catalog.partition.PartitionDesc;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.engine.eval.*;
-import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.engine.exception.InvalidQueryException;
+import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.storage.TupleComparator;
 import org.apache.tajo.util.TUtil;
 
@@ -209,94 +211,6 @@ public class PlannerUtil {
     parentNode.setChild(newNode);
   }
 
-  public static GroupbyNode transformGroupbyTo2P(GroupbyNode groupBy) {
-    Preconditions.checkNotNull(groupBy);
-
-    GroupbyNode child = null;
-
-    // cloning groupby node
-    try {
-      child = (GroupbyNode) groupBy.clone();
-    } catch (CloneNotSupportedException e) {
-      e.printStackTrace();
-    }
-
-    List<Target> firstStepTargets = Lists.newArrayList();
-    Target[] secondTargets = groupBy.getTargets();
-    Target[] firstTargets = child.getTargets();
-
-    Target second;
-    Target first;
-    int targetId =  0;
-    for (int i = 0; i < firstTargets.length; i++) {
-      second = secondTargets[i];
-      first = firstTargets[i];
-
-      List<AggregationFunctionCallEval> secondStepFunctions = EvalTreeUtil.findDistinctAggFunction(second.getEvalTree());
-      List<AggregationFunctionCallEval> firstStepFunctions = EvalTreeUtil.findDistinctAggFunction(first.getEvalTree());
-
-      if (firstStepFunctions.size() == 0) {
-        firstStepTargets.add(first);
-        targetId++;
-      } else {
-        for (AggregationFunctionCallEval func : firstStepFunctions) {
-          Target newTarget;
-
-          if (func.isDistinct()) {
-            List<Column> fields = EvalTreeUtil.findAllColumnRefs(func);
-            newTarget = new Target(new FieldEval(fields.get(0)));
-            String targetName = "column_" + (targetId++);
-            newTarget.setAlias(targetName);
-
-            AggregationFunctionCallEval secondFunc = null;
-            for (AggregationFunctionCallEval sf : secondStepFunctions) {
-              if (func.equals(sf)) {
-                secondFunc = sf;
-                break;
-              }
-            }
-
-            secondFunc.setArgs(new EvalNode [] {new FieldEval(
-                new Column(targetName, newTarget.getEvalTree().getValueType()))});
-          } else {
-            func.setFirstPhase();
-            String targetName = "column_" + (targetId++);
-            newTarget = new Target(func, targetName);
-            AggregationFunctionCallEval secondFunc = null;
-            for (AggregationFunctionCallEval sf : secondStepFunctions) {
-              if (func.equals(sf)) {
-                secondFunc = sf;
-                break;
-              }
-            }
-            secondFunc.setArgs(new EvalNode [] {new FieldEval(
-                new Column(targetName, newTarget.getEvalTree().getValueType()))});
-          }
-          firstStepTargets.add(newTarget);
-        }
-      }
-
-      // Getting new target list and updating input/output schema from the new target list.
-      Target[] targetArray = firstStepTargets.toArray(new Target[firstStepTargets.size()]);
-      Schema targetSchema = PlannerUtil.targetToSchema(targetArray);
-      List<Target> newTarget = Lists.newArrayList();
-      for (Column column : groupBy.getGroupingColumns()) {
-        if (!targetSchema.containsByQualifiedName(column.getQualifiedName())) {
-          newTarget.add(new Target(new FieldEval(column)));
-        }
-      }
-      targetArray = ObjectArrays.concat(targetArray, newTarget.toArray(new Target[newTarget.size()]), Target.class);
-
-      child.setTargets(targetArray);
-      // set the groupby chaining
-      groupBy.setChild(child);
-      groupBy.setInSchema(child.getOutSchema());
-
-    }
-    return child;
-  }
-
-  
   /**
    * Find the top logical node matched to type from the given node
    * 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
index 77e2a0b..1843b5a 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
@@ -18,17 +18,68 @@
 
 package org.apache.tajo.engine.planner;
 
-import org.apache.tajo.algebra.Expr;
-import org.apache.tajo.algebra.Insert;
-import org.apache.tajo.algebra.OpType;
-import org.apache.tajo.algebra.Projection;
+import org.apache.tajo.algebra.*;
+import org.apache.tajo.catalog.CatalogService;
 
 import java.util.Stack;
 
 public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <VerificationState, Expr> {
+  private CatalogService catalog;
 
-  public Expr visitInsert(VerificationState ctx, Stack<Expr> stack, Insert expr) throws PlanningException {
-    Expr child = super.visitInsert(ctx, stack, expr);
+  public PreLogicalPlanVerifier(CatalogService catalog) {
+    this.catalog = catalog;
+  }
+
+  @Override
+  public Expr visitGroupBy(VerificationState ctx, Stack<Expr> stack, Aggregation expr) throws PlanningException {
+    Expr child = super.visitGroupBy(ctx, stack, expr);
+
+    // Enforcer only ordinary grouping set.
+    for (Aggregation.GroupElement groupingElement : expr.getGroupSet()) {
+      if (groupingElement.getType() != Aggregation.GroupType.OrdinaryGroup) {
+        ctx.addVerification(groupingElement.getType() + " is not supported yet");
+      }
+    }
+
+    Projection projection = null;
+    for (Expr parent : stack) {
+      if (parent.getType() == OpType.Projection) {
+        projection = (Projection) parent;
+        break;
+      }
+    }
+
+    if (projection == null) {
+      throw new PlanningException("No Projection");
+    }
+
+    return expr;
+  }
+
+  @Override
+  public Expr visitRelation(VerificationState state, Stack<Expr> stack, Relation expr) throws PlanningException {
+    checkRelationExistence(state, expr.getName());
+    return expr;
+  }
+
+  private boolean checkRelationExistence(VerificationState state, String name) {
+    if (!catalog.existsTable(name)) {
+      state.addVerification(String.format("relation \"%s\" does not exist", name));
+      return false;
+    }
+    return true;
+  }
+
+  ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+  // Insert or Update Section
+  ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Expr visitInsert(VerificationState context, Stack<Expr> stack, Insert expr) throws PlanningException {
+    Expr child = super.visitInsert(context, stack, expr);
+
+    if (expr.hasTableName()) {
+      checkRelationExistence(context, expr.getTableName());
+    }
 
     if (child != null && child.getType() == OpType.Projection) {
       if (expr.hasTargetColumns()) {
@@ -37,13 +88,13 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <VerificationStat
         int targetColumnNum = expr.getTargetColumns().length;
 
         if (targetColumnNum > projectColumnNum)  {
-          ctx.addVerification("INSERT has more target columns than expressions");
+          context.addVerification("INSERT has more target columns than expressions");
         } else if (targetColumnNum < projectColumnNum) {
-          ctx.addVerification("INSERT has more expressions than target columns");
+          context.addVerification("INSERT has more expressions than target columns");
         }
       }
     }
 
-    return child;
+    return expr;
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/e23e78cc/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Projector.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Projector.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Projector.java
index 8d6db22..161d39b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Projector.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/Projector.java
@@ -19,7 +19,6 @@
 package org.apache.tajo.engine.planner;
 
 import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.engine.eval.EvalContext;
 import org.apache.tajo.engine.eval.EvalNode;
 import org.apache.tajo.storage.Tuple;
 
@@ -42,26 +41,11 @@ public class Projector {
     }
   }
 
-  public void eval(EvalContext[] evalContexts, Tuple in) {
+  public void eval(Tuple in, Tuple out) {
     if (targetNum > 0) {
       for (int i = 0; i < evals.length; i++) {
-        evals[i].eval(evalContexts[i], inSchema, in);
+        out.put(i, evals[i].eval(inSchema, in));
       }
     }
   }
-
-  public void terminate(EvalContext [] evalContexts, Tuple out) {
-    for (int i = 0; i < targetNum; i++) {
-      out.put(i, evals[i].terminate(evalContexts[i]));
-    }
-  }
-
-  public EvalContext [] newContexts() {
-    EvalContext [] evalContexts = new EvalContext[targetNum];
-    for (int i = 0; i < targetNum; i++) {
-      evalContexts[i] = evals[i].newContext();
-    }
-
-    return evalContexts;
-  }
 }


Mime
View raw message