You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2013/09/30 05:22:37 UTC

git commit: TAJO-212: Implement type cast expresion. (hyunsik)

Updated Branches:
  refs/heads/master bc19cc2f8 -> 135b27a6a


TAJO-212: Implement type cast expresion. (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/135b27a6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/135b27a6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/135b27a6

Branch: refs/heads/master
Commit: 135b27a6ae481faeb0953fbe53baf81fd54a4628
Parents: bc19cc2
Author: Hyunsik Choi <hy...@apache.org>
Authored: Mon Sep 30 12:18:38 2013 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Mon Sep 30 12:18:38 2013 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |   2 +
 .../java/org/apache/tajo/algebra/CastExpr.java  |  44 ++++++
 .../org/apache/tajo/algebra/CreateTable.java    |  42 ++----
 .../java/org/apache/tajo/algebra/DataType.java  |  68 +++++++++
 .../java/org/apache/tajo/algebra/OpType.java    |   4 +-
 .../org/apache/tajo/datum/BooleanDatum.java     |   5 +
 .../java/org/apache/tajo/datum/Float4Datum.java |   5 +
 .../java/org/apache/tajo/datum/Float8Datum.java |   5 +
 .../java/org/apache/tajo/datum/Int2Datum.java   |   5 +
 .../java/org/apache/tajo/datum/Int4Datum.java   |   7 +-
 .../java/org/apache/tajo/datum/Int8Datum.java   |   5 +
 .../org/apache/tajo/engine/parser/SQLLexer.g4   |   9 +-
 .../org/apache/tajo/engine/parser/SQLParser.g4  |  25 +++-
 .../org/apache/tajo/engine/eval/CastEval.java   | 119 +++++++++++++++
 .../org/apache/tajo/engine/eval/EvalNode.java   |   6 +-
 .../org/apache/tajo/engine/eval/EvalType.java   |   5 +-
 .../apache/tajo/engine/parser/SQLAnalyzer.java  | 138 ++++++++----------
 .../apache/tajo/engine/planner/LogicalPlan.java |   7 +-
 .../tajo/engine/planner/LogicalPlanner.java     |  54 +++----
 .../tajo/engine/planner/TargetListManager.java  |  12 +-
 .../apache/tajo/engine/eval/ExprTestBase.java   | 143 ++++++++++++++++++
 .../tajo/engine/eval/TestSQLExpression.java     |  71 +++++++++
 .../tajo/engine/function/ExprTestBase.java      | 145 -------------------
 .../function/TestPatternMatchingPredicates.java |   1 +
 .../TestStringOperatorsAndFunctions.java        |   1 +
 25 files changed, 624 insertions(+), 304 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index a373870..419e492 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,8 @@ Release 0.2.0 - unreleased
 
   NEW FEATURES
 
+    TAJO-212: Implement type cast expresion. (hyunsik)
+
     TAJO-206: Implement String concatenation operator (||). (hyunsik)
 
     TAJO-213: NULL characters in meta of csv table should be supported.

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-algebra/src/main/java/org/apache/tajo/algebra/CastExpr.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CastExpr.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CastExpr.java
new file mode 100644
index 0000000..349617f
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CastExpr.java
@@ -0,0 +1,44 @@
+/**
+ * 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.algebra;
+
+public class CastExpr extends Expr {
+  private Expr operand;
+  private DataType target;
+
+  public CastExpr(Expr operand, DataType target) {
+    super(OpType.Cast);
+    this.operand = operand;
+    this.target = target;
+  }
+
+  public Expr getOperand() {
+    return operand;
+  }
+
+  public DataType getTarget() {
+    return target;
+  }
+
+  @Override
+  boolean equalsTo(Expr expr) {
+    CastExpr another = (CastExpr) expr;
+    return operand.equals(another.operand) && target.equals(another.target);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
index 1552467..5f96d00 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
@@ -124,47 +124,33 @@ public class CreateTable extends Expr {
         TUtil.checkEquals(params, another.params);
   }
 
-  public static class ColumnDefinition {
+  public static class ColumnDefinition extends DataType {
     String col_name;
-    String data_type;
-    Integer length_or_precision;
-    Integer scale;
 
     public ColumnDefinition(String columnName, String dataType) {
+      super(dataType);
       this.col_name = columnName;
-      this.data_type = dataType;
     }
 
-    public String getColumnName() {
-      return this.col_name;
-    }
-
-    public String getDataType() {
-      return this.data_type;
-    }
-
-    public void setLengthOrPrecision(int lengthOrPrecision) {
-      this.length_or_precision = lengthOrPrecision;
-    }
-
-    public Integer getLengthOrPrecision() {
-      return this.length_or_precision;
-    }
-
-    public void setScale(int scale) {
-      this.scale = scale;
+    public ColumnDefinition(String columnName, DataType dataType) {
+      super(dataType.getTypeName());
+      if (dataType.hasLengthOrPrecision()) {
+        setLengthOrPrecision(dataType.lengthOrPrecision);
+        if (dataType.hasScale()) {
+          setScale(dataType.scale);
+        }
+      }
+      this.col_name = columnName;
     }
 
-    public Integer getScale() {
-      return this.scale;
+    public String getColumnName() {
+      return this.col_name;
     }
 
     public boolean equals(Object obj) {
       if (obj instanceof ColumnDefinition) {
         ColumnDefinition another = (ColumnDefinition) obj;
-        return col_name.equals(another.col_name) && data_type.equals(another.data_type) &&
-            TUtil.checkEquals(length_or_precision, another.length_or_precision) &&
-            TUtil.checkEquals(scale, another.scale);
+        return col_name.equals(another.col_name) && super.equals(another);
       }
 
       return false;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataType.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataType.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataType.java
new file mode 100644
index 0000000..ed8a4a6
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataType.java
@@ -0,0 +1,68 @@
+/**
+ * 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.algebra;
+
+import org.apache.tajo.util.TUtil;
+
+public class DataType extends Expr {
+  String typeName;
+  Integer lengthOrPrecision;
+  Integer scale;
+
+  public DataType(String typeName) {
+    super(OpType.DataType);
+    this.typeName = typeName;
+  }
+
+  public String getTypeName() {
+    return this.typeName;
+  }
+
+  public boolean hasLengthOrPrecision() {
+    return lengthOrPrecision != null;
+  }
+
+  public void setLengthOrPrecision(int lengthOrPrecision) {
+    this.lengthOrPrecision = lengthOrPrecision;
+  }
+
+  public Integer getLengthOrPrecision() {
+    return this.lengthOrPrecision;
+  }
+
+  public boolean hasScale() {
+    return this.scale != null;
+  }
+
+  public void setScale(int scale) {
+    this.scale = scale;
+  }
+
+  public Integer getScale() {
+    return this.scale;
+  }
+
+  @Override
+  boolean equalsTo(Expr expr) {
+    DataType another = (DataType) expr;
+    return typeName.equals(another.typeName) &&
+        TUtil.checkEquals(lengthOrPrecision, another.lengthOrPrecision) &&
+        TUtil.checkEquals(scale, another.scale);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
index ab4e403..145c52c 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
@@ -89,9 +89,11 @@ public enum OpType {
   CountRowsFunction(CountRowsFunctionExpr.class),
   GeneralSetFunction(GeneralSetFunctionExpr.class),
 
+  Cast(CastExpr.class),
+  ScalarSubQuery(ScalarSubQuery.class),
   Literal(LiteralValue.class),
   Null(NullValue.class),
-  ScalarSubQuery(ScalarSubQuery.class);
+  DataType(org.apache.tajo.algebra.DataType.class);
 
   private Class baseClass;
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
index e7c4d39..aeab5aa 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
@@ -56,6 +56,11 @@ public class BooleanDatum extends Datum {
   public void setValue(boolean val) {
     this.val = val;
   }
+
+  @Override
+  public char asChar() {
+    return val ? 't' : 'f';
+  }
 	
 	@Override
 	public short asInt2() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
index 84245b2..97e608a 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
@@ -48,6 +48,11 @@ public class Float4Datum extends Datum implements NumericDatum {
 	public boolean asBool() {
 		throw new InvalidCastException();
 	}
+
+  @Override
+  public char asChar() {
+    return asChars().charAt(0);
+  }
 	
 	@Override
 	public short asInt2() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
index d9389f4..d531942 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
@@ -46,6 +46,11 @@ public class Float8Datum extends Datum implements NumericDatum {
     ByteBuffer bb = ByteBuffer.wrap(bytes);
     this.val = bb.getDouble();
   }
+
+  @Override
+  public char asChar() {
+    return asChars().charAt(0);
+  }
 	
 	@Override
 	public short asInt2() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
index 4101e12..b34031f 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
@@ -43,6 +43,11 @@ public class Int2Datum extends Datum implements NumericDatum {
     ByteBuffer bb = ByteBuffer.wrap(bytes);
     this.val = bb.getShort();
   }
+
+  @Override
+  public char asChar() {
+    return asChars().charAt(0);
+  }
 	
 	@Override
 	public short asInt2() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
index 0b95229..1422187 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
@@ -45,6 +45,11 @@ public class Int4Datum extends Datum implements NumericDatum {
     this.val = bb.getInt();
   }
 
+  @Override
+  public char asChar() {
+    return asChars().charAt(0);
+  }
+
 	@Override
 	public short asInt2() {
 		return (short) val;
@@ -62,7 +67,7 @@ public class Int4Datum extends Datum implements NumericDatum {
 
   @Override
 	public byte asByte() {
-		throw new InvalidCastException();
+		return (byte) val;
 	}
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
index dd00cb4..689adbc 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
@@ -49,6 +49,11 @@ public class Int8Datum extends Datum implements NumericDatum {
 	public boolean asBool() {
 		throw new InvalidCastException();
 	}
+
+  @Override
+  public char asChar() {
+    return asChars().charAt(0);
+  }
 	
 	@Override
 	public short asInt2() {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4 b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
index 46384c8..26bcb67 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
+++ b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
@@ -124,6 +124,7 @@ AVG : A V G;
 BY : B Y;
 
 CASE : C A S E;
+CAST : C A S T;
 CHARACTER : C H A R A C T E R;
 COALESCE : C O A L E S C E;
 COUNT : C O U N T;
@@ -305,8 +306,14 @@ Not_Similar_To : '!~';
 Similar_To_Case_Insensitive : '~*';
 Not_Similar_To_Case_Insensitive : '!~*';
 
+// Cast Operator
+CAST_EXPRESSION
+  : COLON COLON
+  ;
+
 ASSIGN  : ':=';
 EQUAL  : '=';
+COLON :  ':';
 SEMI_COLON :  ';';
 COMMA : ',';
 CONCATENATION_OPERATOR : VERTICAL_BAR VERTICAL_BAR;
@@ -357,7 +364,7 @@ Identifier
   ;
 
 Regular_Identifier
-  : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|Digit|'_'|':')*
+  : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|Digit|'_')*
   ;
 
 /*

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4 b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
index 2c52b70..823dfd5 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
+++ b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
@@ -52,7 +52,7 @@ predefined_type
 
 character_string_type
   : CHARACTER type_length?
-  | CHAR type_length?  |
+  | CHAR type_length?
   | CHARACTER VARYING type_length?
   | CHAR VARYING type_length?
   | VARCHAR type_length?
@@ -593,6 +593,10 @@ null_ordering
 */
 
 boolean_value_expression
+  : or_predicate (CAST_EXPRESSION data_type)?
+  ;
+
+or_predicate
   : and_predicate (OR and_predicate)*
   ;
 
@@ -796,6 +800,7 @@ numeric_primary
   | set_function_specification
   | routine_invocation
   | scalar_subquery
+  | cast_specification
   | LEFT_PAREN numeric_value_expression RIGHT_PAREN
   ;
 
@@ -863,4 +868,22 @@ else_clause
 
 result
   : numeric_value_expression | NULL
+  ;
+
+/*
+===============================================================================
+  cast_specification
+===============================================================================
+*/
+
+cast_specification
+  : CAST LEFT_PAREN cast_operand AS cast_target RIGHT_PAREN
+  ;
+
+cast_operand
+  : boolean_value_expression
+  ;
+
+cast_target
+  : data_type
   ;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/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
new file mode 100644
index 0000000..96ac630
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java
@@ -0,0 +1,119 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.storage.Tuple;
+
+import static org.apache.tajo.common.TajoDataTypes.DataType;
+
+public class CastEval extends EvalNode {
+  @Expose private EvalNode operand;
+  @Expose private DataType target;
+
+  public CastEval(EvalNode operand, DataType target) {
+    super(EvalType.CAST);
+    this.operand = operand;
+    this.target = target;
+  }
+
+  @Override
+  public EvalContext newContext() {
+    CastContext castContext = new CastContext();
+    castContext.childCtx = operand.newContext();
+    return castContext;
+  }
+
+  @Override
+  public DataType[] getValueType() {
+    return new DataType[] {target};
+  }
+
+  @Override
+  public String getName() {
+    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;
+    switch (target.getType()) {
+      case BOOLEAN:
+        return DatumFactory.createBool(operand.terminate(castContext.childCtx).asBool());
+      case CHAR:
+        return DatumFactory.createChar(operand.terminate(castContext.childCtx).asChar());
+      case INT1:
+      case INT2:
+        return DatumFactory.createInt2(operand.terminate(castContext.childCtx).asInt2());
+      case INT4:
+        return DatumFactory.createInt4(operand.terminate(castContext.childCtx).asInt4());
+      case INT8:
+        return DatumFactory.createInt8(operand.terminate(castContext.childCtx).asInt8());
+      case FLOAT4:
+        return DatumFactory.createFloat4(operand.terminate(castContext.childCtx).asFloat4());
+      case FLOAT8:
+        return DatumFactory.createFloat8(operand.terminate(castContext.childCtx).asFloat8());
+      case TEXT:
+        return DatumFactory.createText(operand.terminate(castContext.childCtx).asTextBytes());
+      case BLOB:
+        return DatumFactory.createBlob(operand.terminate(castContext.childCtx).asByteArray());
+      default:
+        throw new InvalidCastException("Cannot cast " + operand.getValueType()[0].getType() + " to "
+            + target.getType());
+    }
+  }
+
+  public String toString() {
+    return "CAST (" + operand + " AS " + target.getType() + ")";
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    boolean valid = obj != null && obj instanceof CastEval;
+    if (valid) {
+      CastEval another = (CastEval) obj;
+      return operand.equals(another.operand) && target.equals(another.target);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public void preOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+    visitor.visit(operand);
+  }
+
+  public void postOrder(EvalNodeVisitor visitor) {
+    visitor.visit(operand);
+    visitor.visit(this);
+  }
+
+  static class CastContext implements EvalContext {
+    EvalContext childCtx;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/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 c6f0f2d..dec9c4a 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
@@ -78,7 +78,7 @@ public abstract class EvalNode implements Cloneable, GsonObject {
 	public abstract String getName();
 	
 	public String toString() {
-		return "("+this.type+"("+leftExpr.toString()+" "+rightExpr.toString()+"))";
+		return "(" + this.type + "(" + leftExpr.toString() + " " + rightExpr.toString() + "))";
 	}
 
   @Override
@@ -90,12 +90,14 @@ public abstract class EvalNode implements Cloneable, GsonObject {
 
   public abstract Datum terminate(EvalContext ctx);
 
+  @Deprecated
 	public void preOrder(EvalNodeVisitor visitor) {
 	  visitor.visit(this);
 	  leftExpr.preOrder(visitor);
 	  rightExpr.preOrder(visitor);
 	}
-	
+
+  @Deprecated
 	public void postOrder(EvalNodeVisitor visitor) {
 	  leftExpr.postOrder(visitor);
 	  rightExpr.postOrder(visitor);	  	  

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
index f5a9e56..9f81b05 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
@@ -54,9 +54,10 @@ public enum EvalType {
   IN(InEval.class),
 
   // Value or Reference
+  CAST(CastEval.class),
+  ROW_CONSTANT(RowConstantEval.class),
   FIELD(FieldEval.class),
-  CONST(ConstEval.class),
-  ROW_CONSTANT(RowConstantEval.class);
+  CONST(ConstEval.class);
 
   private Class<? extends EvalNode> baseClass;
   private String operatorName;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
index b173037..e9773fc 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
@@ -453,31 +453,39 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
   }
 
   @Override
-  public Expr visitAnd_predicate(SQLParser.And_predicateContext ctx) {
-    Expr current = visitBoolean_factor(ctx.boolean_factor(0));
+  public Expr visitBoolean_value_expression(SQLParser.Boolean_value_expressionContext ctx) {
+    Expr current = visitOr_predicate(ctx.or_predicate());
+    if (checkIfExist(ctx.CAST_EXPRESSION())) {
+      current = new CastExpr(current, visitData_type(ctx.data_type()));
+    }
+    return current;
+  }
+
+  @Override
+  public Expr visitOr_predicate(SQLParser.Or_predicateContext ctx) {
+    Expr current = visitAnd_predicate(ctx.and_predicate(0));
 
     Expr left;
     Expr right;
-    for (int i = 1; i < ctx.boolean_factor().size(); i++) {
+    for (int i = 1; i < ctx.and_predicate().size(); i++) {
       left = current;
-      right = visitBoolean_factor(ctx.boolean_factor(i));
-      current = new BinaryOperator(OpType.And, left, right);
+      right = visitAnd_predicate(ctx.and_predicate(i));
+      current = new BinaryOperator(OpType.Or, left, right);
     }
 
     return current;
   }
 
   @Override
-  public Expr visitBoolean_value_expression(SQLParser.Boolean_value_expressionContext ctx) {
-
-    Expr current = visitAnd_predicate(ctx.and_predicate(0));
+  public Expr visitAnd_predicate(SQLParser.And_predicateContext ctx) {
+    Expr current = visitBoolean_factor(ctx.boolean_factor(0));
 
     Expr left;
     Expr right;
-    for (int i = 1; i < ctx.and_predicate().size(); i++) {
+    for (int i = 1; i < ctx.boolean_factor().size(); i++) {
       left = current;
-      right = visitAnd_predicate(ctx.and_predicate(i));
-      current = new BinaryOperator(OpType.Or, left, right);
+      right = visitBoolean_factor(ctx.boolean_factor(i));
+      current = new BinaryOperator(OpType.And, left, right);
     }
 
     return current;
@@ -814,26 +822,18 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
     CreateTable.ColumnDefinition [] elements = new CreateTable.ColumnDefinition[size];
     for (int i = 0; i < size; i++) {
       String name = ctx.field_element(i).name.getText();
-      TypeDefinition typeDef = getDataType(ctx.field_element(i).field_type().data_type());
-      String type = typeDef.getType();
-      elements[i] = new CreateTable.ColumnDefinition(name, type);
-      if (typeDef.getLengthOrPrecision() != null) {
-        elements[i].setLengthOrPrecision(typeDef.getLengthOrPrecision());
-
-        if (typeDef.getScale() != null) {
-          elements[i].setScale(typeDef.getScale());
-        }
-      }
-
+      DataType typeDef = visitData_type(ctx.field_element(i).field_type().data_type());
+      elements[i] = new CreateTable.ColumnDefinition(name, typeDef);
     }
 
     return elements;
   }
 
-  private TypeDefinition getDataType(SQLParser.Data_typeContext type) {
-    SQLParser.Predefined_typeContext predefined_type = type.predefined_type();
+  @Override
+  public DataType visitData_type(SQLParser.Data_typeContext ctx) {
+    SQLParser.Predefined_typeContext predefined_type = ctx.predefined_type();
 
-    TypeDefinition typeDefinition = null;
+    DataType typeDefinition = null;
     if (predefined_type.character_string_type() != null) {
       SQLParser.Character_string_typeContext character_string_type =
           predefined_type.character_string_type();
@@ -841,7 +841,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
       if ((character_string_type.CHARACTER() != null || character_string_type.CHAR() != null) &&
           character_string_type.VARYING() == null) {
 
-        typeDefinition = new TypeDefinition(Type.CHAR.name());
+        typeDefinition = new DataType(Type.CHAR.name());
 
         if (character_string_type.type_length() != null) {
           typeDefinition.setLengthOrPrecision(
@@ -851,7 +851,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
       } else if (character_string_type.VARCHAR() != null
           || character_string_type.VARYING() != null) {
 
-        typeDefinition = new TypeDefinition(Type.VARCHAR.name());
+        typeDefinition = new DataType(Type.VARCHAR.name());
 
         if (character_string_type.type_length() != null) {
           typeDefinition.setLengthOrPrecision(
@@ -859,7 +859,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
         }
 
       } else if (character_string_type.TEXT() != null) {
-        typeDefinition =  new TypeDefinition(Type.TEXT.name());
+        typeDefinition =  new DataType(Type.TEXT.name());
       }
 
     } else if (predefined_type.national_character_string_type() != null) {
@@ -867,9 +867,9 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
           predefined_type.national_character_string_type();
       if ((nchar_type.CHAR() != null || nchar_type.CHARACTER() != null
           || nchar_type.NCHAR() != null) && nchar_type.VARYING() == null) {
-        typeDefinition = new TypeDefinition(Type.NCHAR.name());
+        typeDefinition = new DataType(Type.NCHAR.name());
       } else if (nchar_type.NVARCHAR() != null || nchar_type.VARYING() != null) {
-        typeDefinition = new TypeDefinition(Type.NVARCHAR.name());
+        typeDefinition = new DataType(Type.NVARCHAR.name());
       }
 
       if (nchar_type.type_length() != null) {
@@ -880,7 +880,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
     } else if (predefined_type.binary_large_object_string_type() != null) {
       SQLParser.Binary_large_object_string_typeContext blob_type =
           predefined_type.binary_large_object_string_type();
-      typeDefinition = new TypeDefinition(Type.BLOB.name());
+      typeDefinition = new DataType(Type.BLOB.name());
       if (blob_type.type_length() != null) {
         typeDefinition.setLengthOrPrecision(
             Integer.parseInt(blob_type.type_length().NUMBER().getText()));
@@ -891,22 +891,22 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
         SQLParser.Exact_numeric_typeContext exactType =
             predefined_type.numeric_type().exact_numeric_type();
         if (exactType.TINYINT() != null || exactType.INT1() != null) {
-          typeDefinition = new TypeDefinition(Type.INT1.name());
+          typeDefinition = new DataType(Type.INT1.name());
         } else if (exactType.INT2() != null || exactType.SMALLINT() != null) {
-          typeDefinition = new TypeDefinition(Type.INT2.name());
+          typeDefinition = new DataType(Type.INT2.name());
         } else if (exactType.INT4() != null || exactType.INTEGER() != null ||
             exactType.INT() != null) {
-          typeDefinition = new TypeDefinition(Type.INT4.name());
+          typeDefinition = new DataType(Type.INT4.name());
         } else if (exactType.INT8() != null || exactType.BIGINT() != null) {
-          typeDefinition = new TypeDefinition(Type.INT8.name());
+          typeDefinition = new DataType(Type.INT8.name());
         } else if (exactType.NUMERIC() != null) {
-          typeDefinition = new TypeDefinition(Type.NUMERIC.name());
+          typeDefinition = new DataType(Type.NUMERIC.name());
         } else if (exactType.DECIMAL() != null || exactType.DEC() != null) {
-          typeDefinition = new TypeDefinition(Type.DECIMAL.name());
+          typeDefinition = new DataType(Type.DECIMAL.name());
         }
 
-        if (typeDefinition.getType().equals(Type.NUMERIC.name()) ||
-            typeDefinition.getType().equals(Type.DECIMAL.name())) {
+        if (typeDefinition.getTypeName().equals(Type.NUMERIC.name()) ||
+            typeDefinition.getTypeName().equals(Type.DECIMAL.name())) {
           if (exactType.precision_param() != null) {
             if (exactType.precision_param().scale != null) {
               typeDefinition.setScale(
@@ -921,34 +921,34 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
             predefined_type.numeric_type().approximate_numeric_type();
         if (approximateType.FLOAT() != null || approximateType.FLOAT4() != null
             || approximateType.REAL() != null) {
-          typeDefinition = new TypeDefinition(Type.FLOAT4.name());
+          typeDefinition = new DataType(Type.FLOAT4.name());
         } else if (approximateType.FLOAT8() != null || approximateType.DOUBLE() != null) {
-          typeDefinition = new TypeDefinition(Type.FLOAT8.name());
+          typeDefinition = new DataType(Type.FLOAT8.name());
         }
       }
     } else if (predefined_type.boolean_type() != null)  {
-      typeDefinition = new TypeDefinition(Type.BOOLEAN.name());
+      typeDefinition = new DataType(Type.BOOLEAN.name());
     } else if (predefined_type.datetime_type() != null) {
       SQLParser.Datetime_typeContext dateTimeType = predefined_type.datetime_type();
       if (dateTimeType.DATE() != null) {
-        typeDefinition = new TypeDefinition(Type.DATE.name());
+        typeDefinition = new DataType(Type.DATE.name());
       } else if (dateTimeType.TIME(0) != null && dateTimeType.ZONE() == null) {
-        typeDefinition = new TypeDefinition(Type.TIME.name());
+        typeDefinition = new DataType(Type.TIME.name());
       } else if ((dateTimeType.TIME(0) != null && dateTimeType.ZONE() != null) ||
           dateTimeType.TIMETZ() != null) {
-        typeDefinition = new TypeDefinition(Type.TIMEZ.name());
+        typeDefinition = new DataType(Type.TIMEZ.name());
       } else if (dateTimeType.TIMESTAMP() != null && dateTimeType.ZONE() == null) {
-        typeDefinition = new TypeDefinition(Type.TIMESTAMP.name());
+        typeDefinition = new DataType(Type.TIMESTAMP.name());
       } else if ((dateTimeType.TIMESTAMP() != null && dateTimeType.ZONE() != null) ||
           dateTimeType.TIMESTAMPTZ() != null) {
-        typeDefinition = new TypeDefinition(Type.TIMESTAMPZ.name());
+        typeDefinition = new DataType(Type.TIMESTAMPZ.name());
       }
     } else if (predefined_type.bit_type() != null) {
       SQLParser.Bit_typeContext bitType = predefined_type.bit_type();
       if (bitType.VARBIT() != null || bitType.VARYING() != null) {
-        typeDefinition = new TypeDefinition(Type.VARBIT.name());
+        typeDefinition = new DataType(Type.VARBIT.name());
       } else {
-        typeDefinition = new TypeDefinition(Type.BIT.name());
+        typeDefinition = new DataType(Type.BIT.name());
       }
       if (bitType.type_length() != null) {
         typeDefinition.setLengthOrPrecision(
@@ -957,9 +957,9 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
     } else if (predefined_type.binary_type() != null) {
       SQLParser.Binary_typeContext binaryType = predefined_type.binary_type();
       if (binaryType.VARBINARY() != null || binaryType.VARYING() != null) {
-        typeDefinition = new TypeDefinition(Type.VARBINARY.name());
+        typeDefinition = new DataType(Type.VARBINARY.name());
       } else {
-        typeDefinition = new TypeDefinition(Type.BINARY.name());
+        typeDefinition = new DataType(Type.BINARY.name());
       }
 
       if (binaryType.type_length() != null) {
@@ -971,36 +971,6 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
     return typeDefinition;
   }
 
-  public static class TypeDefinition {
-    private String type;
-    private Integer length_or_precision;
-    private Integer scale;
-
-    TypeDefinition(String type) {
-      this.type = type;
-    }
-
-    String getType() {
-      return type;
-    }
-
-    public void setLengthOrPrecision(Integer length_or_precision) {
-      this.length_or_precision = length_or_precision;
-    }
-
-    public Integer getLengthOrPrecision() {
-      return length_or_precision;
-    }
-
-    void setScale(Integer scale) {
-      this.scale = scale;
-    }
-
-    public Integer getScale() {
-      return this.scale;
-    }
-  }
-
   @Override
   public Expr visitInsert_statement(SQLParser.Insert_statementContext ctx) {
     Insert insertExpr = new Insert();
@@ -1085,4 +1055,10 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
   private static String stripQuote(String str) {
     return str.substring(1, str.length() - 1);
   }
+
+  @Override public Expr visitCast_specification(SQLParser.Cast_specificationContext ctx) {
+    Expr operand = visitChildren(ctx.cast_operand());
+    DataType castTarget = visitData_type(ctx.cast_target().data_type());
+    return new CastExpr(operand, castTarget);
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
index 3ab98f0..286b3b2 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
@@ -75,8 +75,8 @@ public class LogicalPlan {
     return newAndGetBlock(NONAME_BLOCK_PREFIX + (noNameBlockId++));
   }
 
-  public String newNonameColumnName() {
-    return "?_" + (noNameColumnId++);
+  public String newNonameColumnName(String prefix) {
+    return "?" + prefix + "_" + (noNameColumnId++);
   }
 
   /**
@@ -735,7 +735,8 @@ public class LogicalPlan {
             } else {
               Target [] addedTargets = new Target[aggrFunctions.size()];
               for (int i = 0; i < aggrFunctions.size(); i++) {
-                Target aggrFunctionTarget = new Target(aggrFunctions.get(i), newNonameColumnName());
+                Target aggrFunctionTarget = new Target(aggrFunctions.get(i),
+                    newNonameColumnName(aggrFunctions.get(i).getName()));
                 addedTargets[i] = aggrFunctionTarget;
                 EvalTreeUtil.replace(havingCondition, aggrFunctions.get(i),
                     new FieldEval(aggrFunctionTarget.getColumnSchema()));

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/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 f08855a..d6b644b 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
@@ -807,35 +807,19 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     return schema;
   }
 
-  private Column convertColumn(ColumnDefinition columnDefinition) {
-    TajoDataTypes.Type type = TajoDataTypes.Type.valueOf(columnDefinition.getDataType());
-    Column column;
-    switch (type) {
-      case CHAR:
-      case VARCHAR:
-      case NCHAR:
-      case NVARCHAR:
-        column = new Column(columnDefinition.getColumnName(),
-            TajoDataTypes.Type.valueOf(columnDefinition.getDataType()),
-            columnDefinition.getLengthOrPrecision());
-        break;
-      case FLOAT4:
-      case FLOAT8:
-        // TODO: support precision
-        column = new Column(columnDefinition.getColumnName(),
-            TajoDataTypes.Type.valueOf(columnDefinition.getDataType()));
-        break;
-      case NUMERIC:
-      case DECIMAL:
-        // TODO: support precision and scale
-        column = new Column(columnDefinition.getColumnName(),
-            TajoDataTypes.Type.valueOf(columnDefinition.getDataType()));
-        break;
-      default:
-        column = new Column(columnDefinition.getColumnName(),
-            TajoDataTypes.Type.valueOf(columnDefinition.getDataType()));
+  private DataType convertDataType(org.apache.tajo.algebra.DataType dataType) {
+    TajoDataTypes.Type type = TajoDataTypes.Type.valueOf(dataType.getTypeName());
+
+    DataType.Builder builder = DataType.newBuilder();
+    builder.setType(type);
+    if (dataType.hasLengthOrPrecision()) {
+      builder.setLength(dataType.getLengthOrPrecision());
     }
-    return column;
+    return builder.build();
+  }
+
+  private Column convertColumn(ColumnDefinition columnDefinition) {
+    return new Column(columnDefinition.getColumnName(), convertDataType(columnDefinition));
   }
 
   protected LogicalNode visitInsert(PlanContext context, Stack<OpType> stack, Insert expr) throws PlanningException {
@@ -941,6 +925,11 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
             throw new RuntimeException("Unsupported type: " + literal.getValueType());
         }
 
+      case Cast:
+        CastExpr cast = (CastExpr) expr;
+        return new CastEval(createEvalTree(plan, block, cast.getOperand()),
+            convertDataType(cast.getTarget()));
+
       case ValueList: {
         ValueListExpr valueList = (ValueListExpr) expr;
         Datum[] values = new Datum[valueList.getValues().length];
@@ -1182,12 +1171,11 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     for(Target t : targets) {
       DataType type = t.getEvalTree().getValueType()[0];
       String name;
-      if (t.hasAlias()) {
+      if (t.hasAlias() || t.getEvalTree().getType() == EvalType.FIELD) {
+        name = t.getCanonicalName();
+      } else { // if an alias is not given or this target is an expression
+        t.setAlias(plan.newNonameColumnName(t.getEvalTree().getName()));
         name = t.getAlias();
-      } else if (t.getEvalTree().getName().equals("?")) {
-        name = plan.newNonameColumnName();
-      } else {
-        name = t.getEvalTree().getName();
       }
       projected.addColumn(name,type);
     }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java
index ccb64ce..205b1b7 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java
@@ -22,6 +22,7 @@ import org.apache.tajo.algebra.Projection;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.engine.eval.EvalTreeUtil;
+import org.apache.tajo.engine.eval.EvalType;
 import org.apache.tajo.engine.eval.FieldEval;
 
 import java.util.Collection;
@@ -152,12 +153,11 @@ public class TargetListManager {
   public Column getResolvedTargetToColumn(int id) {
     Target t = targets[id];
     String name;
-    if (t.hasAlias()) {
-      name = t.getAlias();
-    } else if (t.getEvalTree().getName().equals("?")) {
-      name = plan.newNonameColumnName();
-    } else {
-      name = t.getEvalTree().getName();
+    if (t.hasAlias() || t.getEvalTree().getType() == EvalType.FIELD) {
+      name = t.getCanonicalName();
+    } else { // if alias name is not given or target is an expression
+      t.setAlias(plan.newNonameColumnName(t.getEvalTree().getName()));
+      name = t.getCanonicalName();
     }
     return new Column(name, t.getEvalTree().getValueType()[0]);
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
new file mode 100644
index 0000000..dd1f894
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.eval;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.TajoTestingCluster;
+import org.apache.tajo.algebra.Expr;
+import org.apache.tajo.catalog.*;
+import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.datum.TextDatum;
+import org.apache.tajo.engine.json.CoreGsonHelper;
+import org.apache.tajo.engine.parser.SQLAnalyzer;
+import org.apache.tajo.engine.planner.LogicalPlan;
+import org.apache.tajo.engine.planner.LogicalPlanner;
+import org.apache.tajo.engine.planner.PlanningException;
+import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.master.TajoMaster;
+import org.apache.tajo.storage.LazyTuple;
+import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.storage.VTuple;
+import org.apache.tajo.util.Bytes;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ExprTestBase {
+  private static TajoTestingCluster util;
+  private static CatalogService cat;
+  private static SQLAnalyzer analyzer;
+  private static LogicalPlanner planner;
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    util = new TajoTestingCluster();
+    util.startCatalogCluster();
+    cat = util.getMiniCatalogCluster().getCatalog();
+    for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
+      cat.createFunction(funcDesc);
+    }
+
+    analyzer = new SQLAnalyzer();
+    planner = new LogicalPlanner(cat);
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    util.shutdownCatalogCluster();
+  }
+
+  private static void assertJsonSerDer(EvalNode expr) {
+    String json = expr.toJson();
+    EvalNode fromJson = CoreGsonHelper.fromJson(json, EvalNode.class);
+    assertEquals(expr, fromJson);
+  }
+
+  private static Target[] getRawTargets(String query) throws PlanningException {
+    Expr expr = analyzer.parse(query);
+    LogicalPlan plan = planner.createPlan(expr);
+    Target [] targets = plan.getRootBlock().getTargetListManager().getUnresolvedTargets();
+    if (targets == null) {
+      throw new PlanningException("Wrong query statement or query plan: " + query);
+    }
+    for (Target t : targets) {
+      assertJsonSerDer(t.getEvalTree());
+    }
+    return targets;
+  }
+
+  public void testSimpleEval(String query, String [] expected) {
+    testEval(null, null, null, query, expected);
+  }
+
+  public void testEval(Schema schema, String tableName, String csvTuple, String query, String [] expected) {
+    LazyTuple lazyTuple;
+    VTuple vtuple  = null;
+    Schema inputSchema = null;
+    if (schema != null) {
+      inputSchema = (Schema) schema.clone();
+      inputSchema.setQualifier(tableName, true);
+
+      int targetIdx [] = new int[inputSchema.getColumnNum()];
+      for (int i = 0; i < targetIdx.length; i++) {
+        targetIdx[i] = i;
+      }
+
+      lazyTuple = new LazyTuple(inputSchema, Bytes.splitPreserveAllTokens(csvTuple.getBytes(), ',', targetIdx), 0);
+      vtuple = new VTuple(inputSchema.getColumnNum());
+      for (int i = 0; i < inputSchema.getColumnNum(); i++) {
+        // If null value occurs, null datum is manually inserted to an input tuple.
+        if (lazyTuple.get(i) instanceof TextDatum && lazyTuple.getText(i).asChars().equals("")) {
+          vtuple.put(i, NullDatum.get());
+        } else {
+          vtuple.put(i, lazyTuple.get(i));
+        }
+      }
+      cat.addTable(new TableDescImpl(tableName, inputSchema, CatalogProtos.StoreType.CSV, new Options(), new Path("/")));
+    }
+
+    Target [] targets = null;
+
+    try {
+      targets = getRawTargets(query);
+    } catch (PlanningException e) {
+      assertTrue("Wrong query statement: " + query, false);
+    }
+
+    EvalContext [] evalContexts = new EvalContext[targets.length];
+    Tuple outTuple = new VTuple(targets.length);
+    for (int i = 0; i < targets.length; i++) {
+      EvalNode eval = targets[i].getEvalTree();
+      evalContexts[i] = eval.newContext();
+      eval.eval(evalContexts[i], inputSchema, vtuple);
+      outTuple.put(i, eval.terminate(evalContexts[i]));
+    }
+
+    if (schema != null) {
+      cat.deleteTable(tableName);
+    }
+
+    for (int i = 0; i < expected.length; i++) {
+      assertEquals(query, expected[i], outTuple.get(i).asChars());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLExpression.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLExpression.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLExpression.java
new file mode 100644
index 0000000..21a94f2
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLExpression.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.eval;
+
+import org.apache.tajo.catalog.Schema;
+import org.junit.Test;
+
+import static org.apache.tajo.common.TajoDataTypes.Type.TEXT;
+
+public class TestSQLExpression extends ExprTestBase {
+
+  @Test
+  public void testCast() {
+    testSimpleEval("select cast (1 as char)", new String[] {"1"});
+    testSimpleEval("select cast (119 as char)", new String[] {"1"});
+
+    testSimpleEval("select cast (1 as int2)", new String[ ]{"1"});
+    testSimpleEval("select cast (1 as int4)", new String[] {"1"});
+    testSimpleEval("select cast (1 as int8)", new String[] {"1"});
+    testSimpleEval("select cast (1 as float)", new String[] {"1.0"});
+    testSimpleEval("select cast (1 as double)", new String[] {"1.0"});
+    testSimpleEval("select cast (1 as text)", new String[] {"1"});
+
+    testSimpleEval("select cast ('123' as int2)", new String[] {"123"});
+    testSimpleEval("select cast ('123' as int4)", new String[] {"123"});
+    testSimpleEval("select cast ('123' as int8)", new String[] {"123"});
+    testSimpleEval("select cast ('123' as float)", new String[] {"123.0"});
+    testSimpleEval("select cast ('123' as double)", new String[] {"123.0"});
+    testSimpleEval("select cast ('123' as text)", new String[] {"123"});
+
+    testSimpleEval("select 123::int2", new String[] {"123"});
+    testSimpleEval("select 123::int4", new String[] {"123"});
+    testSimpleEval("select 123::int8", new String[] {"123"});
+    testSimpleEval("select 123::float", new String[] {"123.0"});
+    testSimpleEval("select 123::double", new String[] {"123.0"});
+    testSimpleEval("select 123::text", new String[] {"123"});
+
+    testSimpleEval("select 123.0::float", new String[] {"123.0"});
+    testSimpleEval("select 123.0::double", new String[] {"123.0"});
+
+    testSimpleEval("select '123'::int", new String[] {"123"});
+    testSimpleEval("select '123'::double", new String[] {"123.0"});
+  }
+
+  @Test
+  public void testCastFromTable() {
+    Schema schema = new Schema();
+    schema.addColumn("col1", TEXT);
+    schema.addColumn("col2", TEXT);
+    testEval(schema, "table1", "123,234", "select cast(col1 as float) as b, cast(col2 as float) as a from table1",
+        new String[]{"123.0", "234.0"});
+    testEval(schema, "table1", "123,234", "select col1::float, col2::float from table1",
+        new String[]{"123.0", "234.0"});
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/ExprTestBase.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/ExprTestBase.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/ExprTestBase.java
deleted file mode 100644
index c3e5d00..0000000
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/ExprTestBase.java
+++ /dev/null
@@ -1,145 +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.function;
-
-import org.apache.hadoop.fs.Path;
-import org.apache.tajo.TajoTestingCluster;
-import org.apache.tajo.algebra.Expr;
-import org.apache.tajo.catalog.*;
-import org.apache.tajo.catalog.proto.CatalogProtos;
-import org.apache.tajo.datum.NullDatum;
-import org.apache.tajo.datum.TextDatum;
-import org.apache.tajo.engine.eval.EvalContext;
-import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.json.CoreGsonHelper;
-import org.apache.tajo.engine.parser.SQLAnalyzer;
-import org.apache.tajo.engine.planner.LogicalPlan;
-import org.apache.tajo.engine.planner.LogicalPlanner;
-import org.apache.tajo.engine.planner.PlanningException;
-import org.apache.tajo.engine.planner.Target;
-import org.apache.tajo.master.TajoMaster;
-import org.apache.tajo.storage.LazyTuple;
-import org.apache.tajo.storage.Tuple;
-import org.apache.tajo.storage.VTuple;
-import org.apache.tajo.util.Bytes;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class ExprTestBase {
-  private static TajoTestingCluster util;
-  private static CatalogService cat;
-  private static SQLAnalyzer analyzer;
-  private static LogicalPlanner planner;
-
-  @BeforeClass
-  public static void setUp() throws Exception {
-    util = new TajoTestingCluster();
-    util.startCatalogCluster();
-    cat = util.getMiniCatalogCluster().getCatalog();
-    for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
-      cat.createFunction(funcDesc);
-    }
-
-    analyzer = new SQLAnalyzer();
-    planner = new LogicalPlanner(cat);
-  }
-
-  @AfterClass
-  public static void tearDown() throws Exception {
-    util.shutdownCatalogCluster();
-  }
-
-  private static void assertJsonSerDer(EvalNode expr) {
-    String json = expr.toJson();
-    EvalNode fromJson = CoreGsonHelper.fromJson(json, EvalNode.class);
-    assertEquals(expr, fromJson);
-  }
-
-  private static Target[] getRawTargets(String query) throws PlanningException {
-    Expr expr = analyzer.parse(query);
-    LogicalPlan plan = planner.createPlan(expr);
-    Target [] targets = plan.getRootBlock().getTargetListManager().getUnresolvedTargets();
-    if (targets == null) {
-      throw new PlanningException("Wrong query statement or query plan: " + query);
-    }
-    for (Target t : targets) {
-      assertJsonSerDer(t.getEvalTree());
-    }
-    return targets;
-  }
-
-  public void testSimpleEval(String query, String [] expected) {
-    testEval(null, null, null, query, expected);
-  }
-
-  public void testEval(Schema schema, String tableName, String csvTuple, String query, String [] expected) {
-    LazyTuple lazyTuple;
-    VTuple vtuple  = null;
-    Schema inputSchema = null;
-    if (schema != null) {
-      inputSchema = (Schema) schema.clone();
-      inputSchema.setQualifier(tableName, true);
-
-      int targetIdx [] = new int[inputSchema.getColumnNum()];
-      for (int i = 0; i < targetIdx.length; i++) {
-        targetIdx[i] = i;
-      }
-
-      lazyTuple = new LazyTuple(inputSchema, Bytes.splitPreserveAllTokens(csvTuple.getBytes(), ',', targetIdx), 0);
-      vtuple = new VTuple(inputSchema.getColumnNum());
-      for (int i = 0; i < inputSchema.getColumnNum(); i++) {
-        // If null value occurs, null datum is manually inserted to an input tuple.
-        if (lazyTuple.get(i) instanceof TextDatum && lazyTuple.getText(i).asChars().equals("")) {
-          vtuple.put(i, NullDatum.get());
-        } else {
-          vtuple.put(i, lazyTuple.get(i));
-        }
-      }
-      cat.addTable(new TableDescImpl(tableName, inputSchema, CatalogProtos.StoreType.CSV, new Options(), new Path("/")));
-    }
-
-    Target [] targets = null;
-
-    try {
-      targets = getRawTargets(query);
-    } catch (PlanningException e) {
-      assertTrue("Wrong query statement: " + query, false);
-    }
-
-    EvalContext [] evalContexts = new EvalContext[targets.length];
-    Tuple outTuple = new VTuple(targets.length);
-    for (int i = 0; i < targets.length; i++) {
-      EvalNode eval = targets[i].getEvalTree();
-      evalContexts[i] = eval.newContext();
-      eval.eval(evalContexts[i], inputSchema, vtuple);
-      outTuple.put(i, eval.terminate(evalContexts[i]));
-    }
-
-    if (schema != null) {
-      cat.deleteTable(tableName);
-    }
-
-    for (int i = 0; i < expected.length; i++) {
-      assertEquals(query, expected[i], outTuple.get(i).asChars());
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java
index 2b43795..3a930d4 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java
@@ -19,6 +19,7 @@
 package org.apache.tajo.engine.function;
 
 import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.eval.ExprTestBase;
 import org.junit.Test;
 
 import static org.apache.tajo.common.TajoDataTypes.Type.TEXT;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
index 9c2a68c..6f080f0 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.function;
 
 
 import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.eval.ExprTestBase;
 import org.junit.Test;
 
 import static org.apache.tajo.common.TajoDataTypes.Type.FLOAT8;