tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hyun...@apache.org
Subject git commit: TAJO-236: Implement LogicalPlanVerifier to check if a logical plan is valid. (hyunsik)
Date Thu, 17 Oct 2013 02:13:06 GMT
Updated Branches:
  refs/heads/master 1325c42e5 -> 0cf9d4e20


TAJO-236: Implement LogicalPlanVerifier to check if a logical plan is valid. (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/0cf9d4e2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/0cf9d4e2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/0cf9d4e2

Branch: refs/heads/master
Commit: 0cf9d4e2024fe513fce8dac14f0e9eff2135482e
Parents: 1325c42
Author: Hyunsik Choi <hyunsik@apache.org>
Authored: Thu Oct 17 11:12:42 2013 +0900
Committer: Hyunsik Choi <hyunsik@apache.org>
Committed: Thu Oct 17 11:12:42 2013 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |   3 +
 .../org/apache/tajo/catalog/CatalogServer.java  |   6 +-
 .../tajo/engine/eval/BasicEvalNodeVisitor.java  | 123 +++++-----
 .../org/apache/tajo/engine/eval/BinaryEval.java |   9 +-
 .../org/apache/tajo/engine/eval/EvalNode.java   |   8 +-
 .../tajo/engine/eval/EvalNodeVisitor2.java      |  52 ++---
 .../apache/tajo/engine/eval/EvalTreeUtil.java   |   7 +-
 .../engine/planner/BasicLogicalPlanVisitor.java |  16 ++
 .../tajo/engine/planner/ExprsVerifier.java      | 164 ++++++++++++++
 .../engine/planner/LogicalPlanVerifier.java     | 225 +++++++++++++++++++
 .../tajo/engine/planner/LogicalPlanVisitor.java |   4 +
 .../tajo/engine/planner/LogicalPlanner.java     |  23 --
 .../tajo/engine/planner/VerificationState.java  |  39 ++++
 .../org/apache/tajo/master/GlobalEngine.java    |  27 ++-
 .../tajo/master/TajoMasterClientService.java    |   2 +-
 .../java/org/apache/tajo/worker/TajoWorker.java |   2 -
 .../java/org/apache/tajo/worker/TaskRunner.java |   5 +-
 .../org/apache/tajo/client/TestTajoClient.java  |  10 -
 18 files changed, 580 insertions(+), 145 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 8c7fb83..d42329b 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -52,6 +52,9 @@ Release 0.2.0 - unreleased
 
   IMPROVEMENTS
 
+    TAJO-236: Implement LogicalPlanVerifier to check if a logical plan is 
+    valid. (hyunsik)
+
     TAJO-254: Refactor package names and class names to have proper names.
     (add a missed changelog)
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
index 62096b1..70cdd28 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
+++ b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/CatalogServer.java
@@ -229,10 +229,8 @@ public class CatalogServer extends AbstractService {
     @Override
     public BoolProto addTable(RpcController controller, TableDescProto tableDesc)
         throws ServiceException {
-      Preconditions.checkArgument(tableDesc.hasId(),
-          "Must be set to the table name");
-      Preconditions.checkArgument(tableDesc.hasPath(),
-          "Must be set to the table URI");
+      Preconditions.checkArgument(tableDesc.hasId(), "Must be set to the table name");
+      Preconditions.checkArgument(tableDesc.hasPath(), "Must be set to the table URI");
 
       wlock.lock();
       try {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
index 9755716..0ee128a 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
@@ -21,16 +21,17 @@ package org.apache.tajo.engine.eval;
 import java.util.Stack;
 
 public class BasicEvalNodeVisitor<CONTEXT, RESULT> implements EvalNodeVisitor2<CONTEXT, RESULT> {
+
   @Override
-  public RESULT visitChild(CONTEXT context, Stack<EvalNode> stack, EvalNode evalNode) {
+  public RESULT visitChild(CONTEXT context, EvalNode evalNode, Stack<EvalNode> stack) {
     RESULT result;
     switch (evalNode.getType()) {
       // Column and Value reference expressions
       case CONST:
-        result = visitConst(context, stack, (ConstEval) evalNode);
+        result = visitConst(context, (ConstEval) evalNode, stack);
         break;
       case ROW_CONSTANT:
-        result = visitRowConstant(context, stack, (RowConstantEval) evalNode);
+        result = visitRowConstant(context, (RowConstantEval) evalNode, stack);
         break;
       case FIELD:
         result = visitField(context, stack, (FieldEval) evalNode);
@@ -38,83 +39,83 @@ public class BasicEvalNodeVisitor<CONTEXT, RESULT> implements EvalNodeVisitor2<C
 
       // Arithmetic expression
       case PLUS:
-        result = visitPlus(context, stack, (BinaryEval) evalNode);
+        result = visitPlus(context, (BinaryEval) evalNode, stack);
         break;
       case MINUS:
-        result = visitMinus(context, stack, (BinaryEval) evalNode);
+        result = visitMinus(context, (BinaryEval) evalNode, stack);
         break;
       case MULTIPLY:
-        result = visitMultiply(context, stack, (BinaryEval) evalNode);
+        result = visitMultiply(context, (BinaryEval) evalNode, stack);
         break;
       case DIVIDE:
-        result = visitDivide(context, stack, (BinaryEval) evalNode);
+        result = visitDivide(context, (BinaryEval) evalNode, stack);
         break;
       case MODULAR:
-        result = visitModular(context, stack, (BinaryEval) evalNode);
+        result = visitModular(context, (BinaryEval) evalNode, stack);
         break;
 
       // Logical Predicates
       case AND:
-        result = visitAnd(context, stack, (BinaryEval) evalNode);
+        result = visitAnd(context, (BinaryEval) evalNode, stack);
         break;
       case OR:
-        result = visitOr(context, stack, (BinaryEval) evalNode);
+        result = visitOr(context, (BinaryEval) evalNode, stack);
         break;
       case NOT:
-        result = visitNot(context, stack, (NotEval) evalNode);
+        result = visitNot(context, (NotEval) evalNode, stack);
         break;
 
       // Comparison Predicates
       case EQUAL:
-        result = visitEqual(context, stack, (BinaryEval) evalNode);
+        result = visitEqual(context, (BinaryEval) evalNode, stack);
         break;
       case NOT_EQUAL:
-        result = visitNotEqual(context, stack, (BinaryEval) evalNode);
+        result = visitNotEqual(context, (BinaryEval) evalNode, stack);
         break;
       case LTH:
-        result = visitLessThan(context, stack, (BinaryEval) evalNode);
+        result = visitLessThan(context, (BinaryEval) evalNode, stack);
         break;
       case LEQ:
-        result = visitLessThanOrEqual(context, stack, (BinaryEval) evalNode);
+        result = visitLessThanOrEqual(context, (BinaryEval) evalNode, stack);
         break;
       case GTH:
-        result = visitGreaterThan(context, stack, (BinaryEval) evalNode);
+        result = visitGreaterThan(context, (BinaryEval) evalNode, stack);
         break;
       case GEQ:
-        result = visitGreaterThanOrEqual(context, stack, (BinaryEval) evalNode);
+        result = visitGreaterThanOrEqual(context, (BinaryEval) evalNode, stack);
         break;
 
       // SQL standard predicates
       case IS_NULL:
-        result = visitIsNull(context, stack, (IsNullEval) evalNode);
+        result = visitIsNull(context, (IsNullEval) evalNode, stack);
         break;
       case CASE:
-        result = visitCaseWhen(context, stack, (CaseWhenEval) evalNode);
+        result = visitCaseWhen(context, (CaseWhenEval) evalNode, stack);
         break;
       case IF_THEN:
-        result = visitIfThen(context, stack, (CaseWhenEval.IfThenEval) evalNode);
+        result = visitIfThen(context, (CaseWhenEval.IfThenEval) evalNode, stack);
         break;
       case IN:
-        result = visitInPredicate(context, stack, (InEval) evalNode);
+        result = visitInPredicate(context, (InEval) evalNode, stack);
         break;
 
       // Pattern match predicates
       case LIKE:
-        result = visitLike(context, stack, (LikePredicateEval) evalNode);
+        result = visitLike(context, (LikePredicateEval) evalNode, stack);
         break;
       case SIMILAR_TO:
-        result = visitSimilarTo(context, stack, (SimilarToPredicateEval) evalNode);
+        result = visitSimilarTo(context, (SimilarToPredicateEval) evalNode, stack);
         break;
       case REGEX:
-        result = visitRegex(context, stack, (RegexPredicateEval) evalNode);
+        result = visitRegex(context, (RegexPredicateEval) evalNode, stack);
         break;
 
       // Functions
       case FUNCTION:
-        result = visitFuncCall(context, stack, (GeneralFunctionEval) evalNode);
+        result = visitFuncCall(context, (GeneralFunctionEval) evalNode, stack);
         break;
       case AGG_FUNCTION:
-        result = visitAggrFuncCall(context, stack, (AggregationFunctionCallEval) evalNode);
+        result = visitAggrFuncCall(context, (AggregationFunctionCallEval) evalNode, stack);
         break;
 
       default:
@@ -126,8 +127,8 @@ public class BasicEvalNodeVisitor<CONTEXT, RESULT> implements EvalNodeVisitor2<C
 
   private RESULT visitDefaultBinaryEval(CONTEXT context, Stack<EvalNode> stack, BinaryEval binaryEval) {
     stack.push(binaryEval);
-    RESULT result = visitChild(context, stack, binaryEval.getLeftExpr());
-    visitChild(context, stack, binaryEval.getRightExpr());
+    RESULT result = visitChild(context, binaryEval.getLeftExpr(), stack);
+    visitChild(context, binaryEval.getRightExpr(), stack);
     stack.pop();
     return result;
   }
@@ -136,19 +137,19 @@ public class BasicEvalNodeVisitor<CONTEXT, RESULT> implements EvalNodeVisitor2<C
     RESULT result = null;
     stack.push(functionEval);
     for (EvalNode arg : functionEval.getArgs()) {
-      result = visitChild(context, stack, arg);
+      result = visitChild(context, arg, stack);
     }
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitConst(CONTEXT context, Stack<EvalNode> stack, ConstEval evalNode) {
+  public RESULT visitConst(CONTEXT context, ConstEval evalNode, Stack<EvalNode> stack) {
     return null;
   }
 
   @Override
-  public RESULT visitRowConstant(CONTEXT context, Stack<EvalNode> stack, RowConstantEval evalNode) {
+  public RESULT visitRowConstant(CONTEXT context, RowConstantEval evalNode, Stack<EvalNode> stack) {
     return null;
   }
 
@@ -158,49 +159,49 @@ public class BasicEvalNodeVisitor<CONTEXT, RESULT> implements EvalNodeVisitor2<C
   }
 
   @Override
-  public RESULT visitPlus(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitPlus(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitMinus(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitMinus(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitMultiply(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitMultiply(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitDivide(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitDivide(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitModular(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitModular(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitAnd(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitAnd(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitOr(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitOr(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitNot(CONTEXT context, Stack<EvalNode> stack, NotEval evalNode) {
+  public RESULT visitNot(CONTEXT context, NotEval evalNode, Stack<EvalNode> stack) {
     RESULT result;
     stack.push(evalNode);
     if (evalNode.getChild() instanceof NotEval) {
-      result = visitChild(context, stack, evalNode);
+      result = visitChild(context, evalNode, stack);
     } else {
-      result = visitChild(context, stack, evalNode.getLeftExpr());
-      visitChild(context, stack, evalNode.getRightExpr());
+      result = visitChild(context, evalNode.getLeftExpr(), stack);
+      visitChild(context, evalNode.getRightExpr(), stack);
     }
     stack.pop();
 
@@ -208,91 +209,91 @@ public class BasicEvalNodeVisitor<CONTEXT, RESULT> implements EvalNodeVisitor2<C
   }
 
   @Override
-  public RESULT visitEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitNotEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitNotEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitLessThan(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitLessThan(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitLessThanOrEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitLessThanOrEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitGreaterThan(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitGreaterThan(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitGreaterThanOrEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode) {
+  public RESULT visitGreaterThanOrEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitIsNull(CONTEXT context, Stack<EvalNode> stack, IsNullEval evalNode) {
+  public RESULT visitIsNull(CONTEXT context, IsNullEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitCaseWhen(CONTEXT context, Stack<EvalNode> stack, CaseWhenEval evalNode) {
+  public RESULT visitCaseWhen(CONTEXT context, CaseWhenEval evalNode, Stack<EvalNode> stack) {
     RESULT result = null;
     stack.push(evalNode);
     for (CaseWhenEval.IfThenEval ifThenEval : evalNode.getIfThenEvals()) {
-      result = visitIfThen(context, stack, ifThenEval);
+      result = visitIfThen(context, ifThenEval, stack);
     }
     if (evalNode.hasElse()) {
-      result = visitChild(context, stack, evalNode.getElse());
+      result = visitChild(context, evalNode.getElse(), stack);
     }
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitIfThen(CONTEXT context, Stack<EvalNode> stack, CaseWhenEval.IfThenEval evalNode) {
+  public RESULT visitIfThen(CONTEXT context, CaseWhenEval.IfThenEval evalNode, Stack<EvalNode> stack) {
     RESULT result;
     stack.push(evalNode);
-    result = visitChild(context, stack, evalNode.getConditionExpr());
-    visitChild(context, stack, evalNode.getResultExpr());
+    result = visitChild(context, evalNode.getConditionExpr(), stack);
+    visitChild(context, evalNode.getResultExpr(), stack);
     stack.pop();
     return result;
   }
 
   @Override
-  public RESULT visitInPredicate(CONTEXT context, Stack<EvalNode> stack, InEval evalNode) {
+  public RESULT visitInPredicate(CONTEXT context, InEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitLike(CONTEXT context, Stack<EvalNode> stack, LikePredicateEval evalNode) {
+  public RESULT visitLike(CONTEXT context, LikePredicateEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitSimilarTo(CONTEXT context, Stack<EvalNode> stack, SimilarToPredicateEval evalNode) {
+  public RESULT visitSimilarTo(CONTEXT context, SimilarToPredicateEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitRegex(CONTEXT context, Stack<EvalNode> stack, RegexPredicateEval evalNode) {
+  public RESULT visitRegex(CONTEXT context, RegexPredicateEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultBinaryEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitFuncCall(CONTEXT context, Stack<EvalNode> stack, GeneralFunctionEval evalNode) {
+  public RESULT visitFuncCall(CONTEXT context, GeneralFunctionEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultFunctionEval(context, stack, evalNode);
   }
 
   @Override
-  public RESULT visitAggrFuncCall(CONTEXT context, Stack<EvalNode> stack, AggregationFunctionCallEval evalNode) {
+  public RESULT visitAggrFuncCall(CONTEXT context, AggregationFunctionCallEval evalNode, Stack<EvalNode> stack) {
     return visitDefaultFunctionEval(context, stack, evalNode);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/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 45ffd11..90a21c5 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
@@ -81,7 +81,10 @@ public class BinaryEval extends EvalNode implements Cloneable {
     return newCtx;
   }
 
-  private DataType determineType(DataType left, DataType right) {
+  /**
+   * This is verified by ExprsVerifier.checkArithmeticOperand().
+   */
+  private DataType determineType(DataType left, DataType right) throws InvalidEvalException {
     switch (left.getType()) {
       case INT4: {
         switch(right.getType()) {
@@ -90,7 +93,6 @@ public class BinaryEval extends EvalNode implements Cloneable {
           case INT8: return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.INT8);
           case FLOAT4: return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.FLOAT4);
           case FLOAT8: return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.FLOAT8);
-          default: throw new InvalidEvalException();
         }
       }
 
@@ -101,7 +103,6 @@ public class BinaryEval extends EvalNode implements Cloneable {
           case INT8: return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.INT8);
           case FLOAT4:
           case FLOAT8: return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.FLOAT8);
-          default: throw new InvalidEvalException();
         }
       }
 
@@ -112,7 +113,6 @@ public class BinaryEval extends EvalNode implements Cloneable {
           case INT8:
           case FLOAT4:
           case FLOAT8: return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.FLOAT8);
-          default: throw new InvalidEvalException();
         }
       }
 
@@ -123,7 +123,6 @@ public class BinaryEval extends EvalNode implements Cloneable {
           case INT8:
           case FLOAT4:
           case FLOAT8: return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.FLOAT8);
-          default: throw new InvalidEvalException();
         }
       }
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/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 14cece8..45f3736 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
@@ -51,16 +51,16 @@ public abstract class EvalNode implements Cloneable, GsonObject {
 		this.leftExpr = expr;
 	}
 	
-	public EvalNode getLeftExpr() {
-		return this.leftExpr;
+	public <T extends EvalNode> T getLeftExpr() {
+		return (T) this.leftExpr;
 	}
 	
 	public void setRightExpr(EvalNode expr) {
 		this.rightExpr = expr;
 	}
 	
-	public EvalNode getRightExpr() {
-		return this.rightExpr;
+	public <T extends EvalNode> T getRightExpr() {
+		return (T) this.rightExpr;
 	}
 
   public EvalNode getExpr(int id) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
index 209f45d..5e9a509 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
@@ -21,45 +21,45 @@ package org.apache.tajo.engine.eval;
 import java.util.Stack;
 
 public interface EvalNodeVisitor2<CONTEXT, RESULT> {
-  RESULT visitChild(CONTEXT context, Stack<EvalNode> stack, EvalNode evalNode);
+  RESULT visitChild(CONTEXT context, EvalNode evalNode, Stack<EvalNode> stack);
 
   // Column and Value reference expressions
-  RESULT visitConst(CONTEXT context, Stack<EvalNode> stack, ConstEval evalNode);
-  RESULT visitRowConstant(CONTEXT context, Stack<EvalNode> stack, RowConstantEval evalNode);
+  RESULT visitConst(CONTEXT context, ConstEval evalNode, Stack<EvalNode> stack);
+  RESULT visitRowConstant(CONTEXT context, RowConstantEval evalNode, Stack<EvalNode> stack);
   RESULT visitField(CONTEXT context, Stack<EvalNode> stack, FieldEval evalNode);
 
   // Arithmetic expression
-  RESULT visitPlus(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitMinus(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitMultiply(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitDivide(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitModular(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+  RESULT visitPlus(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitMinus(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitMultiply(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitDivide(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitModular(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
 
   // Logical Predicates
-  RESULT visitAnd(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitOr(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitNot(CONTEXT context, Stack<EvalNode> stack, NotEval evalNode);
+  RESULT visitAnd(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitOr(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitNot(CONTEXT context, NotEval evalNode, Stack<EvalNode> stack);
 
   // Comparison Predicates
-  RESULT visitEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitNotEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitLessThan(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitLessThanOrEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitGreaterThan(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
-  RESULT visitGreaterThanOrEqual(CONTEXT context, Stack<EvalNode> stack, BinaryEval evalNode);
+  RESULT visitEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitNotEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitLessThan(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitLessThanOrEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitGreaterThan(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitGreaterThanOrEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
 
   // Other Predicates
-  RESULT visitIsNull(CONTEXT context, Stack<EvalNode> stack, IsNullEval evalNode);
-  RESULT visitCaseWhen(CONTEXT context, Stack<EvalNode> stack, CaseWhenEval evalNode);
-  RESULT visitIfThen(CONTEXT context, Stack<EvalNode> stack, CaseWhenEval.IfThenEval evalNode);
-  RESULT visitInPredicate(CONTEXT context, Stack<EvalNode> stack, InEval evalNode);
+  RESULT visitIsNull(CONTEXT context, IsNullEval evalNode, Stack<EvalNode> stack);
+  RESULT visitCaseWhen(CONTEXT context, CaseWhenEval evalNode, Stack<EvalNode> stack);
+  RESULT visitIfThen(CONTEXT context, CaseWhenEval.IfThenEval evalNode, Stack<EvalNode> stack);
+  RESULT visitInPredicate(CONTEXT context, InEval evalNode, Stack<EvalNode> stack);
 
   // Pattern matching predicates
-  RESULT visitLike(CONTEXT context, Stack<EvalNode> stack, LikePredicateEval evalNode);
-  RESULT visitSimilarTo(CONTEXT context, Stack<EvalNode> stack, SimilarToPredicateEval evalNode);
-  RESULT visitRegex(CONTEXT context, Stack<EvalNode> stack, RegexPredicateEval evalNode);
+  RESULT visitLike(CONTEXT context, LikePredicateEval evalNode, Stack<EvalNode> stack);
+  RESULT visitSimilarTo(CONTEXT context, SimilarToPredicateEval evalNode, Stack<EvalNode> stack);
+  RESULT visitRegex(CONTEXT context, RegexPredicateEval evalNode, Stack<EvalNode> stack);
 
   // Functions
-  RESULT visitFuncCall(CONTEXT context, Stack<EvalNode> stack, GeneralFunctionEval evalNode);
-  RESULT visitAggrFuncCall(CONTEXT context, Stack<EvalNode> stack, AggregationFunctionCallEval evalNode);
+  RESULT visitFuncCall(CONTEXT context, GeneralFunctionEval evalNode, Stack<EvalNode> stack);
+  RESULT visitAggrFuncCall(CONTEXT context, AggregationFunctionCallEval evalNode, Stack<EvalNode> stack);
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/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 12b3709..638c92a 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,6 +18,7 @@
 
 package org.apache.tajo.engine.eval;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
@@ -37,7 +38,7 @@ public class EvalTreeUtil {
 
   public static void replace(EvalNode expr, EvalNode targetExpr, EvalNode tobeReplaced) {
     EvalReplaceVisitor replacer = new EvalReplaceVisitor(targetExpr, tobeReplaced);
-    replacer.visitChild(null, new Stack<EvalNode>(), expr);
+    replacer.visitChild(null, expr, new Stack<EvalNode>());
   }
 
   public static class EvalReplaceVisitor extends BasicEvalNodeVisitor<EvalNode, EvalNode> {
@@ -50,8 +51,8 @@ public class EvalTreeUtil {
     }
 
     @Override
-    public EvalNode visitChild(EvalNode context, Stack<EvalNode> stack, EvalNode evalNode) {
-      super.visitChild(context, stack, evalNode);
+    public EvalNode visitChild(EvalNode context, EvalNode evalNode, Stack<EvalNode> stack) {
+      super.visitChild(context, evalNode, stack);
 
       if (evalNode.equals(target)) {
         EvalNode parent = stack.peek();

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/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 768aeb0..22e5f9e 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
@@ -98,6 +98,12 @@ public class BasicLogicalPlanVisitor<CONTEXT, RESULT> implements LogicalPlanVisi
       case INSERT:
         current = visitInsert(context, plan, (InsertNode) node, stack);
         break;
+      case CREATE_TABLE:
+        current = visitCreateTable(context, plan, (CreateTableNode) node, stack);
+        break;
+      case DROP_TABLE:
+        current = visitDropTable(context, plan, (DropTableNode) node, stack);
+        break;
       default:
         throw new PlanningException("Unknown logical node type: " + node.getType());
     }
@@ -231,4 +237,14 @@ public class BasicLogicalPlanVisitor<CONTEXT, RESULT> implements LogicalPlanVisi
     stack.pop();
     return result;
   }
+
+  @Override
+  public RESULT visitCreateTable(CONTEXT context, LogicalPlan plan, CreateTableNode node, Stack<LogicalNode> stack) {
+    return null;
+  }
+
+  @Override
+  public RESULT visitDropTable(CONTEXT context, LogicalPlan plan, DropTableNode node, Stack<LogicalNode> stack) {
+    return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/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
new file mode 100644
index 0000000..a665730
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprsVerifier.java
@@ -0,0 +1,164 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.planner;
+
+import org.apache.tajo.engine.eval.*;
+
+import java.util.Stack;
+
+import static org.apache.tajo.common.TajoDataTypes.DataType;
+import static org.apache.tajo.common.TajoDataTypes.Type;
+
+public class ExprsVerifier extends BasicEvalNodeVisitor<VerificationState, EvalNode> {
+  private static final ExprsVerifier instance;
+
+  static {
+    instance = new ExprsVerifier();
+  }
+
+  public static VerificationState verify(VerificationState state, EvalNode expression) {
+    instance.visitChild(state, expression, new Stack<EvalNode>());
+    return state;
+  }
+
+  private static boolean isCompatibleType(DataType dataType1, DataType dataType2) {
+    if (checkNumericType(dataType1) && checkNumericType(dataType2)) {
+      return true;
+    }
+
+    if (checkTextData(dataType1) && checkTextData(dataType2)) {
+      return true;
+    }
+
+    return false;
+  }
+
+  private static void verifyComparisonOperator(VerificationState state, BinaryEval expr) {
+    DataType leftType = expr.getLeftExpr().getValueType();
+    DataType rightType = expr.getRightExpr().getValueType();
+    if (!isCompatibleType(leftType, rightType)) {
+      state.addVerification("No operator matches the given name and argument type(s): " + expr.toString());
+    }
+  }
+
+  public EvalNode visitEqual(VerificationState state, BinaryEval expr, Stack<EvalNode> stack) {
+    super.visitEqual(state, expr, stack);
+    verifyComparisonOperator(state, expr);
+    return expr;
+  }
+
+  public EvalNode visitNotEqual(VerificationState state, BinaryEval expr, Stack<EvalNode> stack) {
+    super.visitNotEqual(state, expr, stack);
+    verifyComparisonOperator(state, expr);
+    return expr;
+  }
+
+  @Override
+  public EvalNode visitLessThan(VerificationState state, BinaryEval expr, Stack<EvalNode> stack) {
+    super.visitLessThan(state, expr, stack);
+    verifyComparisonOperator(state, expr);
+    return expr;
+  }
+
+  @Override
+  public EvalNode visitLessThanOrEqual(VerificationState state, BinaryEval expr, Stack<EvalNode> stack) {
+    super.visitLessThanOrEqual(state, expr, stack);
+    verifyComparisonOperator(state, expr);
+    return expr;
+  }
+
+  @Override
+  public EvalNode visitGreaterThan(VerificationState state, BinaryEval expr, Stack<EvalNode> stack) {
+    super.visitGreaterThan(state, expr, stack);
+    verifyComparisonOperator(state, expr);
+    return expr;
+  }
+
+  @Override
+  public EvalNode visitGreaterThanOrEqual(VerificationState state, BinaryEval expr, Stack<EvalNode> stack) {
+    super.visitGreaterThanOrEqual(state, expr, stack);
+    verifyComparisonOperator(state, expr);
+    return expr;
+  }
+
+  private static void checkDivisionByZero(VerificationState state, BinaryEval evalNode) {
+    if (evalNode.getRightExpr().getType() == EvalType.CONST) {
+      ConstEval constEval = evalNode.getRightExpr();
+      if (constEval.getValue().asFloat8() == 0) {
+        state.addVerification("division by zero");
+      }
+    }
+  }
+
+  private static void checkArithmeticOperand(VerificationState state, BinaryEval evalNode) {
+    EvalNode leftExpr = evalNode.getLeftExpr();
+    EvalNode rightExpr = evalNode.getRightExpr();
+    if (!(checkNumericType(leftExpr.getValueType())
+        && checkNumericType(rightExpr.getValueType()))) {
+      state.addVerification("No operator matches the given name and argument type(s): " + evalNode.toString());
+    }
+  }
+
+  private static boolean checkNumericType(DataType dataType) {
+    int typeNumber = dataType.getType().getNumber();
+    return Type.INT1.getNumber() < typeNumber && typeNumber <= Type.DECIMAL.getNumber();
+  }
+
+  private static boolean checkTextData(DataType dataType) {
+    int typeNumber = dataType.getType().getNumber();
+    return Type.CHAR.getNumber() < typeNumber && typeNumber <= Type.TEXT.getNumber();
+  }
+
+  @Override
+  public EvalNode visitPlus(VerificationState state, BinaryEval evalNode, Stack<EvalNode> stack) {
+    super.visitDivide(state, evalNode, stack);
+    checkArithmeticOperand(state, evalNode);
+    return evalNode;
+  }
+
+  @Override
+  public EvalNode visitMinus(VerificationState state, BinaryEval evalNode, Stack<EvalNode> stack) {
+    super.visitDivide(state, evalNode, stack);
+    checkArithmeticOperand(state, evalNode);
+    return evalNode;
+  }
+
+  @Override
+  public EvalNode visitMultiply(VerificationState state, BinaryEval evalNode, Stack<EvalNode> stack) {
+    super.visitDivide(state, evalNode, stack);
+    checkArithmeticOperand(state, evalNode);
+    return evalNode;
+  }
+
+  @Override
+  public EvalNode visitDivide(VerificationState state, BinaryEval evalNode, Stack<EvalNode> stack) {
+    super.visitDivide(state, evalNode, stack);
+    checkArithmeticOperand(state, evalNode);
+    checkDivisionByZero(state, evalNode);
+    return evalNode;
+  }
+
+  @Override
+  public EvalNode visitModular(VerificationState state, BinaryEval evalNode, Stack<EvalNode> stack) {
+    super.visitDivide(state, evalNode, stack);
+    checkArithmeticOperand(state, evalNode);
+    checkDivisionByZero(state, evalNode);
+    return evalNode;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/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
new file mode 100644
index 0000000..6491b9b
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java
@@ -0,0 +1,225 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.planner;
+
+import com.google.common.base.Preconditions;
+import org.apache.tajo.catalog.CatalogService;
+import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.engine.planner.logical.*;
+
+import java.util.Stack;
+
+public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationState, LogicalNode> {
+  private TajoConf conf;
+  private CatalogService catalog;
+
+  public LogicalPlanVerifier(TajoConf conf, CatalogService catalog) {
+    this.conf = conf;
+    this.catalog = catalog;
+  }
+
+  @Override
+  public LogicalNode visitProjection(VerificationState state, LogicalPlan plan, ProjectionNode node,
+                                     Stack<LogicalNode> stack) throws PlanningException {
+    visitChild(state, plan, node.getChild(), stack);
+
+    for (Target target : node.getTargets()) {
+      ExprsVerifier.verify(state, target.getEvalTree());
+    }
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitLimit(VerificationState state, LogicalPlan plan, LimitNode node, Stack<LogicalNode> stack)
+      throws PlanningException {
+
+    visitChild(state, plan, node.getChild(), stack);
+    if (node.getFetchFirstNum() < 0) {
+      state.addVerification("LIMIT must not be negative");
+    }
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitGroupBy(VerificationState state, LogicalPlan plan, GroupbyNode node,
+                                  Stack<LogicalNode> stack) throws PlanningException {
+    visitChild(state, plan, node.getChild(), stack);
+
+    if (node.hasTargets()) {
+      for (Target target : node.getTargets()) {
+        ExprsVerifier.verify(state, target.getEvalTree());
+      }
+    }
+
+    if (node.hasHavingCondition()) {
+      ExprsVerifier.verify(state, node.getHavingCondition());
+    }
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitFilter(VerificationState state, LogicalPlan plan, SelectionNode node,
+                                 Stack<LogicalNode> stack) throws PlanningException {
+    visitChild(state, plan, 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);
+
+    if (node.hasJoinQual()) {
+      ExprsVerifier.verify(state, node.getJoinQual());
+    }
+
+    return node;
+  }
+
+  private void verifySetStatement(VerificationState state, BinaryNode setNode) {
+    Preconditions.checkArgument(setNode.getType() == NodeType.UNION || setNode.getType() == NodeType.INTERSECT ||
+      setNode.getType() == NodeType.EXCEPT);
+    Schema left = setNode.getLeftChild().getOutSchema();
+    Schema right = setNode.getRightChild().getOutSchema();
+    NodeType type = setNode.getType();
+
+    if (left.getColumnNum() != right.getColumnNum()) {
+      state.addVerification("each " + type.name() + " query must have the same number of columns");
+      return;
+    }
+
+    Column[] leftColumns = left.toArray();
+    Column[] rightColumns = right.toArray();
+
+    for (int i = 0; i < leftColumns.length; i++) {
+      if (!leftColumns[i].getDataType().equals(rightColumns[i].getDataType())) {
+        state.addVerification(type + " types " + leftColumns[i].getDataType().getType() + " and "
+            + rightColumns[i].getDataType().getType() + " cannot be matched");
+      }
+    }
+  }
+
+  @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);
+    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);
+    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);
+    verifySetStatement(state, node);
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitScan(VerificationState state, LogicalPlan plan, ScanNode node,
+                               Stack<LogicalNode> stack) throws PlanningException {
+    if (node.hasTargets()) {
+      for (Target target : node.getTargets()) {
+        ExprsVerifier.verify(state, target.getEvalTree());
+      }
+    }
+
+    if (node.hasQual()) {
+      ExprsVerifier.verify(state, node.getQual());
+    }
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitStoreTable(VerificationState state, LogicalPlan plan, StoreTableNode node,
+                                     Stack<LogicalNode> stack) throws PlanningException {
+    visitChild(state, plan, node.getChild(), stack);
+
+    if (node.isCreatedTable() && catalog.existsTable(node.getTableName())) {
+      state.addVerification("relation \"" + node.getTableName() + "\" already exists");
+    }
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitInsert(VerificationState state, LogicalPlan plan, InsertNode node,
+                                 Stack<LogicalNode> stack) throws PlanningException {
+    LogicalNode child = visitChild(state, plan, node.getSubQuery(), stack);
+
+    if (node.hasTargetSchema()) {
+      ensureDomains(state, node.getTargetSchema(), node.getSubQuery().getOutSchema());
+    }
+
+    return child;
+  }
+
+  /**
+   * This ensures that corresponding columns in both tables are equivalent to each other.
+   */
+  private static void ensureDomains(VerificationState state, Schema targetTableScheme, Schema schema)
+      throws PlanningException {
+    for (int i = 0; i < schema.getColumnNum(); i++) {
+      if (!schema.getColumn(i).getDataType().equals(targetTableScheme.getColumn(i).getDataType())) {
+        Column targetColumn = targetTableScheme.getColumn(i);
+        Column insertColumn = schema.getColumn(i);
+        state.addVerification("ERROR: " +
+            insertColumn.getColumnName() + " is of type " + insertColumn.getDataType().getType().name() +
+            ", but target column '" + targetColumn.getColumnName() + "' is of type " +
+            targetColumn.getDataType().getType().name());
+      }
+    }
+  }
+
+  @Override
+  public LogicalNode visitCreateTable(VerificationState state, LogicalPlan plan, CreateTableNode node,
+                                      Stack<LogicalNode> stack) {
+    if (catalog.existsTable(node.getTableName())) {
+      state.addVerification("relation \"" + node.getTableName() + "\" already exists");
+    }
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitDropTable(VerificationState state, LogicalPlan plan, DropTableNode node,
+                                    Stack<LogicalNode> stack) {
+    if (!catalog.existsTable(node.getTableName())) {
+      state.addVerification("table \"" + node.getTableName() + "\" does not exist");
+    }
+
+    return node;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/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 e05b09b..c06b7a7 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
@@ -51,4 +51,8 @@ public interface LogicalPlanVisitor <CONTEXT, RESULT> {
       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;
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/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 e41605b..667344e 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
@@ -358,8 +358,6 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     TableSubQueryNode rightSubQuery = new TableSubQueryNode(plan.newPID(), rightContext.block.getName(), right);
     context.plan.connectBlocks(rightContext.block, context.block, BlockType.TableSubQuery);
 
-    verifySetStatement(setOperation.getType(), leftContext.block, rightContext.block);
-
     BinaryNode setOp;
     if (setOperation.getType() == OpType.Union) {
       setOp = new UnionNode(plan.newPID(), leftSubQuery, rightSubQuery);
@@ -388,26 +386,6 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     return setOp;
   }
 
-  private boolean verifySetStatement(OpType type, QueryBlock left, QueryBlock right)
-      throws VerifyException {
-
-    if (left.getCurrentTargets().length != right.getCurrentTargets().length) {
-      throw new VerifyException("ERROR: each " + type.name() + " query must have the same number of columns");
-    }
-
-    Target[] targets1 = left.getCurrentTargets();
-    Target[] targets2 = right.getCurrentTargets();
-
-    for (int i = 0; i < targets1.length; i++) {
-      if (!targets1[i].getDataType().equals(targets2[i].getDataType())) {
-        throw new VerifyException(type + " types " + targets1[i].getDataType().getType() + " and "
-            + targets2[i].getDataType().getType() + " cannot be matched");
-      }
-    }
-
-    return true;
-  }
-
   @Override
   public SelectionNode visitFilter(PlanContext context, Stack<OpType> stack, Selection selection)
       throws PlanningException {
@@ -876,7 +854,6 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
         }
       }
 
-      ensureDomains(targetSchema, subQuery.getOutSchema());
       insertNode = new InsertNode(context.plan.newPID(), desc, subQuery);
       insertNode.setTargetSchema(targetSchema);
       insertNode.setOutSchema(targetSchema);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/VerificationState.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/VerificationState.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/VerificationState.java
new file mode 100644
index 0000000..e1b136d
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/VerificationState.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.planner;
+
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
+public class VerificationState {
+  List<String> errorMessages = Lists.newArrayList();
+
+  public void addVerification(String error) {
+    errorMessages.add(error);
+  }
+
+  public boolean verified() {
+    return errorMessages.size() == 0;
+  }
+
+  public List<String> getErrorMessages() {
+    return errorMessages;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
index 4c12981..9d6b4ff 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
@@ -39,6 +39,7 @@ import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.engine.eval.ConstEval;
 import org.apache.tajo.engine.eval.FieldEval;
 import org.apache.tajo.engine.exception.IllegalQueryStatusException;
+import org.apache.tajo.engine.exception.VerifyException;
 import org.apache.tajo.engine.parser.HiveConverter;
 import org.apache.tajo.engine.parser.SQLAnalyzer;
 import org.apache.tajo.engine.planner.*;
@@ -49,7 +50,6 @@ import org.apache.tajo.master.TajoMaster.MasterContext;
 import org.apache.tajo.master.querymaster.QueryInfo;
 import org.apache.tajo.master.querymaster.QueryJobManager;
 import org.apache.tajo.storage.AbstractStorageManager;
-import org.apache.tajo.storage.StorageUtil;
 
 import java.io.IOException;
 import java.sql.SQLException;
@@ -70,6 +70,7 @@ public class GlobalEngine extends AbstractService {
   private CatalogService catalog;
   private LogicalPlanner planner;
   private LogicalOptimizer optimizer;
+  private LogicalPlanVerifier verifier;
   private DistributedQueryHookManager hookManager;
 
   public GlobalEngine(final MasterContext context) {
@@ -85,6 +86,7 @@ public class GlobalEngine extends AbstractService {
       converter = new HiveConverter();
       planner = new LogicalPlanner(context.getCatalog());
       optimizer = new LogicalOptimizer();
+      verifier = new LogicalPlanVerifier(context.getConf(), context.getCatalog());
 
       hookManager = new DistributedQueryHookManager();
       hookManager.addHook(new CreateTableHook());
@@ -178,7 +180,7 @@ public class GlobalEngine extends AbstractService {
     // parse the query
     Expr expr = analyzer.parse(sql);
     LogicalPlan plan = createLogicalPlan(expr);
-    LogicalRootNode rootNode = (LogicalRootNode) plan.getRootBlock().getRoot();
+    LogicalRootNode rootNode = plan.getRootBlock().getRoot();
 
     if (!PlannerUtil.checkIfDDLPlan(rootNode)) {
       throw new SQLException("This is not update query:\n" + sql);
@@ -213,6 +215,17 @@ public class GlobalEngine extends AbstractService {
       LOG.debug("LogicalPlan:\n" + plan.getRootBlock().getRoot());
     }
 
+    VerificationState state = new VerificationState();
+    verifier.visit(state, plan, plan.getRootBlock());
+
+    if (!state.verified()) {
+      StringBuilder sb = new StringBuilder();
+      for (String error : state.getErrorMessages()) {
+        sb.append("ERROR: ").append(error).append("\n");
+      }
+      throw new VerifyException(sb.toString());
+    }
+
     return plan;
   }
 
@@ -234,16 +247,21 @@ public class GlobalEngine extends AbstractService {
       Preconditions.checkState(createTable.hasPath(), "ERROR: LOCATION must be given.");
     }
 
-    return createTable(createTable.getTableName(), meta, createTable.getPath());
+    return createTableOnDirectory(createTable.getTableName(), meta, createTable.getPath(), true);
   }
 
-  public TableDesc createTable(String tableName, TableMeta meta, Path path) throws IOException {
+  public TableDesc createTableOnDirectory(String tableName, TableMeta meta, Path path, boolean isCreated)
+      throws IOException {
     if (catalog.existsTable(tableName)) {
       throw new AlreadyExistsTableException(tableName);
     }
 
     FileSystem fs = path.getFileSystem(context.getConf());
 
+    if (isCreated) {
+      fs.mkdirs(path);
+    }
+
     if(fs.exists(path) && fs.isFile(path)) {
       throw new IOException("ERROR: LOCATION must be a directory.");
     }
@@ -261,7 +279,6 @@ public class GlobalEngine extends AbstractService {
     meta.setStat(stat);
 
     TableDesc desc = CatalogUtil.newTableDesc(tableName, meta, path);
-    StorageUtil.writeTableMeta(context.getConf(), path, meta);
     catalog.addTable(desc);
 
     LOG.info("Table " + desc.getName() + " is created (" + desc.getMeta().getStat().getNumBytes() + ")");

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
index 38ac2a4..1ed0f54 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
@@ -301,7 +301,7 @@ public class TajoMasterClientService extends AbstractService {
       TableMeta meta = new TableMetaImpl(request.getMeta());
       TableDesc desc;
       try {
-        desc = context.getGlobalEngine().createTable(request.getName(), meta, path);
+        desc = context.getGlobalEngine().createTableOnDirectory(request.getName(), meta, path, false);
       } catch (Exception e) {
         return TableResponse.newBuilder().setErrorMessage(e.getMessage()).build();
       }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TajoWorker.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TajoWorker.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TajoWorker.java
index 99fce45..bb666c6 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TajoWorker.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TajoWorker.java
@@ -18,7 +18,6 @@
 
 package org.apache.tajo.worker;
 
-import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
@@ -157,7 +156,6 @@ public class TajoWorker extends CompositeService {
           webServer.start();
           httpPort = webServer.getPort();
           LOG.info("Worker info server started:" + httpPort);
-          throw new IOException("AAA");
         } catch (IOException e) {
           LOG.error(e.getMessage(), e);
         }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java
index b26c3f0..94c1d8f 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/worker/TaskRunner.java
@@ -18,6 +18,7 @@
 
 package org.apache.tajo.worker;
 
+import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
@@ -181,6 +182,7 @@ public class TaskRunner extends AbstractService {
       // Here, we can setup row-based query engine or columnar query engine.
       this.queryEngine = new TajoQueryEngine(systemConf);
     } catch (Throwable t) {
+      t.printStackTrace();
       LOG.error(t);
     }
 
@@ -363,6 +365,7 @@ public class TaskRunner extends AbstractService {
                     task.run();
                   } catch (Throwable t) {
                     fatalError(taskRunnerContext.getMaster(), taskAttemptId, t.getMessage());
+                    t.printStackTrace();
                   } finally {
                     callFuture = null;
                     taskRequest = null;
@@ -370,7 +373,7 @@ public class TaskRunner extends AbstractService {
                 }
               }
             } catch (Throwable t) {
-              LOG.error(t);
+              t.printStackTrace();
             }
           }
         }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/0cf9d4e2/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java
index b22e9db..530cc20 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java
@@ -53,20 +53,10 @@ public class TestTajoClient {
   public static void setUp() throws Exception {
     cluster = TpchTestBase.getInstance().getTestingCluster();
     conf = cluster.getConfiguration();
-    Thread.sleep(3000);
     tajo = new TajoClient(conf);
-
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
   }
 
-  @AfterClass
-  public static void tearDown() throws Exception {
-//    cluster.shutdownMiniCluster();
-//    if(tajo != null) {
-//      tajo.close();
-//    }
-  }
-
   private static Path writeTmpTable(String tableName) throws IOException {
     Path tablePath = StorageUtil.concatPath(testDir, tableName);
     BackendTestingUtil.writeTmpTable(conf, testDir, tableName, true);


Mime
View raw message