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 2016/05/13 05:32:41 UTC

[1/7] tajo git commit: TAJO-2129: Apply new type implementation to Schema and Catalog.

Repository: tajo
Updated Branches:
  refs/heads/master 01d2fe2a5 -> 8d2bf407f


http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/logical/ScanNode.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/ScanNode.java b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/ScanNode.java
index 0729d6e..f482e30 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/ScanNode.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/ScanNode.java
@@ -27,6 +27,7 @@ import org.apache.tajo.plan.PlanString;
 import org.apache.tajo.plan.Target;
 import org.apache.tajo.plan.expr.EvalNode;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.TUtil;
 
 import java.util.ArrayList;
@@ -72,13 +73,13 @@ public class ScanNode extends RelationNode implements Projectable, SelectableNod
     this.tableDesc = desc;
     this.alias = alias;
 
-    if (!CatalogUtil.isFQTableName(this.tableDesc.getName())) {
+    if (!IdentifierUtil.isFQTableName(this.tableDesc.getName())) {
       throw new IllegalArgumentException("the name in TableDesc must be qualified, but it is \"" +
           desc.getName() + "\"");
     }
 
-    String databaseName = CatalogUtil.extractQualifier(this.tableDesc.getName());
-    String qualifiedAlias = CatalogUtil.buildFQName(databaseName, alias);
+    String databaseName = IdentifierUtil.extractQualifier(this.tableDesc.getName());
+    String qualifiedAlias = IdentifierUtil.buildFQName(databaseName, alias);
     this.setInSchema(tableDesc.getSchema());
     this.getInSchema().setQualifier(qualifiedAlias);
     this.setOutSchema(SchemaBuilder.builder().addAll(getInSchema().getRootColumns()).build());
@@ -108,9 +109,9 @@ public class ScanNode extends RelationNode implements Projectable, SelectableNod
   }
 
   public String getCanonicalName() {
-    if (CatalogUtil.isFQTableName(this.tableDesc.getName())) {
-      String databaseName = CatalogUtil.extractQualifier(this.tableDesc.getName());
-      return hasAlias() ? CatalogUtil.buildFQName(databaseName, alias) : tableDesc.getName();
+    if (IdentifierUtil.isFQTableName(this.tableDesc.getName())) {
+      String databaseName = IdentifierUtil.extractQualifier(this.tableDesc.getName());
+      return hasAlias() ? IdentifierUtil.buildFQName(databaseName, alias) : tableDesc.getName();
     } else {
       return hasAlias() ? alias : tableDesc.getName();
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java
index cbe93d2..95f8f98 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java
@@ -22,7 +22,6 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import org.apache.tajo.algebra.ColumnReferenceExpr;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.NestedPathUtil;
 import org.apache.tajo.catalog.Schema;
@@ -31,6 +30,7 @@ import org.apache.tajo.exception.*;
 import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.logical.RelationNode;
 import org.apache.tajo.plan.logical.ScanNode;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.Pair;
 import org.apache.tajo.util.StringUtils;
 
@@ -100,8 +100,8 @@ public abstract class NameResolver {
         found.add(relation);
 
       // if a table name is not qualified
-      } else if (CatalogUtil.extractSimpleName(relation.getCanonicalName()).equals(tableName) ||
-          CatalogUtil.extractSimpleName(relation.getTableName()).equals(tableName)) {
+      } else if (IdentifierUtil.extractSimpleName(relation.getCanonicalName()).equals(tableName) ||
+          IdentifierUtil.extractSimpleName(relation.getTableName()).equals(tableName)) {
         found.add(relation);
       }
     }
@@ -184,7 +184,7 @@ public abstract class NameResolver {
 
       Column column;
       if (includeSeflDescTable && describeSchemaByItself(relationOp)) {
-        column = guessColumn(CatalogUtil.buildFQName(normalized.getFirst(), normalized.getSecond()));
+        column = guessColumn(IdentifierUtil.buildFQName(normalized.getFirst(), normalized.getSecond()));
 
       } else {
         // Please consider a query case:
@@ -192,9 +192,9 @@ public abstract class NameResolver {
         //
         // The relation lineitem is already renamed to "a", but lineitem.l_orderkey still should be available.
         // The below code makes it possible. Otherwise, it cannot find any match in the relation schema.
-        if (block.isAlreadyRenamedTableName(CatalogUtil.extractQualifier(canonicalName))) {
+        if (block.isAlreadyRenamedTableName(IdentifierUtil.extractQualifier(canonicalName))) {
           canonicalName =
-              CatalogUtil.buildFQName(relationOp.getCanonicalName(), CatalogUtil.extractSimpleName(canonicalName));
+              IdentifierUtil.buildFQName(relationOp.getCanonicalName(), IdentifierUtil.extractSimpleName(canonicalName));
         }
 
         Schema schema = relationOp.getLogicalSchema();
@@ -242,7 +242,7 @@ public abstract class NameResolver {
    */
   static Column lookupColumnFromAllRelsInBlock(LogicalPlan.QueryBlock block,
                                                String columnName, boolean includeSelfDescTable) throws AmbiguousColumnException {
-    Preconditions.checkArgument(CatalogUtil.isSimpleIdentifier(columnName));
+    Preconditions.checkArgument(IdentifierUtil.isSimpleIdentifier(columnName));
 
     List<Column> candidates = new ArrayList<>();
 
@@ -266,7 +266,7 @@ public abstract class NameResolver {
           }
         }
         if (candidateRels.size() == 1) {
-          return guessColumn(CatalogUtil.buildFQName(candidateRels.get(0).getCanonicalName(), columnName));
+          return guessColumn(IdentifierUtil.buildFQName(candidateRels.get(0).getCanonicalName(), columnName));
         } else if (candidateRels.size() > 1) {
           throw new AmbiguousColumnException(columnName);
         }
@@ -377,7 +377,7 @@ public abstract class NameResolver {
 
     // check for dbname.tbname.column_name.nested_field
     if (qualifierParts.length >= 2) {
-      RelationNode rel = lookupTable(block, CatalogUtil.buildFQName(qualifierParts[0], qualifierParts[1]));
+      RelationNode rel = lookupTable(block, IdentifierUtil.buildFQName(qualifierParts[0], qualifierParts[1]));
       if (rel != null) {
         guessedRelations.add(rel);
         columnNamePosition = 2;

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java
index 343b9ab..8cfb1eb 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java
@@ -19,7 +19,6 @@
 package org.apache.tajo.plan.nameresolver;
 
 import org.apache.tajo.algebra.ColumnReferenceExpr;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.exception.AmbiguousColumnException;
@@ -29,6 +28,7 @@ import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.plan.logical.RelationNode;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.Pair;
 
 import java.util.ArrayList;
@@ -57,7 +57,7 @@ public class ResolverByLegacy extends NameResolver {
 
     Pair<String, String> normalized = lookupQualifierAndCanonicalName(block, columnRef, includeSeflDescTable);
     qualifier = normalized.getFirst();
-    qualifiedName = CatalogUtil.buildFQName(qualifier, columnRef.getName());
+    qualifiedName = IdentifierUtil.buildFQName(qualifier, columnRef.getName());
 
     Column found = resolveFromRelsWithinBlock(plan, block, columnRef, includeSeflDescTable);
     if (found == null) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java
index 99921c3..14fb3ef 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java
@@ -22,6 +22,7 @@ import org.apache.tajo.SessionVars;
 import org.apache.tajo.algebra.*;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.exception.NotImplementedException;
 import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.exception.UndefinedColumnException;
 import org.apache.tajo.plan.*;
@@ -36,9 +37,12 @@ import org.apache.tajo.plan.nameresolver.NameResolver;
 import org.apache.tajo.plan.nameresolver.NameResolvingMode;
 import org.apache.tajo.plan.util.PlannerUtil;
 import org.apache.tajo.plan.visitor.SimpleAlgebraVisitor;
+import org.apache.tajo.schema.IdentifierUtil;
 
 import java.util.*;
 
+import static org.apache.tajo.common.TajoDataTypes.Type.RECORD;
+
 /**
  * BaseSchemaBuildPhase builds a basic schema information of tables which have pre-defined schema.
  * For example, tables like the below example have pre-defined schema.
@@ -117,10 +121,10 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
       if (asteriskExpr.hasQualifier()) {
         String qualifier;
 
-        if (CatalogUtil.isFQTableName(asteriskExpr.getQualifier())) {
+        if (IdentifierUtil.isFQTableName(asteriskExpr.getQualifier())) {
           qualifier = asteriskExpr.getQualifier();
         } else {
-          qualifier = CatalogUtil.buildFQName(
+          qualifier = IdentifierUtil.buildFQName(
               ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE), asteriskExpr.getQualifier());
         }
 
@@ -138,7 +142,7 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
 
         // If we cannot find any relation against a qualified column name
         if (relationOp == null) {
-          throw new UndefinedColumnException(CatalogUtil.buildFQName(qualifier, "*"));
+          throw new UndefinedColumnException(IdentifierUtil.buildFQName(qualifier, "*"));
         }
 
         Schema schema = relationOp.getLogicalSchema();
@@ -258,6 +262,10 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
       for (NamedExpr namedExpr : exprs) {
         TajoDataTypes.DataType dataType = typeDeterminant.determineDataType(context, namedExpr.getExpr());
 
+        if (dataType.getType() == RECORD) {
+          throw new NotImplementedException("record projection");
+        }
+
         if (namedExpr.hasAlias()) {
           targets.add(new Target(new FieldEval(new Column(namedExpr.getAlias(), dataType))));
         } else {
@@ -403,11 +411,11 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
         throws TajoException {
 
       String actualRelationName;
-      if (CatalogUtil.isFQTableName(relation.getName())) {
+      if (IdentifierUtil.isFQTableName(relation.getName())) {
         actualRelationName = relation.getName();
       } else {
         actualRelationName =
-            CatalogUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE), relation.getName());
+            IdentifierUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE), relation.getName());
       }
 
       TableDesc desc = catalog.getTableDesc(actualRelationName);
@@ -439,7 +447,7 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
 
       // a table subquery should be dealt as a relation.
       TableSubQueryNode node = ctx.getPlan().createNode(TableSubQueryNode.class);
-      node.init(CatalogUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE), expr.getName()), child);
+      node.init(IdentifierUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE), expr.getName()), child);
       ctx.getQueryBlock().addRelation(node);
 
       return node;
@@ -458,7 +466,7 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
 
       // a table subquery should be dealt as a relation.
       TableSubQueryNode node = ctx.getPlan().createNode(TableSubQueryNode.class);
-      node.init(CatalogUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE),
+      node.init(IdentifierUtil.buildFQName(ctx.getQueryContext().get(SessionVars.CURRENT_DATABASE),
           ctx.generateUniqueSubQueryName()), child);
       ctx.getQueryBlock().addRelation(node);
       if (stack.peek().getType() == OpType.InPredicate) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/SelfDescSchemaBuildPhase.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/SelfDescSchemaBuildPhase.java b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/SelfDescSchemaBuildPhase.java
index 60187d9..a49c423 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/SelfDescSchemaBuildPhase.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/SelfDescSchemaBuildPhase.java
@@ -39,6 +39,7 @@ import org.apache.tajo.plan.rewrite.BaseSchemaBuildPhase.Processor.NameRefInSele
 import org.apache.tajo.plan.util.ExprFinder;
 import org.apache.tajo.plan.util.PlannerUtil;
 import org.apache.tajo.plan.visitor.SimpleAlgebraVisitor;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.StringUtils;
 import org.apache.tajo.util.TUtil;
 import org.apache.tajo.util.graph.DirectedGraphVisitor;
@@ -65,9 +66,9 @@ public class SelfDescSchemaBuildPhase extends LogicalPlanPreprocessPhase {
   }
 
   private static String getQualifiedName(PlanContext context, String simpleName) {
-    return CatalogUtil.isFQTableName(simpleName) ?
+    return IdentifierUtil.isFQTableName(simpleName) ?
         simpleName :
-        CatalogUtil.buildFQName(context.getQueryContext().get(SessionVars.CURRENT_DATABASE), simpleName);
+        IdentifierUtil.buildFQName(context.getQueryContext().get(SessionVars.CURRENT_DATABASE), simpleName);
   }
 
   @Override
@@ -421,7 +422,7 @@ public class SelfDescSchemaBuildPhase extends LogicalPlanPreprocessPhase {
           for (int i = 0; i < paths.length-1; i++) {
             String parentName = paths[i];
             if (i == 0) {
-              parentName = CatalogUtil.buildFQName(eachColumn.getQualifier(), parentName);
+              parentName = IdentifierUtil.buildFQName(eachColumn.getQualifier(), parentName);
             }
             // Leaf column type is TEXT; otherwise, RECORD.
             ColumnVertex childVertex = new ColumnVertex(

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/FilterPushDownRule.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/FilterPushDownRule.java b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/FilterPushDownRule.java
index 36d91bd..eb45af1 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/FilterPushDownRule.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/FilterPushDownRule.java
@@ -42,6 +42,7 @@ import org.apache.tajo.plan.rewrite.rules.FilterPushDownRule.FilterPushDownConte
 import org.apache.tajo.plan.rewrite.rules.IndexScanInfo.SimplePredicate;
 import org.apache.tajo.plan.util.PlannerUtil;
 import org.apache.tajo.plan.visitor.BasicLogicalPlanVisitor;
+import org.apache.tajo.schema.IdentifierUtil;
 
 import java.util.*;
 
@@ -742,9 +743,9 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
         if (partitionColumns != null && !partitionColumns.isEmpty() && node instanceof ScanNode) {
           ScanNode scanNode = (ScanNode)node;
           boolean isPartitionColumn = false;
-          if (CatalogUtil.isFQColumnName(partitionColumns.iterator().next())) {
+          if (IdentifierUtil.isFQColumnName(partitionColumns.iterator().next())) {
             isPartitionColumn = partitionColumns.contains(
-                CatalogUtil.buildFQName(scanNode.getTableName(), c.getSimpleName()));
+                IdentifierUtil.buildFQName(scanNode.getTableName(), c.getSimpleName()));
           } else {
             isPartitionColumn = partitionColumns.contains(c.getSimpleName());
           }
@@ -921,7 +922,7 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
         // Else partition column is a simple name
         boolean isPartitionColumn = false;
         if (hasQualifiedName) {
-          isPartitionColumn = partitionColumns.contains(CatalogUtil.buildFQName(table.getName(), column.getSimpleName()));
+          isPartitionColumn = partitionColumns.contains(IdentifierUtil.buildFQName(table.getName(), column.getSimpleName()));
         } else {
           isPartitionColumn = partitionColumns.contains(column.getSimpleName());
         }
@@ -971,8 +972,8 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
       // Index path can be identified only after filters are pushed into each scan.
       if(context.rewriteRuleContext.getQueryContext().getBool(SessionVars.INDEX_ENABLED)) {
         String databaseName, tableName;
-        databaseName = CatalogUtil.extractQualifier(table.getName());
-        tableName = CatalogUtil.extractSimpleName(table.getName());
+        databaseName = IdentifierUtil.extractQualifier(table.getName());
+        tableName = IdentifierUtil.extractSimpleName(table.getName());
         Set<Predicate> predicates = new HashSet<>();
         for (EvalNode eval : PlannerUtil.getAllEqualEvals(qual)) {
           BinaryEval binaryEval = (BinaryEval) eval;

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/PartitionedTableRewriter.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/PartitionedTableRewriter.java b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/PartitionedTableRewriter.java
index 32e41d3..54b4844 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/PartitionedTableRewriter.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/rules/PartitionedTableRewriter.java
@@ -44,6 +44,7 @@ import org.apache.tajo.plan.util.EvalNodeToExprConverter;
 import org.apache.tajo.plan.util.PlannerUtil;
 import org.apache.tajo.plan.visitor.BasicLogicalPlanVisitor;
 import org.apache.tajo.storage.StorageConstants;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.VTuple;
 import org.apache.tajo.util.StringUtils;
@@ -147,7 +148,7 @@ public class PartitionedTableRewriter implements LogicalPlanRewriteRule {
 
     Path [] filteredPaths = null;
     FileSystem fs = tablePath.getFileSystem(queryContext.getConf());
-    String [] splits = CatalogUtil.splitFQTableName(tableName);
+    String [] splits = IdentifierUtil.splitFQTableName(tableName);
     List<PartitionDescProto> partitions = null;
 
     try {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/serder/EvalNodeSerializer.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/serder/EvalNodeSerializer.java b/tajo-plan/src/main/java/org/apache/tajo/plan/serder/EvalNodeSerializer.java
index db5215b..92d59c6 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/serder/EvalNodeSerializer.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/serder/EvalNodeSerializer.java
@@ -97,7 +97,7 @@ public class EvalNodeSerializer
 
     PlanProto.EvalNode.Builder nodeBuilder = PlanProto.EvalNode.newBuilder();
     nodeBuilder.setId(sid);
-    nodeBuilder.setDataType(TypeConverter.convert(node.getValueType()));
+    nodeBuilder.setDataType(TypeConverter.convert(node.getValueType()).getDataType());
     nodeBuilder.setType(PlanProto.EvalType.valueOf(node.getType().name()));
     return nodeBuilder;
   }
@@ -119,7 +119,7 @@ public class EvalNodeSerializer
       unaryBuilder.setNegative(signedEval.isNegative());
     } else if (unary.getType() == EvalType.CAST) {
       CastEval castEval = (CastEval) unary;
-      unaryBuilder.setCastingType(TypeConverter.convert(castEval.getValueType()));
+      unaryBuilder.setCastingType(TypeConverter.convert(castEval.getValueType()).getDataType());
     }
 
     // registering itself and building EvalNode

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/serder/PlanGsonHelper.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/serder/PlanGsonHelper.java b/tajo-plan/src/main/java/org/apache/tajo/plan/serder/PlanGsonHelper.java
index 77bf103..3a64398 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/serder/PlanGsonHelper.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/serder/PlanGsonHelper.java
@@ -60,6 +60,7 @@ public class PlanGsonHelper {
     adapters.put(Datum.class, new DatumAdapter());
     adapters.put(DataType.class, new DataTypeAdapter());
     adapters.put(TimeZone.class, new TimeZoneGsonSerdeAdapter());
+    adapters.put(org.apache.tajo.type.Type.class, new TypeAdapter());
     adapters.put(Schema.class, new SchemaAdapter());
 
     return adapters;

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/util/EvalNodeToExprConverter.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/util/EvalNodeToExprConverter.java b/tajo-plan/src/main/java/org/apache/tajo/plan/util/EvalNodeToExprConverter.java
index 86f8286..2ad6b6f 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/util/EvalNodeToExprConverter.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/util/EvalNodeToExprConverter.java
@@ -145,7 +145,7 @@ public class EvalNodeToExprConverter extends SimpleEvalNodeVisitor<Object> {
 
   @Override
   protected EvalNode visitConst(Object o, ConstEval evalNode, Stack<EvalNode> stack) {
-    exprs.push(convertDatumToExpr(evalNode.getValueType().baseType(), evalNode.getValue()));
+    exprs.push(convertDatumToExpr(evalNode.getValueType().kind(), evalNode.getValue()));
     return super.visitConst(o, evalNode, stack);
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/ExprsVerifier.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/ExprsVerifier.java b/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/ExprsVerifier.java
index 2afef4a..1cf3f9c 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/ExprsVerifier.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/ExprsVerifier.java
@@ -146,8 +146,8 @@ public class ExprsVerifier extends BasicEvalNodeVisitor<VerificationState, EvalN
     org.apache.tajo.type.Type leftDataType = leftExpr.getValueType();
     org.apache.tajo.type.Type rightDataType = rightExpr.getValueType();
 
-    TajoDataTypes.Type leftType = leftDataType.baseType();
-    TajoDataTypes.Type rightType = rightDataType.baseType();
+    TajoDataTypes.Type leftType = leftDataType.kind();
+    TajoDataTypes.Type rightType = rightDataType.kind();
 
     if (leftType == DATE &&
           (checkIntType(rightDataType) ||
@@ -179,26 +179,26 @@ public class ExprsVerifier extends BasicEvalNodeVisitor<VerificationState, EvalN
   }
 
   private static boolean checkNetworkType(org.apache.tajo.type.Type dataType) {
-    return dataType.baseType() == INET4 || dataType.baseType() == INET6;
+    return dataType.kind() == INET4 || dataType.kind() == INET6;
   }
 
   private static boolean checkIntType(org.apache.tajo.type.Type dataType) {
-    int typeNumber = dataType.baseType().getNumber();
+    int typeNumber = dataType.kind().getNumber();
     return INT1.getNumber() < typeNumber && typeNumber <= INT8.getNumber();
   }
 
   private static boolean checkNumericType(org.apache.tajo.type.Type dataType) {
-    int typeNumber = dataType.baseType().getNumber();
+    int typeNumber = dataType.kind().getNumber();
     return INT1.getNumber() <= typeNumber && typeNumber <= NUMERIC.getNumber();
   }
 
   private static boolean checkTextData(org.apache.tajo.type.Type dataType) {
-    int typeNumber = dataType.baseType().getNumber();
+    int typeNumber = dataType.kind().getNumber();
     return CHAR.getNumber() <= typeNumber && typeNumber <= TEXT.getNumber();
   }
 
   private static boolean checkDateTime(org.apache.tajo.type.Type dataType) {
-    int typeNumber = dataType.baseType().getNumber();
+    int typeNumber = dataType.kind().getNumber();
     return (DATE.getNumber() <= typeNumber && typeNumber <= INTERVAL.getNumber()) ||
         (TIMEZ.getNumber() <= typeNumber && typeNumber <= TIMESTAMPZ.getNumber());
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/PreLogicalPlanVerifier.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/PreLogicalPlanVerifier.java b/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/PreLogicalPlanVerifier.java
index 7fab5ba..2b197ff 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/PreLogicalPlanVerifier.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/verifier/PreLogicalPlanVerifier.java
@@ -25,11 +25,11 @@ import org.apache.tajo.SessionVars;
 import org.apache.tajo.TajoConstants;
 import org.apache.tajo.algebra.*;
 import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.exception.*;
 import org.apache.tajo.plan.algebra.BaseAlgebraVisitor;
 import org.apache.tajo.plan.util.ExprFinder;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.validation.ConstraintViolation;
 
 import java.util.Collection;
@@ -148,10 +148,10 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor<PreLogicalPlanVer
   private boolean assertRelationExistence(Context context, String tableName) {
     String qualifiedName;
 
-    if (CatalogUtil.isFQTableName(tableName)) {
+    if (IdentifierUtil.isFQTableName(tableName)) {
       qualifiedName = tableName;
     } else {
-      qualifiedName = CatalogUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE), tableName);
+      qualifiedName = IdentifierUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE), tableName);
     }
 
     if (!catalog.existsTable(qualifiedName)) {
@@ -171,10 +171,10 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor<PreLogicalPlanVer
 
   private static String guessTableName(Context context, String givenName) {
     String qualifiedName;
-    if (CatalogUtil.isFQTableName(givenName)) {
+    if (IdentifierUtil.isFQTableName(givenName)) {
       qualifiedName = givenName;
     } else {
-      qualifiedName = CatalogUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE), givenName);
+      qualifiedName = IdentifierUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE), givenName);
     }
 
     return qualifiedName;
@@ -327,8 +327,8 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor<PreLogicalPlanVer
         } else {
           if (expr.hasTableName()) {
             String qualifiedName = expr.getTableName();
-            if (TajoConstants.EMPTY_STRING.equals(CatalogUtil.extractQualifier(expr.getTableName()))) {
-              qualifiedName = CatalogUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE),
+            if (TajoConstants.EMPTY_STRING.equals(IdentifierUtil.extractQualifier(expr.getTableName()))) {
+              qualifiedName = IdentifierUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE),
                   expr.getTableName());
             }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-sql-parser/pom.xml
----------------------------------------------------------------------
diff --git a/tajo-sql-parser/pom.xml b/tajo-sql-parser/pom.xml
index cba8af5..956e410 100644
--- a/tajo-sql-parser/pom.xml
+++ b/tajo-sql-parser/pom.xml
@@ -52,6 +52,11 @@
             </goals>
           </execution>
         </executions>
+        <configuration>
+          <excludes>
+            <exclude>**/*.tokens</exclude>
+          </excludes>
+        </configuration>
       </plugin>
       <plugin>
         <artifactId>maven-deploy-plugin</artifactId>

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLLexer.g4
----------------------------------------------------------------------
diff --git a/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLLexer.g4 b/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLLexer.g4
index 2bb3582..db2bfda 100644
--- a/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLLexer.g4
+++ b/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLLexer.g4
@@ -259,7 +259,6 @@ LESS : L E S S;
 LIST : L I S T;
 LOCATION : L O C A T I O N;
 
-MAP : M A P;
 MAX : M A X;
 MAXVALUE : M A X V A L U E;
 MICROSECONDS : M I C R O S E C O N D S;
@@ -288,7 +287,6 @@ QUARTER : Q U A R T E R;
 
 RANGE : R A N G E;
 RANK : R A N K;
-RECORD : R E C O R D;
 REGEXP : R E G E X P;
 RENAME : R E N A M E;
 REPAIR : R E P A I R;
@@ -385,6 +383,11 @@ BYTEA : B Y T E A; // alias for BLOB
 
 INET4 : I N E T '4';
 
+// complex types
+ARRAY : A R R A Y;
+MAP : M A P;
+RECORD : R E C O R D;
+
 // Operators
 Similar_To : '~';
 Not_Similar_To : '!~';

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4
----------------------------------------------------------------------
diff --git a/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4 b/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4
index 1908258..b76b5d9 100644
--- a/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4
+++ b/tajo-sql-parser/src/main/antlr4/org/apache/tajo/parser/sql/SQLParser.g4
@@ -211,7 +211,7 @@ truncate_table_statement
 
 /*
 ===============================================================================
-  11.21 <data types>
+  11.21 <drop table statement>
 ===============================================================================
 */
 
@@ -442,8 +442,7 @@ predefined_type
   | bit_type
   | binary_type
   | network_type
-  | record_type
-  | map_type
+  | complex_type
   ;
 
 character_string_type
@@ -539,6 +538,16 @@ network_type
   : INET4
   ;
 
+complex_type
+  : array_type
+  | record_type
+  | map_type
+  ;
+
+array_type
+  : ARRAY LTH data_type GTH
+  ;
+
 record_type
   : RECORD table_elements
   ;
@@ -765,10 +774,6 @@ factor
   : (sign)? numeric_primary
   ;
 
-array
-  : LEFT_PAREN numeric_value_expression (COMMA numeric_value_expression )* RIGHT_PAREN
-  ;
-
 numeric_primary
   : value_expression_primary (CAST_EXPRESSION cast_target)*
   | numeric_value_function

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-storage/tajo-storage-hdfs/src/main/java/org/apache/tajo/storage/FileTablespace.java
----------------------------------------------------------------------
diff --git a/tajo-storage/tajo-storage-hdfs/src/main/java/org/apache/tajo/storage/FileTablespace.java b/tajo-storage/tajo-storage-hdfs/src/main/java/org/apache/tajo/storage/FileTablespace.java
index ad45749..2aa2b91 100644
--- a/tajo-storage/tajo-storage-hdfs/src/main/java/org/apache/tajo/storage/FileTablespace.java
+++ b/tajo-storage/tajo-storage-hdfs/src/main/java/org/apache/tajo/storage/FileTablespace.java
@@ -40,6 +40,7 @@ import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.expr.EvalNode;
 import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.logical.NodeType;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.storage.fragment.Fragment;
 import org.apache.tajo.util.Bytes;
@@ -612,7 +613,7 @@ public class FileTablespace extends Tablespace {
   @Override
   public void createTable(TableDesc tableDesc, boolean ifNotExists) throws IOException {
     if (!tableDesc.isExternal()) {
-      String [] splitted = CatalogUtil.splitFQTableName(tableDesc.getName());
+      String [] splitted = IdentifierUtil.splitFQTableName(tableDesc.getName());
       String databaseName = splitted[0];
       String simpleTableName = splitted[1];
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/JdbcMetadataProviderBase.java
----------------------------------------------------------------------
diff --git a/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/JdbcMetadataProviderBase.java b/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/JdbcMetadataProviderBase.java
index 8f5e7a8..fb095a4 100644
--- a/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/JdbcMetadataProviderBase.java
+++ b/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/JdbcMetadataProviderBase.java
@@ -30,6 +30,7 @@ import org.apache.tajo.exception.SQLExceptionUtil;
 import org.apache.tajo.exception.TajoInternalError;
 import org.apache.tajo.exception.UndefinedTablespaceException;
 import org.apache.tajo.exception.UnsupportedDataTypeException;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.KeyValueSet;
 import org.apache.tajo.util.Pair;
 
@@ -197,7 +198,7 @@ public abstract class JdbcMetadataProviderBase implements MetadataProvider {
         final String qualifier = resultForColumns.getString("TABLE_NAME");
         final String columnName = resultForColumns.getString("COLUMN_NAME");
         final TypeDesc type = convertDataType(resultForColumns);
-        final Column c = new Column(CatalogUtil.buildFQName(databaseName, qualifier, columnName), type);
+        final Column c = new Column(IdentifierUtil.buildFQName(databaseName, qualifier, columnName), type);
 
         columns.add(new Pair<>(ordinalPos, c));
       }
@@ -224,7 +225,7 @@ public abstract class JdbcMetadataProviderBase implements MetadataProvider {
       stats.setNumRows(-1); // unknown
 
       final TableDesc table = new TableDesc(
-          CatalogUtil.buildFQName(databaseName, name),
+          IdentifierUtil.buildFQName(databaseName, name),
           schema,
           new TableMeta("rowstore", new KeyValueSet()),
           space.getTableUri(databaseName, name)

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/SQLExpressionGenerator.java
----------------------------------------------------------------------
diff --git a/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/SQLExpressionGenerator.java b/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/SQLExpressionGenerator.java
index 0b1df31..da97e32 100644
--- a/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/SQLExpressionGenerator.java
+++ b/tajo-storage/tajo-storage-jdbc/src/main/java/org/apache/tajo/storage/jdbc/SQLExpressionGenerator.java
@@ -19,13 +19,12 @@
 package org.apache.tajo.storage.jdbc;
 
 import com.google.common.base.Function;
-import org.apache.tajo.catalog.CatalogUtil;
-import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.exception.NotImplementedException;
 import org.apache.tajo.exception.TajoRuntimeException;
 import org.apache.tajo.exception.UnsupportedDataTypeException;
 import org.apache.tajo.plan.expr.*;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.type.Type;
 import org.apache.tajo.util.StringUtils;
 
@@ -145,13 +144,13 @@ public class SQLExpressionGenerator extends SimpleEvalNodeVisitor<SQLExpressionG
   protected EvalNode visitField(Context context, FieldEval field, Stack<EvalNode> stack) {
     // strip the database name
     String tableName;
-    if (CatalogUtil.isSimpleIdentifier(field.getQualifier())) {
+    if (IdentifierUtil.isSimpleIdentifier(field.getQualifier())) {
       tableName = field.getQualifier();
     } else {
-      tableName = CatalogUtil.extractSimpleName(field.getQualifier());
+      tableName = IdentifierUtil.extractSimpleName(field.getQualifier());
     }
 
-    context.append(CatalogUtil.buildFQName(tableName, field.getColumnName()));
+    context.append(IdentifierUtil.buildFQName(tableName, field.getColumnName()));
     return field;
   }
 
@@ -272,7 +271,7 @@ public class SQLExpressionGenerator extends SimpleEvalNodeVisitor<SQLExpressionG
    * @return SQL DataType
    */
   public String convertTajoTypeToSQLType(Type dataType) {
-    switch (dataType.baseType()) {
+    switch (dataType.kind()) {
     case INT1:
       return "TINYINT";
     case INT2:
@@ -286,7 +285,7 @@ public class SQLExpressionGenerator extends SimpleEvalNodeVisitor<SQLExpressionG
     case FLOAT8:
       return "DOUBLE";
     default:
-      return dataType.baseType().name();
+      return dataType.kind().name();
     }
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-storage/tajo-storage-pgsql/src/main/java/org/apache/tajo/storage/pgsql/PgSQLTablespace.java
----------------------------------------------------------------------
diff --git a/tajo-storage/tajo-storage-pgsql/src/main/java/org/apache/tajo/storage/pgsql/PgSQLTablespace.java b/tajo-storage/tajo-storage-pgsql/src/main/java/org/apache/tajo/storage/pgsql/PgSQLTablespace.java
index 8386f74..90c5201 100644
--- a/tajo-storage/tajo-storage-pgsql/src/main/java/org/apache/tajo/storage/pgsql/PgSQLTablespace.java
+++ b/tajo-storage/tajo-storage-pgsql/src/main/java/org/apache/tajo/storage/pgsql/PgSQLTablespace.java
@@ -24,6 +24,7 @@ import org.apache.tajo.exception.TajoInternalError;
 import org.apache.tajo.exception.TajoRuntimeException;
 import org.apache.tajo.exception.UndefinedTableException;
 import org.apache.tajo.plan.expr.EvalNode;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.NullScanner;
 import org.apache.tajo.storage.Scanner;
 import org.apache.tajo.storage.fragment.Fragment;
@@ -82,7 +83,7 @@ public class PgSQLTablespace extends JdbcTablespace {
   @Override
   public long getTableVolume(TableDesc table, Optional<EvalNode> filter) {
 
-    String sql = "SELECT pg_table_size('" + CatalogUtil.extractSimpleName(table.getName()) + "')";
+    String sql = "SELECT pg_table_size('" + IdentifierUtil.extractSimpleName(table.getName()) + "')";
 
     try (Statement stmt = conn.createStatement();
          ResultSet rs = stmt.executeQuery(sql)) {


[6/7] tajo git commit: TAJO-2129: Apply new type implementation to Schema and Catalog.

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/test/java/org/apache/tajo/catalog/store/TestHiveCatalogStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/test/java/org/apache/tajo/catalog/store/TestHiveCatalogStore.java b/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/test/java/org/apache/tajo/catalog/store/TestHiveCatalogStore.java
index fdb1853..1260371 100644
--- a/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/test/java/org/apache/tajo/catalog/store/TestHiveCatalogStore.java
+++ b/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/test/java/org/apache/tajo/catalog/store/TestHiveCatalogStore.java
@@ -36,6 +36,7 @@ import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.PartitionKeyProto;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageConstants;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.apache.tajo.util.KeyValueSet;
@@ -106,7 +107,7 @@ public class TestHiveCatalogStore {
         .add("c_comment", TajoDataTypes.Type.TEXT)
         .build();
 
-    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, CUSTOMER), schema, meta,
+    TableDesc table = new TableDesc(IdentifierUtil.buildFQName(DB_NAME, CUSTOMER), schema, meta,
         new Path(warehousePath, new Path(DB_NAME, CUSTOMER)).toUri());
     store.createTable(table.getProto());
     assertTrue(store.existTable(DB_NAME, CUSTOMER));
@@ -142,7 +143,7 @@ public class TestHiveCatalogStore {
         .add("r_comment", TajoDataTypes.Type.TEXT)
         .build();
 
-    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, REGION), schema, meta,
+    TableDesc table = new TableDesc(IdentifierUtil.buildFQName(DB_NAME, REGION), schema, meta,
         new Path(warehousePath, new Path(DB_NAME, REGION)).toUri());
     store.createTable(table.getProto());
     assertTrue(store.existTable(DB_NAME, REGION));
@@ -177,7 +178,7 @@ public class TestHiveCatalogStore {
         .add("r_comment", TajoDataTypes.Type.TEXT)
         .build();
 
-    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, REGION), schema, meta,
+    TableDesc table = new TableDesc(IdentifierUtil.buildFQName(DB_NAME, REGION), schema, meta,
         new Path(warehousePath, new Path(DB_NAME, REGION)).toUri());
     store.createTable(table.getProto());
     assertTrue(store.existTable(DB_NAME, REGION));
@@ -216,7 +217,7 @@ public class TestHiveCatalogStore {
         .add("s_comment", TajoDataTypes.Type.TEXT)
         .build();
 
-    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, SUPPLIER), schema, meta,
+    TableDesc table = new TableDesc(IdentifierUtil.buildFQName(DB_NAME, SUPPLIER), schema, meta,
         new Path(warehousePath, new Path(DB_NAME, SUPPLIER)).toUri());
 
     store.createTable(table.getProto());
@@ -263,7 +264,7 @@ public class TestHiveCatalogStore {
         .build();
 
 
-    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, NATION), schema, meta,
+    TableDesc table = new TableDesc(IdentifierUtil.buildFQName(DB_NAME, NATION), schema, meta,
         new Path(warehousePath, new Path(DB_NAME, NATION)).toUri());
 
     org.apache.tajo.catalog.Schema expressionSchema = SchemaBuilder.builder()
@@ -515,7 +516,7 @@ public class TestHiveCatalogStore {
     String[] tableNames = new String[]{"table1", "table2", "table3"};
 
     for(String tableName : tableNames){
-      TableDesc table = new TableDesc(CatalogUtil.buildFQName("default", tableName), schema, meta,
+      TableDesc table = new TableDesc(IdentifierUtil.buildFQName("default", tableName), schema, meta,
           new Path(warehousePath, new Path(DB_NAME, tableName)).toUri());
       store.createTable(table.getProto());
     }
@@ -567,7 +568,7 @@ public class TestHiveCatalogStore {
         .add("r_comment", TajoDataTypes.Type.TEXT)
         .build();
 
-    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, REGION), schema, meta,
+    TableDesc table = new TableDesc(IdentifierUtil.buildFQName(DB_NAME, REGION), schema, meta,
         new Path(warehousePath, new Path(DB_NAME, REGION)).toUri());
     store.createTable(table.getProto());
     assertTrue(store.existTable(DB_NAME, REGION));
@@ -602,7 +603,7 @@ public class TestHiveCatalogStore {
         .add("r_comment", TajoDataTypes.Type.TEXT)
         .build();
 
-    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, REGION), schema, meta,
+    TableDesc table = new TableDesc(IdentifierUtil.buildFQName(DB_NAME, REGION), schema, meta,
         new Path(warehousePath, new Path(DB_NAME, REGION)).toUri());
     store.createTable(table.getProto());
     assertTrue(store.existTable(DB_NAME, REGION));
@@ -640,7 +641,7 @@ public class TestHiveCatalogStore {
         .add("c_comment", TajoDataTypes.Type.TEXT)
         .build();
 
-    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, CUSTOMER), schema, meta,
+    TableDesc table = new TableDesc(IdentifierUtil.buildFQName(DB_NAME, CUSTOMER), schema, meta,
         new Path(warehousePath, new Path(DB_NAME, CUSTOMER)).toUri());
     store.createTable(table.getProto());
     assertTrue(store.existTable(DB_NAME, CUSTOMER));
@@ -663,7 +664,7 @@ public class TestHiveCatalogStore {
 
   @Test
   public void testDataTypeCompatibility() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testDataTypeCompatibility");
+    String tableName = IdentifierUtil.normalizeIdentifier("testDataTypeCompatibility");
 
     TableMeta meta = new TableMeta(BuiltinStorages.TEXT, new KeyValueSet());
 
@@ -681,7 +682,7 @@ public class TestHiveCatalogStore {
         .add("col11", TajoDataTypes.Type.DATE)
         .build();
 
-    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, tableName), schema, meta,
+    TableDesc table = new TableDesc(IdentifierUtil.buildFQName(DB_NAME, tableName), schema, meta,
       new Path(warehousePath, new Path(DB_NAME, tableName)).toUri());
     store.createTable(table.getProto());
     assertTrue(store.existTable(DB_NAME, tableName));

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/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 df40b9b..6583d4e 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
@@ -49,6 +49,7 @@ import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.NullProto;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.ReturnState;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringListResponse;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringProto;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.NetUtils;
 import org.apache.tajo.util.Pair;
 import org.apache.tajo.util.TUtil;
@@ -441,7 +442,7 @@ public class CatalogServer extends AbstractService {
 
     @Override
     public ReturnState alterTable(RpcController controller, AlterTableDescProto proto) {
-      String [] split = CatalogUtil.splitTableName(proto.getTableName());
+      String [] split = IdentifierUtil.splitTableName(proto.getTableName());
 
       if (linkedMetadataManager.existsDatabase(split[0])) {
         return errInsufficientPrivilege("alter a table in database '" + split[0] + "'");
@@ -666,7 +667,7 @@ public class CatalogServer extends AbstractService {
     @Override
     public ReturnState createTable(RpcController controller, TableDescProto request) {
 
-      String [] splitted = CatalogUtil.splitFQTableName(request.getTableName());
+      String [] splitted = IdentifierUtil.splitFQTableName(request.getTableName());
 
       String dbName = splitted[0];
       String tbName = splitted[1];
@@ -683,7 +684,7 @@ public class CatalogServer extends AbstractService {
       try {
         store.createTable(request);
         LOG.info(String.format("relation \"%s\" is added to the catalog (%s)",
-            CatalogUtil.getCanonicalTableName(dbName, tbName), bindAddress));
+            IdentifierUtil.getCanonicalTableName(dbName, tbName), bindAddress));
         return OK;
 
       } catch (Throwable t) {
@@ -713,7 +714,7 @@ public class CatalogServer extends AbstractService {
       try {
         store.dropTable(dbName, tbName);
         LOG.info(String.format("relation \"%s\" is deleted from the catalog (%s)",
-            CatalogUtil.getCanonicalTableName(dbName, tbName), bindAddress));
+            IdentifierUtil.getCanonicalTableName(dbName, tbName), bindAddress));
 
         return OK;
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/AbstractTableDescriptor.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/AbstractTableDescriptor.java b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/AbstractTableDescriptor.java
index cb071aa..1cf3e64 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/AbstractTableDescriptor.java
+++ b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/AbstractTableDescriptor.java
@@ -21,6 +21,8 @@ package org.apache.tajo.catalog.dictionary;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.proto.CatalogProtos.*;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.KeyValueSetProto;
+import org.apache.tajo.schema.IdentifierUtil;
+import org.apache.tajo.type.TypeFactory;
 
 abstract class AbstractTableDescriptor implements TableDescriptor {
   
@@ -40,13 +42,7 @@ abstract class AbstractTableDescriptor implements TableDescriptor {
       columnBuilder = ColumnProto.newBuilder();
       
       columnBuilder.setName(columnDescriptor.getName().toLowerCase());
-      if (columnDescriptor.getLength() > 0) {
-        columnBuilder.setDataType(CatalogUtil.newDataTypeWithLen(columnDescriptor.getType(),
-            columnDescriptor.getLength()));
-      } else {
-        columnBuilder.setDataType(CatalogUtil.newSimpleDataType(columnDescriptor.getType()));
-      }
-      
+      columnBuilder.setType(TypeFactory.create(columnDescriptor.getType()).getProto());
       schemaBuilder.addFields(columnBuilder.build());
     }
     
@@ -71,7 +67,7 @@ abstract class AbstractTableDescriptor implements TableDescriptor {
   public TableDescProto getTableDescription() {
     TableDescProto.Builder tableBuilder = TableDescProto.newBuilder();
     
-    tableBuilder.setTableName(CatalogUtil.buildFQName(dictionary.getSystemDatabaseName(), getTableNameString()));
+    tableBuilder.setTableName(IdentifierUtil.buildFQName(dictionary.getSystemDatabaseName(), getTableNameString()));
     tableBuilder.setPath(dictionary.getTablePath());
     
     tableBuilder.setSchema(CatalogUtil.getQualfiedSchema(

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/AbstractDBStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/AbstractDBStore.java b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/AbstractDBStore.java
index 88fabe2..2e2db6f 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/AbstractDBStore.java
+++ b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/AbstractDBStore.java
@@ -31,12 +31,14 @@ import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.*;
-import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.exception.*;
 import org.apache.tajo.plan.expr.AlgebraicUtil;
 import org.apache.tajo.plan.util.PartitionFilterAlgebraVisitor;
+import org.apache.tajo.schema.IdentifierUtil;
+import org.apache.tajo.type.TypeProtobufEncoder;
+import org.apache.tajo.type.TypeStringEncoder;
 import org.apache.tajo.util.JavaResourceUtil;
 import org.apache.tajo.util.Pair;
 
@@ -49,6 +51,8 @@ import java.util.*;
 import static org.apache.tajo.catalog.proto.CatalogProtos.AlterTablespaceProto.AlterTablespaceCommand;
 import static org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.KeyValueProto;
 import static org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.KeyValueSetProto;
+import static org.apache.tajo.schema.IdentifierUtil.extractQualifier;
+import static org.apache.tajo.schema.IdentifierUtil.extractSimpleName;
 
 public abstract class AbstractDBStore extends CatalogConstants implements CatalogStore {
   protected final Log LOG = LogFactory.getLog(getClass());
@@ -756,7 +760,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     PreparedStatement pstmt = null;
     ResultSet res = null;
 
-    String[] splitted = CatalogUtil.splitTableName(table.getTableName());
+    final String[] splitted = IdentifierUtil.splitTableName(table.getTableName());
     if (splitted.length == 1) {
       throw new TajoInternalError(
           "createTable() requires a qualified table name, but it is '" + table.getTableName() + "'");
@@ -811,9 +815,9 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
 
       String colSql =
           "INSERT INTO " + TB_COLUMNS +
-              // 1    2            3                 4                 5          6
-              " (TID, COLUMN_NAME, ORDINAL_POSITION, NESTED_FIELD_NUM, DATA_TYPE, TYPE_LENGTH)" +
-              " VALUES(?, ?, ?, ?, ?, ?) ";
+              // 1    2            3                 4
+              " (TID, COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE)" +
+              " VALUES(?, ?, ?, ?) ";
 
       if (LOG.isDebugEnabled()) {
         LOG.debug(colSql);
@@ -822,15 +826,12 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       pstmt = conn.prepareStatement(colSql);
       for (int i = 0; i < table.getSchema().getFieldsCount(); i++) {
         ColumnProto col = table.getSchema().getFields(i);
-        TajoDataTypes.DataType dataType = col.getDataType();
+        org.apache.tajo.type.Type type = TypeProtobufEncoder.decode(col.getType());
 
         pstmt.setInt(1, tableId);
-        pstmt.setString(2, CatalogUtil.extractSimpleName(col.getName()));
+        pstmt.setString(2, extractSimpleName(col.getName()));
         pstmt.setInt(3, i);
-        // the default number of nested fields is 0.
-        pstmt.setInt(4, dataType.hasNumNestedFields() ? dataType.getNumNestedFields() : 0);
-        pstmt.setString(5, dataType.getType().name());
-        pstmt.setInt(6, (col.getDataType().hasLength() ? col.getDataType().getLength() : 0));
+        pstmt.setString(4, TypeStringEncoder.encode(type));
         pstmt.addBatch();
         pstmt.clearParameters();
       }
@@ -911,7 +912,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     PreparedStatement pstmt = null;
     ResultSet res = null;
 
-    String[] splitted = CatalogUtil.splitTableName(statsProto.getTableName());
+    String[] splitted = IdentifierUtil.splitTableName(statsProto.getTableName());
     if (splitted.length == 1) {
       throw new IllegalArgumentException("updateTableStats() requires a qualified table name, but it is \""
           + statsProto.getTableName() + "\".");
@@ -978,7 +979,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       DuplicatePartitionException, UndefinedPartitionException, UndefinedColumnException, UndefinedTableException,
       UndefinedPartitionMethodException, AmbiguousTableException {
 
-    String[] splitted = CatalogUtil.splitTableName(alterTableDescProto.getTableName());
+    String[] splitted = IdentifierUtil.splitTableName(alterTableDescProto.getTableName());
     if (splitted.length == 1) {
       throw new IllegalArgumentException("alterTable() requires a qualified table name, but it is \""
           + alterTableDescProto.getTableName() + "\".");
@@ -993,7 +994,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
 
     switch (alterTableDescProto.getAlterTableType()) {
     case RENAME_TABLE:
-      String simpleNewTableName = CatalogUtil.extractSimpleName(alterTableDescProto.getNewTableName());
+      String simpleNewTableName = extractSimpleName(alterTableDescProto.getNewTableName());
       if (existTable(databaseName, simpleNewTableName)) {
         throw new DuplicateTableException(alterTableDescProto.getNewTableName());
       }
@@ -1149,13 +1150,13 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       throws UndefinedColumnException, AmbiguousTableException {
 
     final String selectColumnSql =
-        "SELECT COLUMN_NAME, DATA_TYPE, TYPE_LENGTH, ORDINAL_POSITION, NESTED_FIELD_NUM from " + TB_COLUMNS +
+        "SELECT COLUMN_NAME, DATA_TYPE, ORDINAL_POSITION from " + TB_COLUMNS +
             " WHERE " + COL_TABLES_PK + " = ?" + " AND COLUMN_NAME = ?" ;
     final String deleteColumnNameSql =
         "DELETE FROM " + TB_COLUMNS + " WHERE TID = ? AND COLUMN_NAME = ?";
     final String insertNewColumnSql =
         "INSERT INTO " + TB_COLUMNS +
-            " (TID, COLUMN_NAME, ORDINAL_POSITION, NESTED_FIELD_NUM, DATA_TYPE, TYPE_LENGTH) VALUES(?, ?, ?, ?, ?, ?) ";
+            " (TID, COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE) VALUES(?, ?, ?, ?) ";
 
     if (LOG.isDebugEnabled()) {
       LOG.debug(selectColumnSql);
@@ -1172,13 +1173,13 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       conn = getConnection();
       conn.setAutoCommit(false);
 
-      String tableName = CatalogUtil.extractQualifier(alterColumnProto.getOldColumnName());
-      String simpleOldColumnName = CatalogUtil.extractSimpleName(alterColumnProto.getOldColumnName());
-      String simpleNewColumnName = CatalogUtil.extractSimpleName(alterColumnProto.getNewColumnName());
+      String tableName = extractQualifier(alterColumnProto.getOldColumnName());
+      String simpleOldColumnName = extractSimpleName(alterColumnProto.getOldColumnName());
+      String simpleNewColumnName = extractSimpleName(alterColumnProto.getNewColumnName());
 
-      if (!tableName.equals(CatalogUtil.extractQualifier(alterColumnProto.getNewColumnName()))) {
+      if (!tableName.equals(extractQualifier(alterColumnProto.getNewColumnName()))) {
         throw new AmbiguousTableException(
-            tableName + ", " + CatalogUtil.extractQualifier(alterColumnProto.getNewColumnName()));
+            tableName + ", " + extractQualifier(alterColumnProto.getNewColumnName()));
       }
 
       //SELECT COLUMN
@@ -1188,15 +1189,15 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       resultSet = pstmt.executeQuery();
 
       CatalogProtos.ColumnProto columnProto = null;
+      String typeStr;
       int ordinalPosition = 0;
-      int nestedFieldNum = 0;
 
       if (resultSet.next()) {
         columnProto = resultToColumnProto(resultSet);
         //NOTE ==> Setting new column Name
         columnProto = columnProto.toBuilder().setName(alterColumnProto.getNewColumnName()).build();
         ordinalPosition = resultSet.getInt("ORDINAL_POSITION");
-        nestedFieldNum = resultSet.getInt("NESTED_FIELD_NUM");
+        typeStr = TypeStringEncoder.encode(TypeProtobufEncoder.decode(columnProto.getType()));
       } else {
         throw new UndefinedColumnException(alterColumnProto.getOldColumnName());
       }
@@ -1217,9 +1218,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       pstmt.setInt(1, tableId);
       pstmt.setString(2, simpleNewColumnName);
       pstmt.setInt(3, ordinalPosition);
-      pstmt.setInt(4, nestedFieldNum);
-      pstmt.setString(5, columnProto.getDataType().getType().name());
-      pstmt.setInt(6, (columnProto.getDataType().hasLength() ? columnProto.getDataType().getLength() : 0));
+      pstmt.setString(4, typeStr);
       pstmt.executeUpdate();
 
       conn.commit();
@@ -1243,7 +1242,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
 
     final String insertNewColumnSql =
         "INSERT INTO " + TB_COLUMNS +
-            " (TID, COLUMN_NAME, ORDINAL_POSITION, NESTED_FIELD_NUM, DATA_TYPE, TYPE_LENGTH) VALUES(?, ?, ?, ?, ?, ?) ";
+            " (TID, COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE) VALUES(?, ?, ?, ?) ";
     final String columnCountSql =
         "SELECT MAX(ORDINAL_POSITION) AS POSITION FROM " + TB_COLUMNS + " WHERE TID = ?";
 
@@ -1251,7 +1250,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       conn = getConnection();
       pstmt = conn.prepareStatement(existColumnSql);
       pstmt.setInt(1, tableId);
-      pstmt.setString(2, CatalogUtil.extractSimpleName(columnProto.getName()));
+      pstmt.setString(2, extractSimpleName(columnProto.getName()));
       resultSet =  pstmt.executeQuery();
 
       if (resultSet.next()) {
@@ -1271,15 +1270,13 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       pstmt.close();
       resultSet = null;
 
-      TajoDataTypes.DataType dataType = columnProto.getDataType();
+      org.apache.tajo.type.Type type = TypeProtobufEncoder.decode(columnProto.getType());
 
       pstmt = conn.prepareStatement(insertNewColumnSql);
       pstmt.setInt(1, tableId);
-      pstmt.setString(2, CatalogUtil.extractSimpleName(columnProto.getName()));
+      pstmt.setString(2, extractSimpleName(columnProto.getName()));
       pstmt.setInt(3, position + 1);
-      pstmt.setInt(4, dataType.hasNumNestedFields() ? dataType.getNumNestedFields() : 0);
-      pstmt.setString(5, dataType.getType().name());
-      pstmt.setInt(6, (columnProto.getDataType().hasLength() ? columnProto.getDataType().getLength() : 0));
+      pstmt.setString(4, TypeStringEncoder.encode(type));
       pstmt.executeUpdate();
 
     } catch (SQLException sqlException) {
@@ -1600,7 +1597,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       }
 
       int tableId = res.getInt(1);
-      tableBuilder.setTableName(CatalogUtil.buildFQName(databaseName, res.getString(2).trim()));
+      tableBuilder.setTableName(IdentifierUtil.buildFQName(databaseName, res.getString(2).trim()));
       TableType tableType = TableType.valueOf(res.getString(3));
       if (tableType == TableType.EXTERNAL) {
         tableBuilder.setIsExternal(true);
@@ -1618,7 +1615,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
         // Geting Column Descriptions
         //////////////////////////////////////////
         CatalogProtos.SchemaProto.Builder schemaBuilder = CatalogProtos.SchemaProto.newBuilder();
-        sql = "SELECT COLUMN_NAME, NESTED_FIELD_NUM, DATA_TYPE, TYPE_LENGTH from " + TB_COLUMNS +
+        sql = "SELECT COLUMN_NAME, DATA_TYPE from " + TB_COLUMNS +
             " WHERE " + COL_TABLES_PK + " = ? ORDER BY ORDINAL_POSITION ASC";
 
         if (LOG.isDebugEnabled()) {
@@ -1847,7 +1844,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
 
     try {
       String sql =
-              "SELECT TID, COLUMN_NAME, ORDINAL_POSITION, NESTED_FIELD_NUM, DATA_TYPE, TYPE_LENGTH FROM " + TB_COLUMNS +
+              "SELECT TID, COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE FROM " + TB_COLUMNS +
                       " ORDER BY TID ASC, ORDINAL_POSITION ASC";
 
       conn = getConnection();
@@ -1860,21 +1857,9 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
         String databaseName = getDatabaseNameOfTable(conn, tid);
         String tableName = getTableName(conn, tid);
         builder.setTid(tid);
-        builder.setName(CatalogUtil.buildFQName(databaseName, tableName, resultSet.getString("COLUMN_NAME")));
-
-        int nestedFieldNum = resultSet.getInt("NESTED_FIELD_NUM");
-
-        Type type = getDataType(resultSet.getString("DATA_TYPE").trim());
-        int typeLength = resultSet.getInt("TYPE_LENGTH");
-
-        if (nestedFieldNum > 0) {
-          builder.setDataType(CatalogUtil.newRecordType(nestedFieldNum));
-        } else if (typeLength > 0) {
-          builder.setDataType(CatalogUtil.newDataTypeWithLen(type, typeLength));
-        } else {
-          builder.setDataType(CatalogUtil.newSimpleDataType(type));
-        }
-        
+        builder.setName(IdentifierUtil.buildFQName(databaseName, tableName, resultSet.getString("COLUMN_NAME")));
+        org.apache.tajo.type.Type type = TypeStringEncoder.decode(resultSet.getString("DATA_TYPE").trim());
+        builder.setType(type.getProto());
         columns.add(builder.build());
       }
     } catch (SQLException se) {
@@ -2484,7 +2469,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     PreparedStatement pstmt = null;
 
     final String databaseName = proto.getTableIdentifier().getDatabaseName();
-    final String tableName = CatalogUtil.extractSimpleName(proto.getTableIdentifier().getTableName());
+    final String tableName = extractSimpleName(proto.getTableIdentifier().getTableName());
 
     try {
 
@@ -2529,7 +2514,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
         // Since the key columns are always sorted in order of their occurrence position in the relation schema,
         // the concatenated name can be uniquely identified.
         columnNamesBuilder.append(columnSpec.getSortKey().getSimpleName()).append(",");
-        dataTypesBuilder.append(columnSpec.getSortKey().getDataType().getType().name()).append(",");
+        dataTypesBuilder.append(columnSpec.getSortKey().getDataType().getType().name()).append("|");
         ordersBuilder.append(columnSpec.isAscending()).append(",");
         nullOrdersBuilder.append(columnSpec.isNullsFirst()).append(",");
       }
@@ -2576,7 +2561,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       pstmt.setString(2, indexName);
       ResultSet res = pstmt.executeQuery();
       if (!res.next()) {
-        throw new UndefinedIndexException(CatalogUtil.buildFQName(databaseName, indexName));
+        throw new UndefinedIndexException(IdentifierUtil.buildFQName(databaseName, indexName));
       }
       pstmt.close();
       res.close();
@@ -2676,7 +2661,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       IndexDescProto.Builder builder = IndexDescProto.newBuilder();
       String tableName = getTableName(conn, res.getInt(COL_TABLES_PK));
       builder.setTableIdentifier(CatalogUtil.buildTableIdentifier(databaseName, tableName));
-      resultToIndexDescProtoBuilder(CatalogUtil.buildFQName(databaseName, tableName), builder, res);
+      resultToIndexDescProtoBuilder(IdentifierUtil.buildFQName(databaseName, tableName), builder, res);
 
       try {
         builder.setTargetRelationSchema(getTable(databaseName, tableName).getSchema());
@@ -2727,7 +2712,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       }
 
       IndexDescProto.Builder builder = IndexDescProto.newBuilder();
-      resultToIndexDescProtoBuilder(CatalogUtil.buildFQName(databaseName, tableName), builder, res);
+      resultToIndexDescProtoBuilder(IdentifierUtil.buildFQName(databaseName, tableName), builder, res);
       builder.setTableIdentifier(CatalogUtil.buildTableIdentifier(databaseName, tableName));
       builder.setTargetRelationSchema(tableDescProto.getSchema());
       proto = builder.build();
@@ -2897,14 +2882,14 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     builder.setIndexPath(res.getString("path"));
     String[] columnNames, dataTypes, orders, nullOrders;
     columnNames = res.getString("column_names").trim().split(",");
-    dataTypes = res.getString("data_types").trim().split(",");
+    dataTypes = res.getString("data_types").trim().split("\\|");
     orders = res.getString("orders").trim().split(",");
     nullOrders = res.getString("null_orders").trim().split(",");
     int columnNum = columnNames.length;
     for (int i = 0; i < columnNum; i++) {
       SortSpecProto.Builder colSpecBuilder = SortSpecProto.newBuilder();
-      colSpecBuilder.setColumn(ColumnProto.newBuilder().setName(CatalogUtil.buildFQName(qualifier, columnNames[i]))
-          .setDataType(CatalogUtil.newSimpleDataType(getDataType(dataTypes[i]))).build());
+      colSpecBuilder.setColumn(ColumnProto.newBuilder().setName(IdentifierUtil.buildFQName(qualifier, columnNames[i]))
+          .setType(TypeStringEncoder.decode(dataTypes[i]).getProto()).build());
       colSpecBuilder.setAscending(orders[i].equals("true"));
       colSpecBuilder.setNullFirst(nullOrders[i].equals("true"));
       builder.addKeySortSpecs(colSpecBuilder.build());
@@ -2916,20 +2901,8 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
   private ColumnProto resultToColumnProto(final ResultSet res) throws SQLException {
     ColumnProto.Builder builder = ColumnProto.newBuilder();
     builder.setName(res.getString("column_name").trim());
-
-    int nestedFieldNum = res.getInt("NESTED_FIELD_NUM");
-
-    Type type = getDataType(res.getString("data_type").trim());
-    int typeLength = res.getInt("type_length");
-
-    if (nestedFieldNum > 0) {
-      builder.setDataType(CatalogUtil.newRecordType(nestedFieldNum));
-    } else if (typeLength > 0) {
-      builder.setDataType(CatalogUtil.newDataTypeWithLen(type, typeLength));
-    } else {
-      builder.setDataType(CatalogUtil.newSimpleDataType(type));
-    }
-
+    org.apache.tajo.type.Type type = TypeStringEncoder.decode(res.getString("data_type").trim());
+    builder.setType(type.getProto());
     return builder.build();
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/derby.xml
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/derby.xml b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/derby.xml
index 96100e8..70ef436 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/derby.xml
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/derby.xml
@@ -19,6 +19,7 @@
 <tns:store xmlns:tns="http://tajo.apache.org/catalogstore" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tajo.apache.org/catalogstore ../DBMSSchemaDefinition.xsd ">
   <!--
       Catalog base version history
+      * 13 - 2016-05-10: Apply new type implementation to Schema and Catalog. (TAJO-2129)
       * 12 - 2015-09-28: Change the variable name storeType to dataFormat (TAJO-1663)
       * 11 - 2015-09-23: Add contents length and file count for partition directory (TAJO-1493)
       * 10 - 2015-09-22: Well support for self-describing data formats (TAJO-1832)
@@ -88,9 +89,7 @@
   				TID INT NOT NULL REFERENCES TABLES (TID) ON DELETE CASCADE,
   				COLUMN_NAME VARCHAR(128) NOT NULL,
   				ORDINAL_POSITION INTEGER NOT NULL,
-  				NESTED_FIELD_NUM INTEGER NOT NULL,
-  				DATA_TYPE CHAR(16),
-  				TYPE_LENGTH INTEGER,
+  				DATA_TYPE VARCHAR(8192),
   				CONSTRAINT COLUMNS_PK PRIMARY KEY (TID, ORDINAL_POSITION)
 				)]]>
 				</tns:sql>

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mariadb/mariadb.xml
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mariadb/mariadb.xml b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mariadb/mariadb.xml
index 4611e70..cb4cddf 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mariadb/mariadb.xml
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mariadb/mariadb.xml
@@ -19,6 +19,7 @@
 <tns:store xmlns:tns="http://tajo.apache.org/catalogstore" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tajo.apache.org/catalogstore ../DBMSSchemaDefinition.xsd ">
   <!--
       Catalog base version history
+      * 14 - 2016-05-10: Apply new type implementation to Schema and Catalog. (TAJO-2129)
       * 13 - 2016-05-07: Add some missing index to MariaDBStore (TAJO-2117)
       * 12 - 2015-09-28: Change the variable name storeType to dataFormat (TAJO-1663)
       * 11 - 2015-09-23: Add contents length and file count for partition directory (TAJO-1493)
@@ -82,9 +83,7 @@
           TID INT NOT NULL,
           COLUMN_NAME VARCHAR(255) BINARY NOT NULL,
           ORDINAL_POSITION INT NOT NULL,
-          NESTED_FIELD_NUM INT NOT NULL,
-          DATA_TYPE CHAR(16),
-          TYPE_LENGTH INTEGER,
+          DATA_TYPE VARCHAR(8192),
           PRIMARY KEY (TID, ORDINAL_POSITION),
           FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE
         )]]>

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/mysql.xml
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/mysql.xml b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/mysql.xml
index c0dadaa..177f1ae 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/mysql.xml
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/mysql.xml
@@ -19,6 +19,7 @@
 <tns:store xmlns:tns="http://tajo.apache.org/catalogstore" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tajo.apache.org/catalogstore ../DBMSSchemaDefinition.xsd ">
   <!--
     Catalog base version history
+    * 13 - 2016-05-10: Apply new type implementation to Schema and Catalog. (TAJO-2129)
     * 12 - 2015-09-28: Change the variable name storeType to dataFormat (TAJO-1663)
     * 11 - 2015-09-23: Add contents length and file count for partition directory (TAJO-1493)
     * 10 - 2015-09-22: Well support for self-describing data formats (TAJO-1832)
@@ -81,9 +82,7 @@
           TID INT NOT NULL,
           COLUMN_NAME VARCHAR(255) BINARY NOT NULL,
           ORDINAL_POSITION INT NOT NULL,
-          NESTED_FIELD_NUM INT NOT NULL,
-          DATA_TYPE CHAR(16),
-          TYPE_LENGTH INTEGER,
+          DATA_TYPE VARCHAR(8192),
           PRIMARY KEY (TID, ORDINAL_POSITION),
           FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE
         )]]>

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/oracle/oracle.xml
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/oracle/oracle.xml b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/oracle/oracle.xml
index 190270c..7caa941 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/oracle/oracle.xml
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/oracle/oracle.xml
@@ -19,6 +19,7 @@
 <tns:store xmlns:tns="http://tajo.apache.org/catalogstore" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tajo.apache.org/catalogstore ../DBMSSchemaDefinition.xsd ">
   <!--
       Catalog base version history
+      * 13 - 2016-05-10: Apply new type implementation to Schema and Catalog. (TAJO-2129)
       * 12 - 2015-09-28: Change the variable name storeType to dataFormat (TAJO-1663)
       * 11 - 2015-09-23: Add contents length and file count for partition directory (TAJO-1493)
       * 10 - 2015-09-22: Well support for self-describing data formats (TAJO-1832)
@@ -134,9 +135,7 @@
 					TID INT NOT NULL,
 					COLUMN_NAME VARCHAR2(255) NOT NULL,
 					ORDINAL_POSITION INT NOT NULL,
-					NESTED_FIELD_NUM INT NOT NULL,
-					DATA_TYPE CHAR(16),
-					TYPE_LENGTH INTEGER,
+					DATA_TYPE VARCHAR(8192),
 					CONSTRAINT COLUMNS_PKEY PRIMARY KEY (TID, ORDINAL_POSITION),
 					FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE
 				)]]>

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/postgresql/postgresql.xml
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/postgresql/postgresql.xml b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/postgresql/postgresql.xml
index 33a1fd2..f5678e9 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/postgresql/postgresql.xml
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/postgresql/postgresql.xml
@@ -21,6 +21,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://tajo.apache.org/catalogstore ../DBMSSchemaDefinition.xsd ">
   <!--
       Catalog base version history
+      * 13 - 2016-05-10: Apply new type implementation to Schema and Catalog. (TAJO-2129)
       * 12 - 2015-09-28: Change the variable name storeType to dataFormat (TAJO-1663)
       * 11 - 2015-09-23: Add contents length and file count for partition directory (TAJO-1493)
       * 10 - 2015-09-22: Well support for self-describing data formats (TAJO-1832)
@@ -94,9 +95,7 @@ xsi:schemaLocation="http://tajo.apache.org/catalogstore ../DBMSSchemaDefinition.
   				TID INT NOT NULL,
   				COLUMN_NAME VARCHAR(255) NOT NULL,
   				ORDINAL_POSITION INT NOT NULL,
-  				NESTED_FIELD_NUM INT NOT NULL,
-  				DATA_TYPE CHAR(16),
-  				TYPE_LENGTH INTEGER,
+  				DATA_TYPE VARCHAR(8192),
   				CONSTRAINT COLUMNS_PKEY PRIMARY KEY (TID, ORDINAL_POSITION),
   				FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE
 				)]]>

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/CatalogTestingUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/CatalogTestingUtil.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/CatalogTestingUtil.java
index 3305801..0b69de0 100644
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/CatalogTestingUtil.java
+++ b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/CatalogTestingUtil.java
@@ -33,6 +33,7 @@ import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.conf.TajoConf.ConfVars;
 import org.apache.tajo.exception.UnsupportedCatalogStore;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.KeyValueSet;
 
 import java.io.IOException;
@@ -184,10 +185,10 @@ public class CatalogTestingUtil {
   }
 
   public static void cleanupBaseData(CatalogService catalog) throws Exception {
-    catalog.dropTable(CatalogUtil.buildFQName("TestDatabase1", "testPartition1"));
-    catalog.dropTable(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
-    catalog.dropTable(CatalogUtil.buildFQName("TestDatabase1", "TestTable1"));
-    catalog.dropTable(CatalogUtil.buildFQName("TestDatabase1", "testTable1"));
+    catalog.dropTable(IdentifierUtil.buildFQName("TestDatabase1", "testPartition1"));
+    catalog.dropTable(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    catalog.dropTable(IdentifierUtil.buildFQName("TestDatabase1", "TestTable1"));
+    catalog.dropTable(IdentifierUtil.buildFQName("TestDatabase1", "testTable1"));
 
     catalog.dropDatabase("TestDatabase1");
     catalog.dropDatabase("testDatabase1");
@@ -198,13 +199,13 @@ public class CatalogTestingUtil {
 
   public static TableDesc buildTableDesc(String databaseName, String tableName, String testDir) throws IOException {
     Schema schema = SchemaBuilder.builder()
-        .add(CatalogUtil.buildFQName(tableName, "Column"), Type.BLOB)
-        .add(CatalogUtil.buildFQName(tableName, "column"), Type.INT4)
-        .add(CatalogUtil.buildFQName(tableName, "cOlumn"), Type.INT8)
+        .add(IdentifierUtil.buildFQName(tableName, "Column"), Type.BLOB)
+        .add(IdentifierUtil.buildFQName(tableName, "column"), Type.INT4)
+        .add(IdentifierUtil.buildFQName(tableName, "cOlumn"), Type.INT8)
         .build();
     Path path = new Path(testDir + "/" + UUID.randomUUID().toString(), tableName);
     TableDesc desc = new TableDesc(
-        CatalogUtil.buildFQName(databaseName, tableName),
+        IdentifierUtil.buildFQName(databaseName, tableName),
         schema,
         new TableMeta("TEXT", new KeyValueSet()),
         path.toUri(), true);
@@ -215,8 +216,8 @@ public class CatalogTestingUtil {
 
   public static TableDesc buildPartitionTableDesc(String databaseName, String tableName, String testDir) throws Exception {
     Schema partSchema = SchemaBuilder.builder()
-        .add(CatalogUtil.buildFQName(tableName, "DaTe"), Type.TEXT)
-        .add(CatalogUtil.buildFQName(tableName, "dAtE"), Type.TEXT)
+        .add(IdentifierUtil.buildFQName(tableName, "DaTe"), Type.TEXT)
+        .add(IdentifierUtil.buildFQName(tableName, "dAtE"), Type.TEXT)
         .build();
     PartitionMethodDesc partitionMethodDesc =
         new PartitionMethodDesc(DEFAULT_DATABASE_NAME, tableName,
@@ -254,7 +255,7 @@ public class CatalogTestingUtil {
     for (int i = 0; i < cols.length; i++) {
       colSpecs[i] = new SortSpec(cols[i], true, false);
     }
-    return new IndexDesc(databaseName, CatalogUtil.extractSimpleName(table.getName()),
+    return new IndexDesc(databaseName, IdentifierUtil.extractSimpleName(table.getName()),
         indexName, new URI("idx_test"), colSpecs,
         IndexMethod.TWO_LEVEL_BIN_TREE, true, true, table.getSchema());
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/MiniCatalogServer.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/MiniCatalogServer.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/MiniCatalogServer.java
index da375b2..edba45c 100644
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/MiniCatalogServer.java
+++ b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/MiniCatalogServer.java
@@ -21,6 +21,7 @@ package org.apache.tajo.catalog;
 import org.apache.tajo.TajoConstants;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.exception.*;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.CommonTestingUtil;
 
 import java.io.IOException;
@@ -83,7 +84,7 @@ public class MiniCatalogServer extends CatalogServer {
   public void cleanup() throws UndefinedTableException, InsufficientPrivilegeException, UndefinedDatabaseException,
       UndefinedTablespaceException {
     for (String table : catalog.getAllTableNames(DEFAULT_DATABASE_NAME)) {
-      catalog.dropTable(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, table));
+      catalog.dropTable(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, table));
     }
     for (String database : catalog.getAllDatabaseNames()) {
       if (!database.equals(TajoConstants.DEFAULT_DATABASE_NAME) &&

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalog.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalog.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalog.java
index 14d6e30..f0cb208 100644
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalog.java
+++ b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalog.java
@@ -33,6 +33,7 @@ import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.exception.UndefinedFunctionException;
 import org.apache.tajo.function.Function;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.apache.tajo.util.KeyValueSet;
 import org.apache.tajo.util.TUtil;
@@ -189,7 +190,7 @@ public class TestCatalog {
         .build();
     Path path = new Path(CommonTestingUtil.getTestDir(), tableName);
     TableDesc table = new TableDesc(
-        CatalogUtil.buildFQName(databaseName, tableName),
+        IdentifierUtil.buildFQName(databaseName, tableName),
         schema1,
         new TableMeta("TEXT", new KeyValueSet()),
         path.toUri(), true);
@@ -290,7 +291,7 @@ public class TestCatalog {
         Collection<String> tablesForThisDatabase = catalog.getAllTableNames(entry.getKey());
         assertEquals(createdTablesMap.get(entry.getKey()).size(), tablesForThisDatabase.size());
         for (String tableName : tablesForThisDatabase) {
-          assertTrue(createdTablesMap.get(entry.getKey()).contains(CatalogUtil.extractSimpleName(tableName)));
+          assertTrue(createdTablesMap.get(entry.getKey()).contains(IdentifierUtil.extractSimpleName(tableName)));
         }
       }
     }
@@ -308,7 +309,7 @@ public class TestCatalog {
         .build();
     Path path = new Path(CommonTestingUtil.getTestDir(), "table1");
     TableDesc meta = new TableDesc(
-        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "getTable"),
+        IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "getTable"),
         schema1,
         "TEXT",
         new KeyValueSet(),
@@ -318,7 +319,7 @@ public class TestCatalog {
     catalog.createTable(meta);
     assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, "getTable"));
 
-    catalog.dropTable(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "getTable"));
+    catalog.dropTable(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "getTable"));
     assertFalse(catalog.existsTable(DEFAULT_DATABASE_NAME, "getTable"));
 	}
 
@@ -328,7 +329,7 @@ public class TestCatalog {
   private static void assertSchemaEquality(String tableName, Schema schema) throws IOException, TajoException {
     Path path = new Path(CommonTestingUtil.getTestDir(), tableName);
     TableDesc tableDesc = new TableDesc(
-        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName),
+        IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName),
         schema,
         "TEXT",
         new KeyValueSet(),
@@ -340,12 +341,12 @@ public class TestCatalog {
     assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     // change it for the equals test.
-    schema.setQualifier(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName));
+    schema.setQualifier(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName));
     TableDesc restored = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
     assertEquals(schema, restored.getSchema());
 
     // drop test
-    catalog.dropTable(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName));
+    catalog.dropTable(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName));
     assertFalse(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
   }
 
@@ -436,7 +437,7 @@ public class TestCatalog {
 
     TableMeta meta = CatalogUtil.newTableMeta(BuiltinStorages.TEXT, server.getConf());
     return new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, tableName), relationSchema, meta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, tableName), relationSchema, meta,
         new Path(CommonTestingUtil.getTestDir(), "indexed").toUri());
   }
 
@@ -632,7 +633,7 @@ public class TestCatalog {
         .add("score", Type.FLOAT8)
         .build();
 
-    String tableName = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "addedtable");
+    String tableName = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "addedtable");
     KeyValueSet opts = new KeyValueSet();
     opts.set("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta("TEXT", opts);
@@ -674,7 +675,7 @@ public class TestCatalog {
         .add("score", Type.FLOAT8)
         .build();
 
-    String tableName = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "addedtable");
+    String tableName = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "addedtable");
     KeyValueSet opts = new KeyValueSet();
     opts.set("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta("TEXT", opts);
@@ -714,7 +715,7 @@ public class TestCatalog {
         .add("score", Type.FLOAT8)
         .build();
 
-    String tableName = CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "addedtable");
+    String tableName = IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "addedtable");
     KeyValueSet opts = new KeyValueSet();
     opts.set("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta("TEXT", opts);
@@ -753,7 +754,7 @@ public class TestCatalog {
         .add("score", Type.FLOAT8)
         .build();
 
-    String tableName = CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "addedtable");
+    String tableName = IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "addedtable");
     KeyValueSet opts = new KeyValueSet();
     opts.set("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta("TEXT", opts);
@@ -793,7 +794,7 @@ public class TestCatalog {
         .build();
 
     String simpleTableName = "addedtable";
-    String tableName = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, simpleTableName);
+    String tableName = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, simpleTableName);
     KeyValueSet opts = new KeyValueSet();
     opts.set("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta("TEXT", opts);
@@ -944,7 +945,7 @@ public class TestCatalog {
 
     catalog.alterTable(alterTableDesc);
 
-    String [] split = CatalogUtil.splitFQTableName(tableName);
+    String [] split = IdentifierUtil.splitFQTableName(tableName);
 
     CatalogProtos.PartitionDescProto resultDesc = catalog.getPartition(split[0], split[1], partitionName);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogAgainstCaseSensitivity.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogAgainstCaseSensitivity.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogAgainstCaseSensitivity.java
index 6b7e458..cab2e49 100644
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogAgainstCaseSensitivity.java
+++ b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogAgainstCaseSensitivity.java
@@ -27,6 +27,7 @@ import org.apache.tajo.catalog.statistics.TableStats;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.exception.UndefinedPartitionException;
 import org.apache.tajo.exception.UndefinedTableException;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -112,7 +113,7 @@ public class TestCatalogAgainstCaseSensitivity {
       tableDescs.put(desc.getName(), desc);
     }
     for (TableDescriptorProto eachTableDescriptor : catalog.getAllTables()) {
-      String qualifiedTableName = CatalogUtil.buildFQName("TestDatabase1", eachTableDescriptor.getName());
+      String qualifiedTableName = IdentifierUtil.buildFQName("TestDatabase1", eachTableDescriptor.getName());
       assertTrue(tableDescs.containsKey(qualifiedTableName));
       TableDesc desc = tableDescs.get(qualifiedTableName);
       assertEquals(desc.getUri().toString(), eachTableDescriptor.getPath());
@@ -129,13 +130,13 @@ public class TestCatalogAgainstCaseSensitivity {
 
     AlterTableDesc alterTableDesc = new AlterTableDesc();
     alterTableDesc.setAlterTableType(AlterTableType.RENAME_TABLE);
-    alterTableDesc.setNewTableName(CatalogUtil.buildFQName("TestDatabase1", "renamed_table"));
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "newTable"));
+    alterTableDesc.setNewTableName(IdentifierUtil.buildFQName("TestDatabase1", "renamed_table"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "newTable"));
     catalog.alterTable(alterTableDesc);
 
     assertFalse(catalog.existsTable("TestDatabase1", "newTable"));
     assertTrue(catalog.existsTable("TestDatabase1", "renamed_table"));
-    catalog.dropTable(CatalogUtil.buildFQName("TestDatabase1", "renamed_table"));
+    catalog.dropTable(IdentifierUtil.buildFQName("TestDatabase1", "renamed_table"));
 
     //////////////////////////////////////////////////////////////////////////////
     // table stats
@@ -177,7 +178,7 @@ public class TestCatalogAgainstCaseSensitivity {
     PartitionDesc partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.ADD_PARTITION);
 
@@ -195,7 +196,7 @@ public class TestCatalogAgainstCaseSensitivity {
     partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.ADD_PARTITION);
 
@@ -243,7 +244,7 @@ public class TestCatalogAgainstCaseSensitivity {
     partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.DROP_PARTITION);
     catalog.alterTable(alterTableDesc);
@@ -259,7 +260,7 @@ public class TestCatalogAgainstCaseSensitivity {
     partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.DROP_PARTITION);
     catalog.alterTable(alterTableDesc);
@@ -282,32 +283,32 @@ public class TestCatalogAgainstCaseSensitivity {
     //////////////////////////////////////////////////////////////////////////////
 
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setAddColumn(new Column(CatalogUtil.buildFQName(databaseName, tableName, "AddedCol1"),
+    alterTableDesc.setAddColumn(new Column(IdentifierUtil.buildFQName(databaseName, tableName, "AddedCol1"),
         CatalogUtil.newSimpleDataType(Type.BLOB)));
-    alterTableDesc.setTableName(CatalogUtil.buildFQName(databaseName, tableName));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName(databaseName, tableName));
     alterTableDesc.setAlterTableType(AlterTableType.ADD_COLUMN);
     catalog.alterTable(alterTableDesc);
 
     TableDesc tableDesc = catalog.getTableDesc(databaseName, tableName);
     assertTrue(
-        tableDesc.getSchema().containsByQualifiedName(CatalogUtil.buildFQName(databaseName, tableName, "AddedCol1")));
+        tableDesc.getSchema().containsByQualifiedName(IdentifierUtil.buildFQName(databaseName, tableName, "AddedCol1")));
 
     //////////////////////////////////////////////////////////////////////////////
     // Test rename column
     //////////////////////////////////////////////////////////////////////////////
 
     alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setColumnName(CatalogUtil.buildFQName(databaseName, tableName, "AddedCol1"));
-    alterTableDesc.setNewColumnName(CatalogUtil.buildFQName(databaseName, tableName, "addedcol1"));
-    alterTableDesc.setTableName(CatalogUtil.buildFQName(databaseName, tableName));
+    alterTableDesc.setColumnName(IdentifierUtil.buildFQName(databaseName, tableName, "AddedCol1"));
+    alterTableDesc.setNewColumnName(IdentifierUtil.buildFQName(databaseName, tableName, "addedcol1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName(databaseName, tableName));
     alterTableDesc.setAlterTableType(AlterTableType.RENAME_COLUMN);
     catalog.alterTable(alterTableDesc);
 
     tableDesc = catalog.getTableDesc(databaseName, tableName);
     assertFalse(
-        tableDesc.getSchema().containsByQualifiedName(CatalogUtil.buildFQName(databaseName, tableName, "AddedCol1")));
+        tableDesc.getSchema().containsByQualifiedName(IdentifierUtil.buildFQName(databaseName, tableName, "AddedCol1")));
     assertTrue(
-        tableDesc.getSchema().containsByQualifiedName(CatalogUtil.buildFQName(databaseName, tableName, "addedcol1")));
+        tableDesc.getSchema().containsByQualifiedName(IdentifierUtil.buildFQName(databaseName, tableName, "addedcol1")));
 
     //////////////////////////////////////////////////////////////////////////////
     // Test get all columns
@@ -351,7 +352,7 @@ public class TestCatalogAgainstCaseSensitivity {
             .add("RecoRd1", new TypeDesc(schema)).build())).build();
 
     TableDesc tableDesc = new TableDesc(
-        CatalogUtil.buildFQName(databaseName, tableName),
+        IdentifierUtil.buildFQName(databaseName, tableName),
         tableSchema,
         CatalogUtil.newTableMeta(BuiltinStorages.JSON, server.getConf()),
         URI.create("hdfs://xxx.com/json_Table")
@@ -409,7 +410,7 @@ public class TestCatalogAgainstCaseSensitivity {
     
     int expected = 0;
     for (String eachTableName : catalog.getAllTableNames(databaseName)) {
-      expected += catalog.getTableDesc(databaseName, eachTableName).getSchema().getAllColumns().size();
+      expected += catalog.getTableDesc(databaseName, eachTableName).getSchema().getRootColumns().size();
     }
     assertEquals(expected, columnCount);
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogExceptions.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogExceptions.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogExceptions.java
index 8ba3d59..3b90e21 100644
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogExceptions.java
+++ b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogExceptions.java
@@ -29,6 +29,7 @@ import org.apache.tajo.catalog.proto.CatalogProtos.TableStatsProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.UpdateTableStatsProto;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.exception.*;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.apache.tajo.util.KeyValueSet;
 import org.junit.AfterClass;
@@ -116,14 +117,14 @@ public class TestCatalogExceptions {
     // TODO: currently, wrong uri does not occur any exception.
     String tableName = "wrongUri";
     Schema schema = SchemaBuilder.builder()
-        .add(CatalogUtil.buildFQName(tableName, "Column"), Type.BLOB)
-        .add(CatalogUtil.buildFQName(tableName, "column"), Type.INT4)
-        .add(CatalogUtil.buildFQName(tableName, "cOlumn"), Type.INT8)
+        .add(IdentifierUtil.buildFQName(tableName, "Column"), Type.BLOB)
+        .add(IdentifierUtil.buildFQName(tableName, "column"), Type.INT4)
+        .add(IdentifierUtil.buildFQName(tableName, "cOlumn"), Type.INT8)
         .build();
     Path path = new Path(CommonTestingUtil.getTestDir(), tableName);
     catalog.createTable(
       new TableDesc(
-        CatalogUtil.buildFQName("TestDatabase1", tableName),
+        IdentifierUtil.buildFQName("TestDatabase1", tableName),
         schema,
         new TableMeta("TEXT", new KeyValueSet()),
         path.toUri(), true));
@@ -137,19 +138,19 @@ public class TestCatalogExceptions {
 
   @Test(expected = UndefinedDatabaseException.class)
   public void dropTableOfUndefinedDatabase() throws Exception {
-    catalog.dropTable(CatalogUtil.buildFQName("undefined", "testPartition1"));
+    catalog.dropTable(IdentifierUtil.buildFQName("undefined", "testPartition1"));
   }
 
   @Test(expected = UndefinedTableException.class)
   public void dropUndefinedTable() throws Exception {
-    catalog.dropTable(CatalogUtil.buildFQName("TestDatabase1", "undefined"));
+    catalog.dropTable(IdentifierUtil.buildFQName("TestDatabase1", "undefined"));
   }
 
   @Test(expected = UndefinedTableException.class)
   public void testUpdateTableStatsOfUndefinedTable() throws Exception {
     catalog.updateTableStats(
       UpdateTableStatsProto.newBuilder().
-        setTableName(CatalogUtil.buildFQName("TestDatabase1", "undefined")).
+        setTableName(IdentifierUtil.buildFQName("TestDatabase1", "undefined")).
         setStats(
           TableStatsProto.newBuilder().
             setNumRows(0).
@@ -165,7 +166,7 @@ public class TestCatalogExceptions {
     PartitionDesc partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.ADD_PARTITION);
 
@@ -178,7 +179,7 @@ public class TestCatalogExceptions {
     PartitionDesc partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.ADD_PARTITION);
 
@@ -188,7 +189,7 @@ public class TestCatalogExceptions {
     partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.ADD_PARTITION);
 
@@ -201,7 +202,7 @@ public class TestCatalogExceptions {
     PartitionDesc partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "undefined"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "undefined"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.ADD_PARTITION);
 
@@ -215,7 +216,7 @@ public class TestCatalogExceptions {
     PartitionDesc partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.ADD_PARTITION);
 
@@ -228,7 +229,7 @@ public class TestCatalogExceptions {
     PartitionDesc partitionDesc = CatalogTestingUtil.buildPartitionDesc(partitionName);
 
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestPartition1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestPartition1"));
     alterTableDesc.setPartitionDesc(partitionDesc);
     alterTableDesc.setAlterTableType(AlterTableType.DROP_PARTITION);
     catalog.alterTable(alterTableDesc);
@@ -238,17 +239,17 @@ public class TestCatalogExceptions {
   public void testRenameUndefinedTable() throws Exception {
     AlterTableDesc alterTableDesc = new AlterTableDesc();
     alterTableDesc.setAlterTableType(AlterTableType.RENAME_TABLE);
-    alterTableDesc.setNewTableName(CatalogUtil.buildFQName("TestDatabase1", "renamed_table"));
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "undefined"));
+    alterTableDesc.setNewTableName(IdentifierUtil.buildFQName("TestDatabase1", "renamed_table"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "undefined"));
     catalog.alterTable(alterTableDesc);
   }
 
   @Test(expected = UndefinedTableException.class)
   public void testRenameColumnOfUndefinedTable() throws Exception {
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setColumnName(CatalogUtil.buildFQName("TestDatabase1", "undefined", "AddedCol1"));
-    alterTableDesc.setNewColumnName(CatalogUtil.buildFQName("TestDatabase1", "undefined", "addedcol1"));
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "undefined"));
+    alterTableDesc.setColumnName(IdentifierUtil.buildFQName("TestDatabase1", "undefined", "AddedCol1"));
+    alterTableDesc.setNewColumnName(IdentifierUtil.buildFQName("TestDatabase1", "undefined", "addedcol1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "undefined"));
     alterTableDesc.setAlterTableType(AlterTableType.RENAME_COLUMN);
     catalog.alterTable(alterTableDesc);
   }
@@ -256,9 +257,9 @@ public class TestCatalogExceptions {
   @Test(expected = UndefinedColumnException.class)
   public void testRenameUndefinedColumn() throws Exception {
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setColumnName(CatalogUtil.buildFQName("TestDatabase1", "TestTable1", "undefined"));
-    alterTableDesc.setNewColumnName(CatalogUtil.buildFQName("TestDatabase1", "TestTable1", "undefined"));
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestTable1"));
+    alterTableDesc.setColumnName(IdentifierUtil.buildFQName("TestDatabase1", "TestTable1", "undefined"));
+    alterTableDesc.setNewColumnName(IdentifierUtil.buildFQName("TestDatabase1", "TestTable1", "undefined"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestTable1"));
     alterTableDesc.setAlterTableType(AlterTableType.RENAME_COLUMN);
     catalog.alterTable(alterTableDesc);
   }
@@ -266,9 +267,9 @@ public class TestCatalogExceptions {
   @Test(expected = DuplicateColumnException.class)
   public void testAddDuplicateColumn() throws Exception {
     AlterTableDesc alterTableDesc = new AlterTableDesc();
-    alterTableDesc.setAddColumn(new Column(CatalogUtil.buildFQName("TestDatabase1", "TestTable1", "cOlumn"),
+    alterTableDesc.setAddColumn(new Column(IdentifierUtil.buildFQName("TestDatabase1", "TestTable1", "cOlumn"),
         CatalogUtil.newSimpleDataType(Type.BLOB)));
-    alterTableDesc.setTableName(CatalogUtil.buildFQName("TestDatabase1", "TestTable1"));
+    alterTableDesc.setTableName(IdentifierUtil.buildFQName("TestDatabase1", "TestTable1"));
     alterTableDesc.setAlterTableType(AlterTableType.ADD_COLUMN);
     catalog.alterTable(alterTableDesc);
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-cli/src/main/java/org/apache/tajo/cli/tools/TajoDump.java
----------------------------------------------------------------------
diff --git a/tajo-cli/src/main/java/org/apache/tajo/cli/tools/TajoDump.java b/tajo-cli/src/main/java/org/apache/tajo/cli/tools/TajoDump.java
index f2df0cd..7eb50bb 100644
--- a/tajo-cli/src/main/java/org/apache/tajo/cli/tools/TajoDump.java
+++ b/tajo-cli/src/main/java/org/apache/tajo/cli/tools/TajoDump.java
@@ -26,6 +26,7 @@ import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.client.TajoClient;
 import org.apache.tajo.client.TajoClientImpl;
 import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.service.ServiceTrackerFactory;
 import org.apache.tajo.util.NetUtils;
 import org.apache.tajo.util.Pair;
@@ -164,10 +165,10 @@ public class TajoDump {
       throws SQLException, ServiceException {
     writer.write("\n");
     writer.write("--\n");
-    writer.write(String.format("-- Database name: %s%n", CatalogUtil.denormalizeIdentifier(databaseName)));
+    writer.write(String.format("-- Database name: %s%n", IdentifierUtil.denormalizeIdentifier(databaseName)));
     writer.write("--\n");
     writer.write("\n");
-    writer.write(String.format("CREATE DATABASE IF NOT EXISTS %s;", CatalogUtil.denormalizeIdentifier(databaseName)));
+    writer.write(String.format("CREATE DATABASE IF NOT EXISTS %s;", IdentifierUtil.denormalizeIdentifier(databaseName)));
     writer.write("\n\n");
 
     // returned list is immutable.
@@ -175,7 +176,7 @@ public class TajoDump {
     Collections.sort(tableNames);
     for (String tableName : tableNames) {
       try {
-        String fqName = CatalogUtil.buildFQName(databaseName, tableName);
+        String fqName = IdentifierUtil.buildFQName(databaseName, tableName);
         TableDesc table = client.getTableDesc(fqName);
 
         if (table.getMeta().getDataFormat().equalsIgnoreCase("SYSTEM")) {
@@ -198,7 +199,7 @@ public class TajoDump {
 //            writer.write(DDLBuilder.buildDDLForAddPartition(table, eachPartitionProto));
 //          }
           writer.write(String.format("ALTER TABLE %s REPAIR PARTITION;",
-            CatalogUtil.denormalizeIdentifier(databaseName) + "." + CatalogUtil.denormalizeIdentifier(tableName)));
+            IdentifierUtil.denormalizeIdentifier(databaseName) + "." + IdentifierUtil.denormalizeIdentifier(tableName)));
 
           writer.write("\n\n");
         }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-cli/src/main/java/org/apache/tajo/cli/tsql/commands/DescTableCommand.java
----------------------------------------------------------------------
diff --git a/tajo-cli/src/main/java/org/apache/tajo/cli/tsql/commands/DescTableCommand.java b/tajo-cli/src/main/java/org/apache/tajo/cli/tsql/commands/DescTableCommand.java
index 43fcf2e..9632b66 100644
--- a/tajo-cli/src/main/java/org/apache/tajo/cli/tsql/commands/DescTableCommand.java
+++ b/tajo-cli/src/main/java/org/apache/tajo/cli/tsql/commands/DescTableCommand.java
@@ -24,7 +24,6 @@ import jline.console.completer.StringsCompleter;
 import org.apache.commons.lang.CharUtils;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.tajo.TajoConstants;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
@@ -32,6 +31,7 @@ import org.apache.tajo.catalog.proto.CatalogProtos.IndexDescProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.SortSpecProto;
 import org.apache.tajo.cli.tsql.TajoCli;
 import org.apache.tajo.exception.TajoException;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.FileUtil;
 import org.apache.tajo.util.StringUtils;
 
@@ -72,7 +72,7 @@ public class DescTableCommand extends TajoShellCommand {
             sb.append("\"").append(index.getIndexName()).append("\" ");
             sb.append(index.getIndexMethod()).append(" (");
             for (SortSpecProto key : index.getKeySortSpecsList()) {
-              sb.append(CatalogUtil.extractSimpleName(key.getColumn().getName()));
+              sb.append(IdentifierUtil.extractSimpleName(key.getColumn().getName()));
               sb.append(key.getAscending() ? " ASC" : " DESC");
               sb.append(key.getNullFirst() ? " NULLS FIRST, " : " NULLS LAST, ");
             }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java b/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java
index 8811c13..2f654cd 100644
--- a/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java
+++ b/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java
@@ -21,12 +21,12 @@
  */
 package org.apache.tajo.jdbc;
 
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.client.ResultSetUtil;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.common.type.TajoTypeUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
@@ -53,8 +53,8 @@ public class TajoResultSetMetaData implements ResultSetMetaData {
   @Override
   public String getCatalogName(int column) throws SQLException {
     Column c = schema.getColumn(column - 1);
-    if (CatalogUtil.isFQColumnName(c.getQualifiedName())) {
-      return CatalogUtil.splitFQTableName(c.getQualifier())[0];
+    if (IdentifierUtil.isFQColumnName(c.getQualifiedName())) {
+      return IdentifierUtil.splitFQTableName(c.getQualifier())[0];
     }
     return "";
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-cluster-tests/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java
----------------------------------------------------------------------
diff --git a/tajo-cluster-tests/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java b/tajo-cluster-tests/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java
index 9816064..282d389 100644
--- a/tajo-cluster-tests/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java
+++ b/tajo-cluster-tests/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java
@@ -36,6 +36,7 @@ import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.engine.planner.global.MasterPlan;
 import org.apache.tajo.engine.query.QueryContext;
 import org.apache.tajo.exception.TajoException;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.session.Session;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.apache.tajo.util.FileUtil;
@@ -120,7 +121,7 @@ public class LocalTajoTestingUtility {
       TableStats stats = new TableStats();
       stats.setNumBytes(TPCH.tableVolumes.get(names[i]));
       TableDesc tableDesc = new TableDesc(
-          CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, names[i]), schemas[i], meta,
+          IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, names[i]), schemas[i], meta,
           tablePath.toUri());
       tableDesc.setStats(stats);
       util.getMaster().getCatalog().createTable(tableDesc);

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-cluster-tests/src/test/java/org/apache/tajo/QueryTestCaseBase.java
----------------------------------------------------------------------
diff --git a/tajo-cluster-tests/src/test/java/org/apache/tajo/QueryTestCaseBase.java b/tajo-cluster-tests/src/test/java/org/apache/tajo/QueryTestCaseBase.java
index aebd7b9..315f954 100644
--- a/tajo-cluster-tests/src/test/java/org/apache/tajo/QueryTestCaseBase.java
+++ b/tajo-cluster-tests/src/test/java/org/apache/tajo/QueryTestCaseBase.java
@@ -31,7 +31,6 @@ import org.apache.hadoop.fs.Path;
 import org.apache.tajo.algebra.*;
 import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.cli.tsql.InvalidStatementException;
 import org.apache.tajo.cli.tsql.ParsedResult;
@@ -53,6 +52,7 @@ import org.apache.tajo.plan.LogicalPlanner;
 import org.apache.tajo.plan.verifier.LogicalPlanVerifier;
 import org.apache.tajo.plan.verifier.PreLogicalPlanVerifier;
 import org.apache.tajo.plan.verifier.VerificationState;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.BufferPool;
 import org.apache.tajo.storage.StorageUtil;
 import org.apache.tajo.util.FileUtil;
@@ -221,7 +221,7 @@ public class QueryTestCaseBase {
   @AfterClass
   public static void tearDownClass() throws Exception {
     for (String tableName : createdTableGlobalSet) {
-      client.updateQuery("DROP TABLE IF EXISTS " + CatalogUtil.denormalizeIdentifier(tableName));
+      client.updateQuery("DROP TABLE IF EXISTS " + IdentifierUtil.denormalizeIdentifier(tableName));
     }
     createdTableGlobalSet.clear();
 
@@ -303,7 +303,7 @@ public class QueryTestCaseBase {
     try {
       // if the current database is "default", we don't need create it because it is already prepated at startup time.
       if (!currentDatabase.equals(TajoConstants.DEFAULT_DATABASE_NAME)) {
-        client.updateQuery("CREATE DATABASE IF NOT EXISTS " + CatalogUtil.denormalizeIdentifier(currentDatabase));
+        client.updateQuery("CREATE DATABASE IF NOT EXISTS " + IdentifierUtil.denormalizeIdentifier(currentDatabase));
       }
       client.selectDatabase(currentDatabase);
       currentResultFS = currentResultPath.getFileSystem(testBase.getTestingCluster().getConfiguration());
@@ -1047,10 +1047,10 @@ public class QueryTestCaseBase {
         DropTable dropTable = (DropTable) expr;
         String tableName = dropTable.getTableName();
         assertTrue("table '" + tableName + "' existence check",
-            client.existTable(CatalogUtil.buildFQName(currentDatabase, tableName)));
+            client.existTable(IdentifierUtil.buildFQName(currentDatabase, tableName)));
         assertTrue("table drop is failed.", client.updateQuery(parsedResult.getHistoryStatement()));
         assertFalse("table '" + tableName + "' dropped check",
-            client.existTable(CatalogUtil.buildFQName(currentDatabase, tableName)));
+            client.existTable(IdentifierUtil.buildFQName(currentDatabase, tableName)));
         if (isLocalTable) {
           createdTableGlobalSet.remove(tableName);
         }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-cluster-tests/src/test/java/org/apache/tajo/TajoTestingCluster.java
----------------------------------------------------------------------
diff --git a/tajo-cluster-tests/src/test/java/org/apache/tajo/TajoTestingCluster.java b/tajo-cluster-tests/src/test/java/org/apache/tajo/TajoTestingCluster.java
index 8de4cb9..4b89c8e 100644
--- a/tajo-cluster-tests/src/test/java/org/apache/tajo/TajoTestingCluster.java
+++ b/tajo-cluster-tests/src/test/java/org/apache/tajo/TajoTestingCluster.java
@@ -45,10 +45,10 @@ import org.apache.tajo.querymaster.Query;
 import org.apache.tajo.querymaster.QueryMasterTask;
 import org.apache.tajo.querymaster.Stage;
 import org.apache.tajo.querymaster.StageState;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.service.ServiceTrackerFactory;
 import org.apache.tajo.storage.FileTablespace;
 import org.apache.tajo.storage.TablespaceManager;
-import org.apache.tajo.util.KeyValueSet;
 import org.apache.tajo.util.NetUtils;
 import org.apache.tajo.util.Pair;
 import org.apache.tajo.util.history.QueryHistory;
@@ -63,7 +63,6 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.TimeZone;
 import java.util.UUID;
 
 public class TajoTestingCluster {
@@ -652,8 +651,8 @@ public class TajoTestingCluster {
         fs.mkdirs(rootDir);
       }
       Path tablePath;
-      if (CatalogUtil.isFQTableName(tableName)) {
-        Pair<String, String> name = CatalogUtil.separateQualifierAndName(tableName);
+      if (IdentifierUtil.isFQTableName(tableName)) {
+        Pair<String, String> name = IdentifierUtil.separateQualifierAndName(tableName);
         tablePath = new Path(rootDir, new Path(name.getFirst(), name.getSecond()));
       } else {
         tablePath = new Path(rootDir, tableName);

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/Assert.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/Assert.java b/tajo-common/src/main/java/org/apache/tajo/Assert.java
new file mode 100644
index 0000000..b5e05ad
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/Assert.java
@@ -0,0 +1,36 @@
+/**
+ * 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;
+
+import org.apache.tajo.exception.TajoInternalError;
+
+public class Assert {
+
+  public static void assertNotNull(Object obj) {
+    if (obj == null) {
+      throw new TajoInternalError("The argument must not be NULL.");
+    }
+  }
+
+  public static void assertCondition(boolean condition, String message, Object... arguments) {
+    if (!condition) {
+      throw new TajoInternalError(String.format(message, arguments));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/exception/InvalidValueForCastException.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/exception/InvalidValueForCastException.java b/tajo-common/src/main/java/org/apache/tajo/exception/InvalidValueForCastException.java
index 6af8d1a..63ee354 100644
--- a/tajo-common/src/main/java/org/apache/tajo/exception/InvalidValueForCastException.java
+++ b/tajo-common/src/main/java/org/apache/tajo/exception/InvalidValueForCastException.java
@@ -39,6 +39,6 @@ public class InvalidValueForCastException extends TajoException {
   }
 
   public InvalidValueForCastException(Type src, Type target) {
-    super(Errors.ResultCode.INVALID_VALUE_FOR_CAST, src.baseType().name(), target.baseType().name());
+    super(Errors.ResultCode.INVALID_VALUE_FOR_CAST, src.kind().name(), target.kind().name());
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/json/CommonGsonHelper.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/CommonGsonHelper.java b/tajo-common/src/main/java/org/apache/tajo/json/CommonGsonHelper.java
index d838b6a..68d4465 100644
--- a/tajo-common/src/main/java/org/apache/tajo/json/CommonGsonHelper.java
+++ b/tajo-common/src/main/java/org/apache/tajo/json/CommonGsonHelper.java
@@ -40,6 +40,7 @@ public class CommonGsonHelper {
 	private static Map<Type, GsonSerDerAdapter<?>> registerAdapters() {
     Map<Type, GsonSerDerAdapter<?>> adapters = new HashMap<>();
     adapters.put(Datum.class, new DatumAdapter());
+    adapters.put(Type.class, new TypeAdapter());
 
     return adapters;
 	}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/json/TypeAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/json/TypeAdapter.java b/tajo-common/src/main/java/org/apache/tajo/json/TypeAdapter.java
new file mode 100644
index 0000000..5c3c1e4
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/json/TypeAdapter.java
@@ -0,0 +1,42 @@
+/**
+ * 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.json;
+
+import com.google.gson.*;
+import org.apache.tajo.type.TypeStringEncoder;
+
+import java.lang.reflect.Type;
+
+
+public class TypeAdapter implements GsonSerDerAdapter<org.apache.tajo.type.Type> {
+
+  @Override
+  public org.apache.tajo.type.Type deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+      throws JsonParseException {
+    JsonObject obj = (JsonObject) json;
+    return TypeStringEncoder.decode(CommonGsonHelper.getOrDie(obj, "type").getAsString());
+  }
+
+  @Override
+  public JsonElement serialize(org.apache.tajo.type.Type src, Type typeOfSrc, JsonSerializationContext context) {
+    JsonObject json = new JsonObject();
+    json.addProperty("type", TypeStringEncoder.encode(src));
+    return json;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/schema/ANSISQLIdentifierPolicy.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/schema/ANSISQLIdentifierPolicy.java b/tajo-common/src/main/java/org/apache/tajo/schema/ANSISQLIdentifierPolicy.java
index c195bb6..cfe91c1 100644
--- a/tajo-common/src/main/java/org/apache/tajo/schema/ANSISQLIdentifierPolicy.java
+++ b/tajo-common/src/main/java/org/apache/tajo/schema/ANSISQLIdentifierPolicy.java
@@ -29,12 +29,12 @@ public class ANSISQLIdentifierPolicy extends IdentifierPolicy {
   }
 
   @Override
-  public String getIdentifierQuoteString() {
+  public char getIdentifierQuoteString() {
     return ANSI_SQL_QUOTE_STRING;
   }
 
   @Override
-  String getIdentifierSeperator() {
+  char getIdentifierSeperator() {
     return ANSI_SQL_SEPERATOR_STRING;
   }
 


[5/7] tajo git commit: TAJO-2129: Apply new type implementation to Schema and Catalog.

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/schema/Field.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/schema/Field.java b/tajo-common/src/main/java/org/apache/tajo/schema/Field.java
new file mode 100644
index 0000000..90193ac
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/schema/Field.java
@@ -0,0 +1,106 @@
+/**
+ * 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.schema;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.type.Type;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * Represent a field in a schema.
+ */
+public class Field implements Cloneable {
+  protected final QualifiedIdentifier name;
+  protected final Type type;
+
+  public Field(QualifiedIdentifier name, Type type) {
+    this.type = type;
+    this.name = name;
+  }
+
+  public static Field Record(QualifiedIdentifier name, Field ... fields) {
+    return Record(name, Arrays.asList(fields));
+  }
+
+  public static Field Record(QualifiedIdentifier name, Collection<Field> fields) {
+    return new Field(name, Type.Record(fields));
+  }
+
+  @VisibleForTesting
+  public static Field Field(String name, Type type) {
+    return new Field(QualifiedIdentifier.$(name), type);
+  }
+
+  public static Field Field(QualifiedIdentifier name, Type type) {
+    return new Field(name, type);
+  }
+
+  public QualifiedIdentifier name() {
+    return this.name;
+  }
+
+  public TajoDataTypes.Type baseType() {
+    return this.type.kind();
+  }
+
+  public <T extends Type> T type() {
+    return (T) type;
+  }
+
+  public boolean isStruct() {
+    return type.isStruct();
+  }
+
+  public boolean isNull() {
+    return type.isNull();
+  }
+
+  @Override
+  public String toString() {
+    return name + " (" + type + ")";
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(type, name);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj instanceof Field) {
+      Field other = (Field) obj;
+      return type.equals(other.type) && name.equals(other.name);
+    }
+
+    return false;
+  }
+
+  @Override
+  public Field clone() throws CloneNotSupportedException {
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/schema/Identifier.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/schema/Identifier.java b/tajo-common/src/main/java/org/apache/tajo/schema/Identifier.java
index d71dbdc..23ea0fb 100644
--- a/tajo-common/src/main/java/org/apache/tajo/schema/Identifier.java
+++ b/tajo-common/src/main/java/org/apache/tajo/schema/Identifier.java
@@ -18,17 +18,26 @@
 
 package org.apache.tajo.schema;
 
+import org.apache.tajo.common.ProtoObject;
+import org.apache.tajo.common.TajoDataTypes.IdentifierProto;
 import org.apache.tajo.schema.IdentifierPolicy.IdentifierCase;
 
 import java.util.Objects;
 
+import static org.apache.tajo.schema.IdentifierPolicy.DefaultPolicy;
+
 /**
- * Identifier Element
+ * Represents an identifier part
  */
-public class Identifier {
+public class Identifier implements ProtoObject<IdentifierProto> {
   private String name;
   private boolean quoted;
 
+  /**
+   * Identifier constructor
+   * @param name Identifier part string
+   * @param quoted quoted or not
+   */
   private Identifier(String name, boolean quoted) {
     this.name = name;
     this.quoted = quoted;
@@ -42,7 +51,12 @@ public class Identifier {
     return new Identifier(name, quoted);
   }
 
-  public String displayString(IdentifierPolicy policy) {
+  /**
+   * Raw string for an identifier, which is equivalent to an identifier directly used in SQL statements.
+   * @param policy IdentifierPolicy
+   * @return Raw string
+   */
+  public String raw(IdentifierPolicy policy) {
     StringBuilder sb = new StringBuilder();
     if (quoted) {
       appendByCase(sb, policy.storesQuotedIdentifierAs());
@@ -56,11 +70,11 @@ public class Identifier {
   }
 
   /**
-   * Raw string of an identifier
-   * @param policy Identifier Policy
-   * @return raw string
+   * Interned string of an identifier
+   * @param policy IdentifierPolicy
+   * @return interned string
    */
-  public String raw(IdentifierPolicy policy) {
+  public String interned(IdentifierPolicy policy) {
     StringBuilder sb = new StringBuilder();
     if (quoted) {
       appendByCase(sb, policy.storesQuotedIdentifierAs());
@@ -87,7 +101,7 @@ public class Identifier {
 
   @Override
   public String toString() {
-    return displayString(IdentifierPolicy.DefaultPolicy());
+    return raw(DefaultPolicy());
   }
 
   public int hashCode() {
@@ -101,9 +115,21 @@ public class Identifier {
 
     if (obj instanceof Identifier) {
       Identifier other = (Identifier) obj;
-      return other.name == other.name && quoted == other.quoted;
+      return name.equals(other.name) && quoted == other.quoted;
     }
 
     return false;
   }
+
+  @Override
+  public IdentifierProto getProto() {
+    return IdentifierProto.newBuilder()
+        .setName(name)
+        .setQuoted(quoted)
+        .build();
+  }
+
+  public static Identifier fromProto(IdentifierProto proto) {
+    return new Identifier(proto.getName(), proto.getQuoted());
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/schema/IdentifierPolicy.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/schema/IdentifierPolicy.java b/tajo-common/src/main/java/org/apache/tajo/schema/IdentifierPolicy.java
index 56762e7..75da186 100644
--- a/tajo-common/src/main/java/org/apache/tajo/schema/IdentifierPolicy.java
+++ b/tajo-common/src/main/java/org/apache/tajo/schema/IdentifierPolicy.java
@@ -24,9 +24,9 @@ package org.apache.tajo.schema;
 public abstract class IdentifierPolicy {
 
   /** Quote String; e.g., 'abc' */
-  public static final String ANSI_SQL_QUOTE_STRING = "'";
+  public static final char ANSI_SQL_QUOTE_STRING = '\'';
   /** Separator; e.g., abc.xyz */
-  public static final String ANSI_SQL_SEPERATOR_STRING = ".";
+  public static final char ANSI_SQL_SEPERATOR_STRING = '.';
   /** Maximum length of identifiers */
   public final static int MAX_IDENTIFIER_LENGTH = 128;
 
@@ -49,7 +49,7 @@ public abstract class IdentifierPolicy {
    *
    * @return the quoting string or a space if quoting is not supported
    */
-  abstract String getIdentifierQuoteString();
+  abstract char getIdentifierQuoteString();
 
   /**
    * Retrieves the <code>String</code> that this policy uses as the separator between
@@ -57,7 +57,7 @@ public abstract class IdentifierPolicy {
    *
    * @return the separator string
    */
-  abstract String getIdentifierSeperator();
+  abstract char getIdentifierSeperator();
 
   /**
    * Retrieves the maximum number of characters this policy allows for a column name.

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/schema/IdentifierUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/schema/IdentifierUtil.java b/tajo-common/src/main/java/org/apache/tajo/schema/IdentifierUtil.java
new file mode 100644
index 0000000..f086410
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/schema/IdentifierUtil.java
@@ -0,0 +1,333 @@
+/**
+ * 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.schema;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import org.apache.tajo.TajoConstants;
+import org.apache.tajo.schema.IdentifierPolicy.IdentifierCase;
+import org.apache.tajo.util.Pair;
+import org.apache.tajo.util.StringUtils;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+import static org.apache.tajo.schema.Identifier._;
+import static org.apache.tajo.schema.IdentifierPolicy.DefaultPolicy;
+import static org.apache.tajo.schema.QualifiedIdentifier.$;
+
+/**
+ * Util methods for Identifiers
+ */
+public class IdentifierUtil {
+
+  public final static String IDENTIFIER_DELIMITER_REGEXP = "\\.";
+  public final static String IDENTIFIER_DELIMITER = ".";
+  public final static String IDENTIFIER_QUOTE_STRING = "\"";
+  public final static int MAX_IDENTIFIER_LENGTH = 128;
+
+  public static final Set<String> RESERVED_KEYWORDS_SET = new HashSet<>();
+  public static final String [] RESERVED_KEYWORDS = {
+      "AS", "ALL", "AND", "ANY", "ASYMMETRIC", "ASC",
+      "BOTH",
+      "CASE", "CAST", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP",
+      "DESC", "DISTINCT",
+      "END", "ELSE", "EXCEPT",
+      "FALSE", "FULL", "FROM",
+      "GROUP",
+      "HAVING",
+      "ILIKE", "IN", "INNER", "INTERSECT", "INTO", "IS",
+      "JOIN",
+      "LEADING", "LEFT", "LIKE", "LIMIT",
+      "NATURAL", "NOT", "NULL",
+      "ON", "OUTER", "OR", "ORDER",
+      "RIGHT",
+      "SELECT", "SOME", "SYMMETRIC",
+      "TABLE", "THEN", "TRAILING", "TRUE",
+      "OVER",
+      "UNION", "UNIQUE", "USING",
+      "WHEN", "WHERE", "WINDOW", "WITH"
+  };
+
+  public static QualifiedIdentifier makeIdentifier(String raw, IdentifierPolicy policy) {
+    if (raw == null || raw.equals("")) {
+      return $(raw);
+    }
+
+    final String [] splitted = raw.split(IDENTIFIER_DELIMITER_REGEXP);
+    final ImmutableList.Builder<Identifier> builder = ImmutableList.builder();
+
+    for (String part : splitted) {
+      boolean quoted = isDelimited(part, policy);
+      if (quoted) {
+        builder.add(_(stripQuote(part), true));
+      } else {
+        builder.add(internIdentifierPart(part, policy));
+      }
+    }
+    return $(builder.build());
+  }
+
+  public static Identifier internIdentifierPart(String rawPart, IdentifierPolicy policy) {
+    IdentifierCase unquotedIdentifierCase = policy.storesUnquotedIdentifierAs();
+    final String interned;
+    if (unquotedIdentifierCase == IdentifierCase.LowerCase) {
+      interned = rawPart.toLowerCase(Locale.ENGLISH);
+    } else if (unquotedIdentifierCase == IdentifierCase.UpperCase) {
+      interned = rawPart.toUpperCase(Locale.ENGLISH);
+    } else {
+      interned = rawPart;
+    }
+
+    return _(interned, false);
+  }
+
+  /**
+   * Normalize an identifier. Normalization means a translation from a identifier to be a refined identifier name.
+   *
+   * Identifier can be composed of multiple parts as follows:
+   * <pre>
+   *   database_name.table_name.column_name
+   * </pre>
+   *
+   * Each regular identifier part can be composed alphabet ([a-z][A-Z]), number([0-9]), and underscore([_]).
+   * Also, the first letter must be an alphabet character.
+   *
+   * <code>normalizeIdentifier</code> normalizes each part of an identifier.
+   *
+   * In detail, for each part, it performs as follows:
+   * <ul>
+   *   <li>changing a part without double quotation to be lower case letters</li>
+   *   <li>eliminating double quotation marks from identifier</li>
+   * </ul>
+   *
+   * @param identifier The identifier to be normalized
+   * @return The normalized identifier
+   */
+  public static String normalizeIdentifier(String identifier) {
+    if (identifier == null || identifier.equals("")) {
+      return identifier;
+    }
+    String [] splitted = identifier.split(IDENTIFIER_DELIMITER_REGEXP);
+
+    StringBuilder sb = new StringBuilder();
+    boolean first = true;
+    for (String part : splitted) {
+      if (first) {
+        first = false;
+      } else {
+        sb.append(IDENTIFIER_DELIMITER);
+      }
+      sb.append(normalizeIdentifierPart(part));
+    }
+    return sb.toString();
+  }
+
+  public static String normalizeIdentifierPart(String part) {
+    return isDelimited(part) ? stripQuote(part) : part.toLowerCase();
+  }
+
+  /**
+   * Denormalize an identifier. Denormalize means a translation from a stored identifier
+   * to be a printable identifier name.
+   *
+   * In detail, for each part, it performs as follows:
+   * <ul>
+   *   <li>changing a part including upper case character or non-ascii character to be lower case letters</li>
+   *   <li>eliminating double quotation marks from identifier</li>
+   * </ul>
+   *
+   * @param identifier The identifier to be normalized
+   * @return The denormalized identifier
+   */
+  public static String denormalizeIdentifier(String identifier) {
+    String [] splitted = identifier.split(IDENTIFIER_DELIMITER_REGEXP);
+
+    StringBuilder sb = new StringBuilder();
+    boolean first = true;
+    for (String part : splitted) {
+      if (first) {
+        first = false;
+      } else {
+        sb.append(IDENTIFIER_DELIMITER);
+      }
+      sb.append(denormalizePart(part));
+    }
+    return sb.toString();
+  }
+
+  public static String denormalizePart(String identifier) {
+    if (isShouldBeQuoted(identifier)) {
+      return StringUtils.doubleQuote(identifier);
+    } else {
+      return identifier;
+    }
+  }
+
+  public static boolean isShouldBeQuoted(String interned) {
+    for (char character : interned.toCharArray()) {
+      if (Character.isUpperCase(character)) {
+        return true;
+      }
+
+      if (!StringUtils.isPartOfAnsiSQLIdentifier(character)) {
+        return true;
+      }
+
+      if (RESERVED_KEYWORDS_SET.contains(interned.toUpperCase())) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  public static String stripQuote(String raw) {
+    return raw.substring(1, raw.length() - 1);
+  }
+
+  public static boolean isDelimited(String raw) {
+    return isDelimited(raw, DefaultPolicy());
+  }
+
+  public static boolean isDelimited(String raw, IdentifierPolicy policy) {
+    char quoteString = policy.getIdentifierQuoteString();
+    boolean openQuote = raw.charAt(0) == quoteString;
+    boolean closeQuote = raw.charAt(raw.length() - 1) == quoteString;
+
+    // if at least one quote mark exists, the identifier must be grater than equal to 2 characters,
+    if (openQuote ^ closeQuote && raw.length() < 2) {
+      throw new IllegalArgumentException("Invalid Identifier: " + raw);
+    }
+
+    // does not allow the empty identifier (''),
+    if (openQuote && closeQuote && raw.length() == 2) {
+      throw new IllegalArgumentException("zero-length delimited identifier: " + raw);
+    }
+
+    // Ensure the quote open and close
+    return openQuote && closeQuote;
+  }
+
+  /**
+   * True if a given name is a simple identifier, meaning is not a dot-chained name.
+   *
+   * @param columnOrTableName Column or Table name to be checked
+   * @return True if a given name is a simple identifier. Otherwise, it will return False.
+   */
+  public static boolean isSimpleIdentifier(String columnOrTableName) {
+    return columnOrTableName.split(IDENTIFIER_DELIMITER_REGEXP).length == 1;
+  }
+
+  public static boolean isFQColumnName(String tableName) {
+    return tableName.split(IDENTIFIER_DELIMITER_REGEXP).length == 3;
+  }
+
+  public static boolean isFQTableName(String tableName) {
+    int lastDelimiterIdx = tableName.lastIndexOf(IDENTIFIER_DELIMITER);
+    return lastDelimiterIdx > -1;
+  }
+
+  public static String [] splitFQTableName(String qualifiedName) {
+    String [] splitted = splitTableName(qualifiedName);
+    if (splitted.length == 1) {
+      throw new IllegalArgumentException("Table name is expected to be qualified, but was \""
+          + qualifiedName + "\".");
+    }
+    return splitted;
+  }
+
+  public static String [] splitTableName(String tableName) {
+    int lastDelimiterIdx = tableName.lastIndexOf(IDENTIFIER_DELIMITER);
+    if (lastDelimiterIdx > -1) {
+      return new String [] {
+          tableName.substring(0, lastDelimiterIdx),
+          tableName.substring(lastDelimiterIdx + 1, tableName.length())
+      };
+    } else {
+      return new String [] {tableName};
+    }
+  }
+
+  public static String buildFQName(String... identifiers) {
+    boolean first = true;
+    StringBuilder sb = new StringBuilder();
+    for(String id : identifiers) {
+      if (first) {
+        first = false;
+      } else {
+        sb.append(IDENTIFIER_DELIMITER);
+      }
+
+      sb.append(id);
+    }
+
+    return sb.toString();
+  }
+
+  public static Pair<String, String> separateQualifierAndName(String name) {
+    Preconditions.checkArgument(isFQTableName(name), "Must be a qualified name.");
+    return new Pair<>(extractQualifier(name), extractSimpleName(name));
+  }
+
+  /**
+   * Extract a qualification name from an identifier.
+   *
+   * For example, consider a table identifier like 'database1.table1'.
+   * In this case, this method extracts 'database1'.
+   *
+   * @param name The identifier to be extracted
+   * @return The extracted qualifier
+   */
+  public static String extractQualifier(String name) {
+    int lastDelimiterIdx = name.lastIndexOf(IDENTIFIER_DELIMITER);
+    if (lastDelimiterIdx > -1) {
+      return name.substring(0, lastDelimiterIdx);
+    } else {
+      return TajoConstants.EMPTY_STRING;
+    }
+  }
+
+  /**
+   * Extract a simple name from an identifier.
+   *
+   * For example, consider a table identifier like 'database1.table1'.
+   * In this case, this method extracts 'table1'.
+   *
+   * @param name The identifier to be extracted
+   * @return The extracted simple name
+   */
+  public static String extractSimpleName(String name) {
+    int lastDelimiterIdx = name.lastIndexOf(IDENTIFIER_DELIMITER);
+    if (lastDelimiterIdx > -1) {
+      // plus one means skipping a delimiter.
+      return name.substring(lastDelimiterIdx + 1, name.length());
+    } else {
+      return name;
+    }
+  }
+
+  public static String getCanonicalTableName(String databaseName, String tableName) {
+    StringBuilder sb = new StringBuilder(databaseName);
+    sb.append(IDENTIFIER_DELIMITER);
+    sb.append(tableName);
+    return sb.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/schema/PgSQLIdentifierPolicy.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/schema/PgSQLIdentifierPolicy.java b/tajo-common/src/main/java/org/apache/tajo/schema/PgSQLIdentifierPolicy.java
index 0aca2d7..31f6d08 100644
--- a/tajo-common/src/main/java/org/apache/tajo/schema/PgSQLIdentifierPolicy.java
+++ b/tajo-common/src/main/java/org/apache/tajo/schema/PgSQLIdentifierPolicy.java
@@ -29,12 +29,12 @@ public class PgSQLIdentifierPolicy extends IdentifierPolicy {
   }
 
   @Override
-  public String getIdentifierQuoteString() {
+  public char getIdentifierQuoteString() {
     return ANSI_SQL_QUOTE_STRING;
   }
 
   @Override
-  String getIdentifierSeperator() {
+  char getIdentifierSeperator() {
     return ANSI_SQL_SEPERATOR_STRING;
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/schema/QualifiedIdentifier.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/schema/QualifiedIdentifier.java b/tajo-common/src/main/java/org/apache/tajo/schema/QualifiedIdentifier.java
index 57317b5..761958e 100644
--- a/tajo-common/src/main/java/org/apache/tajo/schema/QualifiedIdentifier.java
+++ b/tajo-common/src/main/java/org/apache/tajo/schema/QualifiedIdentifier.java
@@ -22,51 +22,70 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import org.apache.tajo.common.ProtoObject;
+import org.apache.tajo.common.TajoDataTypes.IdentifierProto;
+import org.apache.tajo.common.TajoDataTypes.QualifiedIdentifierProto;
 import org.apache.tajo.util.StringUtils;
 
 import javax.annotation.Nullable;
 import java.util.Collection;
+import java.util.Objects;
 
 import static org.apache.tajo.schema.IdentifierPolicy.DefaultPolicy;
 
-public class QualifiedIdentifier {
+/**
+ * Represents a qualified identifier. In other words, it represents identifiers for
+ * all kinds of of database objects, such as databases, tables, and columns.
+ */
+public class QualifiedIdentifier implements ProtoObject<QualifiedIdentifierProto> {
   private ImmutableList<Identifier> names;
 
-  private QualifiedIdentifier(ImmutableList<Identifier> names) {
-    this.names = names;
+  private QualifiedIdentifier(Collection<Identifier> names) {
+    this.names = ImmutableList.copyOf(names);
   }
 
-  public String displayString(final IdentifierPolicy policy) {
-    return StringUtils.join(names, policy.getIdentifierSeperator(), new Function<Identifier, String>() {
+  /**
+   * Return a raw string representation for an identifier, which is equivalent to ones used in SQL statements.
+   *
+   * @param policy IdentifierPolicy
+   * @return Raw identifier string
+   */
+  public String raw(final IdentifierPolicy policy) {
+    return StringUtils.join(names, "" + policy.getIdentifierSeperator(), new Function<Identifier, String>() {
       @Override
       public String apply(@Nullable Identifier identifier) {
-        return identifier.displayString(policy);
+        return identifier.raw(policy);
       }
     });
   }
 
+  public String interned() {
+    return interned(DefaultPolicy());
+  }
+
   /**
    * Raw string of qualified identifier
    * @param policy Identifier Policy
    * @return raw string
    */
-  public String raw(final IdentifierPolicy policy) {
-    return StringUtils.join(names, policy.getIdentifierSeperator(), new Function<Identifier, String>() {
+  public String interned(final IdentifierPolicy policy) {
+    return StringUtils.join(names, "" + policy.getIdentifierSeperator(), new Function<Identifier, String>() {
       @Override
       public String apply(@Nullable Identifier identifier) {
-        return identifier.raw(policy);
+        return identifier.interned(policy);
       }
     });
   }
 
   @Override
   public String toString() {
-    return displayString(DefaultPolicy());
+    return interned(DefaultPolicy());
   }
 
   @Override
   public int hashCode() {
-    return names.hashCode();
+    return Objects.hash(names);
   }
 
   public boolean equals(Object obj) {
@@ -89,12 +108,41 @@ public class QualifiedIdentifier {
     return new QualifiedIdentifier(ImmutableList.copyOf(names));
   }
 
+  public static QualifiedIdentifier fromProto(QualifiedIdentifierProto proto) {
+    Collection<Identifier> ids = Collections2.transform(proto.getNamesList(), new Function<IdentifierProto, Identifier>() {
+      @Override
+      public Identifier apply(@Nullable IdentifierProto identifierProto) {
+        return Identifier.fromProto(identifierProto);
+      }
+    });
+    return new QualifiedIdentifier(ids);
+  }
+
+  /**
+   * It takes interned strings. It assumes all parameters already stripped. It is used only for tests.
+   * @param names interned strings
+   * @return QualifiedIdentifier
+   */
   @VisibleForTesting
   public static QualifiedIdentifier $(String...names) {
-    ImmutableList.Builder<Identifier> builder = new ImmutableList.Builder();
-    for (String n :names) {
-      builder.add(Identifier._(n));
+    final ImmutableList.Builder<Identifier> builder = ImmutableList.builder();
+    for (String n : names) {
+      for (String split : n.split(StringUtils.escapeRegexp(""+DefaultPolicy().getIdentifierSeperator()))) {
+        builder.add(Identifier._(split, IdentifierUtil.isShouldBeQuoted(split)));
+      }
     }
     return new QualifiedIdentifier(builder.build());
   }
+
+  @Override
+  public QualifiedIdentifierProto getProto() {
+    return QualifiedIdentifierProto.newBuilder()
+        .addAllNames(Iterables.transform(names, new Function<Identifier, IdentifierProto>() {
+          @Override
+          public IdentifierProto apply(@Nullable Identifier identifier) {
+            return identifier.getProto();
+          }
+        }))
+        .build();
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/schema/Schema.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/schema/Schema.java b/tajo-common/src/main/java/org/apache/tajo/schema/Schema.java
index dfd0b72..771e03b 100644
--- a/tajo-common/src/main/java/org/apache/tajo/schema/Schema.java
+++ b/tajo-common/src/main/java/org/apache/tajo/schema/Schema.java
@@ -18,162 +18,38 @@
 
 package org.apache.tajo.schema;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
-import org.apache.tajo.type.Type;
 import org.apache.tajo.util.StringUtils;
 
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
-import java.util.Objects;
-
-import static org.apache.tajo.common.TajoDataTypes.Type.RECORD;
 
 /**
  * A field is a pair of a name and a type. Schema is an ordered list of fields.
  */
-public class Schema implements Iterable<Schema.NamedType> {
-  private final ImmutableList<NamedType> namedTypes;
+public class Schema implements Iterable<Field> {
+  private final ImmutableList<Field> fields;
 
-  public Schema(Collection<NamedType> namedTypes) {
-    this.namedTypes = ImmutableList.copyOf(namedTypes);
+  public Schema(Collection<Field> fields) {
+    this.fields = ImmutableList.copyOf(fields);
   }
 
-  public static Schema Schema(NamedType...fields) {
+  public static Schema Schema(Field...fields) {
     return new Schema(Arrays.asList(fields));
   }
 
-  public static Schema Schema(Collection<NamedType> fields) {
+  public static Schema Schema(Collection<Field> fields) {
     return new Schema(fields);
   }
 
   @Override
   public String toString() {
-    return StringUtils.join(namedTypes, ",");
-  }
-
-  public static NamedStructType Struct(QualifiedIdentifier name, NamedType... namedTypes) {
-    return Struct(name, Arrays.asList(namedTypes));
-  }
-
-  public static NamedStructType Struct(QualifiedIdentifier name, Collection<NamedType> namedTypes) {
-    return new NamedStructType(name, namedTypes);
-  }
-
-  public static NamedPrimitiveType Field(QualifiedIdentifier name, Type type) {
-    return new NamedPrimitiveType(name, type);
+    return StringUtils.join(fields, ", ");
   }
 
   @Override
-  public Iterator<NamedType> iterator() {
-    return namedTypes.iterator();
-  }
-
-  public static abstract class NamedType {
-    protected final QualifiedIdentifier name;
-
-    public NamedType(QualifiedIdentifier name) {
-      this.name = name;
-    }
-
-    public QualifiedIdentifier name() {
-      return this.name;
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hash(name);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-
-      if (this == obj) {
-        return true;
-      }
-
-      if (obj instanceof NamedType) {
-        NamedType other = (NamedType) obj;
-        return this.name.equals(other.name);
-      }
-
-      return false;
-    }
-  }
-
-  public static class NamedPrimitiveType extends NamedType {
-    private final Type type;
-
-    public NamedPrimitiveType(QualifiedIdentifier name, Type type) {
-      super(name);
-      Preconditions.checkArgument(type.baseType() != RECORD);
-      this.type = type;
-    }
-
-    public Type type() {
-      return type;
-    }
-
-    @Override
-    public String toString() {
-      return name + " " + type;
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hash(name, type);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (obj == this) {
-        return true;
-      }
-
-      if (obj instanceof NamedPrimitiveType) {
-        NamedPrimitiveType other = (NamedPrimitiveType) obj;
-        return super.equals(other) && this.type.equals(type);
-      }
-
-      return false;
-    }
-  }
-
-  public static class NamedStructType extends NamedType {
-    private final ImmutableList<NamedType> fields;
-
-    public NamedStructType(QualifiedIdentifier name, Collection<NamedType> fields) {
-      super(name);
-      this.fields = ImmutableList.copyOf(fields);
-    }
-
-    public Collection<NamedType> fields() {
-      return this.fields;
-    }
-
-    @Override
-    public String toString() {
-      return name + " record (" + StringUtils.join(fields, ",") + ")";
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hash(name, fields);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (obj == this) {
-        return true;
-      }
-
-      if (obj instanceof NamedStructType) {
-        NamedStructType other = (NamedStructType) obj;
-        return super.equals(other) && fields.equals(other.fields);
-      }
-
-      return false;
-    }
+  public Iterator<Field> iterator() {
+    return fields.iterator();
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/schema/package-info.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/schema/package-info.java b/tajo-common/src/main/java/org/apache/tajo/schema/package-info.java
new file mode 100644
index 0000000..88ce440
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/schema/package-info.java
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+
+/**
+ * Provide Schema and its relevant classes and utilities.
+ */
+package org.apache.tajo.schema;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Any.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Any.java b/tajo-common/src/main/java/org/apache/tajo/type/Any.java
index d61afae..342fdb6 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Any.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Any.java
@@ -18,16 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
-
-import java.util.Objects;
+import static org.apache.tajo.common.TajoDataTypes.Type.ANY;
 
 public class Any extends Type {
-
-  public static Any INSTANCE = new Any();
-
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.ANY;
+  public Any() {
+    super(ANY);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Array.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Array.java b/tajo-common/src/main/java/org/apache/tajo/type/Array.java
index 9a595fd..3432238 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Array.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Array.java
@@ -18,47 +18,17 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import com.google.common.collect.ImmutableList;
 
-import java.util.Objects;
+import static org.apache.tajo.common.TajoDataTypes.Type.ARRAY;
 
-public class Array extends Type {
-  private final Type elementType;
+public class Array extends TypeParamterizedType {
 
   public Array(Type elementType) {
-    this.elementType = elementType;
+    super(ARRAY, ImmutableList.of(elementType));
   }
 
   public Type elementType() {
-    return this.elementType;
-  }
-
-  @Override
-  public boolean hasParam() {
-    return true;
-  }
-
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.ARRAY;
-  }
-
-  @Override
-  public String toString() {
-    return "array<" + elementType + ">";
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(baseType(), elementType);
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object instanceof Array) {
-      return elementType.equals(((Array)object).elementType);
-    }
-
-    return false;
+    return this.params.get(0);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Blob.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Blob.java b/tajo-common/src/main/java/org/apache/tajo/type/Blob.java
index 104dd12..360ea13 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Blob.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Blob.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.BLOB;
 
 public class Blob extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.BLOB;
+  public Blob() {
+    super(BLOB);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Bool.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Bool.java b/tajo-common/src/main/java/org/apache/tajo/type/Bool.java
index ddd7300..923e8e9 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Bool.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Bool.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.BOOLEAN;
 
 public class Bool extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.BOOLEAN;
+  public Bool() {
+    super(BOOLEAN);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Char.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Char.java b/tajo-common/src/main/java/org/apache/tajo/type/Char.java
index 348e041..586775e 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Char.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Char.java
@@ -18,47 +18,16 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import com.google.common.collect.ImmutableList;
 
-import java.util.Objects;
-
-public class Char extends Type {
-  private final int length;
+import static org.apache.tajo.common.TajoDataTypes.Type.CHAR;
 
+public class Char extends ValueParamterizedType {
   public Char(int length) {
-    this.length = length;
+    super(CHAR, ImmutableList.of(length));
   }
 
   public int length() {
-    return length;
-  }
-
-  @Override
-  public boolean hasParam() {
-    return true;
-  }
-
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.CHAR;
-  }
-
-  @Override
-  public String toString() {
-    return "char(" + length + ")";
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(baseType(), length);
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object instanceof Char) {
-      return length == ((Char) object).length;
-    }
-
-    return false;
+    return params.get(0);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Date.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Date.java b/tajo-common/src/main/java/org/apache/tajo/type/Date.java
index 0febc1a..a68ab97 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Date.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Date.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.DATE;
 
 public class Date extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.DATE;
+  public Date() {
+    super(DATE);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Float4.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Float4.java b/tajo-common/src/main/java/org/apache/tajo/type/Float4.java
index 47ccd6b..b8c8218 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Float4.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Float4.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.FLOAT4;
 
 public class Float4 extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.FLOAT4;
+  public Float4() {
+    super(FLOAT4);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Float8.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Float8.java b/tajo-common/src/main/java/org/apache/tajo/type/Float8.java
index 6d2702c..f36fac8 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Float8.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Float8.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.FLOAT8;
 
 public class Float8 extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.FLOAT8;
+  public Float8() {
+    super(FLOAT8);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Inet4.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Inet4.java b/tajo-common/src/main/java/org/apache/tajo/type/Inet4.java
index 05dc0cf..541841e 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Inet4.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Inet4.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.INET4;
 
 public class Inet4 extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.INET4;
+  public Inet4() {
+    super(INET4);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Int1.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Int1.java b/tajo-common/src/main/java/org/apache/tajo/type/Int1.java
index 9288328..d86d36e 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Int1.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Int1.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.INT1;
 
 public class Int1 extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.INT1;
+  public Int1() {
+    super(INT1);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Int2.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Int2.java b/tajo-common/src/main/java/org/apache/tajo/type/Int2.java
index 44db4cb..e7c2215 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Int2.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Int2.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.INT2;
 
 public class Int2 extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.INT2;
+  public Int2() {
+    super(INT2);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Int4.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Int4.java b/tajo-common/src/main/java/org/apache/tajo/type/Int4.java
index 0837e2c..e8db784 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Int4.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Int4.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.INT4;
 
 public class Int4 extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.INT4;
+  public Int4() {
+    super(INT4);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Int8.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Int8.java b/tajo-common/src/main/java/org/apache/tajo/type/Int8.java
index 3d4049c..999e9ac 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Int8.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Int8.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.INT8;
 
 public class Int8 extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.INT8;
+  public Int8() {
+    super(INT8);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Interval.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Interval.java b/tajo-common/src/main/java/org/apache/tajo/type/Interval.java
index 6c99526..d6dc17e 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Interval.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Interval.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.INTERVAL;
 
 public class Interval extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.INTERVAL;
+  public Interval() {
+    super(INTERVAL);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Map.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Map.java b/tajo-common/src/main/java/org/apache/tajo/type/Map.java
index afc1cc3..786d6af 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Map.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Map.java
@@ -18,49 +18,20 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import com.google.common.collect.ImmutableList;
 
-import java.util.Objects;
-
-public class Map extends Type {
-  private final Type keyType;
-  private final Type valueType;
+import static org.apache.tajo.common.TajoDataTypes.Type.MAP;
 
+public class Map extends TypeParamterizedType {
   public Map(Type keyType, Type valueType) {
-    this.keyType = keyType;
-    this.valueType = valueType;
+    super(MAP, ImmutableList.of(keyType, valueType));
   }
 
   public Type keyType() {
-    return this.keyType;
+    return this.params.get(0);
   }
 
   public Type valueType() {
-    return this.valueType;
-  }
-
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.MAP;
-  }
-
-  @Override
-  public String toString() {
-    return "map<" + keyType + "," + valueType + ">";
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(baseType(), keyType, valueType);
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object instanceof Map) {
-      Map other = (Map) object;
-      return keyType.equals(other.keyType) && valueType.equals(other.valueType);
-    }
-
-    return false;
+    return this.params.get(1);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Null.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Null.java b/tajo-common/src/main/java/org/apache/tajo/type/Null.java
index fe823e1..74cf052 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Null.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Null.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.NULL_TYPE;
 
 public class Null extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.NULL_TYPE;
+  public Null() {
+    super(NULL_TYPE);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Numeric.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Numeric.java b/tajo-common/src/main/java/org/apache/tajo/type/Numeric.java
index 75ef392..c21325d 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Numeric.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Numeric.java
@@ -18,49 +18,21 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import com.google.common.collect.ImmutableList;
 
-import java.util.Objects;
+import static org.apache.tajo.common.TajoDataTypes.Type.NUMERIC;
 
-public class Numeric extends Type {
-  private final int precision;
-  private final int scale;
+public class Numeric extends ValueParamterizedType {
 
   public Numeric(int precision, int scale) {
-    this.precision = precision;
-    this.scale = scale;
+    super(NUMERIC, ImmutableList.of(precision, scale));
   }
 
   public int precision() {
-    return this.precision;
+    return this.params.get(0);
   }
 
   public int scale() {
-    return this.scale;
-  }
-
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.NUMERIC;
-  }
-
-  @Override
-  public String toString() {
-    return "numeric(" + precision + "," + scale + ")";
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(baseType(), precision, scale);
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object instanceof Numeric) {
-      Numeric other = (Numeric) object;
-      return precision == other.precision && scale == other.scale;
-    }
-
-    return false;
+    return this.params.get(1);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Protobuf.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Protobuf.java b/tajo-common/src/main/java/org/apache/tajo/type/Protobuf.java
index 59d3c1a..e286724 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Protobuf.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Protobuf.java
@@ -18,25 +18,17 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.PROTOBUF;
 
 public class Protobuf extends Type {
   private String msgName;
 
   public Protobuf(String msgName) {
+    super(PROTOBUF);
     this.msgName = msgName;
   }
 
   public String getMessageName() {
     return this.msgName;
   }
-
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.PROTOBUF;
-  }
-
-  public boolean hasParam() {
-    return true;
-  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Record.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Record.java b/tajo-common/src/main/java/org/apache/tajo/type/Record.java
new file mode 100644
index 0000000..46d7e19
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Record.java
@@ -0,0 +1,79 @@
+/**
+ * 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.type;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.tajo.schema.Field;
+import org.apache.tajo.util.StringUtils;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+import static org.apache.tajo.common.TajoDataTypes.Type.RECORD;
+
+/**
+ * Represents Record type
+ */
+public class Record extends Type implements Iterable<Field> {
+  private final ImmutableList<Field> fields;
+
+  public Record(Collection<Field> fields) {
+    super(RECORD);
+    this.fields = ImmutableList.copyOf(fields);
+  }
+
+  public int size() {
+    return fields.size();
+  }
+
+  public Field field(int idx) {
+    return fields.get(idx);
+  }
+
+  public List<Field> fields() {
+    return this.fields;
+  }
+
+  @Override
+  public String toString() {
+    return "RECORD(" + StringUtils.join(fields, ", ") + ")";
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(kind(), Objects.hash(fields));
+  }
+
+  @Override
+  public boolean equals(Object object) {
+    if (object instanceof Record) {
+      Record other = (Record) object;
+      return fields.equals(other.fields);
+    }
+
+    return false;
+  }
+
+  @Override
+  public Iterator<Field> iterator() {
+    return fields.iterator();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Struct.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Struct.java b/tajo-common/src/main/java/org/apache/tajo/type/Struct.java
deleted file mode 100644
index 551eb81..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/type/Struct.java
+++ /dev/null
@@ -1,72 +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.type;
-
-import com.google.common.collect.ImmutableList;
-import org.apache.tajo.common.TajoDataTypes;
-import org.apache.tajo.util.StringUtils;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-
-public class Struct extends Type {
-  private final ImmutableList<Type> memberTypes;
-
-  public Struct(Collection<Type> memberTypes) {
-    this.memberTypes = ImmutableList.copyOf(memberTypes);
-  }
-
-  public int size() {
-    return memberTypes.size();
-  }
-
-  public Type memberType(int idx) {
-    return memberTypes.get(idx);
-  }
-
-  public List<Type> memberTypes() {
-    return this.memberTypes;
-  }
-
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.RECORD;
-  }
-
-  @Override
-  public String toString() {
-    return "struct(" + StringUtils.join(memberTypes, ",") + ")";
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(baseType(), Objects.hash(memberTypes));
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object instanceof Struct) {
-      Struct other = (Struct) object;
-      return memberTypes.equals(other.memberTypes);
-    }
-
-    return false;
-  }
-}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Text.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Text.java b/tajo-common/src/main/java/org/apache/tajo/type/Text.java
index e523afe..aab49a4 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Text.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Text.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.TEXT;
 
 public class Text extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.TEXT;
+  public Text() {
+    super(TEXT);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Time.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Time.java b/tajo-common/src/main/java/org/apache/tajo/type/Time.java
index 3b1414c..12fe5f8 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Time.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Time.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.TIME;
 
 public class Time extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.TIME;
+  public Time() {
+    super(TIME);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Timestamp.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Timestamp.java b/tajo-common/src/main/java/org/apache/tajo/type/Timestamp.java
index 5b02314..577f877 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Timestamp.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Timestamp.java
@@ -18,11 +18,10 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import static org.apache.tajo.common.TajoDataTypes.Type.TIMESTAMP;
 
 public class Timestamp extends Type {
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.TIMESTAMP;
+  public Timestamp() {
+    super(TIMESTAMP);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Type.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Type.java b/tajo-common/src/main/java/org/apache/tajo/type/Type.java
index fdea07e..35d666c 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Type.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Type.java
@@ -18,12 +18,21 @@
 
 package org.apache.tajo.type;
 
+import org.apache.tajo.common.ProtoObject;
 import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.TypeProto;
+import org.apache.tajo.exception.TajoRuntimeException;
+import org.apache.tajo.exception.UnsupportedException;
+import org.apache.tajo.schema.Field;
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 
-public abstract class Type {
+/**
+ * Represents Type
+ */
+public abstract class Type implements Cloneable, ProtoObject<TypeProto> {
 
   // No paramter types
   public static final Any Any = new Any();
@@ -43,39 +52,64 @@ public abstract class Type {
   public static final Blob Blob = new Blob();
   public static final Inet4 Inet4 = new Inet4();
 
-  public abstract TajoDataTypes.Type baseType();
+  protected TajoDataTypes.Type kind;
+
+  public Type(TajoDataTypes.Type kind) {
+    this.kind = kind;
+  }
+
+  public TajoDataTypes.Type kind() {
+    return kind;
+  }
+
+  public boolean isTypeParameterized() {
+    return false;
+  }
 
-  public boolean hasParam() {
+  public boolean isValueParameterized() {
     return false;
   }
 
+  public List<Type> getTypeParameters() {
+    throw new TajoRuntimeException(new UnsupportedException());
+  }
+
+  public List<Integer> getValueParameters() {
+    throw new TajoRuntimeException(new UnsupportedException());
+  }
+
   protected static String typeName(TajoDataTypes.Type type) {
-    return type.name().toLowerCase();
+    return type.name().toUpperCase();
   }
 
   @Override
   public int hashCode() {
-    return baseType().hashCode();
+    return kind().hashCode();
   }
 
   @Override
   public boolean equals(Object t) {
-    return t instanceof Type && ((Type)t).baseType() == baseType();
+    return t instanceof Type && ((Type)t).kind() == kind();
   }
 
   @Override
   public String toString() {
-    return typeName(baseType());
+    return typeName(kind());
   }
 
   public boolean isStruct() {
-    return this.baseType() == TajoDataTypes.Type.RECORD;
+    return this.kind() == TajoDataTypes.Type.RECORD;
   }
 
-  public boolean isNull() { return this.baseType() == TajoDataTypes.Type.NULL_TYPE; }
+  public boolean isNull() { return this.kind() == TajoDataTypes.Type.NULL_TYPE; }
 
+  public static int DEFAULT_PRECISION = 0;
   public static int DEFAULT_SCALE = 0;
 
+  public static Numeric Numeric() {
+    return new Numeric(DEFAULT_PRECISION, DEFAULT_SCALE);
+  }
+
   public static Numeric Numeric(int precision) {
     return new Numeric(precision, DEFAULT_SCALE);
   }
@@ -84,22 +118,6 @@ public abstract class Type {
     return new Numeric(precision, scale);
   }
 
-  public static Date Date() {
-    return new Date();
-  }
-
-  public static Time Time() {
-    return new Time();
-  }
-
-  public static Timestamp Timestamp() {
-    return new Timestamp();
-  }
-
-  public static Interval Interval() {
-    return new Interval();
-  }
-
   public static Char Char(int len) {
     return new Char(len);
   }
@@ -108,30 +126,18 @@ public abstract class Type {
     return new Varchar(len);
   }
 
-  public static Text Text() {
-    return new Text();
-  }
-
-  public static Blob Blob() {
-    return new Blob();
-  }
-
-  public static Inet4 Inet4() {
-    return new Inet4();
-  }
-
-  public static Struct Struct(Collection<Type> types) {
-    return new Struct(types);
-  }
-
-  public static Struct Struct(Type ... types) {
-    return new Struct(Arrays.asList(types));
+  public static Record Record(Collection<Field> types) {
+    return new Record(types);
   }
 
   public static Array Array(Type type) {
     return new Array(type);
   }
 
+  public static Record Record(Field... types) {
+    return new Record(Arrays.asList(types));
+  }
+
   public static Map Map(Type keyType, Type valueType) {
     return new Map(keyType, valueType);
   }
@@ -139,4 +145,9 @@ public abstract class Type {
   public static Null Null() {
     return new Null();
   }
+
+  @Override
+  public TypeProto getProto() {
+    return TypeProtobufEncoder.encode(this);
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/TypeFactory.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/TypeFactory.java b/tajo-common/src/main/java/org/apache/tajo/type/TypeFactory.java
new file mode 100644
index 0000000..e2cf45b
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/type/TypeFactory.java
@@ -0,0 +1,184 @@
+/**
+ * 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.type;
+
+import org.apache.tajo.Assert;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.exception.NotImplementedException;
+import org.apache.tajo.exception.TajoInternalError;
+import org.apache.tajo.exception.TajoRuntimeException;
+import org.apache.tajo.exception.UnsupportedException;
+import org.apache.tajo.schema.Field;
+import org.apache.tajo.util.StringUtils;
+
+import java.util.List;
+
+import static org.apache.tajo.type.Type.Char;
+import static org.apache.tajo.type.Type.Null;
+import static org.apache.tajo.type.Type.Varchar;
+
+public class TypeFactory {
+  /**
+   * This is for base types.
+   *
+   * @param baseType legacy base type
+   * @return Type
+   */
+  public static Type create(TajoDataTypes.Type baseType) {
+    switch (baseType) {
+    case BOOLEAN:
+      return Type.Bool;
+    case INT1:
+      return Type.Int1;
+    case INT2:
+      return Type.Int2;
+    case INT4:
+      return Type.Int4;
+    case INT8:
+      return Type.Int8;
+    case FLOAT4:
+      return Type.Float4;
+    case FLOAT8:
+      return Type.Float8;
+    case DATE:
+      return Type.Date;
+    case TIME:
+      return Type.Time;
+    case TIMESTAMP:
+      return Type.Timestamp;
+    case INTERVAL:
+      return Type.Interval;
+    case CHAR:
+      return Type.Char(1); // default len = 1
+    case TEXT:
+      return Type.Text;
+    case BLOB:
+      return Type.Blob;
+    case INET4:
+      return Type.Inet4;
+    case RECORD:
+      // for better exception
+      throw new TajoRuntimeException(new NotImplementedException("record projection"));
+    case NULL_TYPE:
+      return Type.Null;
+    case ANY:
+      return Type.Any;
+
+    case BOOLEAN_ARRAY:
+      return Type.Array(Type.Bool);
+    case INT1_ARRAY:
+      return Type.Array(Type.Int1);
+    case INT2_ARRAY:
+      return Type.Array(Type.Int2);
+    case INT4_ARRAY:
+      return Type.Array(Type.Int4);
+    case INT8_ARRAY:
+      return Type.Array(Type.Int8);
+    case FLOAT4_ARRAY:
+      return Type.Array(Type.Float4);
+    case FLOAT8_ARRAY:
+      return Type.Array(Type.Float8);
+    case TIMESTAMP_ARRAY:
+      return Type.Array(Type.Timestamp);
+    case DATE_ARRAY:
+      return Type.Array(Type.Date);
+    case TIME_ARRAY:
+      return Type.Array(Type.Time);
+    case TEXT_ARRAY:
+      return Type.Array(Type.Text);
+
+    default:
+      throw new TajoRuntimeException(new UnsupportedException(baseType.name()));
+    }
+  }
+
+  public static Type create(TajoDataTypes.Type baseType,
+                            List<Type> typeParams,
+                            List<Integer> valueParams,
+                            List<Field> fieldParams) {
+    switch (baseType) {
+    case CHAR: {
+      Assert.assertCondition(valueParams.size() == 1,
+          "Char type requires 1 integer parameters, but it takes (%s).", StringUtils.join(typeParams));
+      return Char(valueParams.get(0));
+    }
+    case VARCHAR: {
+      Assert.assertCondition(valueParams.size() == 1,
+          "Varchar type requires 1 integer parameters, but it takes (%s).", StringUtils.join(typeParams));
+      return Varchar(valueParams.get(0));
+    }
+    case TEXT: return Type.Text;
+
+    case BOOLEAN: return Type.Bool;
+    case INT1: return Type.Int1;
+    case INT2: return Type.Int2;
+    case INT4: return Type.Int4;
+    case INT8: return Type.Int8;
+    case FLOAT4: return Type.Float4;
+    case FLOAT8: return Type.Float8;
+    case NUMERIC: {
+      if (valueParams.size() == 0) {
+        return Numeric.Numeric();
+
+      } else {
+        for (Object p : valueParams) {
+          Assert.assertCondition(p instanceof Integer, "Numeric type requires integer parameters");
+        }
+        if (valueParams.size() == 1) {
+          return Numeric.Numeric(valueParams.get(0));
+        } else if (valueParams.size() == 2) {
+          return Numeric.Numeric(valueParams.get(0), valueParams.get(1));
+        } else {
+          Assert.assertCondition(false,
+              "Numeric type can take 2 or less integer parameters, but it takes (%s).", StringUtils.join(valueParams));
+        }
+      }
+    }
+
+    case DATE: return Type.Date;
+    case TIME: return Type.Time;
+    case TIMESTAMP: return Type.Timestamp;
+    case INTERVAL: return Type.Interval;
+    case BLOB: return Type.Blob;
+    case INET4: return Type.Inet4;
+
+    case ARRAY: {
+      Assert.assertCondition(typeParams.size() == 1,
+          "Array Type requires 1 type parameters, but it takes (%s).", StringUtils.join(typeParams));
+      return Type.Array(typeParams.get(0));
+    }
+    case RECORD: {
+      Assert.assertCondition(fieldParams.size() >= 1,
+          "Record Type requires at least 1 field parameters, but it takes (%s).", StringUtils.join(fieldParams));
+      return Type.Record(fieldParams);
+    }
+    case MAP: {
+      Assert.assertCondition(typeParams.size() == 2,
+          "Map Type requires 2 type parameters, but it takes (%s).", StringUtils.join(typeParams));
+
+      return Type.Map(typeParams.get(0), typeParams.get(1));
+    }
+    case NULL_TYPE:
+      return Null();
+
+    default:
+      throw new TajoInternalError(new UnsupportedException(baseType.name()));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/TypeParamterizedType.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/TypeParamterizedType.java b/tajo-common/src/main/java/org/apache/tajo/type/TypeParamterizedType.java
new file mode 100644
index 0000000..bacf6c7
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/type/TypeParamterizedType.java
@@ -0,0 +1,77 @@
+/**
+ * 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.type;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.util.StringUtils;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a type-parameterized Type (e.g., Map&lt;Int, String&gt; and Array&lt;Double&gt;)
+ */
+public abstract class TypeParamterizedType extends Type {
+  protected ImmutableList<Type> params;
+
+  public TypeParamterizedType(TajoDataTypes.Type type, ImmutableList<Type> params) {
+    super(type);
+    this.params = params;
+  }
+
+  @Override
+  public boolean isTypeParameterized() {
+    return true;
+  }
+
+  @Override
+  public List<Type> getTypeParameters() {
+    return params;
+  }
+
+  @Override
+  public boolean equals(Object object) {
+    if (object == this) {
+      return true;
+    }
+
+    if (object instanceof TypeParamterizedType) {
+      TypeParamterizedType other = (TypeParamterizedType) object;
+      return this.kind.equals(other.kind) && params.equals(other.params);
+    }
+
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(kind(), params);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(typeName(this.kind));
+    sb.append("<");
+    sb.append(StringUtils.join(params, ","));
+    sb.append(">");
+    return sb.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/TypeProtobufEncoder.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/TypeProtobufEncoder.java b/tajo-common/src/main/java/org/apache/tajo/type/TypeProtobufEncoder.java
new file mode 100644
index 0000000..4fd2897
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/type/TypeProtobufEncoder.java
@@ -0,0 +1,185 @@
+/**
+ * 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.type;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.QualifiedIdentifierProto;
+import org.apache.tajo.common.TajoDataTypes.TypeElement;
+import org.apache.tajo.common.TajoDataTypes.TypeProto;
+import org.apache.tajo.exception.TajoInternalError;
+import org.apache.tajo.schema.Field;
+import org.apache.tajo.schema.QualifiedIdentifier;
+
+import javax.annotation.Nullable;
+import java.util.*;
+
+import static java.util.Collections.EMPTY_LIST;
+import static org.apache.tajo.Assert.assertCondition;
+import static org.apache.tajo.common.TajoDataTypes.Type.*;
+import static org.apache.tajo.type.Type.Array;
+import static org.apache.tajo.type.Type.Map;
+import static org.apache.tajo.type.Type.Record;
+
+public class TypeProtobufEncoder {
+  public static TypeProto encode(Type type) {
+
+    final TypeProto.Builder builder = TypeProto.newBuilder();
+    new Visitor(builder).visit(type);
+    return builder.build();
+  }
+
+  public static Type decode(TypeProto proto) {
+    Stack<Type> stack = new Stack<>();
+
+    for (int curIdx = 0; curIdx < proto.getElementsCount(); curIdx++) {
+      TypeElement e = proto.getElements(curIdx);
+
+      if (e.hasChildNum()) { // if it is a type-parameterized, that is
+        List<Type> childTypes = popMultiItems(stack, e.getChildNum());
+
+        if (e.getKind() == ARRAY || e.getKind() == MAP) {
+          stack.push(createTypeParameterizedType(e, childTypes));
+
+        } else { // record
+          assertCondition(e.getKind() == RECORD,
+              "This type must be RECORD type.");
+          assertCondition(childTypes.size() == e.getFieldNamesCount(),
+              "The number of Field types and names must be equal.");
+
+          ImmutableList.Builder<Field> fields = ImmutableList.builder();
+          for (int i = 0; i < childTypes.size(); i++) {
+            fields.add(new Field(QualifiedIdentifier.fromProto(e.getFieldNames(i)), childTypes.get(i)));
+          }
+          stack.push(Record(fields.build()));
+        }
+
+      } else {
+        stack.push(createPrimitiveType(e));
+      }
+    }
+
+    assertCondition(stack.size() == 1, "Stack size has two or more items.");
+    return stack.pop();
+  }
+
+  static List<Type> popMultiItems(Stack<Type> stack, int num) {
+    List<Type> typeParams = new ArrayList<>();
+    for (int i = 0; i < num; i++) {
+      typeParams.add(0, stack.pop());
+    }
+    return typeParams;
+  }
+
+  static boolean isValueParameterized(TajoDataTypes.Type baseType) {
+    return baseType == CHAR || baseType == VARCHAR || baseType == NUMERIC;
+  }
+
+  static Type createPrimitiveType(TypeElement element) {
+    assertPrimitiveType(element);
+
+    if (isValueParameterized(element.getKind())) {
+      return TypeFactory.create(element.getKind(), EMPTY_LIST, element.getValueParamsList(), EMPTY_LIST);
+    } else if (element.getKind() == PROTOBUF) { // TODO - PROTOBUF type should be removed later
+      return new Protobuf(element.getStringParams(0));
+    } else {
+      return TypeFactory.create(element.getKind());
+    }
+  }
+
+  static Type createTypeParameterizedType(TypeElement element, List<Type> childTypes) {
+    switch (element.getKind()) {
+    case ARRAY:
+      return Array(childTypes.get(0));
+    case MAP:
+      return Map(childTypes.get(0), childTypes.get(1));
+    default:
+      throw new TajoInternalError(element.getKind().name() + " is not a type-parameterized type.");
+    }
+  }
+
+  static void assertPrimitiveType(TypeElement element) {
+    TajoDataTypes.Type baseType = element.getKind();
+    if (baseType == MAP || baseType == RECORD || baseType == ARRAY) {
+      throw new TajoInternalError(baseType.name() + " is not a primitive type.");
+    }
+  }
+
+  static class Visitor extends TypeVisitor {
+    final TypeProto.Builder builder;
+
+    Visitor(TypeProto.Builder builder) {
+      this.builder = builder;
+    }
+
+    @Override
+    public void visitPrimitive(Type type) {
+      TypeElement.Builder typeElemBuilder = TypeElement.newBuilder()
+          .setKind(type.kind);
+
+      if (type.isValueParameterized()) {
+        typeElemBuilder.addAllValueParams(type.getValueParameters());
+      } else if (type.kind == PROTOBUF) {
+        typeElemBuilder.addStringParams(((Protobuf)type).getMessageName());
+      }
+
+      builder.addElements(typeElemBuilder);
+    }
+
+    @Override
+    public void visitMap(Map map) {
+      super.visitMap(map);
+      builder.addElements(TypeElement.newBuilder()
+             .setKind(map.kind)
+             .setChildNum(2)
+          );
+    }
+
+    @Override
+    public void visitArray(Array array) {
+      super.visitArray(array);
+      builder
+          .addElements(TypeElement.newBuilder()
+              .setKind(array.kind)
+              .setChildNum(1)
+          );
+    }
+
+    @Override
+    public void visitRecord(Record record) {
+      super.visitRecord(record);
+
+      Collection<QualifiedIdentifierProto> field_names =
+          Collections2.transform(record.fields(), new Function<Field, QualifiedIdentifierProto>() {
+        @Override
+        public QualifiedIdentifierProto apply(@Nullable Field field) {
+          return field.name().getProto();
+        }
+      });
+
+      builder
+          .addElements(TypeElement.newBuilder()
+              .setChildNum(record.size())
+              .addAllFieldNames(field_names)
+              .setKind(RECORD));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/TypeStringEncoder.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/TypeStringEncoder.java b/tajo-common/src/main/java/org/apache/tajo/type/TypeStringEncoder.java
new file mode 100644
index 0000000..b6e1b18
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/type/TypeStringEncoder.java
@@ -0,0 +1,296 @@
+/**
+ * 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.type;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import org.apache.tajo.Assert;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.exception.TajoInternalError;
+import org.apache.tajo.exception.UnsupportedException;
+import org.apache.tajo.schema.Field;
+import org.apache.tajo.schema.IdentifierUtil;
+import org.apache.tajo.schema.QualifiedIdentifier;
+import org.apache.tajo.util.StringUtils;
+
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.Stack;
+
+import static org.apache.tajo.schema.IdentifierPolicy.DefaultPolicy;
+
+/**
+ * This class enables to serialize a type into a string representation and vice versa.
+ */
+public class TypeStringEncoder {
+
+  /**
+   * Encode a type into a string representation
+   * @param type A type
+   * @return A type string representation
+   */
+  public static String encode(Type type) {
+    StringBuilder sb = new StringBuilder(type.kind().name());
+
+    if (type.isTypeParameterized()) {
+      sb.append("<");
+      sb.append(StringUtils.join(type.getTypeParameters(), ",", new Function<Type, String>() {
+        @Override
+        public String apply(@Nullable Type type) {
+          return TypeStringEncoder.encode(type);
+        }
+      }));
+      sb.append(">");
+    }
+
+    // Assume all parameter values are integers.
+    if (type.isValueParameterized()) {
+      sb.append("(");
+      sb.append(StringUtils.join(type.getValueParameters(), ","));
+      sb.append(")");
+    }
+
+    if (type.isStruct()) {
+      Record record = (Record) type;
+      sb.append("[");
+      sb.append(StringUtils.join(record.fields(), ",", new Function<Field, String>() {
+        @Override
+        public String apply(@Nullable Field field) {
+          return serializeField(field);
+        }
+      }));
+      sb.append("]");
+    }
+
+    return sb.toString();
+  }
+
+  /**
+   * Make a string from a field
+   * @param field A field
+   * @return String representation for a field
+   */
+  static String serializeField(Field field) {
+    return field.name().raw(DefaultPolicy()) + " " + encode(field.type());
+  }
+
+  /**
+   * Decode a string representation to a Type.
+   * @param signature Type string representation
+   * @return Type
+   */
+  public static Type decode(String signature) {
+
+    // termination condition in this recursion
+    if (!(signature.contains("<") || signature.contains("(") || signature.contains("["))) {
+      return createType(signature,
+          ImmutableList.<Type>of(),
+          ImmutableList.<Integer>of(),
+          ImmutableList.<Field>of());
+    }
+
+    final Stack<Character> stack = new Stack<>();
+    final Stack<Integer> spanStack = new Stack<>();
+    String baseType = null;
+    for (int i = 0; i < signature.length(); i++) {
+      char c = signature.charAt(i);
+
+      if (c == '<') {
+        if (stack.isEmpty()) {
+          Assert.assertCondition(baseType == null, "Expected baseName to be null");
+          baseType = signature.substring(0, i);
+        }
+        stack.push('<');
+        spanStack.push(i + 1);
+
+      } else if (c == '>') {
+        Assert.assertCondition(stack.pop() == '<', "Bad signature: '%s'", signature);
+        int paramStartIdx = spanStack.pop();
+
+        if (stack.isEmpty()) { // ensure outermost parameters
+          return createType(baseType,
+              parseList(signature.substring(paramStartIdx, i), new Function<String, Type>() {
+                @Override
+                public Type apply(@Nullable String s) {
+                  return decode(s);
+                }
+              }),
+              ImmutableList.<Integer>of(),
+              ImmutableList.<Field>of());
+        }
+
+      } else if (c == '[') {
+        if (stack.isEmpty()) {
+          Assert.assertCondition(baseType == null, "Expected baseName to be null");
+          baseType = signature.substring(0, i);
+        }
+
+        stack.push('[');
+        spanStack.push(i + 1);
+
+      } else if (c == ']') {
+        Assert.assertCondition(stack.pop() == '[', "Bad signature: '%s'", signature);
+
+        int paramStartIdx = spanStack.pop();
+        if (stack.isEmpty()) { // ensure outermost parameters
+          return createType(baseType,
+              ImmutableList.<Type>of(),
+              ImmutableList.<Integer>of(),
+              parseList(signature.substring(paramStartIdx, i), new Function<String, Field>() {
+                @Override
+                public Field apply(@Nullable String s) {
+                  return parseField(s);
+                }
+              }));
+        }
+
+      } else if (c == '(') {
+        if (stack.isEmpty()) {
+          Assert.assertCondition(baseType == null, "Expected baseName to be null");
+          baseType = signature.substring(0, i);
+        }
+        stack.push('(');
+        spanStack.push(i + 1);
+
+      } else if (c == ')') {
+        Assert.assertCondition(stack.pop() == '(', "Bad signature: '%s'", signature);
+        int paramStartIdx = spanStack.pop();
+
+        if (stack.isEmpty()) { // ensure outermost parameters
+          return createType(baseType,
+              ImmutableList.<Type>of(),
+              parseList(signature.substring(paramStartIdx, i), new Function<String, Integer>() {
+                @Override
+                public Integer apply(@Nullable String s) {
+                  return parseValue(s);
+                }
+              }),
+              ImmutableList.<Field>of());
+        }
+      }
+    }
+
+    return null;
+  }
+
+  public static int parseValue(String literal) {
+    try {
+      return Integer.parseInt(literal);
+    } catch (NumberFormatException e) {
+      throw new TajoInternalError(e);
+    }
+  }
+
+  /**
+   * Parse a string delimited by comma into a list of object instances depending on <pre>itemParser</pre>.
+   * @param str String delimited by comma
+   * @param itemParser A function to transform a string to an object.
+   * @param <T> Type to be transformed from a string
+   * @return List of object instances
+   */
+  static <T> List<T> parseList(String str, Function<String, T> itemParser) {
+    if (!str.contains(",")) { // if just one item
+      return ImmutableList.of(itemParser.apply(str));
+    }
+
+    final ImmutableList.Builder<T> fields = ImmutableList.builder();
+    final Stack<Character> stack = new Stack<>();
+    int paramStartIdx = 0;
+    for (int i = 0; i < str.length(); i++) {
+      char c = str.charAt(i);
+
+      if (c == '<' || c == '[' || c == '(') {
+        stack.push(c);
+      } else if (c == '>') {
+        Assert.assertCondition(stack.pop() == '<', "Bad signature: '%s'", str);
+      } else if (c == ']') {
+        Assert.assertCondition(stack.pop() == '[', "Bad signature: '%s'", str);
+      } else if (c == ')') {
+        Assert.assertCondition(stack.pop() == '(', "Bad signature: '%s'", str);
+      } else if (c == ',') {
+        if (stack.isEmpty()) { // ensure outermost type parameters
+          fields.add(itemParser.apply(str.substring(paramStartIdx, i)));
+          paramStartIdx = i + 1;
+        }
+      }
+    }
+
+    Assert.assertCondition(stack.empty(), "Bad signature: '%s'", str);
+    if (paramStartIdx < str.length()) {
+      fields.add(itemParser.apply(str.substring(paramStartIdx, str.length())));
+    }
+
+    return fields.build();
+  }
+
+  /**
+   * Make a field from a string representation
+   * @param str String
+   * @return Field
+   */
+  static Field parseField(String str) {
+    // A field consists of an identifier and a type, and they are delimited by space.
+    if (!str.contains(" ")) {
+      Assert.assertCondition(false, "Bad field signature: '%s'", str);
+    }
+
+    // Stack to track the nested bracket depth
+    Stack<Character> stack = new Stack<>();
+    int paramStartIdx = 0;
+    for (int i = 0; i < str.length(); i++) {
+      char c = str.charAt(i);
+
+      if (c == '<' || c == '[' || c == '(') {
+        stack.push(c);
+      } else if (c == '>') { // for validation
+        Assert.assertCondition(stack.pop() == '<', "Bad field signature: '%s'", str);
+      } else if (c == ']') { // for validation
+        Assert.assertCondition(stack.pop() == '[', "Bad field signature: '%s'", str);
+      } else if (c == ')') { // for validation
+        Assert.assertCondition(stack.pop() == '(', "Bad field signature: '%s'", str);
+
+      } else if (c == ' ') {
+        if (stack.isEmpty()) { // ensure outermost type parameters
+          QualifiedIdentifier identifier =
+              IdentifierUtil.makeIdentifier(str.substring(paramStartIdx, i), DefaultPolicy());
+          String typePart = str.substring(i + 1, str.length());
+          return new Field(identifier, decode(typePart));
+        }
+      }
+    }
+
+    return null;
+  }
+
+  public static Type createType(String baseTypeStr,
+                                List<Type> typeParams,
+                                List<Integer> valueParams,
+                                List<Field> fieldParams) {
+    final TajoDataTypes.Type baseType;
+
+    try {
+      baseType = TajoDataTypes.Type.valueOf(baseTypeStr);
+    } catch (Throwable t) {
+      throw new TajoInternalError(new UnsupportedException(baseTypeStr));
+    }
+
+    return TypeFactory.create(baseType, typeParams, valueParams, fieldParams);
+  }
+
+}


[2/7] tajo git commit: TAJO-2129: Apply new type implementation to Schema and Catalog.

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenContext.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenContext.java b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenContext.java
index 0dea104..c2840c5 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenContext.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenContext.java
@@ -116,7 +116,7 @@ public class EvalCodeGenContext extends TajoGeneratorAdapter {
       if (entry.getKey().getType() == EvalType.CONST) {
         ConstEval constEval = (ConstEval) entry.getKey();
 
-        if (constEval.getValueType().baseType() == TajoDataTypes.Type.INTERVAL) {
+        if (constEval.getValueType().kind() == TajoDataTypes.Type.INTERVAL) {
           IntervalDatum datum = (IntervalDatum) constEval.getValue();
 
           final String internalName = TajoGeneratorAdapter.getInternalName(IntervalDatum.class);
@@ -141,7 +141,7 @@ public class EvalCodeGenContext extends TajoGeneratorAdapter {
         initMethod.visitTypeInsn(Opcodes.NEW, internalName);
         consAdapter.dup();
         emitCreateEval(consAdapter, initMethod, inEval.getLeftExpr());
-        emitRowConstantEval(consAdapter, initMethod, (RowConstantEval) inEval.getRightExpr());
+        emitRowConstantEval(consAdapter, initMethod, inEval.getRightExpr());
         consAdapter.push(inEval.isNot());
         consAdapter.invokeSpecial(InEval.class, "<init>", void.class,
             new Class [] {EvalNode.class, RowConstantEval.class, boolean.class});

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenerator.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenerator.java b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenerator.java
index 5ee6d82..981370b 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenerator.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenerator.java
@@ -170,7 +170,7 @@ public class EvalCodeGenerator extends SimpleEvalNodeVisitor<EvalCodeGenContext>
       context.emitNullityCheck(ifNull);
 
       SignedEval signed = (SignedEval) unary;
-      switch (signed.getValueType().baseType()) {
+      switch (signed.getValueType().kind()) {
       case BOOLEAN:
       case CHAR:
       case INT1:
@@ -375,7 +375,7 @@ public class EvalCodeGenerator extends SimpleEvalNodeVisitor<EvalCodeGenContext>
       String methodName = null;
       Class returnType = null;
       Class [] paramTypes = null;
-      switch (field.getValueType().baseType()) {
+      switch (field.getValueType().kind()) {
       case BOOLEAN:
         methodName = "getByte";
         returnType = byte.class;
@@ -479,7 +479,7 @@ public class EvalCodeGenerator extends SimpleEvalNodeVisitor<EvalCodeGenContext>
   }
 
   public static int store(EvalCodeGenContext context, org.apache.tajo.type.Type type, int idx) {
-    switch (type.baseType()) {
+    switch (type.kind()) {
     case NULL_TYPE:
     case BOOLEAN:
     case CHAR:
@@ -642,7 +642,7 @@ public class EvalCodeGenerator extends SimpleEvalNodeVisitor<EvalCodeGenContext>
 
   @Override
   public EvalNode visitConst(EvalCodeGenContext context, ConstEval constEval, Stack<EvalNode> stack) {
-    switch (constEval.getValueType().baseType()) {
+    switch (constEval.getValueType().kind()) {
     case NULL_TYPE:
 
       if (stack.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoGeneratorAdapter.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoGeneratorAdapter.java b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoGeneratorAdapter.java
index 8a958bb..d11701b 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoGeneratorAdapter.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoGeneratorAdapter.java
@@ -162,12 +162,12 @@ class TajoGeneratorAdapter {
   }
 
   public static boolean isJVMInternalInt(org.apache.tajo.type.Type type) {
-    final TajoDataTypes.Type baseType = type.baseType();
+    final TajoDataTypes.Type baseType = type.kind();
     return baseType == BOOLEAN || baseType == INT1 || baseType == INT2 || baseType == INT4 || baseType== INET4;
   }
 
   public static int getWordSize(org.apache.tajo.type.Type type) {
-    final TajoDataTypes.Type baseType = type.baseType();
+    final TajoDataTypes.Type baseType = type.kind();
     if (baseType == INT8 || baseType == FLOAT8 || baseType == TIMESTAMP || baseType == TIME) {
       return 2;
     } else {
@@ -249,7 +249,7 @@ class TajoGeneratorAdapter {
       }
     } else {
 
-      if (type.baseType() == TEXT) {
+      if (type.kind() == TEXT) {
         invokeVirtual(String.class, "compareTo", int.class, new Class[]{String.class});
       } else {
         int opCode = TajoGeneratorAdapter.getOpCode(evalType, type);
@@ -282,7 +282,7 @@ class TajoGeneratorAdapter {
   }
 
   public void load(org.apache.tajo.type.Type type, int idx) {
-    switch (type.baseType()) {
+    switch (type.kind()) {
     case NULL_TYPE:
     case BOOLEAN:
     case CHAR:
@@ -401,7 +401,7 @@ class TajoGeneratorAdapter {
   }
 
   public void pushDummyValue(org.apache.tajo.type.Type type) {
-    TajoDataTypes.Type baseType = type.baseType();
+    TajoDataTypes.Type baseType = type.kind();
 
     if (type.isNull()) {
       pushNullOfThreeValuedLogic();
@@ -448,19 +448,19 @@ class TajoGeneratorAdapter {
   }
 
   public static boolean isPrimitiveOpCode(EvalType evalType, org.apache.tajo.type.Type returnType) {
-    return TUtil.containsInNestedMap(OpCodesMap, evalType, returnType.baseType());
+    return TUtil.containsInNestedMap(OpCodesMap, evalType, returnType.kind());
   }
 
   public static int getOpCode(EvalType evalType, org.apache.tajo.type.Type returnType) {
     if (!isPrimitiveOpCode(evalType, returnType)) {
       throw new CompilationError("No Such OpCode for " + evalType + " returning " + returnType);
     }
-    return TUtil.getFromNestedMap(OpCodesMap, evalType, returnType.baseType());
+    return TUtil.getFromNestedMap(OpCodesMap, evalType, returnType.kind());
   }
 
   public void castInsn(org.apache.tajo.type.Type srcType, org.apache.tajo.type.Type targetType) {
-    TajoDataTypes.Type srcBaseType = srcType.baseType();
-    TajoDataTypes.Type targetBaseType = targetType.baseType();
+    TajoDataTypes.Type srcBaseType = srcType.kind();
+    TajoDataTypes.Type targetBaseType = targetType.kind();
     switch(srcBaseType) {
     case BOOLEAN:
     case CHAR: {
@@ -600,7 +600,7 @@ class TajoGeneratorAdapter {
     methodvisitor.visitJumpInsn(Opcodes.IFEQ, ifNull);  // datum
 
     aload(datum);
-    switch (type.baseType()) {
+    switch (type.kind()) {
     case BOOLEAN:
     case INT1:
     case INT2:
@@ -643,7 +643,7 @@ class TajoGeneratorAdapter {
     String convertMethod;
     Class returnType;
     Class [] paramTypes;
-    switch (type.baseType()) {
+    switch (type.kind()) {
     case NULL_TYPE:
       pop();      // pop null flag
       pop(type);  // pop null datum
@@ -895,7 +895,7 @@ class TajoGeneratorAdapter {
     int varId = nextVarId;
     nextVarId += TajoGeneratorAdapter.getWordSize(type);
 
-    switch (type.baseType()) {
+    switch (type.kind()) {
     case NULL_TYPE:
     case BOOLEAN:
     case CHAR:
@@ -928,7 +928,7 @@ class TajoGeneratorAdapter {
   }
 
   public void emitBoxing(EvalCodeGenContext context, org.apache.tajo.type.Type type) {
-    switch (type.baseType()) {
+    switch (type.kind()) {
     case CHAR:
     case TEXT:
 
@@ -954,7 +954,7 @@ class TajoGeneratorAdapter {
   }
 
   public void emitUnboxing(EvalCodeGenContext context, org.apache.tajo.type.Type type) {
-    switch (type.baseType()) {
+    switch (type.kind()) {
     case CHAR:
     case TEXT:
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/engine/codegen/VariablesPreBuilder.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/VariablesPreBuilder.java b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/VariablesPreBuilder.java
index 9d0f9d0..bc2ccfc 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/VariablesPreBuilder.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/VariablesPreBuilder.java
@@ -55,9 +55,9 @@ class VariablesPreBuilder extends SimpleEvalNodeVisitor<EvalCodeGenContext> {
   @Override
   public EvalNode visitConst(EvalCodeGenContext context, ConstEval constEval, Stack<EvalNode> stack) {
 
-    if (constEval.getValueType().baseType() == TajoDataTypes.Type.INTERVAL) {
+    if (constEval.getValueType().kind() == TajoDataTypes.Type.INTERVAL) {
       if (!context.symbols.containsKey(constEval)) {
-        String fieldName = constEval.getValueType().baseType().name() + "_" + context.seqId++;
+        String fieldName = constEval.getValueType().kind().name() + "_" + context.seqId++;
         context.symbols.put(constEval, fieldName);
 
         context.classWriter.visitField(Opcodes.ACC_PRIVATE, fieldName,

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
index cdab04f..fd34c46 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
@@ -349,13 +349,13 @@ public class GlobalPlanner {
   private AggregationFunctionCallEval createSumFunction(EvalNode[] args) throws TajoException {
     FunctionDesc functionDesc = null;
     functionDesc = getCatalog().getFunction("sum", CatalogProtos.FunctionType.AGGREGATION,
-        TypeConverter.convert(args[0].getValueType()));
+        TypeConverter.convert(args[0].getValueType()).getDataType());
     return new AggregationFunctionCallEval(functionDesc, args);
   }
 
   private AggregationFunctionCallEval createCountFunction(EvalNode [] args) throws TajoException {
     FunctionDesc functionDesc = getCatalog().getFunction("count", CatalogProtos.FunctionType.AGGREGATION,
-        TypeConverter.convert(args[0].getValueType()));
+        TypeConverter.convert(args[0].getValueType()).getDataType());
     return new AggregationFunctionCallEval(functionDesc, args);
   }
 
@@ -367,13 +367,13 @@ public class GlobalPlanner {
 
   private AggregationFunctionCallEval createMaxFunction(EvalNode [] args) throws TajoException {
     FunctionDesc functionDesc = getCatalog().getFunction("max", CatalogProtos.FunctionType.AGGREGATION,
-        TypeConverter.convert(args[0].getValueType()));
+        TypeConverter.convert(args[0].getValueType()).getDataType());
     return new AggregationFunctionCallEval(functionDesc, args);
   }
 
   private AggregationFunctionCallEval createMinFunction(EvalNode [] args) throws TajoException {
     FunctionDesc functionDesc = getCatalog().getFunction("min", CatalogProtos.FunctionType.AGGREGATION,
-        TypeConverter.convert(args[0].getValueType()));
+        TypeConverter.convert(args[0].getValueType()).getDataType());
     return new AggregationFunctionCallEval(functionDesc, args);
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java b/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
index 22024e4..d423c04 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
@@ -54,6 +54,7 @@ import org.apache.tajo.plan.logical.ScanNode;
 import org.apache.tajo.querymaster.QueryJobEvent;
 import org.apache.tajo.rpc.BlockingRpcServer;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.*;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.session.Session;
 import org.apache.tajo.util.KeyValueSet;
 import org.apache.tajo.util.NetUtils;
@@ -771,8 +772,8 @@ public class TajoMasterClientService extends AbstractService {
 
         String databaseName;
         String tableName;
-        if (CatalogUtil.isFQTableName(request.getValue())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getValue());
+        if (IdentifierUtil.isFQTableName(request.getValue())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getValue());
           databaseName = splitted[0];
           tableName = splitted[1];
         } else {
@@ -832,8 +833,8 @@ public class TajoMasterClientService extends AbstractService {
 
         String databaseName;
         String tableName;
-        if (CatalogUtil.isFQTableName(request.getValue())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getValue());
+        if (IdentifierUtil.isFQTableName(request.getValue())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getValue());
           databaseName = splitted[0];
           tableName = splitted[1];
         } else {
@@ -968,8 +969,8 @@ public class TajoMasterClientService extends AbstractService {
 
         String databaseName;
         String tableName;
-        if (CatalogUtil.isFQTableName(request.getValue())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getValue());
+        if (IdentifierUtil.isFQTableName(request.getValue())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getValue());
           databaseName = splitted[0];
           tableName = splitted[1];
         } else {
@@ -997,8 +998,8 @@ public class TajoMasterClientService extends AbstractService {
         Session session = context.getSessionManager().getSession(request.getSessionId().getId());
 
         String indexName, databaseName;
-        if (CatalogUtil.isFQTableName(request.getValue())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getValue());
+        if (IdentifierUtil.isFQTableName(request.getValue())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getValue());
           databaseName = splitted[0];
           indexName = splitted[1];
         } else {
@@ -1026,8 +1027,8 @@ public class TajoMasterClientService extends AbstractService {
         Session session = context.getSessionManager().getSession(request.getSessionId().getId());
 
         String indexName, databaseName;
-        if (CatalogUtil.isFQTableName(request.getValue())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getValue());
+        if (IdentifierUtil.isFQTableName(request.getValue())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getValue());
           databaseName = splitted[0];
           indexName = splitted[1];
         } else {
@@ -1053,8 +1054,8 @@ public class TajoMasterClientService extends AbstractService {
         Session session = context.getSessionManager().getSession(request.getSessionId().getId());
 
         String tableName, databaseName;
-        if (CatalogUtil.isFQTableName(request.getValue())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getValue());
+        if (IdentifierUtil.isFQTableName(request.getValue())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getValue());
           databaseName = splitted[0];
           tableName = splitted[1];
         } else {
@@ -1082,8 +1083,8 @@ public class TajoMasterClientService extends AbstractService {
         Session session = context.getSessionManager().getSession(request.getSessionId().getId());
 
         String tableName, databaseName;
-        if (CatalogUtil.isFQTableName(request.getValue())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getValue());
+        if (IdentifierUtil.isFQTableName(request.getValue())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getValue());
           databaseName = splitted[0];
           tableName = splitted[1];
         } else {
@@ -1108,8 +1109,8 @@ public class TajoMasterClientService extends AbstractService {
         Session session = context.getSessionManager().getSession(request.getSessionId().getId());
 
         String tableName, databaseName;
-        if (CatalogUtil.isFQTableName(request.getTableName())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getTableName());
+        if (IdentifierUtil.isFQTableName(request.getTableName())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getTableName());
           databaseName = splitted[0];
           tableName = splitted[1];
         } else {
@@ -1139,8 +1140,8 @@ public class TajoMasterClientService extends AbstractService {
         Session session = context.getSessionManager().getSession(request.getSessionId().getId());
 
         String tableName, databaseName;
-        if (CatalogUtil.isFQTableName(request.getTableName())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getTableName());
+        if (IdentifierUtil.isFQTableName(request.getTableName())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getTableName());
           databaseName = splitted[0];
           tableName = splitted[1];
         } else {
@@ -1168,8 +1169,8 @@ public class TajoMasterClientService extends AbstractService {
         QueryContext queryContext = new QueryContext(conf, session);
 
         String indexName, databaseName;
-        if (CatalogUtil.isFQTableName(request.getValue())) {
-          String [] splitted = CatalogUtil.splitFQTableName(request.getValue());
+        if (IdentifierUtil.isFQTableName(request.getValue())) {
+          String [] splitted = IdentifierUtil.splitFQTableName(request.getValue());
           databaseName = splitted[0];
           indexName = splitted[1];
         } else {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java b/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
index 55d5442..9c3a1ad 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
@@ -31,6 +31,7 @@ import org.apache.tajo.exception.UndefinedTableException;
 import org.apache.tajo.master.TajoMaster;
 import org.apache.tajo.plan.logical.CreateTableNode;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.Tablespace;
 import org.apache.tajo.storage.TablespaceManager;
 import org.apache.tajo.util.Pair;
@@ -89,7 +90,7 @@ public class CreateTableExecutor {
     Pair<String, String> separatedNames = getQualifiedName(queryContext.getCurrentDatabase(), tableName);
     String databaseName = separatedNames.getFirst();
     String simpleTableName = separatedNames.getSecond();
-    String qualifiedName = CatalogUtil.buildFQName(databaseName, simpleTableName);
+    String qualifiedName = IdentifierUtil.buildFQName(databaseName, simpleTableName);
 
     // Check if the table to be created already exists
     boolean exists = catalog.existsTable(databaseName, simpleTableName);
@@ -125,8 +126,8 @@ public class CreateTableExecutor {
   }
 
   private Pair<String, String> getQualifiedName(String currentDatabase, String tableName) {
-    if (CatalogUtil.isFQTableName(tableName)) {
-      String [] splitted = CatalogUtil.splitFQTableName(tableName);
+    if (IdentifierUtil.isFQTableName(tableName)) {
+      String [] splitted = IdentifierUtil.splitFQTableName(tableName);
       return new Pair<>(splitted[0], splitted[1]);
     } else {
       return new Pair<>(currentDatabase, tableName);

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java b/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java
index 6a22141..c480d04 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java
@@ -42,6 +42,7 @@ import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.logical.*;
 import org.apache.tajo.plan.rewrite.rules.PartitionedTableRewriter;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.FileTablespace;
 import org.apache.tajo.storage.StorageUtil;
 import org.apache.tajo.storage.Tablespace;
@@ -138,15 +139,15 @@ public class DDLExecutor {
       throws DuplicateIndexException, UndefinedTableException, UndefinedDatabaseException {
 
     String databaseName, simpleIndexName, qualifiedIndexName;
-    if (CatalogUtil.isFQTableName(createIndexNode.getIndexName())) {
-      String[] splits = CatalogUtil.splitFQTableName(createIndexNode.getIndexName());
+    if (IdentifierUtil.isFQTableName(createIndexNode.getIndexName())) {
+      String[] splits = IdentifierUtil.splitFQTableName(createIndexNode.getIndexName());
       databaseName = splits[0];
       simpleIndexName = splits[1];
       qualifiedIndexName = createIndexNode.getIndexName();
     } else {
       databaseName = queryContext.getCurrentDatabase();
       simpleIndexName = createIndexNode.getIndexName();
-      qualifiedIndexName = CatalogUtil.buildFQName(databaseName, simpleIndexName);
+      qualifiedIndexName = IdentifierUtil.buildFQName(databaseName, simpleIndexName);
     }
 
     if (catalog.existIndexByName(databaseName, simpleIndexName)) {
@@ -158,7 +159,7 @@ public class DDLExecutor {
       throw new InternalError("Cannot find the table of the relation");
     }
 
-    IndexDesc indexDesc = new IndexDesc(databaseName, CatalogUtil.extractSimpleName(scanNode.getTableName()),
+    IndexDesc indexDesc = new IndexDesc(databaseName, IdentifierUtil.extractSimpleName(scanNode.getTableName()),
         simpleIndexName, createIndexNode.getIndexPath(),
         createIndexNode.getKeySortSpecs(), createIndexNode.getIndexMethod(),
         createIndexNode.isUnique(), false, scanNode.getLogicalSchema());
@@ -170,8 +171,8 @@ public class DDLExecutor {
       throws UndefinedIndexException, UndefinedDatabaseException {
 
     String databaseName, simpleIndexName;
-    if (CatalogUtil.isFQTableName(dropIndexNode.getIndexName())) {
-      String[] splits = CatalogUtil.splitFQTableName(dropIndexNode.getIndexName());
+    if (IdentifierUtil.isFQTableName(dropIndexNode.getIndexName())) {
+      String[] splits = IdentifierUtil.splitFQTableName(dropIndexNode.getIndexName());
       databaseName = splits[0];
       simpleIndexName = splits[1];
     } else {
@@ -293,15 +294,15 @@ public class DDLExecutor {
 
     String databaseName;
     String simpleTableName;
-    if (CatalogUtil.isFQTableName(tableName)) {
-      String[] splitted = CatalogUtil.splitFQTableName(tableName);
+    if (IdentifierUtil.isFQTableName(tableName)) {
+      String[] splitted = IdentifierUtil.splitFQTableName(tableName);
       databaseName = splitted[0];
       simpleTableName = splitted[1];
     } else {
       databaseName = queryContext.getCurrentDatabase();
       simpleTableName = tableName;
     }
-    String qualifiedName = CatalogUtil.buildFQName(databaseName, simpleTableName);
+    String qualifiedName = IdentifierUtil.buildFQName(databaseName, simpleTableName);
 
     boolean exists = catalog.existsTable(qualifiedName);
     if (!exists) {
@@ -340,15 +341,15 @@ public class DDLExecutor {
 
     List<TableDesc> tableDescList = new ArrayList<>();
     for (String eachTableName : tableNames) {
-      if (CatalogUtil.isFQTableName(eachTableName)) {
-        String[] split = CatalogUtil.splitFQTableName(eachTableName);
+      if (IdentifierUtil.isFQTableName(eachTableName)) {
+        String[] split = IdentifierUtil.splitFQTableName(eachTableName);
         databaseName = split[0];
         simpleTableName = split[1];
       } else {
         databaseName = queryContext.getCurrentDatabase();
         simpleTableName = eachTableName;
       }
-      final String qualifiedName = CatalogUtil.buildFQName(databaseName, simpleTableName);
+      final String qualifiedName = IdentifierUtil.buildFQName(databaseName, simpleTableName);
 
       if (!catalog.existsTable(databaseName, simpleTableName)) {
         throw new UndefinedTableException(qualifiedName);
@@ -404,15 +405,15 @@ public class DDLExecutor {
 
     String databaseName;
     String simpleTableName;
-    if (CatalogUtil.isFQTableName(tableName)) {
-      String[] split = CatalogUtil.splitFQTableName(tableName);
+    if (IdentifierUtil.isFQTableName(tableName)) {
+      String[] split = IdentifierUtil.splitFQTableName(tableName);
       databaseName = split[0];
       simpleTableName = split[1];
     } else {
       databaseName = queryContext.getCurrentDatabase();
       simpleTableName = tableName;
     }
-    final String qualifiedName = CatalogUtil.buildFQName(databaseName, simpleTableName);
+    final String qualifiedName = IdentifierUtil.buildFQName(databaseName, simpleTableName);
 
     if (!catalog.existsTable(databaseName, simpleTableName)) {
       throw new UndefinedTableException(qualifiedName);
@@ -573,8 +574,8 @@ public class DDLExecutor {
 
     String databaseName;
     String simpleTableName;
-    if (CatalogUtil.isFQTableName(tableName)) {
-      String[] split = CatalogUtil.splitFQTableName(tableName);
+    if (IdentifierUtil.isFQTableName(tableName)) {
+      String[] split = IdentifierUtil.splitFQTableName(tableName);
       databaseName = split[0];
       simpleTableName = split[1];
     } else {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/master/exec/NonForwardQueryResultSystemScanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/NonForwardQueryResultSystemScanner.java b/tajo-core/src/main/java/org/apache/tajo/master/exec/NonForwardQueryResultSystemScanner.java
index c3280fa..ac917ef 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/exec/NonForwardQueryResultSystemScanner.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/NonForwardQueryResultSystemScanner.java
@@ -28,7 +28,6 @@ import org.apache.tajo.TaskId;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.proto.CatalogProtos.*;
 import org.apache.tajo.catalog.statistics.TableStats;
-import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.datum.DatumFactory;
 import org.apache.tajo.engine.codegen.CompilationError;
@@ -40,6 +39,7 @@ import org.apache.tajo.engine.planner.global.GlobalPlanner;
 import org.apache.tajo.engine.planner.global.MasterPlan;
 import org.apache.tajo.engine.planner.physical.PhysicalExec;
 import org.apache.tajo.engine.query.QueryContext;
+import org.apache.tajo.exception.InvalidSessionException;
 import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.exception.TajoInternalError;
 import org.apache.tajo.ipc.ClientProtos.SerializedResultSet;
@@ -52,13 +52,15 @@ import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.logical.ScanNode;
 import org.apache.tajo.resource.NodeResource;
 import org.apache.tajo.resource.NodeResources;
-import org.apache.tajo.exception.InvalidSessionException;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.RowStoreUtil;
 import org.apache.tajo.storage.RowStoreUtil.RowStoreEncoder;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.VTuple;
 import org.apache.tajo.tuple.memory.MemoryBlock;
 import org.apache.tajo.tuple.memory.MemoryRowBlock;
+import org.apache.tajo.type.Type;
+import org.apache.tajo.type.TypeProtobufEncoder;
 import org.apache.tajo.util.KeyValueSet;
 import org.apache.tajo.worker.TaskAttemptContext;
 
@@ -285,11 +287,11 @@ public class NonForwardQueryResultSystemScanner implements NonForwardQueryResult
         } else if ("ordinal_position".equalsIgnoreCase(colObj.getSimpleName())) {
           aTuple.put(fieldId, DatumFactory.createInt4(columnId));
         } else if ("data_type".equalsIgnoreCase(colObj.getSimpleName())) {
-          aTuple.put(fieldId, DatumFactory.createText(column.getDataType().getType().toString()));
+          aTuple.put(fieldId, DatumFactory.createText(column.getType().toString()));
         } else if ("type_length".equalsIgnoreCase(colObj.getSimpleName())) {
-          DataType dataType = column.getDataType();
-          if (dataType.hasLength()) {
-            aTuple.put(fieldId, DatumFactory.createInt4(dataType.getLength()));
+          Type type = TypeProtobufEncoder.decode(column.getType());
+          if (type.isValueParameterized()) {
+            aTuple.put(fieldId, DatumFactory.createInt4(type.getValueParameters().get(0)));
           } else {
             aTuple.put(fieldId, DatumFactory.createNullDatum());
           }
@@ -557,7 +559,7 @@ public class NonForwardQueryResultSystemScanner implements NonForwardQueryResult
   
   private List<Tuple> fetchSystemTable(TableDesc tableDesc, Schema inSchema) {
     List<Tuple> tuples = null;
-    String tableName = CatalogUtil.extractSimpleName(tableDesc.getName());
+    String tableName = IdentifierUtil.extractSimpleName(tableDesc.getName());
 
     if ("tablespace".equalsIgnoreCase(tableName)) {
       tuples = getTablespaces(inSchema);

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java b/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java
index f0a6b76..58f4ec0 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java
@@ -60,6 +60,7 @@ import org.apache.tajo.plan.function.python.PythonScriptEngine;
 import org.apache.tajo.plan.function.python.TajoScriptEngine;
 import org.apache.tajo.plan.logical.*;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.tuple.memory.MemoryBlock;
@@ -595,15 +596,15 @@ public class QueryExecutor {
       throws DuplicateIndexException {
 
     String databaseName, simpleIndexName, qualifiedIndexName;
-    if (CatalogUtil.isFQTableName(createIndexNode.getIndexName())) {
-      String[] splits = CatalogUtil.splitFQTableName(createIndexNode.getIndexName());
+    if (IdentifierUtil.isFQTableName(createIndexNode.getIndexName())) {
+      String[] splits = IdentifierUtil.splitFQTableName(createIndexNode.getIndexName());
       databaseName = splits[0];
       simpleIndexName = splits[1];
       qualifiedIndexName = createIndexNode.getIndexName();
     } else {
       databaseName = queryContext.getCurrentDatabase();
       simpleIndexName = createIndexNode.getIndexName();
-      qualifiedIndexName = CatalogUtil.buildFQName(databaseName, simpleIndexName);
+      qualifiedIndexName = IdentifierUtil.buildFQName(databaseName, simpleIndexName);
     }
 
     if (catalog.existIndexByName(databaseName, simpleIndexName)) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/master/exec/prehook/CreateTableHook.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/prehook/CreateTableHook.java b/tajo-core/src/main/java/org/apache/tajo/master/exec/prehook/CreateTableHook.java
index 0c02b6e..e6fee07 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/exec/prehook/CreateTableHook.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/prehook/CreateTableHook.java
@@ -18,12 +18,12 @@
 
 package org.apache.tajo.master.exec.prehook;
 
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.engine.query.QueryContext;
 import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.logical.CreateTableNode;
 import org.apache.tajo.plan.logical.LogicalRootNode;
 import org.apache.tajo.plan.logical.NodeType;
+import org.apache.tajo.schema.IdentifierUtil;
 
 public class CreateTableHook implements DistributedQueryHook {
 
@@ -37,8 +37,7 @@ public class CreateTableHook implements DistributedQueryHook {
   public void hook(QueryContext queryContext, LogicalPlan plan) throws Exception {
     LogicalRootNode rootNode = plan.getRootBlock().getRoot();
     CreateTableNode createTableNode = rootNode.getChild();
-    String [] splitted  = CatalogUtil.splitFQTableName(createTableNode.getTableName());
-    String databaseName = splitted[0];
+    String [] splitted  = IdentifierUtil.splitFQTableName(createTableNode.getTableName());
     String tableName = splitted[1];
     queryContext.setOutputTable(tableName);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
index f00c85e..5c9a9db 100644
--- a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
+++ b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
@@ -1008,16 +1008,6 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
   }
 
   @Override
-  public Expr visitArray(ArrayContext ctx) {
-    int size = ctx.numeric_value_expression().size();
-    Expr[] exprs = new Expr[size];
-    for (int i = 0; i < size; i++) {
-      exprs[i] = visit(ctx.numeric_value_expression(i));
-    }
-    return new ValueListExpr(exprs);
-  }
-
-  @Override
   public Expr visitPattern_matching_predicate(Pattern_matching_predicateContext ctx) {
     Expr predicand = visitChildren(ctx.row_value_predicand());
     Expr pattern = new LiteralValue(stripQuote(ctx.Character_String_Literal().getText()),
@@ -1626,15 +1616,24 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
     } else if (checkIfExist(predefined_type.network_type())) {
       typeDefinition = new DataTypeExpr(Type.INET4.name());
 
+    } else if (checkIfExist(predefined_type.complex_type())) {
+      Complex_typeContext complexType = predefined_type.complex_type();
+
+      if (checkIfExist(complexType.array_type())) {
+        DataTypeExpr elementType = visitData_type(complexType.array_type().data_type());
+        typeDefinition = new DataTypeExpr(new DataTypeExpr.ArrayType(elementType));
 
-    } else if (checkIfExist(predefined_type.record_type())) {
-      ColumnDefinition [] nestedRecordDefine = getDefinitions(predefined_type.record_type().table_elements());
-      typeDefinition = new DataTypeExpr(new DataTypeExpr.RecordType(nestedRecordDefine));
+      } else if (checkIfExist(complexType.record_type())) {
+        ColumnDefinition[] nestedRecordDefine = getDefinitions(complexType.record_type().table_elements());
+        typeDefinition = new DataTypeExpr(new DataTypeExpr.RecordType(nestedRecordDefine));
 
-    } else if (checkIfExist(predefined_type.map_type())) {
-      Map_typeContext mapTypeContext = predefined_type.map_type();
-      typeDefinition = new DataTypeExpr(
-          new MapType(visitData_type(mapTypeContext.key_type), visitData_type(mapTypeContext.value_type)));
+      } else if (checkIfExist(complexType.map_type())) {
+        Map_typeContext mapTypeContext = complexType.map_type();
+        typeDefinition = new DataTypeExpr(
+            new MapType(visitData_type(mapTypeContext.key_type), visitData_type(mapTypeContext.value_type)));
+      }
+    } else {
+      throw new TajoInternalError("Reached code points that shouldn't be reached");
     }
 
     return typeDefinition;

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/querymaster/Query.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/querymaster/Query.java b/tajo-core/src/main/java/org/apache/tajo/querymaster/Query.java
index d57040e..289d933 100644
--- a/tajo-core/src/main/java/org/apache/tajo/querymaster/Query.java
+++ b/tajo-core/src/main/java/org/apache/tajo/querymaster/Query.java
@@ -50,6 +50,7 @@ import org.apache.tajo.exception.ErrorUtil;
 import org.apache.tajo.master.event.*;
 import org.apache.tajo.plan.logical.*;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageConstants;
 import org.apache.tajo.storage.Tablespace;
 import org.apache.tajo.storage.TablespaceManager;
@@ -544,8 +545,8 @@ public class Query implements EventHandler<QueryEvent> {
               finalOutputDir, partitions);
 
             String databaseName, simpleTableName;
-            if (CatalogUtil.isFQTableName(tableDesc.getName())) {
-              String[] split = CatalogUtil.splitFQTableName(tableDesc.getName());
+            if (IdentifierUtil.isFQTableName(tableDesc.getName())) {
+              String[] split = IdentifierUtil.splitFQTableName(tableDesc.getName());
               databaseName = split[0];
               simpleTableName = split[1];
             } else {
@@ -630,21 +631,21 @@ public class Query implements EventHandler<QueryEvent> {
 
         CreateIndexNode createIndexNode = (CreateIndexNode) lastStage.getBlock().getPlan();
         String databaseName, simpleIndexName, qualifiedIndexName;
-        if (CatalogUtil.isFQTableName(createIndexNode.getIndexName())) {
-          String [] splits = CatalogUtil.splitFQTableName(createIndexNode.getIndexName());
+        if (IdentifierUtil.isFQTableName(createIndexNode.getIndexName())) {
+          String [] splits = IdentifierUtil.splitFQTableName(createIndexNode.getIndexName());
           databaseName = splits[0];
           simpleIndexName = splits[1];
           qualifiedIndexName = createIndexNode.getIndexName();
         } else {
           databaseName = queryContext.getCurrentDatabase();
           simpleIndexName = createIndexNode.getIndexName();
-          qualifiedIndexName = CatalogUtil.buildFQName(databaseName, simpleIndexName);
+          qualifiedIndexName = IdentifierUtil.buildFQName(databaseName, simpleIndexName);
         }
         ScanNode scanNode = PlannerUtil.findTopNode(createIndexNode, NodeType.SCAN);
         if (scanNode == null) {
           throw new IOException("Cannot find the table of the relation");
         }
-        IndexDesc indexDesc = new IndexDesc(databaseName, CatalogUtil.extractSimpleName(scanNode.getTableName()),
+        IndexDesc indexDesc = new IndexDesc(databaseName, IdentifierUtil.extractSimpleName(scanNode.getTableName()),
             simpleIndexName, createIndexNode.getIndexPath(),
             createIndexNode.getKeySortSpecs(), createIndexNode.getIndexMethod(),
             createIndexNode.isUnique(), false, scanNode.getLogicalSchema());

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core/src/main/java/org/apache/tajo/ws/rs/resources/TablesResource.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/ws/rs/resources/TablesResource.java b/tajo-core/src/main/java/org/apache/tajo/ws/rs/resources/TablesResource.java
index 3afe7c8..e5bd0f6 100644
--- a/tajo-core/src/main/java/org/apache/tajo/ws/rs/resources/TablesResource.java
+++ b/tajo-core/src/main/java/org/apache/tajo/ws/rs/resources/TablesResource.java
@@ -21,10 +21,10 @@ package org.apache.tajo.ws.rs.resources;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.master.TajoMaster.MasterContext;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.ws.rs.*;
 
 import javax.ws.rs.*;
@@ -174,8 +174,8 @@ public class TablesResource {
           JerseyResourceDelegateContextKey.valueOf(JerseyResourceDelegateUtil.MasterContextKey, MasterContext.class);
       MasterContext masterContext = context.get(masterContextKey);
       
-      if (CatalogUtil.isFQTableName(tableName)) {
-        tableName = CatalogUtil.extractSimpleName(tableName);
+      if (IdentifierUtil.isFQTableName(tableName)) {
+        tableName = IdentifierUtil.extractSimpleName(tableName);
       }
       
       CatalogService catalogService = masterContext.getCatalog();
@@ -239,8 +239,8 @@ public class TablesResource {
           JerseyResourceDelegateContextKey.valueOf(JerseyResourceDelegateUtil.MasterContextKey, MasterContext.class);
       MasterContext masterContext = context.get(masterContextKey);
       
-      if (CatalogUtil.isFQTableName(tableName)) {
-        tableName = CatalogUtil.extractSimpleName(tableName);
+      if (IdentifierUtil.isFQTableName(tableName)) {
+        tableName = IdentifierUtil.extractSimpleName(tableName);
       }
       
       CatalogService catalogService = masterContext.getCatalog();
@@ -249,7 +249,7 @@ public class TablesResource {
         return Response.status(Status.NOT_FOUND).build();
       }
       
-      String canonicalTableName = CatalogUtil.getCanonicalTableName(databaseName, tableName);
+      String canonicalTableName = IdentifierUtil.getCanonicalTableName(databaseName, tableName);
 
       try {
         catalogService.dropTable(canonicalTableName);

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
index e3cf73a..8c76aba 100644
--- a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
@@ -27,6 +27,7 @@ import org.apache.tajo.common.type.TajoTypeUtil;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.datum.TextDatum;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.VersionInfo;
 
 import java.sql.*;
@@ -110,7 +111,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public String getIdentifierQuoteString() throws SQLException {
-    return CatalogConstants.IDENTIFIER_QUOTE_STRING;
+    return IdentifierUtil.IDENTIFIER_QUOTE_STRING;
   }
 
   @Override
@@ -167,7 +168,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public String getCatalogSeparator() throws SQLException {
-    return CatalogConstants.IDENTIFIER_DELIMITER;
+    return IdentifierUtil.IDENTIFIER_DELIMITER;
   }
 
   @Override
@@ -182,7 +183,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public int getMaxColumnNameLength() throws SQLException {
-    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
+    return IdentifierUtil.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
@@ -217,7 +218,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public int getMaxCursorNameLength() throws SQLException {
-    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
+    return IdentifierUtil.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
@@ -227,17 +228,17 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public int getMaxSchemaNameLength() throws SQLException {
-    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
+    return IdentifierUtil.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
   public int getMaxProcedureNameLength() throws SQLException {
-    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
+    return IdentifierUtil.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
   public int getMaxCatalogNameLength() throws SQLException {
-    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
+    return IdentifierUtil.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
@@ -262,7 +263,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public int getMaxTableNameLength() throws SQLException {
-    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
+    return IdentifierUtil.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
@@ -503,7 +504,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
         for (String table: tables) {
           if (table.matches(regtableNamePattern)) {
             TableDesc tableDesc = conn.getCatalogAdminClient().getTableDesc(
-                CatalogUtil.buildFQName(databaseName, table));
+                IdentifierUtil.buildFQName(databaseName, table));
             int pos = 0;
 
             for (Column column: tableDesc.getLogicalSchema().getRootColumns()) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestResultSet.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestResultSet.java b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestResultSet.java
index 050029e..17fd759 100644
--- a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestResultSet.java
+++ b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestResultSet.java
@@ -32,6 +32,7 @@ import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.datum.DatumFactory;
 import org.apache.tajo.ipc.ClientProtos.SerializedResultSet;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.tuple.memory.MemoryBlock;
 import org.apache.tajo.tuple.memory.MemoryRowBlock;
@@ -99,7 +100,7 @@ public class TestResultSet {
     stats.setAvgRows(tupleNum);
     stats.setNumBlocks(1000);
     stats.setNumShuffleOutputs(100);
-    desc = new TableDesc(CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "score"),
+    desc = new TableDesc(IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "score"),
         scoreSchema, scoreMeta, p.toUri());
     desc.setStats(stats);
     assertEquals(tupleNum, rowBlock.rows());

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoDatabaseMetaData.java b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoDatabaseMetaData.java
index 1b694c0..8951590 100644
--- a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoDatabaseMetaData.java
+++ b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoDatabaseMetaData.java
@@ -21,8 +21,8 @@ package org.apache.tajo.jdbc;
 import com.google.common.collect.Sets;
 import org.apache.tajo.QueryTestCaseBase;
 import org.apache.tajo.TajoConstants;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.common.type.TajoTypeUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.TUtil;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -260,9 +260,9 @@ public class TestTajoDatabaseMetaData extends QueryTestCaseBase {
 
   private static String getTestColName(String dbName, String tableName, int i) {
     if (i % 2 == 1) {
-      return CatalogUtil.denormalizeIdentifier(dbName + "_" + tableName + "_col") + " int";
+      return IdentifierUtil.denormalizeIdentifier(dbName + "_" + tableName + "_col") + " int";
     } else {
-      return CatalogUtil.denormalizeIdentifier(dbName + "_" + tableName + "_COL") + " int";
+      return IdentifierUtil.denormalizeIdentifier(dbName + "_" + tableName + "_COL") + " int";
     }
   }
 
@@ -293,7 +293,7 @@ public class TestTajoDatabaseMetaData extends QueryTestCaseBase {
 
           TUtil.putToNestedList(tables, dbName, tableName);
 
-          executeString("CREATE TABLE " + dbName + "." + CatalogUtil.denormalizeIdentifier(tableName) +
+          executeString("CREATE TABLE " + dbName + "." + IdentifierUtil.denormalizeIdentifier(tableName) +
               " (" + getTestColName(dbName, tableName, 1) +
               ") PARTITION BY COLUMN (" + getTestColName(dbName, tableName, 2) + ")").close();
           assertTableExists(dbName + "." + tableName);
@@ -308,7 +308,7 @@ public class TestTajoDatabaseMetaData extends QueryTestCaseBase {
 
           TUtil.putToNestedList(tables, dbName, tableName);
 
-          executeString("CREATE TABLE " + dbName + "." + CatalogUtil.denormalizeIdentifier(tableName) +
+          executeString("CREATE TABLE " + dbName + "." + IdentifierUtil.denormalizeIdentifier(tableName) +
               " (" + getTestColName(dbName, tableName, 1) +
               ") PARTITION BY COLUMN (" + getTestColName(dbName, tableName, 2) + ")").close();
           assertTableExists(dbName + "." + tableName);

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
index c36b133..c202642 100644
--- a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
+++ b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
@@ -20,10 +20,10 @@ package org.apache.tajo.jdbc;
 
 import com.google.common.collect.Maps;
 import org.apache.tajo.*;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.client.QueryStatus;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -338,7 +338,7 @@ public class TestTajoJdbc extends QueryTestCaseBase {
       assertEquals(22, numCols);
       int numColumns = 0;
 
-      TableDesc tableDesc = client.getTableDesc(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName));
+      TableDesc tableDesc = client.getTableDesc(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName));
       assertNotNull(tableDesc);
 
       List<Column> columns = tableDesc.getSchema().getRootColumns();
@@ -495,7 +495,7 @@ public class TestTajoJdbc extends QueryTestCaseBase {
 
   @Test
   public void testCreateTableWithDateAndTimestamp() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testCreateTableWithDateAndTimestamp");
+    String tableName = IdentifierUtil.normalizeIdentifier("testCreateTableWithDateAndTimestamp");
 
     int result;
     Statement stmt = null;
@@ -612,7 +612,7 @@ public class TestTajoJdbc extends QueryTestCaseBase {
         conn = DriverManager.getConnection(connUri);
         assertTrue(conn.isValid(100));
 
-        String tableName = CatalogUtil.normalizeIdentifier("testAlterTablePartition");
+        String tableName = IdentifierUtil.normalizeIdentifier("testAlterTablePartition");
         resultSet = executeString(
           "create table " + tableName + " (col1 int4, col2 int4) partition by column(key float8) ");
         resultSet.close();
@@ -699,7 +699,7 @@ public class TestTajoJdbc extends QueryTestCaseBase {
 
   @Test
   public void testTableValueWithTimeZone() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testTableValueWithTimeZone");
+    String tableName = IdentifierUtil.normalizeIdentifier("testTableValueWithTimeZone");
 
     Statement stmt = null;
     ResultSet res = null;

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java b/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java
index d5e9354..92ba368 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java
@@ -22,7 +22,10 @@ import com.google.common.collect.Sets;
 import org.apache.commons.collections.set.UnmodifiableSet;
 import org.apache.tajo.OverridableConf;
 import org.apache.tajo.algebra.*;
-import org.apache.tajo.catalog.*;
+import org.apache.tajo.catalog.CatalogService;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.CatalogUtil.Direction;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.*;
@@ -109,8 +112,8 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
    * @return a pair including left/right hand side terms
    */
   private static Pair<EvalNode, EvalNode> convertTypesIfNecessary(Context ctx, EvalNode lhs, EvalNode rhs) {
-    Type lhsType = lhs.getValueType().baseType();
-    Type rhsType = rhs.getValueType().baseType();
+    Type lhsType = lhs.getValueType().kind();
+    Type rhsType = rhs.getValueType().kind();
 
     // If one of both is NULL, it just returns the original types without casting.
     if (lhsType == Type.NULL_TYPE || rhsType == Type.NULL_TYPE) {
@@ -145,7 +148,7 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
   private static EvalNode convertType(Context ctx, EvalNode evalNode, DataType toType) {
 
     // if original and toType is the same, we don't need type conversion.
-    if (evalNode.getValueType().equals(TypeConverter.convert(toType))) {
+    if (evalNode.getValueType().equals(convert(toType))) {
       return evalNode;
     }
     // the conversion to null is not allowed.
@@ -312,9 +315,9 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
 
     // implicit type conversion
     DataType widestType = CatalogUtil.getWidestType(
-        convert(predicand.getValueType()),
-        convert(begin.getValueType()),
-        convert(end.getValueType()));
+        convert(predicand.getValueType()).getDataType(),
+        convert(begin.getValueType()).getDataType(),
+        convert(end.getValueType()).getDataType());
 
     BetweenPredicateEval betweenEval = new BetweenPredicateEval(
         between.isNot(),
@@ -343,15 +346,15 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
     }
 
     // Getting the widest type from all if-then expressions and else expression.
-    DataType widestType = convert(caseWhenEval.getIfThenEvals().get(0).getResult().getValueType());
+    DataType widestType = convert(caseWhenEval.getIfThenEvals().get(0).getResult().getValueType()).getDataType();
     for (int i = 1; i < caseWhenEval.getIfThenEvals().size(); i++) {
       widestType = CatalogUtil.getWidestType(
-          convert(caseWhenEval.getIfThenEvals().get(i).getResult().getValueType()),
+          convert(caseWhenEval.getIfThenEvals().get(i).getResult().getValueType()).getDataType(),
           widestType);
     }
     if (caseWhen.hasElseResult()) {
       widestType = CatalogUtil.getWidestType(
-          widestType, convert(caseWhenEval.getElse().getValueType()));
+          widestType, convert(caseWhenEval.getElse().getValueType()).getDataType());
     }
 
     assertEval(widestType != null, "Invalid Type Conversion for CaseWhen");
@@ -439,10 +442,10 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
     EvalNode rhs = visit(ctx, stack, expr.getRight());
     stack.pop();
 
-    if (lhs.getValueType().baseType() != Type.TEXT) {
+    if (lhs.getValueType().kind() != Type.TEXT) {
       lhs = convertType(ctx, lhs, CatalogUtil.newSimpleDataType(Type.TEXT));
     }
-    if (rhs.getValueType().baseType() != Type.TEXT) {
+    if (rhs.getValueType().kind() != Type.TEXT) {
       rhs = convertType(ctx, rhs, CatalogUtil.newSimpleDataType(Type.TEXT));
     }
 
@@ -587,7 +590,7 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
 
     for (int i = 0; i < params.length; i++) {
       givenArgs[i] = visit(ctx, stack, params[i]);
-      paramTypes[i] = TypeConverter.convert(givenArgs[i].getValueType());
+      paramTypes[i] = convert(givenArgs[i].getValueType()).getDataType();
     }
 
     stack.pop(); // <--- Pop
@@ -664,7 +667,7 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
     if (setFunction.getSignature().equalsIgnoreCase("count")) {
       paramTypes[0] = CatalogUtil.newSimpleDataType(Type.ANY);
     } else {
-      paramTypes[0] = TypeConverter.convert(givenArgs[0].getValueType());
+      paramTypes[0] = convert(givenArgs[0].getValueType()).getDataType();
     }
 
     if (!catalog.containFunction(setFunction.getSignature(), functionType, paramTypes)) {
@@ -721,11 +724,11 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
       } else if (windowFunc.getSignature().equalsIgnoreCase("row_number")) {
         paramTypes[0] = CatalogUtil.newSimpleDataType(Type.INT8);
       } else {
-        paramTypes[0] = convert(givenArgs[0].getValueType());
+        paramTypes[0] = convert(givenArgs[0].getValueType()).getDataType();
       }
       for (int i = 1; i < params.length; i++) {
         givenArgs[i] = visit(ctx, stack, params[i]);
-        paramTypes[i] = convert(givenArgs[i].getValueType());
+        paramTypes[i] = convert(givenArgs[i].getValueType()).getDataType();
       }
     } else {
       if (windowFunc.getSignature().equalsIgnoreCase("rank")) {
@@ -786,10 +789,11 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
       // some cast operation may require earlier evaluation with timezone.
       return new ConstEval(
           DatumFactory.cast(constEval.getValue(),
-              LogicalPlanner.convertDataType(expr.getTarget()).getDataType(), ctx.timeZone));
+              convert(LogicalPlanner.convertDataType(expr.getTarget())).getDataType(), ctx.timeZone));
 
     } else {
-      return new CastEval(ctx.queryContext, child, LogicalPlanner.convertDataType(expr.getTarget()).getDataType());
+      return new CastEval(ctx.queryContext, child,
+          convert(LogicalPlanner.convertDataType(expr.getTarget())).getDataType());
     }
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/ExprNormalizer.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/ExprNormalizer.java b/tajo-plan/src/main/java/org/apache/tajo/plan/ExprNormalizer.java
index d66263f..967bf8b 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/ExprNormalizer.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/ExprNormalizer.java
@@ -20,12 +20,12 @@ package org.apache.tajo.plan;
 
 import com.google.common.collect.Sets;
 import org.apache.tajo.algebra.*;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.exception.UndefinedColumnException;
 import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.plan.nameresolver.NameResolver;
 import org.apache.tajo.plan.nameresolver.NameResolvingMode;
 import org.apache.tajo.plan.visitor.SimpleAlgebraVisitor;
+import org.apache.tajo.schema.IdentifierUtil;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -339,7 +339,7 @@ class ExprNormalizer extends SimpleAlgebraVisitor<ExprNormalizer.ExprNormalizedR
       return expr;
     }
     // if a column reference is not qualified, it finds and sets the qualified column name.
-    if (!(expr.hasQualifier() && CatalogUtil.isFQTableName(expr.getQualifier()))) {
+    if (!(expr.hasQualifier() && IdentifierUtil.isFQTableName(expr.getQualifier()))) {
       if (!ctx.block.namedExprsMgr.contains(expr.getCanonicalName()) && expr.getType() == OpType.Column) {
         try {
           String normalized =

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java b/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java
index 39caec7..aaf64cd 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java
@@ -21,10 +21,9 @@ package org.apache.tajo.plan;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.BuiltinStorages;
 import org.apache.tajo.OverridableConf;
@@ -49,6 +48,10 @@ import org.apache.tajo.plan.nameresolver.NameResolvingMode;
 import org.apache.tajo.plan.rewrite.rules.ProjectionPushDownRule;
 import org.apache.tajo.plan.util.ExprFinder;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.Field;
+import org.apache.tajo.schema.IdentifierUtil;
+import org.apache.tajo.type.Type;
+import org.apache.tajo.type.TypeFactory;
 import org.apache.tajo.storage.StorageConstants;
 import org.apache.tajo.util.KeyValueSet;
 import org.apache.tajo.util.Pair;
@@ -62,12 +65,12 @@ import static org.apache.tajo.algebra.CreateTable.PartitionType;
 import static org.apache.tajo.plan.ExprNormalizer.ExprNormalizedResult;
 import static org.apache.tajo.plan.LogicalPlan.BlockType;
 import static org.apache.tajo.plan.verifier.SyntaxErrorUtil.makeSyntaxError;
+import static org.apache.tajo.type.Type.*;
 
 /**
  * This class creates a logical plan from a nested tajo algebra expression ({@link org.apache.tajo.algebra})
  */
 public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContext, LogicalNode> {
-  private static Log LOG = LogFactory.getLog(LogicalPlanner.class);
   private final CatalogService catalog;
   private final StorageService storage;
 
@@ -1468,7 +1471,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
 
     // make table subquery node which has set operation as its subquery
     TableSubQueryNode setOpTableSubQueryNode = context.plan.createNode(TableSubQueryNode.class);
-    setOpTableSubQueryNode.init(CatalogUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE),
+    setOpTableSubQueryNode.init(IdentifierUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE),
         context.generateUniqueSubQueryName()), setOperationNode);
     setTargetOfTableSubQuery(context, currentBlock, setOpTableSubQueryNode);
     currentBlock.registerNode(setOpTableSubQueryNode);
@@ -1619,9 +1622,9 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     // Get and set a target table
     String databaseName;
     String tableName;
-    if (CatalogUtil.isFQTableName(expr.getTableName())) {
-      databaseName = CatalogUtil.extractQualifier(expr.getTableName());
-      tableName = CatalogUtil.extractSimpleName(expr.getTableName());
+    if (IdentifierUtil.isFQTableName(expr.getTableName())) {
+      databaseName = IdentifierUtil.extractQualifier(expr.getTableName());
+      tableName = IdentifierUtil.extractSimpleName(expr.getTableName());
     } else {
       databaseName = context.queryContext.get(SessionVars.CURRENT_DATABASE);
       tableName = expr.getTableName();
@@ -1839,8 +1842,8 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     throws TajoException {
     String parentTableName = expr.getLikeParentTableName();
 
-    if (CatalogUtil.isFQTableName(parentTableName) == false) {
-      parentTableName = CatalogUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE),
+    if (IdentifierUtil.isFQTableName(parentTableName) == false) {
+      parentTableName = IdentifierUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE),
           parentTableName);
     }
     TableDesc baseTable = catalog.getTableDesc(parentTableName);
@@ -1870,11 +1873,11 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     createTableNode.setIfNotExists(expr.isIfNotExists());
 
     // Set a table name to be created.
-    if (CatalogUtil.isFQTableName(expr.getTableName())) {
+    if (IdentifierUtil.isFQTableName(expr.getTableName())) {
       createTableNode.setTableName(expr.getTableName());
     } else {
       createTableNode.setTableName(
-          CatalogUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE), expr.getTableName()));
+          IdentifierUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE), expr.getTableName()));
     }
     // This is CREATE TABLE <tablename> LIKE <parentTable>
     if(expr.getLikeParentTableName() != null) {
@@ -1929,8 +1932,13 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
       // If the table schema is defined
       // ex) CREATE TABLE tbl(col1 type, col2 type) AS SELECT ...
       if (expr.hasTableElements()) {
-        createTableNode.setOutSchema(convertTableElementsSchema(expr.getTableElements()));
-        createTableNode.setTableSchema(convertTableElementsSchema(expr.getTableElements()));
+        createTableNode.setOutSchema(SchemaBuilder.builder()
+            .addAll2(convertTableElementsSchema(expr.getTableElements()))
+            .build());
+
+        createTableNode.setTableSchema(SchemaBuilder.builder()
+            .addAll2(convertTableElementsSchema(expr.getTableElements()))
+            .build());
       } else {
         // if no table definition, the select clause's output schema will be used.
         // ex) CREATE TABLE tbl AS SELECT ...
@@ -1997,11 +2005,11 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     } else {
 
       String tableName = createTable.getTableName();
-      String databaseName = CatalogUtil.isFQTableName(tableName) ?
-          CatalogUtil.extractQualifier(tableName) : context.queryContext.get(SessionVars.CURRENT_DATABASE);
+      String databaseName = IdentifierUtil.isFQTableName(tableName) ?
+          IdentifierUtil.extractQualifier(tableName) : context.queryContext.get(SessionVars.CURRENT_DATABASE);
 
       return storage.getTableURI(
-          createTable.getTableSpaceName(), databaseName, CatalogUtil.extractSimpleName(tableName));
+          createTable.getTableSpaceName(), databaseName, IdentifierUtil.extractSimpleName(tableName));
     }
   }
 
@@ -2043,13 +2051,12 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
    * @param elements to be transformed
    * @return schema transformed from table definition elements
    */
-  private static Schema convertTableElementsSchema(ColumnDefinition[] elements) {
-    return SchemaBuilder.builder().addAll(elements, new Function<ColumnDefinition, Column>() {
-      @Override
-      public Column apply(@Nullable ColumnDefinition input) {
-        return convertColumn(input);
-      }
-    }).build();
+  private static Collection<Field> convertTableElementsSchema(ColumnDefinition[] elements) {
+    ImmutableList.Builder<Field> list = ImmutableList.builder();
+    for (ColumnDefinition colDef : elements) {
+      list.add(FieldConverter.convert(convertColumn(colDef)));
+    }
+    return list.build();
   }
 
   /**
@@ -2096,40 +2103,50 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     return new Column(columnDefinition.getColumnName(), convertDataType(columnDefinition));
   }
 
-  public static TypeDesc convertDataType(DataTypeExpr dataType) {
+  public static Type convertDataType(DataTypeExpr dataType) {
     TajoDataTypes.Type type = TajoDataTypes.Type.valueOf(dataType.getTypeName());
 
-    TajoDataTypes.DataType.Builder builder = TajoDataTypes.DataType.newBuilder();
-    builder.setType(type);
-
-    if (dataType.hasLengthOrPrecision()) {
-      builder.setLength(dataType.getLengthOrPrecision());
-    } else {
-      if (type == TajoDataTypes.Type.CHAR) {
-        builder.setLength(1);
+    if (type == TajoDataTypes.Type.CHAR || type == TajoDataTypes.Type.NCHAR) {
+      if (dataType.hasLengthOrPrecision()) {
+        return Char(dataType.getLengthOrPrecision());
+      } else {
+        // Default length is 1. It's because of compatibility with the legacy code.
+        return Char(1);
+      }
+    } else if (type == TajoDataTypes.Type.VARCHAR || type == TajoDataTypes.Type.NVARCHAR) {
+      if (dataType.hasLengthOrPrecision()) {
+        return Char(dataType.getLengthOrPrecision());
+      } else {
+        // Default length is 1. It's because of compatibility with the legacy code.
+        return Varchar(1);
+      }
+    } else if (type == TajoDataTypes.Type.ARRAY) {
+      return Array(convertDataType(dataType.getElementType()));
+    } else if (type == TajoDataTypes.Type.RECORD) {
+      return Record(convertTableElementsSchema(dataType.getNestedRecordTypes()));
+    } else if (type == TajoDataTypes.Type.MAP) {
+      return Map(convertDataType(dataType.getKeyType()), convertDataType(dataType.getValueType()));
+    } else if (type == TajoDataTypes.Type.NUMERIC) {
+      if (dataType.hasLengthOrPrecision() && dataType.hasScale()) {
+        return Numeric(dataType.getLengthOrPrecision(), dataType.getScale());
+      } else if (dataType.hasLengthOrPrecision()) {
+        return Numeric(dataType.getLengthOrPrecision());
+      } else {
+        return Numeric();
       }
-    }
-
-    TypeDesc typeDesc;
-    if (type == TajoDataTypes.Type.RECORD) {
-      Schema nestedRecordSchema = convertTableElementsSchema(dataType.getNestedRecordTypes());
-      typeDesc = new TypeDesc(nestedRecordSchema);
     } else {
-      typeDesc = new TypeDesc(builder.build());
+      return TypeFactory.create(type);
     }
-
-    return typeDesc;
   }
 
-
   @Override
   public LogicalNode visitDropTable(PlanContext context, Stack<Expr> stack, DropTable dropTable) {
     DropTableNode dropTableNode = context.queryBlock.getNodeFromExpr(dropTable);
     String qualified;
-    if (CatalogUtil.isFQTableName(dropTable.getTableName())) {
+    if (IdentifierUtil.isFQTableName(dropTable.getTableName())) {
       qualified = dropTable.getTableName();
     } else {
-      qualified = CatalogUtil.buildFQName(
+      qualified = IdentifierUtil.buildFQName(
           context.queryContext.get(SessionVars.CURRENT_DATABASE), dropTable.getTableName());
     }
     dropTableNode.init(qualified, dropTable.isIfExists(), dropTable.isPurge());
@@ -2189,11 +2206,11 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
 
     QueryBlock block = context.queryBlock;
     CreateIndexNode createIndexNode = block.getNodeFromExpr(createIndex);
-    if (CatalogUtil.isFQTableName(createIndex.getIndexName())) {
+    if (IdentifierUtil.isFQTableName(createIndex.getIndexName())) {
       createIndexNode.setIndexName(createIndex.getIndexName());
     } else {
       createIndexNode.setIndexName(
-          CatalogUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE), createIndex.getIndexName()));
+          IdentifierUtil.buildFQName(context.queryContext.get(SessionVars.CURRENT_DATABASE), createIndex.getIndexName()));
     }
     createIndexNode.setUnique(createIndex.isUnique());
     Sort.SortSpec[] sortSpecs = createIndex.getSortSpecs();

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/NamedExprsManager.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/NamedExprsManager.java b/tajo-plan/src/main/java/org/apache/tajo/plan/NamedExprsManager.java
index 53f2610..ee47700 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/NamedExprsManager.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/NamedExprsManager.java
@@ -315,14 +315,15 @@ public class NamedExprsManager {
       // But, if this reference name is not primary name, it cannot use the reference name.
       // It changes the given reference name to the primary name.
       if (evalNode.getType() != EvalType.CONST && isEvaluated(normalized) && !isPrimaryName(refId, referenceName)) {
-        return new Target(new FieldEval(getPrimaryName(refId), convert(evalNode.getValueType())), referenceName);
+        return new Target(new FieldEval(getPrimaryName(refId), convert(evalNode.getValueType()).getDataType()),
+            referenceName);
       }
 
       EvalNode referredEval;
       if (evalNode.getType() == EvalType.CONST) {
         referredEval = evalNode;
       } else {
-        referredEval = new FieldEval(idToNamesMap.get(refId).get(0), convert(evalNode.getValueType()));
+        referredEval = new FieldEval(idToNamesMap.get(refId).get(0), convert(evalNode.getValueType()).getDataType());
       }
       return new Target(referredEval, referenceName);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java b/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java
index 9fc5c0d..f67b50f 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java
@@ -60,14 +60,14 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<LogicalPlanner.PlanCon
   public DataType visitUnaryOperator(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, UnaryOperator expr)
       throws TajoException {
     stack.push(expr);
-    DataType dataType = null;
+    DataType dataType;
     switch (expr.getType()) {
     case IsNullPredicate:
     case ExistsPredicate:
       dataType = BOOL_TYPE;
       break;
     case Cast:
-      dataType = LogicalPlanner.convertDataType(((CastExpr)expr).getTarget()).getDataType();
+      dataType = convert(LogicalPlanner.convertDataType(((CastExpr)expr).getTarget())).getDataType();
       break;
     default:
       dataType = visit(ctx, stack, expr.getChild());
@@ -83,7 +83,7 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<LogicalPlanner.PlanCon
     DataType lhsType = visit(ctx, stack, expr.getLeft());
     DataType rhsType = visit(ctx, stack, expr.getRight());
     stack.pop();
-    return convert(computeBinaryType(expr.getType(), convert(lhsType), convert(rhsType)));
+    return convert(computeBinaryType(expr.getType(), convert(lhsType), convert(rhsType))).getDataType();
   }
 
   public Type computeBinaryType(OpType type, Type lhsDataType, Type rhsDataType) throws TajoException {
@@ -278,7 +278,7 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<LogicalPlanner.PlanCon
   @Override
   public DataType visitDataType(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, DataTypeExpr expr)
       throws TajoException {
-    return LogicalPlanner.convertDataType(expr).getDataType();
+    return convert(LogicalPlanner.convertDataType(expr)).getDataType();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java
index 25c12d4..4f1ece6 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java
@@ -20,10 +20,10 @@ package org.apache.tajo.plan.expr;
 
 import com.google.common.base.Objects;
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.TypeConverter;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.type.Type;
+import org.apache.tajo.type.TypeFactory;
 
 public class ConstEval extends EvalNode implements Comparable<ConstEval>, Cloneable {
 	@Expose Datum datum = null;
@@ -51,7 +51,7 @@ public class ConstEval extends EvalNode implements Comparable<ConstEval>, Clonea
 
   @Override
 	public Type getValueType() {
-    return TypeConverter.convert(datum.type());
+    return TypeFactory.create(datum.type());
 	}
 
   @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalTreeUtil.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalTreeUtil.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalTreeUtil.java
index a83c5bd..f4b706f 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalTreeUtil.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalTreeUtil.java
@@ -33,6 +33,7 @@ import org.apache.tajo.exception.TajoInternalError;
 import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.Target;
 import org.apache.tajo.plan.util.ExprFinder;
+import org.apache.tajo.schema.IdentifierUtil;
 
 import java.util.*;
 
@@ -180,7 +181,7 @@ public class EvalTreeUtil {
     case DIVIDE:
     case CONST:
     case FUNCTION:
-        return TypeConverter.convert(expr.getValueType());
+        return TypeConverter.convert(expr.getValueType()).getDataType();
 
     case FIELD:
       FieldEval fieldEval = (FieldEval) expr;
@@ -393,14 +394,14 @@ public class EvalTreeUtil {
 
   private static boolean isJoinQualWithOnlyColumns(@Nullable LogicalPlan.QueryBlock block,
                                                    Column left, Column right) {
-    String leftQualifier = CatalogUtil.extractQualifier(left.getQualifiedName());
-    String rightQualifier = CatalogUtil.extractQualifier(right.getQualifiedName());
+    String leftQualifier = IdentifierUtil.extractQualifier(left.getQualifiedName());
+    String rightQualifier = IdentifierUtil.extractQualifier(right.getQualifiedName());
 
     // if block is given, it will track an original expression of each term in order to decide whether
     // this expression is a join condition, or not.
     if (block != null) {
-      boolean leftQualified = CatalogUtil.isFQColumnName(left.getQualifiedName());
-      boolean rightQualified = CatalogUtil.isFQColumnName(right.getQualifiedName());
+      boolean leftQualified = IdentifierUtil.isFQColumnName(left.getQualifiedName());
+      boolean rightQualified = IdentifierUtil.isFQColumnName(right.getQualifiedName());
 
       if (!leftQualified) { // if left one is aliased name
 
@@ -410,7 +411,7 @@ public class EvalTreeUtil {
 
         // ensure there is only one column of an original expression
         if (foundColumns.size() == 1) {
-          leftQualifier = CatalogUtil.extractQualifier(foundColumns.iterator().next().getCanonicalName());
+          leftQualifier = IdentifierUtil.extractQualifier(foundColumns.iterator().next().getCanonicalName());
         }
       }
       if (!rightQualified) { // if right one is aliased name
@@ -421,7 +422,7 @@ public class EvalTreeUtil {
 
         // ensure there is only one column of an original expression
         if (foundColumns.size() == 1) {
-          rightQualifier = CatalogUtil.extractQualifier(foundColumns.iterator().next().getCanonicalName());
+          rightQualifier = IdentifierUtil.extractQualifier(foundColumns.iterator().next().getCanonicalName());
         }
       }
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java
index 60144ce..b527780 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java
@@ -18,45 +18,52 @@
 
 package org.apache.tajo.plan.expr;
 
-import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.FieldConverter;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.catalog.TypeConverter;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
+import org.apache.tajo.schema.Field;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.type.Type;
 
+import static org.apache.tajo.schema.Field.Field;
+import static org.apache.tajo.schema.QualifiedIdentifier.$;
+
 public class FieldEval extends EvalNode implements Cloneable {
-	@Expose private Column column;
-	@Expose	private int fieldId = -1;
+	private Field field;
+	private int fieldId = -1;
 	
-	public FieldEval(String columnName, DataType domain) {
+	public FieldEval(String columnName, DataType type) {
 		super(EvalType.FIELD);
-		this.column = new Column(columnName, domain);
+		this.field = Field($(columnName), TypeConverter.convert(type));
 	}
 
   public FieldEval(String columnName, Type type) {
     super(EvalType.FIELD);
-    this.column = new Column(columnName, TypeConverter.convert(type));
+    this.field = Field($(columnName), type);
   }
 	
-	public FieldEval(Column column) {
+	public FieldEval(Column field) {
 	  super(EvalType.FIELD);
-	  this.column = column;
+	  this.field = FieldConverter.convert(field);
 	}
 
   @Override
   public EvalNode bind(EvalContext evalContext, Schema schema) {
     super.bind(evalContext, schema);
     // TODO - column namespace should be improved to simplify name handling and resolving.
-    if (column.hasQualifier()) {
-      fieldId = schema.getColumnId(column.getQualifiedName());
-    } else {
-      fieldId = schema.getColumnIdByName(column.getSimpleName());
+
+    fieldId = schema.getColumnId(field.name().interned());
+
+    if (fieldId == -1) { // fallback
+      fieldId = schema.getColumnIdByName(field.name().interned());
     }
+
     if (fieldId == -1) {
-      throw new IllegalStateException("No Such Column Reference: " + column + ", schema: " + schema);
+      throw new IllegalStateException("No Such Column Reference: " + field + ", schema: " + schema);
     }
     return this;
   }
@@ -70,7 +77,7 @@ public class FieldEval extends EvalNode implements Cloneable {
 
   @Override
 	public Type getValueType() {
-		return TypeConverter.convert(column.getDataType());
+		return field.type();
 	}
 
   @Override
@@ -84,48 +91,47 @@ public class FieldEval extends EvalNode implements Cloneable {
   }
 
   public Column getColumnRef() {
-    return column;
+    return FieldConverter.convert(field);
   }
 	
 	public String getQualifier() {
-	  return column.getQualifier();
+	  return IdentifierUtil.extractQualifier(field.name().interned());
 	}
 	
 	public String getColumnName() {
-	  return column.getSimpleName();
+    return IdentifierUtil.extractSimpleName(field.name().interned());
 	}
 	
 	public void replaceColumnRef(String columnName) {
-	  this.column = new Column(columnName, this.column.getDataType());
+	  this.field = Field(columnName, this.field.type());
 	}
 
 	@Override
 	public String getName() {
-		return this.column.getQualifiedName();
+		return this.field.name().interned();
 	}
 
 	public String toString() {
-	  return this.column.toString();
+	  return this.field.toString();
 	}
 	
   public boolean equals(Object obj) {
-    if (obj instanceof FieldEval) {
-      FieldEval other = (FieldEval) obj;
-      
-      return column.equals(other.column);      
+    if (this == obj) {
+      return true;
     }
-    return false;
+
+    return obj instanceof FieldEval && field.equals(((FieldEval) obj).field);
   }
   
   @Override
   public int hashCode() {
-    return column.hashCode();
+    return field.hashCode();
   }
   
   @Override
   public Object clone() throws CloneNotSupportedException {
     FieldEval eval = (FieldEval) super.clone();
-    eval.column = this.column;
+    eval.field = this.field;
     eval.fieldId = fieldId;
     
     return eval;

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java
index aaaba22..21d3517 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java
@@ -19,11 +19,11 @@
 package org.apache.tajo.plan.expr;
 
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.catalog.TypeConverter;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.type.Type;
+import org.apache.tajo.type.TypeFactory;
 import org.apache.tajo.util.StringUtils;
 import org.apache.tajo.util.TUtil;
 
@@ -39,7 +39,7 @@ public class RowConstantEval extends ValueSetEval {
 
   @Override
   public Type getValueType() {
-    return TypeConverter.convert(values[0].type());
+    return TypeFactory.create(values[0].type());
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateDatabaseNode.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateDatabaseNode.java b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateDatabaseNode.java
index 28bd4cd..404dd33 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateDatabaseNode.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateDatabaseNode.java
@@ -19,8 +19,8 @@
 package org.apache.tajo.plan.logical;
 
 import com.google.common.base.Objects;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.plan.PlanString;
+import org.apache.tajo.schema.IdentifierUtil;
 
 public class CreateDatabaseNode extends LogicalNode implements Cloneable {
   private String databaseName;
@@ -82,7 +82,7 @@ public class CreateDatabaseNode extends LogicalNode implements Cloneable {
   @Override
   public String toString() {
     return "CREATE DATABASE " + (ifNotExists ? " IF NOT EXISTS " : "")
-        + CatalogUtil.denormalizeIdentifier(databaseName);
+        + IdentifierUtil.denormalizeIdentifier(databaseName);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-plan/src/main/java/org/apache/tajo/plan/logical/JoinSpec.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/JoinSpec.java b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/JoinSpec.java
index 643aa3d..06afd68 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/JoinSpec.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/JoinSpec.java
@@ -31,7 +31,7 @@ public class JoinSpec implements Cloneable {
 
     @Override
     public int compare(EvalNode e1, EvalNode e2) {
-      return e1.toJson().compareTo(e2.toJson());
+      return e1.toString().compareTo(e2.toString());
     }
   }
 
@@ -69,7 +69,7 @@ public class JoinSpec implements Cloneable {
     return predicates.size() > 0;
   }
 
-  public void setPredicates(Set<EvalNode> predicates) {
+  public void setPredicates(Collection<EvalNode> predicates) {
     this.predicates.clear();
     if (predicates == null || predicates.isEmpty()) {
       if (type == JoinType.INNER) {
@@ -81,7 +81,7 @@ public class JoinSpec implements Cloneable {
   }
 
   public void setSingletonPredicate(EvalNode predicates) {
-    this.setPredicates(new HashSet<>(Arrays.asList(AlgebraicUtil.toConjunctiveNormalFormArray(predicates))));
+    this.setPredicates(Arrays.asList(AlgebraicUtil.toConjunctiveNormalFormArray(predicates)));
   }
 
   public EvalNode getSingletonPredicate() {


[3/7] tajo git commit: TAJO-2129: Apply new type implementation to Schema and Catalog.

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java
index 0b2e3f0..3b50503 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java
@@ -27,10 +27,10 @@ import org.apache.tajo.QueryTestCaseBase;
 import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageConstants;
 import org.apache.tajo.util.KeyValueSet;
 import org.junit.Test;
@@ -40,7 +40,7 @@ import java.sql.ResultSet;
 import java.util.Map;
 
 import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
-import static org.apache.tajo.catalog.CatalogUtil.buildFQName;
+import static org.apache.tajo.schema.IdentifierUtil.buildFQName;
 import static org.junit.Assert.*;
 
 
@@ -59,7 +59,7 @@ public class TestCTASQuery extends QueryTestCaseBase {
     ResultSet res = executeQuery();
     res.close();
 
-    String tableName = CatalogUtil.normalizeIdentifier("testCtasWithoutTableDefinition");
+    String tableName = IdentifierUtil.normalizeIdentifier("testCtasWithoutTableDefinition");
     CatalogService catalog = testBase.getTestingCluster().getMaster().getCatalog();
     String qualifiedTableName = buildFQName(DEFAULT_DATABASE_NAME, tableName);
     TableDesc desc = catalog.getTableDesc(qualifiedTableName);
@@ -103,7 +103,7 @@ public class TestCTASQuery extends QueryTestCaseBase {
     ResultSet res = executeQuery();
     res.close();
 
-    String tableName = CatalogUtil.normalizeIdentifier("testCtasWithColumnedPartition");
+    String tableName = IdentifierUtil.normalizeIdentifier("testCtasWithColumnedPartition");
 
     TajoTestingCluster cluster = testBase.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
@@ -205,7 +205,7 @@ public class TestCTASQuery extends QueryTestCaseBase {
 
     assertEquals(expected, actual);
 
-    TableDesc desc = client.getTableDesc(CatalogUtil.normalizeIdentifier(res2.getMetaData().getTableName(1)));
+    TableDesc desc = client.getTableDesc(IdentifierUtil.normalizeIdentifier(res2.getMetaData().getTableName(1)));
     assertNotNull(desc);
   }
 
@@ -218,7 +218,7 @@ public class TestCTASQuery extends QueryTestCaseBase {
     resultSetToString(res2);
     res2.close();
 
-    TableDesc desc =  client.getTableDesc(CatalogUtil.normalizeIdentifier(res2.getMetaData().getTableName(1)));
+    TableDesc desc =  client.getTableDesc(IdentifierUtil.normalizeIdentifier(res2.getMetaData().getTableName(1)));
     assertNotNull(desc);
     assertTrue("RCFILE".equalsIgnoreCase(desc.getMeta().getDataFormat()));
   }
@@ -232,7 +232,7 @@ public class TestCTASQuery extends QueryTestCaseBase {
     resultSetToString(res2);
     res2.close();
 
-    TableDesc desc =  client.getTableDesc(CatalogUtil.normalizeIdentifier(res2.getMetaData().getTableName(1)));
+    TableDesc desc =  client.getTableDesc(IdentifierUtil.normalizeIdentifier(res2.getMetaData().getTableName(1)));
     assertNotNull(desc);
     assertTrue("TEXT".equalsIgnoreCase(desc.getMeta().getDataFormat()));
   }
@@ -246,7 +246,7 @@ public class TestCTASQuery extends QueryTestCaseBase {
     resultSetToString(res2);
     res2.close();
 
-    TableDesc desc =  client.getTableDesc(CatalogUtil.normalizeIdentifier(res2.getMetaData().getTableName(1)));
+    TableDesc desc =  client.getTableDesc(IdentifierUtil.normalizeIdentifier(res2.getMetaData().getTableName(1)));
     assertNotNull(desc);
     assertTrue("TEXT".equalsIgnoreCase(desc.getMeta().getDataFormat()));
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateDatabase.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateDatabase.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateDatabase.java
index 453c174..d1713c2 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateDatabase.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateDatabase.java
@@ -20,7 +20,7 @@ package org.apache.tajo.engine.query;
 
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
-import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
@@ -31,7 +31,7 @@ public class TestCreateDatabase extends QueryTestCaseBase {
 
   @Test
   public final void testCreateAndDropDatabase() throws Exception {
-    String databaseName = CatalogUtil.normalizeIdentifier("testCreateAndDropDatabase");
+    String databaseName = IdentifierUtil.normalizeIdentifier("testCreateAndDropDatabase");
 
     ResultSet res = null;
     try {
@@ -46,7 +46,7 @@ public class TestCreateDatabase extends QueryTestCaseBase {
 
   @Test
   public final void testCreateIfNotExists() throws Exception {
-    String databaseName = CatalogUtil.normalizeIdentifier("testCreateIfNotExists");
+    String databaseName = IdentifierUtil.normalizeIdentifier("testCreateIfNotExists");
 
     assertDatabaseNotExists(databaseName);
     executeString("CREATE DATABASE " + databaseName + ";").close();
@@ -61,7 +61,7 @@ public class TestCreateDatabase extends QueryTestCaseBase {
 
   @Test
   public final void testDropIfExists() throws Exception {
-    String databaseName = CatalogUtil.normalizeIdentifier("testDropIfExists");
+    String databaseName = IdentifierUtil.normalizeIdentifier("testDropIfExists");
     assertDatabaseNotExists(databaseName);
     executeString("CREATE DATABASE " + databaseName + ";").close();
     assertDatabaseExists(databaseName);

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java
index b7196bd..3aee9bf 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java
@@ -24,6 +24,7 @@ import org.apache.tajo.QueryTestCaseBase;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageUtil;
 import org.apache.tajo.util.KeyValueSet;
 import org.junit.Test;
@@ -101,9 +102,9 @@ public class TestCreateTable extends QueryTestCaseBase {
                                               final String newTableName,
                                               String createTableStmt) throws Exception {
     // create one table
-    executeString("CREATE DATABASE " + CatalogUtil.denormalizeIdentifier(databaseName)).close();
-    getClient().existDatabase(CatalogUtil.denormalizeIdentifier(databaseName));
-    final String oldFQTableName = CatalogUtil.buildFQName(databaseName, originalTableName);
+    executeString("CREATE DATABASE " + IdentifierUtil.denormalizeIdentifier(databaseName)).close();
+    getClient().existDatabase(IdentifierUtil.denormalizeIdentifier(databaseName));
+    final String oldFQTableName = IdentifierUtil.buildFQName(databaseName, originalTableName);
 
     ResultSet res = executeString(createTableStmt);
     res.close();
@@ -119,11 +120,11 @@ public class TestCreateTable extends QueryTestCaseBase {
         new Path(oldTableDesc.getUri()));
 
     // Rename
-    client.executeQuery("ALTER TABLE " + CatalogUtil.denormalizeIdentifier(oldFQTableName)
-        + " RENAME to " + CatalogUtil.denormalizeIdentifier(newTableName));
+    client.executeQuery("ALTER TABLE " + IdentifierUtil.denormalizeIdentifier(oldFQTableName)
+        + " RENAME to " + IdentifierUtil.denormalizeIdentifier(newTableName));
 
     // checking the existence of the new table directory and validating the path
-    final String newFQTableName = CatalogUtil.buildFQName(databaseName, newTableName);
+    final String newFQTableName = IdentifierUtil.buildFQName(databaseName, newTableName);
     TableDesc newTableDesc = client.getTableDesc(newFQTableName);
     assertTrue(fs.exists(new Path(newTableDesc.getUri())));
     assertEquals(StorageUtil.concatPath(warehouseDir, databaseName, newTableName), new Path(newTableDesc.getUri()));
@@ -678,4 +679,18 @@ public class TestCreateTable extends QueryTestCaseBase {
     executeString("drop table d10.schemaless").close();
     executeString("drop database d10").close();
   }
+
+  @Test
+  public final void testComplexType1() throws Exception {
+    try {
+      executeString("CREATE DATABASE D11;").close();
+
+      assertTableNotExists("d11.complex_type1");
+      executeQuery().close();
+      assertTableExists("d11.complex_type1");
+    } finally {
+      executeString("DROP TABLE IF EXISTS D11.complex_type1");
+      executeString("DROP DATABASE IF EXISTS D11").close();
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java
index b87639f..6f2a546 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java
@@ -27,8 +27,8 @@ import org.apache.hadoop.io.compress.DeflateCodec;
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
 import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
@@ -189,7 +189,7 @@ public class TestInsertQuery extends QueryTestCaseBase {
 
   @Test
   public final void testInsertIntoPartitionedTable() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testInsertIntoPartitionedTable");
+    String tableName = IdentifierUtil.normalizeIdentifier("testInsertIntoPartitionedTable");
     executeString("create table " + tableName + " (n_name TEXT, n_regionkey INT4)" +
         "USING csv PARTITION by column(n_nationkey INT4)" ).close();
 
@@ -355,7 +355,7 @@ public class TestInsertQuery extends QueryTestCaseBase {
       assertEquals(8, desc.getStats().getNumRows().intValue());
     }
 
-    res = executeString("select * from " + CatalogUtil.denormalizeIdentifier(getCurrentDatabase()) + ".table1");
+    res = executeString("select * from " + IdentifierUtil.denormalizeIdentifier(getCurrentDatabase()) + ".table1");
 
     assertTrue(res.next());
     assertEquals(1, res.getLong(1));
@@ -450,7 +450,7 @@ public class TestInsertQuery extends QueryTestCaseBase {
 
   @Test
   public final void testInsertOverwriteIntoSelect() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("insertoverwriteintoselect");
+    String tableName = IdentifierUtil.normalizeIdentifier("insertoverwriteintoselect");
     ResultSet res = executeString("create table " + tableName + " as select l_orderkey from default.lineitem");
     assertFalse(res.next());
     res.close();
@@ -478,7 +478,7 @@ public class TestInsertQuery extends QueryTestCaseBase {
 
   @Test
   public final void testInsertOverwriteCapitalTableName() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testInsertOverwriteCapitalTableName");
+    String tableName = IdentifierUtil.normalizeIdentifier("testInsertOverwriteCapitalTableName");
     ResultSet res = executeString("create table " + tableName + " as select * from default.lineitem");
     res.close();
 
@@ -505,7 +505,7 @@ public class TestInsertQuery extends QueryTestCaseBase {
 
   @Test
   public final void testInsertOverwriteWithCompression() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testInsertOverwriteWithCompression");
+    String tableName = IdentifierUtil.normalizeIdentifier("testInsertOverwriteWithCompression");
     ResultSet res = executeFile("testInsertOverwriteWithCompression_ddl.sql");
     res.close();
 
@@ -670,7 +670,7 @@ public class TestInsertQuery extends QueryTestCaseBase {
   }
 
   public final void testInsertOverwriteAllValues(String rawTableName, String query) throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier(rawTableName);
+    String tableName = IdentifierUtil.normalizeIdentifier(rawTableName);
     ResultSet res = executeString("create table " + tableName +" (col1 int4, col2 float4, col3 text)");
     res.close();
     CatalogService catalog = testingCluster.getMaster().getCatalog();
@@ -710,7 +710,7 @@ public class TestInsertQuery extends QueryTestCaseBase {
   }
 
   public final void testInsertOverwriteSomeValues(String rawTableName, String sql) throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier(rawTableName);
+    String tableName = IdentifierUtil.normalizeIdentifier(rawTableName);
     ResultSet res = executeString("create table " + tableName +" (col1 int4, col2 float4, col3 text)");
     res.close();
     CatalogService catalog = testingCluster.getMaster().getCatalog();

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java
index 496d112..d1c9fd5 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java
@@ -23,7 +23,7 @@ import org.apache.tajo.NamedTest;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.annotation.NotThreadSafe;
 import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -157,7 +157,7 @@ public class TestJoinOnPartitionedTables extends TestJoinQuery {
   @Test
   public final void testCasebyCase1() throws Exception {
     // Left outer join with a small table and a large partition table which not matched any partition path.
-    String tableName = CatalogUtil.normalizeIdentifier("largePartitionedTable");
+    String tableName = IdentifierUtil.normalizeIdentifier("largePartitionedTable");
     executeString(
         "create table " + tableName + " (l_partkey int4, l_suppkey int4, l_linenumber int4, \n" +
             "l_quantity float8, l_extendedprice float8, l_discount float8, l_tax float8, \n" +
@@ -198,7 +198,7 @@ public class TestJoinOnPartitionedTables extends TestJoinQuery {
   // TODO: This test should be reverted after resolving TAJO-1600
 //  @Test
   public final void testBroadcastMultiColumnPartitionTable() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testBroadcastMultiColumnPartitionTable");
+    String tableName = IdentifierUtil.normalizeIdentifier("testBroadcastMultiColumnPartitionTable");
     ResultSet res = testBase.execute(
         "create table " + tableName + " (col1 int4, col2 float4) partition by column(col3 text, col4 text) ");
     res.close();
@@ -226,7 +226,7 @@ public class TestJoinOnPartitionedTables extends TestJoinQuery {
 
   @Test
   public final void testSelfJoin() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("paritioned_nation");
+    String tableName = IdentifierUtil.normalizeIdentifier("paritioned_nation");
     ResultSet res = executeString(
         "create table " + tableName + " (n_name text,"
             + "  n_comment text, n_regionkey int8) USING text "
@@ -284,7 +284,7 @@ public class TestJoinOnPartitionedTables extends TestJoinQuery {
       Because of the where condition[where a.o_orderdate='1995-02-21 and a.o_orderstatus in ('F')],
         orders_partition table aliased a is small and broadcast target.
     */
-    String tableName = CatalogUtil.normalizeIdentifier("partitioned_orders");
+    String tableName = IdentifierUtil.normalizeIdentifier("partitioned_orders");
     ResultSet res = executeString(
         "create table " + tableName + " (o_orderkey INT8, o_custkey INT8, o_totalprice FLOAT8, o_orderpriority TEXT,\n" +
             "o_clerk TEXT, o_shippriority INT4, o_comment TEXT) USING TEXT WITH ('text.delimiter'='|')\n" +

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestSimpleQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestSimpleQuery.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestSimpleQuery.java
index f62bb23..fafc75e 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestSimpleQuery.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestSimpleQuery.java
@@ -19,7 +19,6 @@
 package org.apache.tajo.engine.query;
 
 import org.apache.tajo.*;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.client.QueryStatus;
 import org.apache.tajo.client.TajoClientUtil;
 import org.apache.tajo.exception.QueryNotFoundException;
@@ -30,6 +29,7 @@ import org.apache.tajo.master.QueryManager;
 import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.session.Session;
 import org.apache.tajo.util.StringUtils;
 import org.junit.AfterClass;
@@ -84,12 +84,12 @@ public class TestSimpleQuery extends QueryTestCaseBase {
   }
 
   private static void createTestTable() throws Exception {
-    partitionedTable = CatalogUtil.normalizeIdentifier("TestSimpleQuery_Partitioned");
+    partitionedTable = IdentifierUtil.normalizeIdentifier("TestSimpleQuery_Partitioned");
     client.executeQueryAndGetResult("create table " + partitionedTable +
         " (col4 text)  partition by column(col1 int4, col2 int4, col3 float8) "
         + "as select l_returnflag, l_orderkey, l_partkey, l_quantity from lineitem");
 
-    table = CatalogUtil.normalizeIdentifier("TestSimpleQuery");
+    table = IdentifierUtil.normalizeIdentifier("TestSimpleQuery");
     client.executeQueryAndGetResult("create table " + table
         + " (col4 text, col1 int4, col2 int4, col3 float8) "
         + "as select l_returnflag, l_orderkey, l_partkey, l_quantity from lineitem");

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java
index e74d722..103a0f6 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java
@@ -39,6 +39,7 @@ import org.apache.tajo.exception.ReturnStateUtil;
 import org.apache.tajo.ipc.ClientProtos;
 import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.querymaster.QueryMasterTask;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageConstants;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.junit.Test;
@@ -76,7 +77,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testCreateColumnPartitionedTable() throws Exception {
     ResultSet res;
-    String tableName = CatalogUtil.normalizeIdentifier("testCreateColumnPartitionedTable");
+    String tableName = IdentifierUtil.normalizeIdentifier("testCreateColumnPartitionedTable");
     ClientProtos.SubmitQueryResponse response;
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -133,7 +134,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   public final void testCreateColumnPartitionedTableWithJoin() throws Exception {
     ResultSet res;
     ClientProtos.SubmitQueryResponse response;
-    String tableName = CatalogUtil.normalizeIdentifier("testCreateColumnPartitionedTableWithJoin");
+    String tableName = IdentifierUtil.normalizeIdentifier("testCreateColumnPartitionedTableWithJoin");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -187,7 +188,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testCreateColumnPartitionedTableWithSelectedColumns() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testCreateColumnPartitionedTableWithSelectedColumns");
+    String tableName = IdentifierUtil.normalizeIdentifier("testCreateColumnPartitionedTableWithSelectedColumns");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -216,7 +217,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testColumnPartitionedTableByOneColumn() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableByOneColumn");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableByOneColumn");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -274,7 +275,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testQueryCasesOnColumnPartitionedTable() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testQueryCasesOnColumnPartitionedTable");
+    String tableName = IdentifierUtil.normalizeIdentifier("testQueryCasesOnColumnPartitionedTable");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -367,7 +368,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testColumnPartitionedTableByThreeColumns() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableByThreeColumns");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableByThreeColumns");
 
     if (nodeType == NodeType.INSERT) {
       res = testBase.execute(
@@ -454,7 +455,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testInsertIntoColumnPartitionedTableByThreeColumns() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testInsertIntoColumnPartitionedTableByThreeColumns");
+    String tableName = IdentifierUtil.normalizeIdentifier("testInsertIntoColumnPartitionedTableByThreeColumns");
 
     if (nodeType == NodeType.INSERT) {
       res = testBase.execute(
@@ -641,7 +642,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testColumnPartitionedTableByOneColumnsWithCompression() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableByOneColumnsWithCompression");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableByOneColumnsWithCompression");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -692,7 +693,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testColumnPartitionedTableByTwoColumnsWithCompression() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableByTwoColumnsWithCompression");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableByTwoColumnsWithCompression");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString("create table " + tableName + " (col3 float8, col4 text) USING text " +
@@ -751,7 +752,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testColumnPartitionedTableByThreeColumnsWithCompression() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableByThreeColumnsWithCompression");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableByThreeColumnsWithCompression");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -849,7 +850,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testColumnPartitionedTableNoMatchedPartition() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableNoMatchedPartition");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableNoMatchedPartition");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -920,7 +921,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testColumnPartitionedTableWithSmallerExpressions1() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableWithSmallerExpressions1");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableWithSmallerExpressions1");
     res = executeString(
         "create table " + tableName + " (col1 int4, col2 int4, null_col int4) partition by column(key float8) ");
     res.close();
@@ -948,7 +949,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   public final void testColumnPartitionedTableWithSmallerExpressions2() throws Exception {
     ResultSet res = null;
     ClientProtos.SubmitQueryResponse response = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableWithSmallerExpressions2");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableWithSmallerExpressions2");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -1033,7 +1034,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testColumnPartitionedTableWithSmallerExpressions5() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableWithSmallerExpressions5");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableWithSmallerExpressions5");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -1063,7 +1064,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testColumnPartitionedTableWithSmallerExpressions6() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testColumnPartitionedTableWithSmallerExpressions6");
+    String tableName = IdentifierUtil.normalizeIdentifier("testColumnPartitionedTableWithSmallerExpressions6");
 
     if (nodeType == NodeType.INSERT) {
       res = executeString(
@@ -1307,7 +1308,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
 
   @Test
   public final void testDuplicatedPartitions() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testDuplicatedPartitions");
+    String tableName = IdentifierUtil.normalizeIdentifier("testDuplicatedPartitions");
 
     try {
       executeString("CREATE TABLE lineitem2 as select * from lineitem").close();
@@ -1349,7 +1350,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testPatternMatchingPredicatesAndStringFunctions() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testPatternMatchingPredicatesAndStringFunctions");
+    String tableName = IdentifierUtil.normalizeIdentifier("testPatternMatchingPredicatesAndStringFunctions");
     String expectedResult;
 
     if (nodeType == NodeType.INSERT) {
@@ -1447,7 +1448,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testDatePartitionColumn() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testDatePartitionColumn");
+    String tableName = IdentifierUtil.normalizeIdentifier("testDatePartitionColumn");
     String expectedResult;
 
     if (nodeType == NodeType.INSERT) {
@@ -1556,7 +1557,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testTimestampPartitionColumn() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testTimestampPartitionColumn");
+    String tableName = IdentifierUtil.normalizeIdentifier("testTimestampPartitionColumn");
     String expectedResult;
 
     if (nodeType == NodeType.INSERT) {
@@ -1625,7 +1626,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testTimePartitionColumn() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testTimePartitionColumn");
+    String tableName = IdentifierUtil.normalizeIdentifier("testTimePartitionColumn");
     String  expectedResult;
 
     if (nodeType == NodeType.INSERT) {
@@ -1708,7 +1709,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
     executeString("create database test_partition").close();
 
     String databaseName = "test_partition";
-    String tableName = CatalogUtil.normalizeIdentifier("part");
+    String tableName = IdentifierUtil.normalizeIdentifier("part");
 
     if (nodeType == NodeType.INSERT) {
       executeString(
@@ -1757,7 +1758,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
     FileSystem fs = FileSystem.get(conf);
     Path path = null;
 
-    String tableName = CatalogUtil.normalizeIdentifier("testAbnormalDirectories");
+    String tableName = IdentifierUtil.normalizeIdentifier("testAbnormalDirectories");
     if (nodeType == NodeType.INSERT) {
       executeString(
         "create table " + tableName + " (col1 int4, col2 int4) partition by column(key float8) ").close();
@@ -1859,7 +1860,7 @@ public class TestTablePartitions extends QueryTestCaseBase {
   @Test
   public final void testPartitionWithInOperator() throws Exception {
     ResultSet res = null;
-    String tableName = CatalogUtil.normalizeIdentifier("testPartitionWithInOperator");
+    String tableName = IdentifierUtil.normalizeIdentifier("testPartitionWithInOperator");
     String result, expectedResult;
 
     if (nodeType == NodeType.INSERT) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java b/tajo-core-tests/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java
index 56334ae..a46b627 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java
@@ -35,6 +35,7 @@ import org.apache.tajo.parser.sql.SQLAnalyzer;
 import org.apache.tajo.plan.LogicalOptimizer;
 import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.LogicalPlanner;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.TablespaceManager;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.junit.AfterClass;
@@ -72,7 +73,7 @@ public class TestExecutionBlockCursor {
     for (String table : tpch.getTableNames()) {
       TableMeta m = CatalogUtil.newTableMeta(BuiltinStorages.TEXT, util.getConfiguration());
       TableDesc d = CatalogUtil.newTableDesc(
-          CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, table), tpch.getSchema(table), m, CommonTestingUtil.getTestDir());
+          IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, table), tpch.getSchema(table), m, CommonTestingUtil.getTestDir());
       TableStats stats = new TableStats();
       stats.setNumBytes(TPCH.tableVolumes.get(table));
       d.setStats(stats);

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/querymaster/TestTaskStatusUpdate.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/querymaster/TestTaskStatusUpdate.java b/tajo-core-tests/src/test/java/org/apache/tajo/querymaster/TestTaskStatusUpdate.java
index 34eefda..baae7ed 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/querymaster/TestTaskStatusUpdate.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/querymaster/TestTaskStatusUpdate.java
@@ -22,8 +22,8 @@ import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryId;
 import org.apache.tajo.QueryTestCaseBase;
 import org.apache.tajo.TajoConstants;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.history.QueryHistory;
 import org.apache.tajo.util.history.StageHistory;
 import org.junit.BeforeClass;
@@ -118,7 +118,7 @@ public class TestTaskStatusUpdate extends QueryTestCaseBase {
   }
 
   private void createColumnPartitionedTable() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("ColumnPartitionedTable");
+    String tableName = IdentifierUtil.normalizeIdentifier("ColumnPartitionedTable");
     ResultSet res = executeString(
         "create table " + tableName + " (col1 int4, col2 int4) partition by column(key float8) ");
     res.close();

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/ws/rs/resources/TestTablesResource.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/ws/rs/resources/TestTablesResource.java b/tajo-core-tests/src/test/java/org/apache/tajo/ws/rs/resources/TestTablesResource.java
index 381c044..b1b4822 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/ws/rs/resources/TestTablesResource.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/ws/rs/resources/TestTablesResource.java
@@ -19,11 +19,11 @@ package org.apache.tajo.ws.rs.resources;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.tajo.QueryTestCaseBase;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.conf.TajoConf.ConfVars;
 import org.apache.tajo.error.Errors.ResultCode;
 import org.apache.tajo.plan.serder.PlanGsonHelper;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.ws.rs.netty.gson.GsonFeature;
 import org.apache.tajo.ws.rs.requests.NewSessionRequest;
 import org.apache.tajo.ws.rs.requests.SubmitQueryRequest;
@@ -137,7 +137,7 @@ public class TestTablesResource extends QueryTestCaseBase {
 
     boolean tableFound = false;
     for (String table: tableNames) {
-      if (StringUtils.equalsIgnoreCase(tableName, CatalogUtil.extractSimpleName(table))) {
+      if (StringUtils.equalsIgnoreCase(tableName, IdentifierUtil.extractSimpleName(table))) {
         tableFound = true;
         break;
       }
@@ -158,7 +158,7 @@ public class TestTablesResource extends QueryTestCaseBase {
         .request().get(new GenericType<>(TableDesc.class));
     
     assertNotNull(selectedTable);
-    assertTrue(StringUtils.equalsIgnoreCase(tableName, CatalogUtil.extractSimpleName(selectedTable.getName())));
+    assertTrue(StringUtils.equalsIgnoreCase(tableName, IdentifierUtil.extractSimpleName(selectedTable.getName())));
   }
   
   @Test
@@ -183,7 +183,7 @@ public class TestTablesResource extends QueryTestCaseBase {
         .request().get(new GenericType<>(TableDesc.class));
     
     assertNotNull(selectedTable);
-    assertTrue(StringUtils.equalsIgnoreCase(tableName, CatalogUtil.extractSimpleName(selectedTable.getName())));
+    assertTrue(StringUtils.equalsIgnoreCase(tableName, IdentifierUtil.extractSimpleName(selectedTable.getName())));
     
     Response response = restClient.target(tablesURI)
         .path("/{tableName}").resolveTemplate("tableName", tableName)

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/queries/TestCreateTable/create_table_various_types.sql
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/queries/TestCreateTable/create_table_various_types.sql b/tajo-core-tests/src/test/resources/queries/TestCreateTable/create_table_various_types.sql
index bfa5e97..45cd7a2 100644
--- a/tajo-core-tests/src/test/resources/queries/TestCreateTable/create_table_various_types.sql
+++ b/tajo-core-tests/src/test/resources/queries/TestCreateTable/create_table_various_types.sql
@@ -46,5 +46,6 @@ create table various_types (
   -- col42 binary(10),
   -- col43 varbinary(10),
   -- col44 binary Varying(10),
-  col45 blOb
+  col45 blOb,
+  col46 array<integer>
 );
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/queries/TestCreateTable/testComplexType1.sql
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/queries/TestCreateTable/testComplexType1.sql b/tajo-core-tests/src/test/resources/queries/TestCreateTable/testComplexType1.sql
new file mode 100644
index 0000000..0bba96e
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/queries/TestCreateTable/testComplexType1.sql
@@ -0,0 +1,6 @@
+CREATE TABLE d11.complex_type1 (
+  col1 array<double>,
+  col2 array<record (last_name text, first_name text, age int)>,
+  col3 array<map<text, text>>,
+  col4 array<array<double>>
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/positive/create_table_with_array_type.sql
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/positive/create_table_with_array_type.sql b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/positive/create_table_with_array_type.sql
new file mode 100644
index 0000000..fac2555
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/queries/TestSQLAnalyzer/positive/create_table_with_array_type.sql
@@ -0,0 +1,6 @@
+create table table1 (
+  col1 array<int>,
+  col2 array<text>,
+  col3 array<record (name text, age int)>,
+  col3 array<array<float>>
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestCommonConditionReduce/test51.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestCommonConditionReduce/test51.plan b/tajo-core-tests/src/test/resources/results/TestCommonConditionReduce/test51.plan
index 5f1d6c0..9dd7b84 100644
--- a/tajo-core-tests/src/test/resources/results/TestCommonConditionReduce/test51.plan
+++ b/tajo-core-tests/src/test/resources/results/TestCommonConditionReduce/test51.plan
@@ -1,7 +1,7 @@
 explain
 -------------------------------
 SCAN(0) on default.lineitem
-  => filter: (default.lineitem.l_linenumber (INT4) = 1 AND (default.lineitem.l_orderkey (INT4) = 1 AND (default.lineitem.l_suppkey (INT4) = 7706 AND (default.lineitem.l_comment (TEXT) IS NOT NULL AND default.lineitem.l_commitdate (TEXT) IS NOT NULL))))
+  => filter: (default.lineitem.l_orderkey (INT4) = 1 AND (default.lineitem.l_linenumber (INT4) = 1 AND (default.lineitem.l_suppkey (INT4) = 7706 AND (default.lineitem.l_commitdate (TEXT) IS NOT NULL AND default.lineitem.l_comment (TEXT) IS NOT NULL))))
   => target list: default.lineitem.l_comment (TEXT), default.lineitem.l_commitdate (TEXT), default.lineitem.l_discount (FLOAT8), default.lineitem.l_extendedprice (FLOAT8), default.lineitem.l_linenumber (INT4), default.lineitem.l_linestatus (TEXT), default.lineitem.l_orderkey (INT4), default.lineitem.l_partkey (INT4), default.lineitem.l_quantity (FLOAT8), default.lineitem.l_receiptdate (TEXT), default.lineitem.l_returnflag (TEXT), default.lineitem.l_shipdate (TEXT), default.lineitem.l_shipinstruct (TEXT), default.lineitem.l_shipmode (TEXT), default.lineitem.l_suppkey (INT4), default.lineitem.l_tax (FLOAT8)
   => out schema: {(16) default.lineitem.l_comment (TEXT), default.lineitem.l_commitdate (TEXT), default.lineitem.l_discount (FLOAT8), default.lineitem.l_extendedprice (FLOAT8), default.lineitem.l_linenumber (INT4), default.lineitem.l_linestatus (TEXT), default.lineitem.l_orderkey (INT4), default.lineitem.l_partkey (INT4), default.lineitem.l_quantity (FLOAT8), default.lineitem.l_receiptdate (TEXT), default.lineitem.l_returnflag (TEXT), default.lineitem.l_shipdate (TEXT), default.lineitem.l_shipinstruct (TEXT), default.lineitem.l_shipmode (TEXT), default.lineitem.l_suppkey (INT4), default.lineitem.l_tax (FLOAT8)}
   => in schema: {(16) default.lineitem.l_comment (TEXT), default.lineitem.l_commitdate (TEXT), default.lineitem.l_discount (FLOAT8), default.lineitem.l_extendedprice (FLOAT8), default.lineitem.l_linenumber (INT4), default.lineitem.l_linestatus (TEXT), default.lineitem.l_orderkey (INT4), default.lineitem.l_partkey (INT4), default.lineitem.l_quantity (FLOAT8), default.lineitem.l_receiptdate (TEXT), default.lineitem.l_returnflag (TEXT), default.lineitem.l_shipdate (TEXT), default.lineitem.l_shipinstruct (TEXT), default.lineitem.l_shipmode (TEXT), default.lineitem.l_suppkey (INT4), default.lineitem.l_tax (FLOAT8)}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash.plan b/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash.plan
index 7848e95..5558eb9 100644
--- a/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash.plan
+++ b/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash.plan
@@ -20,7 +20,7 @@ JOIN(11)(INNER)
            => in schema: {(3) default.r.r_comment (TEXT), default.r.r_name (TEXT), default.r.r_regionkey (INT4)}
          SCAN(0) on default.nation as n
            => filter: default.n.n_name (TEXT) = MOROCCO
-           => target list: default.n.n_comment (TEXT), default.n.n_name (TEXT) as name, default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)
+           => target list: default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), default.n.n_name (TEXT) as name
            => out schema: {(4) default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), name (TEXT)}
            => in schema: {(4) default.n.n_comment (TEXT), default.n.n_name (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)}
    SCAN(5) on default.supplier as s
@@ -73,7 +73,7 @@ JOIN(11)(INNER)
               => in schema: {(3) default.r.r_comment (TEXT), default.r.r_name (TEXT), default.r.r_regionkey (INT4)}
             SCAN(0) on default.nation as n
               => filter: default.n.n_name (TEXT) = MOROCCO
-              => target list: default.n.n_comment (TEXT), default.n.n_name (TEXT) as name, default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)
+              => target list: default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), default.n.n_name (TEXT) as name
               => out schema: {(4) default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), name (TEXT)}
               => in schema: {(4) default.n.n_comment (TEXT), default.n.n_name (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)}
    SCAN(5) on default.supplier as s

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash_NoBroadcast.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash_NoBroadcast.plan b/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash_NoBroadcast.plan
index 2f7da99..65f8b1c 100644
--- a/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash_NoBroadcast.plan
+++ b/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Hash_NoBroadcast.plan
@@ -20,7 +20,7 @@ JOIN(11)(INNER)
            => in schema: {(3) default.r.r_comment (TEXT), default.r.r_name (TEXT), default.r.r_regionkey (INT4)}
          SCAN(0) on default.nation as n
            => filter: default.n.n_name (TEXT) = MOROCCO
-           => target list: default.n.n_comment (TEXT), default.n.n_name (TEXT) as name, default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)
+           => target list: default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), default.n.n_name (TEXT) as name
            => out schema: {(4) default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), name (TEXT)}
            => in schema: {(4) default.n.n_comment (TEXT), default.n.n_name (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)}
    SCAN(5) on default.supplier as s
@@ -58,7 +58,7 @@ Block Id: eb_0000000000000_0000_000002 [LEAF]
 
 SCAN(0) on default.nation as n
   => filter: default.n.n_name (TEXT) = MOROCCO
-  => target list: default.n.n_comment (TEXT), default.n.n_name (TEXT) as name, default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)
+  => target list: default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), default.n.n_name (TEXT) as name
   => out schema: {(4) default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), name (TEXT)}
   => in schema: {(4) default.n.n_comment (TEXT), default.n.n_name (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)}
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort.plan b/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort.plan
index 7848e95..5558eb9 100644
--- a/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort.plan
+++ b/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort.plan
@@ -20,7 +20,7 @@ JOIN(11)(INNER)
            => in schema: {(3) default.r.r_comment (TEXT), default.r.r_name (TEXT), default.r.r_regionkey (INT4)}
          SCAN(0) on default.nation as n
            => filter: default.n.n_name (TEXT) = MOROCCO
-           => target list: default.n.n_comment (TEXT), default.n.n_name (TEXT) as name, default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)
+           => target list: default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), default.n.n_name (TEXT) as name
            => out schema: {(4) default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), name (TEXT)}
            => in schema: {(4) default.n.n_comment (TEXT), default.n.n_name (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)}
    SCAN(5) on default.supplier as s
@@ -73,7 +73,7 @@ JOIN(11)(INNER)
               => in schema: {(3) default.r.r_comment (TEXT), default.r.r_name (TEXT), default.r.r_regionkey (INT4)}
             SCAN(0) on default.nation as n
               => filter: default.n.n_name (TEXT) = MOROCCO
-              => target list: default.n.n_comment (TEXT), default.n.n_name (TEXT) as name, default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)
+              => target list: default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), default.n.n_name (TEXT) as name
               => out schema: {(4) default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), name (TEXT)}
               => in schema: {(4) default.n.n_comment (TEXT), default.n.n_name (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)}
    SCAN(5) on default.supplier as s

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort_NoBroadcast.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort_NoBroadcast.plan b/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort_NoBroadcast.plan
index 2f7da99..65f8b1c 100644
--- a/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort_NoBroadcast.plan
+++ b/tajo-core-tests/src/test/resources/results/TestInnerJoinWithSubQuery/testJoinWithMultipleJoinQual2.Sort_NoBroadcast.plan
@@ -20,7 +20,7 @@ JOIN(11)(INNER)
            => in schema: {(3) default.r.r_comment (TEXT), default.r.r_name (TEXT), default.r.r_regionkey (INT4)}
          SCAN(0) on default.nation as n
            => filter: default.n.n_name (TEXT) = MOROCCO
-           => target list: default.n.n_comment (TEXT), default.n.n_name (TEXT) as name, default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)
+           => target list: default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), default.n.n_name (TEXT) as name
            => out schema: {(4) default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), name (TEXT)}
            => in schema: {(4) default.n.n_comment (TEXT), default.n.n_name (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)}
    SCAN(5) on default.supplier as s
@@ -58,7 +58,7 @@ Block Id: eb_0000000000000_0000_000002 [LEAF]
 
 SCAN(0) on default.nation as n
   => filter: default.n.n_name (TEXT) = MOROCCO
-  => target list: default.n.n_comment (TEXT), default.n.n_name (TEXT) as name, default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)
+  => target list: default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), default.n.n_name (TEXT) as name
   => out schema: {(4) default.n.n_comment (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4), name (TEXT)}
   => in schema: {(4) default.n.n_comment (TEXT), default.n.n_name (TEXT), default.n.n_nationkey (INT4), default.n.n_regionkey (INT4)}
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash.plan
index d5e35ee..785a0eb 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash.plan
@@ -10,7 +10,7 @@ JOIN(8)(LEFT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(LEFT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
@@ -54,7 +54,7 @@ JOIN(8)(LEFT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(LEFT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan
index d1a96c9..cd1484d 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan
@@ -10,7 +10,7 @@ JOIN(8)(LEFT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(LEFT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
@@ -80,7 +80,7 @@ Block Id: eb_0000000000000_0000_000003 [INTERMEDIATE]
 [q_0000000000000_0000] 3 => 5 (type=HASH_SHUFFLE, key=default.t1.id (INT4), num=32)
 
 JOIN(7)(LEFT_OUTER)
-  => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+  => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
   => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
   => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
   => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort.plan
index d5e35ee..785a0eb 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort.plan
@@ -10,7 +10,7 @@ JOIN(8)(LEFT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(LEFT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
@@ -54,7 +54,7 @@ JOIN(8)(LEFT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(LEFT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan
index d1a96c9..cd1484d 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testLeftOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan
@@ -10,7 +10,7 @@ JOIN(8)(LEFT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(LEFT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
@@ -80,7 +80,7 @@ Block Id: eb_0000000000000_0000_000003 [INTERMEDIATE]
 [q_0000000000000_0000] 3 => 5 (type=HASH_SHUFFLE, key=default.t1.id (INT4), num=32)
 
 JOIN(7)(LEFT_OUTER)
-  => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+  => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
   => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
   => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
   => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash.plan
index 43fc9f7..87b13bf 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash.plan
@@ -17,7 +17,7 @@ SORT(5)
            => out schema: {(2) default.c.id (INT4), default.c.name (TEXT)}
            => in schema: {(4) default.c.id (INT4), default.c.name (TEXT), default.c.score (FLOAT4), default.c.type (TEXT)}
          SCAN(1) on default.testouterjoinandcasewhen2 as b
-           => target list: default.b.id (INT4), default.b.id (INT4) as id2, default.b.name (TEXT), default.b.name (TEXT) as name2
+           => target list: default.b.id (INT4), default.b.name (TEXT), default.b.id (INT4) as id2, default.b.name (TEXT) as name2
            => out schema: {(4) default.b.id (INT4), default.b.name (TEXT), id2 (INT4), name2 (TEXT)}
            => in schema: {(4) default.b.id (INT4), default.b.name (TEXT), default.b.score (FLOAT4), default.b.type (TEXT)}
       SCAN(0) on default.testouterjoinandcasewhen1 as a
@@ -68,7 +68,7 @@ SORT(15)
            => out schema: {(2) default.c.id (INT4), default.c.name (TEXT)}
            => in schema: {(4) default.c.id (INT4), default.c.name (TEXT), default.c.score (FLOAT4), default.c.type (TEXT)}
          SCAN(1) on default.testouterjoinandcasewhen2 as b
-           => target list: default.b.id (INT4), default.b.id (INT4) as id2, default.b.name (TEXT), default.b.name (TEXT) as name2
+           => target list: default.b.id (INT4), default.b.name (TEXT), default.b.id (INT4) as id2, default.b.name (TEXT) as name2
            => out schema: {(4) default.b.id (INT4), default.b.name (TEXT), id2 (INT4), name2 (TEXT)}
            => in schema: {(4) default.b.id (INT4), default.b.name (TEXT), default.b.score (FLOAT4), default.b.type (TEXT)}
       SCAN(0) on default.testouterjoinandcasewhen1 as a

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash_NoBroadcast.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash_NoBroadcast.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash_NoBroadcast.plan
index 749c8c0..4134f9b 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash_NoBroadcast.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Hash_NoBroadcast.plan
@@ -17,7 +17,7 @@ SORT(5)
            => out schema: {(2) default.c.id (INT4), default.c.name (TEXT)}
            => in schema: {(4) default.c.id (INT4), default.c.name (TEXT), default.c.score (FLOAT4), default.c.type (TEXT)}
          SCAN(1) on default.testouterjoinandcasewhen2 as b
-           => target list: default.b.id (INT4), default.b.id (INT4) as id2, default.b.name (TEXT), default.b.name (TEXT) as name2
+           => target list: default.b.id (INT4), default.b.name (TEXT), default.b.id (INT4) as id2, default.b.name (TEXT) as name2
            => out schema: {(4) default.b.id (INT4), default.b.name (TEXT), id2 (INT4), name2 (TEXT)}
            => in schema: {(4) default.b.id (INT4), default.b.name (TEXT), default.b.score (FLOAT4), default.b.type (TEXT)}
       SCAN(0) on default.testouterjoinandcasewhen1 as a
@@ -56,7 +56,7 @@ Block Id: eb_0000000000000_0000_000002 [LEAF]
 [q_0000000000000_0000] 2 => 4 (type=HASH_SHUFFLE, key=default.b.id (INT4), num=32)
 
 SCAN(1) on default.testouterjoinandcasewhen2 as b
-  => target list: default.b.id (INT4), default.b.id (INT4) as id2, default.b.name (TEXT), default.b.name (TEXT) as name2
+  => target list: default.b.id (INT4), default.b.name (TEXT), default.b.id (INT4) as id2, default.b.name (TEXT) as name2
   => out schema: {(4) default.b.id (INT4), default.b.name (TEXT), id2 (INT4), name2 (TEXT)}
   => in schema: {(4) default.b.id (INT4), default.b.name (TEXT), default.b.score (FLOAT4), default.b.type (TEXT)}
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort.plan
index 43fc9f7..87b13bf 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort.plan
@@ -17,7 +17,7 @@ SORT(5)
            => out schema: {(2) default.c.id (INT4), default.c.name (TEXT)}
            => in schema: {(4) default.c.id (INT4), default.c.name (TEXT), default.c.score (FLOAT4), default.c.type (TEXT)}
          SCAN(1) on default.testouterjoinandcasewhen2 as b
-           => target list: default.b.id (INT4), default.b.id (INT4) as id2, default.b.name (TEXT), default.b.name (TEXT) as name2
+           => target list: default.b.id (INT4), default.b.name (TEXT), default.b.id (INT4) as id2, default.b.name (TEXT) as name2
            => out schema: {(4) default.b.id (INT4), default.b.name (TEXT), id2 (INT4), name2 (TEXT)}
            => in schema: {(4) default.b.id (INT4), default.b.name (TEXT), default.b.score (FLOAT4), default.b.type (TEXT)}
       SCAN(0) on default.testouterjoinandcasewhen1 as a
@@ -68,7 +68,7 @@ SORT(15)
            => out schema: {(2) default.c.id (INT4), default.c.name (TEXT)}
            => in schema: {(4) default.c.id (INT4), default.c.name (TEXT), default.c.score (FLOAT4), default.c.type (TEXT)}
          SCAN(1) on default.testouterjoinandcasewhen2 as b
-           => target list: default.b.id (INT4), default.b.id (INT4) as id2, default.b.name (TEXT), default.b.name (TEXT) as name2
+           => target list: default.b.id (INT4), default.b.name (TEXT), default.b.id (INT4) as id2, default.b.name (TEXT) as name2
            => out schema: {(4) default.b.id (INT4), default.b.name (TEXT), id2 (INT4), name2 (TEXT)}
            => in schema: {(4) default.b.id (INT4), default.b.name (TEXT), default.b.score (FLOAT4), default.b.type (TEXT)}
       SCAN(0) on default.testouterjoinandcasewhen1 as a

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort_NoBroadcast.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort_NoBroadcast.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort_NoBroadcast.plan
index 749c8c0..4134f9b 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort_NoBroadcast.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testOuterJoinAndCaseWhen1.Sort_NoBroadcast.plan
@@ -17,7 +17,7 @@ SORT(5)
            => out schema: {(2) default.c.id (INT4), default.c.name (TEXT)}
            => in schema: {(4) default.c.id (INT4), default.c.name (TEXT), default.c.score (FLOAT4), default.c.type (TEXT)}
          SCAN(1) on default.testouterjoinandcasewhen2 as b
-           => target list: default.b.id (INT4), default.b.id (INT4) as id2, default.b.name (TEXT), default.b.name (TEXT) as name2
+           => target list: default.b.id (INT4), default.b.name (TEXT), default.b.id (INT4) as id2, default.b.name (TEXT) as name2
            => out schema: {(4) default.b.id (INT4), default.b.name (TEXT), id2 (INT4), name2 (TEXT)}
            => in schema: {(4) default.b.id (INT4), default.b.name (TEXT), default.b.score (FLOAT4), default.b.type (TEXT)}
       SCAN(0) on default.testouterjoinandcasewhen1 as a
@@ -56,7 +56,7 @@ Block Id: eb_0000000000000_0000_000002 [LEAF]
 [q_0000000000000_0000] 2 => 4 (type=HASH_SHUFFLE, key=default.b.id (INT4), num=32)
 
 SCAN(1) on default.testouterjoinandcasewhen2 as b
-  => target list: default.b.id (INT4), default.b.id (INT4) as id2, default.b.name (TEXT), default.b.name (TEXT) as name2
+  => target list: default.b.id (INT4), default.b.name (TEXT), default.b.id (INT4) as id2, default.b.name (TEXT) as name2
   => out schema: {(4) default.b.id (INT4), default.b.name (TEXT), id2 (INT4), name2 (TEXT)}
   => in schema: {(4) default.b.id (INT4), default.b.name (TEXT), default.b.score (FLOAT4), default.b.type (TEXT)}
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash.plan
index 8e7074e..0f8ca51 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash.plan
@@ -10,7 +10,7 @@ JOIN(8)(RIGHT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(RIGHT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
@@ -54,7 +54,7 @@ JOIN(8)(RIGHT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(RIGHT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan
index fab3809..dfb2287 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Hash_NoBroadcast.plan
@@ -10,7 +10,7 @@ JOIN(8)(RIGHT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(RIGHT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
@@ -80,7 +80,7 @@ Block Id: eb_0000000000000_0000_000003 [INTERMEDIATE]
 [q_0000000000000_0000] 3 => 5 (type=HASH_SHUFFLE, key=default.t1.id (INT4), num=32)
 
 JOIN(7)(RIGHT_OUTER)
-  => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+  => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
   => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
   => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
   => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort.plan
index 8e7074e..0f8ca51 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort.plan
@@ -10,7 +10,7 @@ JOIN(8)(RIGHT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(RIGHT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
@@ -54,7 +54,7 @@ JOIN(8)(RIGHT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(RIGHT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan
index fab3809..dfb2287 100644
--- a/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan
+++ b/tajo-core-tests/src/test/resources/results/TestOuterJoinQuery/testRightOuterJoinPredicationCaseByCase3.1.Sort_NoBroadcast.plan
@@ -10,7 +10,7 @@ JOIN(8)(RIGHT_OUTER)
      => out schema: {(1) default.t3.id (INT4)}
      => in schema: {(2) default.t3.id (INT4), default.t3.name (TEXT)}
    JOIN(7)(RIGHT_OUTER)
-     => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+     => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
      => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
      => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
      => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
@@ -80,7 +80,7 @@ Block Id: eb_0000000000000_0000_000003 [INTERMEDIATE]
 [q_0000000000000_0000] 3 => 5 (type=HASH_SHUFFLE, key=default.t1.id (INT4), num=32)
 
 JOIN(7)(RIGHT_OUTER)
-  => Join Cond: (default.t1.id (INT4) = default.t2.id (INT4) AND (concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33))
+  => Join Cond: ((concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-11 OR concat(default.t1.name (TEXT),CAST (default.t2.id (INT4) AS TEXT)) = table11-33) AND default.t1.id (INT4) = default.t2.id (INT4))
   => target list: default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)
   => out schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}
   => in schema: {(3) default.t1.id (INT4), default.t1.name (TEXT), default.t2.id (INT4)}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/resources/results/TestTPCH/testFirstJoinInQ7.plan
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestTPCH/testFirstJoinInQ7.plan b/tajo-core-tests/src/test/resources/results/TestTPCH/testFirstJoinInQ7.plan
index d17f26c..416f13b 100644
--- a/tajo-core-tests/src/test/resources/results/TestTPCH/testFirstJoinInQ7.plan
+++ b/tajo-core-tests/src/test/resources/results/TestTPCH/testFirstJoinInQ7.plan
@@ -11,12 +11,12 @@ UNION(8)
         => in schema: {(4) c_nationkey (INT4), cust_nation (TEXT), s_nationkey (INT4), supp_nation (TEXT)}
          SCAN(4) on default.nation as n1
            => filter: default.n1.n_name (TEXT) = GERMANY
-           => target list: default.n1.n_name (TEXT) as supp_nation, default.n1.n_nationkey (INT4) as s_nationkey
+           => target list: default.n1.n_nationkey (INT4) as s_nationkey, default.n1.n_name (TEXT) as supp_nation
            => out schema: {(2) s_nationkey (INT4), supp_nation (TEXT)}
            => in schema: {(4) default.n1.n_comment (TEXT), default.n1.n_name (TEXT), default.n1.n_nationkey (INT4), default.n1.n_regionkey (INT4)}
          SCAN(5) on default.nation as n2
            => filter: default.n2.n_name (TEXT) = FRANCE
-           => target list: default.n2.n_name (TEXT) as cust_nation, default.n2.n_nationkey (INT4) as c_nationkey
+           => target list: default.n2.n_nationkey (INT4) as c_nationkey, default.n2.n_name (TEXT) as cust_nation
            => out schema: {(2) c_nationkey (INT4), cust_nation (TEXT)}
            => in schema: {(4) default.n2.n_comment (TEXT), default.n2.n_name (TEXT), default.n2.n_nationkey (INT4), default.n2.n_regionkey (INT4)}
    PROJECTION(3)
@@ -29,12 +29,12 @@ UNION(8)
         => in schema: {(4) c_nationkey (INT4), cust_nation (TEXT), s_nationkey (INT4), supp_nation (TEXT)}
          SCAN(0) on default.nation as n1
            => filter: default.n1.n_name (TEXT) = FRANCE
-           => target list: default.n1.n_name (TEXT) as supp_nation, default.n1.n_nationkey (INT4) as s_nationkey
+           => target list: default.n1.n_nationkey (INT4) as s_nationkey, default.n1.n_name (TEXT) as supp_nation
            => out schema: {(2) s_nationkey (INT4), supp_nation (TEXT)}
            => in schema: {(4) default.n1.n_comment (TEXT), default.n1.n_name (TEXT), default.n1.n_nationkey (INT4), default.n1.n_regionkey (INT4)}
          SCAN(1) on default.nation as n2
            => filter: default.n2.n_name (TEXT) = GERMANY
-           => target list: default.n2.n_name (TEXT) as cust_nation, default.n2.n_nationkey (INT4) as c_nationkey
+           => target list: default.n2.n_nationkey (INT4) as c_nationkey, default.n2.n_name (TEXT) as cust_nation
            => out schema: {(2) c_nationkey (INT4), cust_nation (TEXT)}
            => in schema: {(4) default.n2.n_comment (TEXT), default.n2.n_name (TEXT), default.n2.n_nationkey (INT4), default.n2.n_regionkey (INT4)}
 explain
@@ -70,7 +70,7 @@ Block Id: eb_0000000000000_0000_000001 [LEAF]
 
 SCAN(1) on default.nation as n2
   => filter: default.n2.n_name (TEXT) = GERMANY
-  => target list: default.n2.n_name (TEXT) as cust_nation, default.n2.n_nationkey (INT4) as c_nationkey
+  => target list: default.n2.n_nationkey (INT4) as c_nationkey, default.n2.n_name (TEXT) as cust_nation
   => out schema: {(2) c_nationkey (INT4), cust_nation (TEXT)}
   => in schema: {(4) default.n2.n_comment (TEXT), default.n2.n_name (TEXT), default.n2.n_nationkey (INT4), default.n2.n_regionkey (INT4)}
 
@@ -83,7 +83,7 @@ Block Id: eb_0000000000000_0000_000002 [LEAF]
 
 SCAN(0) on default.nation as n1
   => filter: default.n1.n_name (TEXT) = FRANCE
-  => target list: default.n1.n_name (TEXT) as supp_nation, default.n1.n_nationkey (INT4) as s_nationkey
+  => target list: default.n1.n_nationkey (INT4) as s_nationkey, default.n1.n_name (TEXT) as supp_nation
   => out schema: {(2) s_nationkey (INT4), supp_nation (TEXT)}
   => in schema: {(4) default.n1.n_comment (TEXT), default.n1.n_name (TEXT), default.n1.n_nationkey (INT4), default.n1.n_regionkey (INT4)}
 
@@ -96,7 +96,7 @@ Block Id: eb_0000000000000_0000_000004 [LEAF]
 
 SCAN(5) on default.nation as n2
   => filter: default.n2.n_name (TEXT) = FRANCE
-  => target list: default.n2.n_name (TEXT) as cust_nation, default.n2.n_nationkey (INT4) as c_nationkey
+  => target list: default.n2.n_nationkey (INT4) as c_nationkey, default.n2.n_name (TEXT) as cust_nation
   => out schema: {(2) c_nationkey (INT4), cust_nation (TEXT)}
   => in schema: {(4) default.n2.n_comment (TEXT), default.n2.n_name (TEXT), default.n2.n_nationkey (INT4), default.n2.n_regionkey (INT4)}
 
@@ -109,7 +109,7 @@ Block Id: eb_0000000000000_0000_000005 [LEAF]
 
 SCAN(4) on default.nation as n1
   => filter: default.n1.n_name (TEXT) = GERMANY
-  => target list: default.n1.n_name (TEXT) as supp_nation, default.n1.n_nationkey (INT4) as s_nationkey
+  => target list: default.n1.n_nationkey (INT4) as s_nationkey, default.n1.n_name (TEXT) as supp_nation
   => out schema: {(2) s_nationkey (INT4), supp_nation (TEXT)}
   => in schema: {(4) default.n1.n_comment (TEXT), default.n1.n_name (TEXT), default.n1.n_nationkey (INT4), default.n1.n_regionkey (INT4)}
 


[7/7] tajo git commit: TAJO-2129: Apply new type implementation to Schema and Catalog.

Posted by hy...@apache.org.
TAJO-2129: Apply new type implementation to Schema and Catalog.

Closes #1016


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

Branch: refs/heads/master
Commit: 8d2bf407f5e462216eb84d193c300b46dc2817f9
Parents: 01d2fe2
Author: Hyunsik Choi <hy...@apache.org>
Authored: Thu May 12 22:29:43 2016 -0700
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Thu May 12 22:29:43 2016 -0700

----------------------------------------------------------------------
 CHANGES                                         |   2 +
 .../apache/tajo/algebra/ColumnDefinition.java   |  11 +-
 .../org/apache/tajo/algebra/DataTypeExpr.java   |  63 +++-
 .../tajo/catalog/AbstractCatalogClient.java     |   9 +-
 .../main/java/org/apache/tajo/DataTypeUtil.java |   4 +-
 .../apache/tajo/catalog/CatalogConstants.java   |   4 -
 .../org/apache/tajo/catalog/CatalogUtil.java    | 260 +--------------
 .../java/org/apache/tajo/catalog/Column.java    |  52 +--
 .../org/apache/tajo/catalog/DDLBuilder.java     |  19 +-
 .../org/apache/tajo/catalog/FieldConverter.java |  60 +---
 .../apache/tajo/catalog/ListSchemaBuilder.java  |  14 +-
 .../org/apache/tajo/catalog/NestedPathUtil.java |   2 +-
 .../org/apache/tajo/catalog/SchemaBuilder.java  |  54 ++-
 .../org/apache/tajo/catalog/SchemaLegacy.java   |  90 ++---
 .../org/apache/tajo/catalog/SchemaUtil.java     |   2 +-
 .../apache/tajo/catalog/SetSchemaBuilder.java   |  32 +-
 .../org/apache/tajo/catalog/TypeConverter.java  | 131 ++++----
 .../tajo/catalog/json/CatalogGsonHelper.java    |   1 +
 .../tajo/catalog/statistics/TableStats.java     |   9 +-
 .../src/main/proto/CatalogProtos.proto          |   2 +-
 .../apache/tajo/catalog/TestCatalogUtil.java    |   3 +-
 .../tajo/catalog/store/HiveCatalogStore.java    |  26 +-
 .../tajo/catalog/store/HiveCatalogUtil.java     |  10 +-
 .../catalog/store/TestHiveCatalogStore.java     |  23 +-
 .../org/apache/tajo/catalog/CatalogServer.java  |   9 +-
 .../dictionary/AbstractTableDescriptor.java     |  12 +-
 .../tajo/catalog/store/AbstractDBStore.java     | 119 +++----
 .../src/main/resources/schemas/derby/derby.xml  |   5 +-
 .../main/resources/schemas/mariadb/mariadb.xml  |   5 +-
 .../src/main/resources/schemas/mysql/mysql.xml  |   5 +-
 .../main/resources/schemas/oracle/oracle.xml    |   5 +-
 .../resources/schemas/postgresql/postgresql.xml |   5 +-
 .../apache/tajo/catalog/CatalogTestingUtil.java |  23 +-
 .../apache/tajo/catalog/MiniCatalogServer.java  |   3 +-
 .../org/apache/tajo/catalog/TestCatalog.java    |  29 +-
 .../TestCatalogAgainstCaseSensitivity.java      |  37 ++-
 .../tajo/catalog/TestCatalogExceptions.java     |  47 +--
 .../org/apache/tajo/cli/tools/TajoDump.java     |   9 +-
 .../cli/tsql/commands/DescTableCommand.java     |   4 +-
 .../apache/tajo/jdbc/TajoResultSetMetaData.java |   6 +-
 .../apache/tajo/LocalTajoTestingUtility.java    |   3 +-
 .../java/org/apache/tajo/QueryTestCaseBase.java |  10 +-
 .../org/apache/tajo/TajoTestingCluster.java     |   7 +-
 .../src/main/java/org/apache/tajo/Assert.java   |  36 ++
 .../exception/InvalidValueForCastException.java |   2 +-
 .../org/apache/tajo/json/CommonGsonHelper.java  |   1 +
 .../java/org/apache/tajo/json/TypeAdapter.java  |  42 +++
 .../tajo/schema/ANSISQLIdentifierPolicy.java    |   4 +-
 .../main/java/org/apache/tajo/schema/Field.java | 106 ++++++
 .../java/org/apache/tajo/schema/Identifier.java |  44 ++-
 .../apache/tajo/schema/IdentifierPolicy.java    |   8 +-
 .../org/apache/tajo/schema/IdentifierUtil.java  | 333 +++++++++++++++++++
 .../tajo/schema/PgSQLIdentifierPolicy.java      |   4 +-
 .../apache/tajo/schema/QualifiedIdentifier.java |  76 ++++-
 .../java/org/apache/tajo/schema/Schema.java     | 142 +-------
 .../org/apache/tajo/schema/package-info.java    |  22 ++
 .../src/main/java/org/apache/tajo/type/Any.java |  12 +-
 .../main/java/org/apache/tajo/type/Array.java   |  40 +--
 .../main/java/org/apache/tajo/type/Blob.java    |   7 +-
 .../main/java/org/apache/tajo/type/Bool.java    |   7 +-
 .../main/java/org/apache/tajo/type/Char.java    |  41 +--
 .../main/java/org/apache/tajo/type/Date.java    |   7 +-
 .../main/java/org/apache/tajo/type/Float4.java  |   7 +-
 .../main/java/org/apache/tajo/type/Float8.java  |   7 +-
 .../main/java/org/apache/tajo/type/Inet4.java   |   7 +-
 .../main/java/org/apache/tajo/type/Int1.java    |   7 +-
 .../main/java/org/apache/tajo/type/Int2.java    |   7 +-
 .../main/java/org/apache/tajo/type/Int4.java    |   7 +-
 .../main/java/org/apache/tajo/type/Int8.java    |   7 +-
 .../java/org/apache/tajo/type/Interval.java     |   7 +-
 .../src/main/java/org/apache/tajo/type/Map.java |  41 +--
 .../main/java/org/apache/tajo/type/Null.java    |   7 +-
 .../main/java/org/apache/tajo/type/Numeric.java |  40 +--
 .../java/org/apache/tajo/type/Protobuf.java     |  12 +-
 .../main/java/org/apache/tajo/type/Record.java  |  79 +++++
 .../main/java/org/apache/tajo/type/Struct.java  |  72 ----
 .../main/java/org/apache/tajo/type/Text.java    |   7 +-
 .../main/java/org/apache/tajo/type/Time.java    |   7 +-
 .../java/org/apache/tajo/type/Timestamp.java    |   7 +-
 .../main/java/org/apache/tajo/type/Type.java    |  97 +++---
 .../java/org/apache/tajo/type/TypeFactory.java  | 184 ++++++++++
 .../apache/tajo/type/TypeParamterizedType.java  |  77 +++++
 .../apache/tajo/type/TypeProtobufEncoder.java   | 185 +++++++++++
 .../org/apache/tajo/type/TypeStringEncoder.java | 296 +++++++++++++++++
 .../java/org/apache/tajo/type/TypeVisitor.java  |  54 +++
 .../apache/tajo/type/ValueParamterizedType.java |  79 +++++
 .../main/java/org/apache/tajo/type/Varchar.java |  40 +--
 .../java/org/apache/tajo/type/package-info.java |  29 ++
 tajo-common/src/main/proto/DataTypes.proto      |  21 ++
 .../java/org/apache/tajo/schema/TestSchema.java |  26 +-
 .../tajo/schema/TestTajoIdentifierPolicy.java   |   4 +-
 .../java/org/apache/tajo/type/TestType.java     | 105 +++---
 .../org/apache/tajo/type/TestTypeEncoder.java   | 124 +++++++
 .../tajo/type/TestTypeProtobufEncoder.java      |  30 ++
 .../apache/tajo/type/TestTypeStringEncoder.java |  29 ++
 .../apache/tajo/cli/tools/TestDDLBuilder.java   |   5 +-
 .../org/apache/tajo/cli/tsql/TestTajoCli.java   |   6 +-
 .../tajo/cli/tsql/TestTajoCliNegatives.java     |   2 +-
 .../org/apache/tajo/client/TestTajoClient.java  |  28 +-
 .../apache/tajo/engine/eval/ExprTestBase.java   |  16 +-
 .../apache/tajo/engine/eval/TestEvalTree.java   |   8 +-
 .../tajo/engine/eval/TestEvalTreeUtil.java      |   3 +-
 .../planner/TestEvalNodeToExprConverter.java    |   3 +-
 .../engine/planner/TestJoinOrderAlgorithm.java  |   9 +-
 .../engine/planner/TestLogicalOptimizer.java    |   7 +-
 .../tajo/engine/planner/TestLogicalPlanner.java |  48 +--
 .../tajo/engine/planner/TestPlannerUtil.java    |   7 +-
 .../physical/TestFullOuterHashJoinExec.java     |   9 +-
 .../physical/TestFullOuterMergeJoinExec.java    |  11 +-
 .../physical/TestLeftOuterHashJoinExec.java     |   9 +-
 .../planner/physical/TestPhysicalPlanner.java   |   7 +-
 .../physical/TestProgressExternalSortExec.java  |   3 +-
 .../physical/TestRightOuterHashJoinExec.java    |   7 +-
 .../physical/TestRightOuterMergeJoinExec.java   |  11 +-
 .../engine/planner/physical/TestSortExec.java   |   3 +-
 .../tajo/engine/query/TestAlterTable.java       |  21 +-
 .../apache/tajo/engine/query/TestCTASQuery.java |  16 +-
 .../tajo/engine/query/TestCreateDatabase.java   |   8 +-
 .../tajo/engine/query/TestCreateTable.java      |  27 +-
 .../tajo/engine/query/TestInsertQuery.java      |  16 +-
 .../query/TestJoinOnPartitionedTables.java      |  10 +-
 .../tajo/engine/query/TestSimpleQuery.java      |   6 +-
 .../tajo/engine/query/TestTablePartitions.java  |  47 +--
 .../tajo/master/TestExecutionBlockCursor.java   |   3 +-
 .../tajo/querymaster/TestTaskStatusUpdate.java  |   4 +-
 .../ws/rs/resources/TestTablesResource.java     |   8 +-
 .../create_table_various_types.sql              |   3 +-
 .../TestCreateTable/testComplexType1.sql        |   6 +
 .../positive/create_table_with_array_type.sql   |   6 +
 .../TestCommonConditionReduce/test51.plan       |   2 +-
 .../testJoinWithMultipleJoinQual2.Hash.plan     |   4 +-
 ...nWithMultipleJoinQual2.Hash_NoBroadcast.plan |   4 +-
 .../testJoinWithMultipleJoinQual2.Sort.plan     |   4 +-
 ...nWithMultipleJoinQual2.Sort_NoBroadcast.plan |   4 +-
 ...tOuterJoinPredicationCaseByCase3.1.Hash.plan |   4 +-
 ...edicationCaseByCase3.1.Hash_NoBroadcast.plan |   4 +-
 ...tOuterJoinPredicationCaseByCase3.1.Sort.plan |   4 +-
 ...edicationCaseByCase3.1.Sort_NoBroadcast.plan |   4 +-
 .../testOuterJoinAndCaseWhen1.Hash.plan         |   4 +-
 ...tOuterJoinAndCaseWhen1.Hash_NoBroadcast.plan |   4 +-
 .../testOuterJoinAndCaseWhen1.Sort.plan         |   4 +-
 ...tOuterJoinAndCaseWhen1.Sort_NoBroadcast.plan |   4 +-
 ...tOuterJoinPredicationCaseByCase3.1.Hash.plan |   4 +-
 ...edicationCaseByCase3.1.Hash_NoBroadcast.plan |   4 +-
 ...tOuterJoinPredicationCaseByCase3.1.Sort.plan |   4 +-
 ...edicationCaseByCase3.1.Sort_NoBroadcast.plan |   4 +-
 .../results/TestTPCH/testFirstJoinInQ7.plan     |  16 +-
 .../tajo/engine/codegen/EvalCodeGenContext.java |   4 +-
 .../tajo/engine/codegen/EvalCodeGenerator.java  |   8 +-
 .../engine/codegen/TajoGeneratorAdapter.java    |  28 +-
 .../engine/codegen/VariablesPreBuilder.java     |   4 +-
 .../engine/planner/global/GlobalPlanner.java    |   8 +-
 .../tajo/master/TajoMasterClientService.java    |  41 +--
 .../tajo/master/exec/CreateTableExecutor.java   |   7 +-
 .../apache/tajo/master/exec/DDLExecutor.java    |  35 +-
 .../NonForwardQueryResultSystemScanner.java     |  16 +-
 .../apache/tajo/master/exec/QueryExecutor.java  |   7 +-
 .../master/exec/prehook/CreateTableHook.java    |   5 +-
 .../org/apache/tajo/parser/sql/SQLAnalyzer.java |  33 +-
 .../java/org/apache/tajo/querymaster/Query.java |  13 +-
 .../tajo/ws/rs/resources/TablesResource.java    |  12 +-
 .../apache/tajo/jdbc/TajoDatabaseMetaData.java  |  19 +-
 .../org/apache/tajo/jdbc/TestResultSet.java     |   3 +-
 .../tajo/jdbc/TestTajoDatabaseMetaData.java     |  10 +-
 .../java/org/apache/tajo/jdbc/TestTajoJdbc.java |  10 +-
 .../org/apache/tajo/plan/ExprAnnotator.java     |  40 ++-
 .../org/apache/tajo/plan/ExprNormalizer.java    |   4 +-
 .../org/apache/tajo/plan/LogicalPlanner.java    | 109 +++---
 .../org/apache/tajo/plan/NamedExprsManager.java |   5 +-
 .../org/apache/tajo/plan/TypeDeterminant.java   |   8 +-
 .../org/apache/tajo/plan/expr/ConstEval.java    |   4 +-
 .../org/apache/tajo/plan/expr/EvalTreeUtil.java |  15 +-
 .../org/apache/tajo/plan/expr/FieldEval.java    |  60 ++--
 .../apache/tajo/plan/expr/RowConstantEval.java  |   4 +-
 .../tajo/plan/logical/CreateDatabaseNode.java   |   4 +-
 .../org/apache/tajo/plan/logical/JoinSpec.java  |   6 +-
 .../org/apache/tajo/plan/logical/ScanNode.java  |  13 +-
 .../tajo/plan/nameresolver/NameResolver.java    |  18 +-
 .../plan/nameresolver/ResolverByLegacy.java     |   4 +-
 .../tajo/plan/rewrite/BaseSchemaBuildPhase.java |  22 +-
 .../plan/rewrite/SelfDescSchemaBuildPhase.java  |   7 +-
 .../plan/rewrite/rules/FilterPushDownRule.java  |  11 +-
 .../rewrite/rules/PartitionedTableRewriter.java |   3 +-
 .../tajo/plan/serder/EvalNodeSerializer.java    |   4 +-
 .../apache/tajo/plan/serder/PlanGsonHelper.java |   1 +
 .../tajo/plan/util/EvalNodeToExprConverter.java |   2 +-
 .../tajo/plan/verifier/ExprsVerifier.java       |  14 +-
 .../plan/verifier/PreLogicalPlanVerifier.java   |  14 +-
 tajo-sql-parser/pom.xml                         |   5 +
 .../org/apache/tajo/parser/sql/SQLLexer.g4      |   7 +-
 .../org/apache/tajo/parser/sql/SQLParser.g4     |  19 +-
 .../org/apache/tajo/storage/FileTablespace.java |   3 +-
 .../storage/jdbc/JdbcMetadataProviderBase.java  |   5 +-
 .../storage/jdbc/SQLExpressionGenerator.java    |  13 +-
 .../tajo/storage/pgsql/PgSQLTablespace.java     |   3 +-
 195 files changed, 3135 insertions(+), 1888 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index eec145c..840ba56 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,8 @@ Release 0.12.0 - unreleased
 
   IMPROVEMENT
 
+    TAJO-2129: Apply new type implementation to Schema and Catalog. (hyunsik)
+
     TAJO-2071: Supporting DATE type in Parquet format. 
     (Jongyoung Park via hyunsik)
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnDefinition.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnDefinition.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnDefinition.java
index 2a829e1..aa26bfc 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnDefinition.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnDefinition.java
@@ -24,11 +24,6 @@ public  class ColumnDefinition extends DataTypeExpr {
   @Expose @SerializedName("ColumnDefName")
   String columnName;
 
-  public ColumnDefinition(String columnName, String dataType) {
-    super(dataType);
-    this.columnName = columnName;
-  }
-
   public ColumnDefinition(String columnName, DataTypeExpr dataType) {
     super(dataType.getTypeName());
 
@@ -42,15 +37,17 @@ public  class ColumnDefinition extends DataTypeExpr {
       }
     }
 
-    // nested records
     if (dataType.isRecordType()) {
       this.recordType = dataType.recordType;
     }
 
-    // map type
     if (dataType.isMapType()) {
       this.mapType = dataType.mapType;
     }
+
+    if (dataType.isArrayType()) {
+      this.arrayType = dataType.arrayType;
+    }
   }
 
   public String getColumnName() {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataTypeExpr.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataTypeExpr.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataTypeExpr.java
index d63532d..bd5caac 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataTypeExpr.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataTypeExpr.java
@@ -19,11 +19,15 @@
 package org.apache.tajo.algebra;
 
 import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
 import com.google.gson.annotations.Expose;
 import com.google.gson.annotations.SerializedName;
+import org.apache.tajo.Assert;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.util.TUtil;
 
+import static org.apache.tajo.Assert.assertNotNull;
+
 public class DataTypeExpr extends Expr {
   @Expose @SerializedName("DataTypeName")
   String typeName;
@@ -31,6 +35,8 @@ public class DataTypeExpr extends Expr {
   Integer lengthOrPrecision;
   @Expose @SerializedName("Scale")
   Integer scale;
+  @Expose @SerializedName("Array")
+  ArrayType arrayType; // not null if the type is ARRAY
   @Expose @SerializedName("Record")
   RecordType recordType; // not null if the type is RECORD
   @Expose @SerializedName("Map")
@@ -38,18 +44,27 @@ public class DataTypeExpr extends Expr {
 
   public DataTypeExpr(String typeName) {
     super(OpType.DataType);
+    assertNotNull(typeName);
     this.typeName = typeName;
   }
 
+  public DataTypeExpr(ArrayType array) {
+    super(OpType.DataType);
+    assertNotNull(array);
+    this.typeName = Type.ARRAY.name();
+    this.arrayType = array;
+  }
+
   public DataTypeExpr(RecordType record) {
     super(OpType.DataType);
+    assertNotNull(record);
     this.typeName = Type.RECORD.name();
     this.recordType = record;
   }
 
   public DataTypeExpr(MapType map) {
     super(OpType.DataType);
-    // RECORD = 51 in DataTypes.proto
+    assertNotNull(map);
     this.typeName = Type.MAP.name();
     this.mapType = map;
   }
@@ -59,15 +74,34 @@ public class DataTypeExpr extends Expr {
   }
 
   public boolean isPrimitiveType() {
-    return !this.isRecordType() && !isMapType();
+    return !isArrayType()&& !isRecordType() && !isMapType();
+  }
+
+  public boolean isArrayType() {
+    return arrayType != null;
   }
 
   public boolean isRecordType() {
-    return this.typeName.equals(Type.RECORD.name());
+    return recordType != null;
   }
 
   public boolean isMapType() {
-    return this.typeName.equals(Type.MAP.name());
+    return mapType != null;
+  }
+
+  public DataTypeExpr getElementType() {
+    Preconditions.checkState(isArrayType());
+    return arrayType.type;
+  }
+
+  public DataTypeExpr getKeyType() {
+    Preconditions.checkState(isMapType());
+    return mapType.keyType;
+  }
+
+  public DataTypeExpr getValueType() {
+    Preconditions.checkState(isMapType());
+    return mapType.valueType;
   }
 
   public ColumnDefinition [] getNestedRecordTypes() {
@@ -125,6 +159,27 @@ public class DataTypeExpr extends Expr {
     return dataType;
   }
 
+  public static class ArrayType implements JsonSerializable, Cloneable {
+    @Expose
+    @SerializedName("type")
+    DataTypeExpr type;
+
+    public ArrayType(DataTypeExpr elementType) {
+      this.type = elementType;
+    }
+
+    @Override
+    public String toJson() {
+      return JsonHelper.toJson(this);
+    }
+
+    public Object clone() throws CloneNotSupportedException {
+      ArrayType newMap = (ArrayType) super.clone();
+      newMap.type = type;
+      return newMap;
+    }
+  }
+
   public static class RecordType implements JsonSerializable, Cloneable {
     @Expose @SerializedName("Schema")
     ColumnDefinition [] schema; // not null if the type is RECORD

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java b/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java
index b0acbb1..2c4d41e 100644
--- a/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java
+++ b/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/AbstractCatalogClient.java
@@ -32,6 +32,7 @@ import org.apache.tajo.exception.*;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.NullProto;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.ReturnState;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringListResponse;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.ProtoUtil;
 
 import java.io.Closeable;
@@ -281,7 +282,7 @@ public abstract class AbstractCatalogClient implements CatalogService, Closeable
 
   @Override
   public TableDesc getTableDesc(String qualifiedName) throws UndefinedTableException {
-    String[] splitted = CatalogUtil.splitFQTableName(qualifiedName);
+    String[] splitted = IdentifierUtil.splitFQTableName(qualifiedName);
     return getTableDesc(splitted[0], splitted[1]);
   }
 
@@ -596,7 +597,7 @@ public abstract class AbstractCatalogClient implements CatalogService, Closeable
   public void dropTable(String tableName)
       throws UndefinedDatabaseException, UndefinedTableException, InsufficientPrivilegeException {
 
-    String[] splitted = CatalogUtil.splitFQTableName(tableName);
+    String[] splitted = IdentifierUtil.splitFQTableName(tableName);
     final String databaseName = splitted[0];
     final String simpleName = splitted[1];
 
@@ -617,7 +618,7 @@ public abstract class AbstractCatalogClient implements CatalogService, Closeable
 
   @Override
   public final boolean existsTable(final String databaseName, final String tableName) {
-    if (CatalogUtil.isFQTableName(tableName)) {
+    if (IdentifierUtil.isFQTableName(tableName)) {
       throw new IllegalArgumentException(
           "tableName cannot be composed of multiple parts, but it is \"" + tableName + "\"");
     }
@@ -640,7 +641,7 @@ public abstract class AbstractCatalogClient implements CatalogService, Closeable
 
   @Override
   public final boolean existsTable(final String tableName) {
-    String[] splitted = CatalogUtil.splitFQTableName(tableName);
+    String[] splitted = IdentifierUtil.splitFQTableName(tableName);
     return existsTable(splitted[0], splitted[1]);
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/DataTypeUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/DataTypeUtil.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/DataTypeUtil.java
index 9cbdbe0..69206aa 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/DataTypeUtil.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/DataTypeUtil.java
@@ -87,8 +87,8 @@ public class DataTypeUtil {
    */
   public static org.apache.tajo.type.Type determineType(org.apache.tajo.type.Type left,
                                                         org.apache.tajo.type.Type right) {
-    TajoDataTypes.Type rhsBaseType = right.baseType();
-    switch (left.baseType()) {
+    TajoDataTypes.Type rhsBaseType = right.kind();
+    switch (left.kind()) {
 
     case INT1:
     case INT2:

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogConstants.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogConstants.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogConstants.java
index f2acf98..6acbc34 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogConstants.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogConstants.java
@@ -19,10 +19,6 @@
 package org.apache.tajo.catalog;
 
 public class CatalogConstants {
-  public final static String IDENTIFIER_DELIMITER_REGEXP = "\\.";
-  public final static String IDENTIFIER_DELIMITER = ".";
-  public final static String IDENTIFIER_QUOTE_STRING = "\"";
-  public final static int MAX_IDENTIFIER_LENGTH = 128;
   // Linux and BSD's max username length is 32. For compatibility with other systems, we should follow it.
   public final static int MAX_USERNAME_LENGTH = 32;
   public final static int MAX_STATEMENT_LENGTH = 128 * 1024;

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
index 2b20907..22dd5a4 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
@@ -18,12 +18,10 @@
 
 package org.apache.tajo.catalog;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.BuiltinStorages;
 import org.apache.tajo.DataTypeUtil;
-import org.apache.tajo.TajoConstants;
 import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.partition.PartitionDesc;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
@@ -35,6 +33,7 @@ import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.exception.InvalidOperationException;
 import org.apache.tajo.exception.UndefinedOperatorException;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageConstants;
 import org.apache.tajo.util.KeyValueSet;
 import org.apache.tajo.util.Pair;
@@ -51,233 +50,6 @@ import static org.apache.tajo.common.TajoDataTypes.Type;
 
 public class CatalogUtil {
 
-  /**
-   * Normalize an identifier. Normalization means a translation from a identifier to be a refined identifier name.
-   *
-   * Identifier can be composed of multiple parts as follows:
-   * <pre>
-   *   database_name.table_name.column_name
-   * </pre>
-   *
-   * Each regular identifier part can be composed alphabet ([a-z][A-Z]), number([0-9]), and underscore([_]).
-   * Also, the first letter must be an alphabet character.
-   *
-   * <code>normalizeIdentifier</code> normalizes each part of an identifier.
-   *
-   * In detail, for each part, it performs as follows:
-   * <ul>
-   *   <li>changing a part without double quotation to be lower case letters</li>
-   *   <li>eliminating double quotation marks from identifier</li>
-   * </ul>
-   *
-   * @param identifier The identifier to be normalized
-   * @return The normalized identifier
-   */
-  public static String normalizeIdentifier(String identifier) {
-    if (identifier == null || identifier.equals("")) {
-      return identifier;
-    }
-    String [] splitted = identifier.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP);
-
-    StringBuilder sb = new StringBuilder();
-    boolean first = true;
-    for (String part : splitted) {
-      if (first) {
-        first = false;
-      } else {
-        sb.append(CatalogConstants.IDENTIFIER_DELIMITER);
-      }
-      sb.append(normalizeIdentifierPart(part));
-    }
-    return sb.toString();
-  }
-
-  public static String normalizeIdentifierPart(String part) {
-    return isDelimited(part) ? stripQuote(part) : part.toLowerCase();
-  }
-
-  /**
-   * Denormalize an identifier. Denormalize means a translation from a stored identifier
-   * to be a printable identifier name.
-   *
-   * In detail, for each part, it performs as follows:
-   * <ul>
-   *   <li>changing a part including upper case character or non-ascii character to be lower case letters</li>
-   *   <li>eliminating double quotation marks from identifier</li>
-   * </ul>
-   *
-   * @param identifier The identifier to be normalized
-   * @return The denormalized identifier
-   */
-  public static String denormalizeIdentifier(String identifier) {
-    String [] splitted = identifier.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP);
-
-    StringBuilder sb = new StringBuilder();
-    boolean first = true;
-    for (String part : splitted) {
-      if (first) {
-        first = false;
-      } else {
-        sb.append(CatalogConstants.IDENTIFIER_DELIMITER);
-      }
-      sb.append(denormalizePart(part));
-    }
-    return sb.toString();
-  }
-
-  public static String denormalizePart(String identifier) {
-    if (isShouldBeQuoted(identifier)) {
-      return StringUtils.doubleQuote(identifier);
-    } else {
-      return identifier;
-    }
-  }
-
-  public static boolean isShouldBeQuoted(String columnName) {
-    for (char character : columnName.toCharArray()) {
-      if (Character.isUpperCase(character)) {
-        return true;
-      }
-
-      if (!StringUtils.isPartOfAnsiSQLIdentifier(character)) {
-        return true;
-      }
-
-      if (RESERVED_KEYWORDS_SET.contains(columnName.toUpperCase())) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  public static String stripQuote(String str) {
-    return str.substring(1, str.length() - 1);
-  }
-
-  public static boolean isDelimited(String identifier) {
-    boolean openQuote = identifier.charAt(0) == '"';
-    boolean closeQuote = identifier.charAt(identifier.length() - 1) == '"';
-
-    // if at least one quote mark exists, the identifier must be grater than equal to 2 characters,
-    if (openQuote ^ closeQuote && identifier.length() < 2) {
-      throw new IllegalArgumentException("Invalid Identifier: " + identifier);
-    }
-
-    // does not allow the empty identifier (''),
-    if (openQuote && closeQuote && identifier.length() == 2) {
-      throw new IllegalArgumentException("zero-length delimited identifier: " + identifier);
-    }
-
-    // Ensure the quote open and close
-    return openQuote && closeQuote;
-  }
-
-  /**
-   * True if a given name is a simple identifier, meaning is not a dot-chained name.
-   *
-   * @param columnOrTableName Column or Table name to be checked
-   * @return True if a given name is a simple identifier. Otherwise, it will return False.
-   */
-  public static boolean isSimpleIdentifier(String columnOrTableName) {
-    return columnOrTableName.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP).length == 1;
-  }
-
-  public static boolean isFQColumnName(String tableName) {
-    return tableName.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP).length == 3;
-  }
-
-  public static boolean isFQTableName(String tableName) {
-    int lastDelimiterIdx = tableName.lastIndexOf(CatalogConstants.IDENTIFIER_DELIMITER);
-    return lastDelimiterIdx > -1;
-  }
-
-  public static String [] splitFQTableName(String qualifiedName) {
-    String [] splitted = CatalogUtil.splitTableName(qualifiedName);
-    if (splitted.length == 1) {
-      throw new IllegalArgumentException("Table name is expected to be qualified, but was \""
-          + qualifiedName + "\".");
-    }
-    return splitted;
-  }
-
-  public static String [] splitTableName(String tableName) {
-    int lastDelimiterIdx = tableName.lastIndexOf(CatalogConstants.IDENTIFIER_DELIMITER);
-    if (lastDelimiterIdx > -1) {
-      return new String [] {
-          tableName.substring(0, lastDelimiterIdx),
-          tableName.substring(lastDelimiterIdx + 1, tableName.length())
-      };
-    } else {
-      return new String [] {tableName};
-    }
-  }
-
-  public static String buildFQName(String... identifiers) {
-    boolean first = true;
-    StringBuilder sb = new StringBuilder();
-    for(String id : identifiers) {
-      if (first) {
-        first = false;
-      } else {
-        sb.append(CatalogConstants.IDENTIFIER_DELIMITER);
-      }
-
-      sb.append(id);
-    }
-
-    return sb.toString();
-  }
-
-  public static Pair<String, String> separateQualifierAndName(String name) {
-    Preconditions.checkArgument(isFQTableName(name), "Must be a qualified name.");
-    return new Pair<>(extractQualifier(name), extractSimpleName(name));
-  }
-
-  /**
-   * Extract a qualification name from an identifier.
-   *
-   * For example, consider a table identifier like 'database1.table1'.
-   * In this case, this method extracts 'database1'.
-   *
-   * @param name The identifier to be extracted
-   * @return The extracted qualifier
-   */
-  public static String extractQualifier(String name) {
-    int lastDelimiterIdx = name.lastIndexOf(CatalogConstants.IDENTIFIER_DELIMITER);
-    if (lastDelimiterIdx > -1) {
-      return name.substring(0, lastDelimiterIdx);
-    } else {
-      return TajoConstants.EMPTY_STRING;
-    }
-  }
-
-  /**
-   * Extract a simple name from an identifier.
-   *
-   * For example, consider a table identifier like 'database1.table1'.
-   * In this case, this method extracts 'table1'.
-   *
-   * @param name The identifier to be extracted
-   * @return The extracted simple name
-   */
-  public static String extractSimpleName(String name) {
-    int lastDelimiterIdx = name.lastIndexOf(CatalogConstants.IDENTIFIER_DELIMITER);
-    if (lastDelimiterIdx > -1) {
-      // plus one means skipping a delimiter.
-      return name.substring(lastDelimiterIdx + 1, name.length());
-    } else {
-      return name;
-    }
-  }
-
-  public static String getCanonicalTableName(String databaseName, String tableName) {
-    StringBuilder sb = new StringBuilder(databaseName);
-    sb.append(CatalogConstants.IDENTIFIER_DELIMITER);
-    sb.append(tableName);
-    return sb.toString();
-  }
-
 
   public static String getBackwardCompitableDataFormat(String dataFormat) {
     return getDataFormatAsString(asDataFormat(dataFormat));
@@ -400,7 +172,7 @@ public class CatalogUtil {
   }
 
   public static String columnToDDLString(Column column) {
-    StringBuilder sb = new StringBuilder(denormalizeIdentifier(column.getSimpleName()));
+    StringBuilder sb = new StringBuilder(IdentifierUtil.denormalizeIdentifier(column.getSimpleName()));
     sb.append(" ").append(column.getDataType().getType());
     if (column.getDataType().hasLength()) {
       sb.append(" (").append(column.getDataType().getLength()).append(")");
@@ -738,32 +510,8 @@ public class CatalogUtil {
     }
   }
 
-  public static final Set<String> RESERVED_KEYWORDS_SET = new HashSet<>();
-
-  static final String [] RESERVED_KEYWORDS = {
-      "AS", "ALL", "AND", "ANY", "ASYMMETRIC", "ASC",
-      "BOTH",
-      "CASE", "CAST", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP",
-      "DESC", "DISTINCT",
-      "END", "ELSE", "EXCEPT",
-      "FALSE", "FULL", "FROM",
-      "GROUP",
-      "HAVING",
-      "ILIKE", "IN", "INNER", "INTERSECT", "INTO", "IS",
-      "JOIN",
-      "LEADING", "LEFT", "LIKE", "LIMIT",
-      "NATURAL", "NOT", "NULL",
-      "ON", "OUTER", "OR", "ORDER",
-      "RIGHT",
-      "SELECT", "SOME", "SYMMETRIC",
-      "TABLE", "THEN", "TRAILING", "TRUE",
-      "OVER",
-      "UNION", "UNIQUE", "USING",
-      "WHEN", "WHERE", "WINDOW", "WITH"
-  };
-
   static {
-    Collections.addAll(RESERVED_KEYWORDS_SET, RESERVED_KEYWORDS);
+    Collections.addAll(IdentifierUtil.RESERVED_KEYWORDS_SET, IdentifierUtil.RESERVED_KEYWORDS);
   }
 
   public static AlterTableDesc renameColumn(String tableName, String oldColumName, String newColumName,
@@ -1045,7 +793,7 @@ public class CatalogUtil {
   public static String getUnifiedSimpleColumnName(Schema originalSchema, String[] columnNames) {
     String[] simpleNames = new String[columnNames.length];
     for (int i = 0; i < simpleNames.length; i++) {
-      String[] identifiers = columnNames[i].split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP);
+      String[] identifiers = columnNames[i].split(IdentifierUtil.IDENTIFIER_DELIMITER_REGEXP);
       simpleNames[i] = identifiers[identifiers.length-1];
     }
     Arrays.sort(simpleNames, new ColumnPosComparator(originalSchema));

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
index 641b674..ddf0c83 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
@@ -26,24 +26,27 @@ import org.apache.tajo.common.ProtoObject;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.type.Type;
+import org.apache.tajo.type.TypeProtobufEncoder;
 
 /**
  * Describes a column. It is an immutable object.
  */
+@Deprecated
 public class Column implements ProtoObject<ColumnProto>, GsonObject {
 	@Expose protected String name;
-	@Expose protected TypeDesc typeDesc;
+  @Expose protected Type type;
 
   /**
    * Column Constructor
    *
    * @param name field name
-   * @param typeDesc Type description
+   * @param type Type description
    */
-  public Column(String name, TypeDesc typeDesc) {
+  public Column(String name, TypeDesc type) {
     this.name = name;
-    this.typeDesc = typeDesc;
+    this.type = TypeConverter.convert(type);
   }
 
   /**
@@ -70,22 +73,13 @@ public class Column implements ProtoObject<ColumnProto>, GsonObject {
    * @param type Type
    */
   public Column(String name, Type type) {
-    this(name, TypeConverter.convert(type));
-  }
-
-  /**
-   *
-   * @param name Column name
-   * @param type Data Type
-   * @param typeLength The length of type
-   */
-  public Column(String name, TajoDataTypes.Type type, int typeLength) {
-    this(name, CatalogUtil.newDataTypeWithLen(type, typeLength));
+    this.name = name;
+    this.type = type;
   }
 
 	public Column(ColumnProto proto) {
     name = proto.getName();
-    typeDesc = new TypeDesc(proto.getDataType());
+    type = TypeProtobufEncoder.decode(proto.getType());
 	}
 
   /**
@@ -93,7 +87,7 @@ public class Column implements ProtoObject<ColumnProto>, GsonObject {
    * @return True if a column includes a table name. Otherwise, it returns False.
    */
   public boolean hasQualifier() {
-    return name.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP).length > 1;
+    return name.split(IdentifierUtil.IDENTIFIER_DELIMITER_REGEXP).length > 1;
   }
 
   /**
@@ -109,7 +103,7 @@ public class Column implements ProtoObject<ColumnProto>, GsonObject {
    * @return The qualifier
    */
   public String getQualifier() {
-    return CatalogUtil.extractQualifier(name);
+    return IdentifierUtil.extractQualifier(name);
   }
 
   /**
@@ -117,7 +111,7 @@ public class Column implements ProtoObject<ColumnProto>, GsonObject {
    * @return The simple name without qualifications
    */
   public String getSimpleName() {
-    return CatalogUtil.extractSimpleName(name);
+    return IdentifierUtil.extractSimpleName(name);
   }
 
   /**
@@ -126,7 +120,14 @@ public class Column implements ProtoObject<ColumnProto>, GsonObject {
    * @return TypeDesc
    */
   public TypeDesc getTypeDesc() {
-    return this.typeDesc;
+    return TypeConverter.convert(this.type);
+  }
+
+  /**
+   * @return Type which includes domain type and scale.
+   */
+  public Type getType() {
+    return this.type;
   }
 
   /**
@@ -134,21 +135,20 @@ public class Column implements ProtoObject<ColumnProto>, GsonObject {
    * @return DataType which includes domain type and scale.
    */
 	public DataType getDataType() {
-		return this.typeDesc.dataType;
+		return TypeConverter.convert(this.type).getDataType();
 	}
 	
 	@Override
 	public boolean equals(Object o) {
 		if (o instanceof Column) {
 			Column another = (Column)o;
-			return name.equals(another.name) && typeDesc.equals(another.typeDesc);
+			return name.equals(another.name) && type.equals(another.type);
     }
 		return false;
 	}
 	
   public int hashCode() {
-    return Objects.hashCode(name, typeDesc);
-
+    return Objects.hashCode(name, type);
   }
 
   /**
@@ -160,13 +160,13 @@ public class Column implements ProtoObject<ColumnProto>, GsonObject {
     ColumnProto.Builder builder = ColumnProto.newBuilder();
     builder
         .setName(this.name)
-        .setDataType(this.typeDesc.getDataType());
+        .setType(this.type.getProto());
     return builder.build();
 	}
 	
 	public String toString() {
     StringBuilder sb = new StringBuilder(getQualifiedName());
-    sb.append(" (").append(typeDesc.toString()).append(")");
+    sb.append(" (").append(type.toString()).append(")");
 	  return sb.toString();
 	}
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/DDLBuilder.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/DDLBuilder.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/DDLBuilder.java
index e2250eb..387c669 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/DDLBuilder.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/DDLBuilder.java
@@ -21,6 +21,7 @@ package org.apache.tajo.catalog;
 import com.google.common.base.Function;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos.PartitionDescProto;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.util.KeyValueSet;
 import org.apache.tajo.util.StringUtils;
 
@@ -36,11 +37,11 @@ public class DDLBuilder {
     StringBuilder sb = new StringBuilder();
 
     sb.append("--\n")
-      .append("-- Name: ").append(CatalogUtil.denormalizeIdentifier(desc.getName())).append("; Type: TABLE;")
+      .append("-- Name: ").append(IdentifierUtil.denormalizeIdentifier(desc.getName())).append("; Type: TABLE;")
       .append(" Storage: ").append(desc.getMeta().getDataFormat());
     sb.append("\n-- Path: ").append(desc.getUri());
     sb.append("\n--\n");
-    sb.append("CREATE EXTERNAL TABLE ").append(CatalogUtil.denormalizeIdentifier(desc.getName()));
+    sb.append("CREATE EXTERNAL TABLE ").append(IdentifierUtil.denormalizeIdentifier(desc.getName()));
     buildSchema(sb, desc.getSchema());
     buildUsingClause(sb, desc.getMeta());
     buildWithClause(sb, desc.getMeta());
@@ -59,10 +60,10 @@ public class DDLBuilder {
     StringBuilder sb = new StringBuilder();
 
     sb.append("--\n")
-        .append("-- Name: ").append(CatalogUtil.denormalizeIdentifier(desc.getName())).append("; Type: TABLE;")
+        .append("-- Name: ").append(IdentifierUtil.denormalizeIdentifier(desc.getName())).append("; Type: TABLE;")
         .append(" Storage: ").append(desc.getMeta().getDataFormat());
     sb.append("\n--\n");
-    sb.append("CREATE TABLE ").append(CatalogUtil.denormalizeIdentifier(desc.getName()));
+    sb.append("CREATE TABLE ").append(IdentifierUtil.denormalizeIdentifier(desc.getName()));
     buildSchema(sb, desc.getSchema());
     buildUsingClause(sb, desc.getMeta());
     buildWithClause(sb, desc.getMeta());
@@ -79,11 +80,11 @@ public class DDLBuilder {
     StringBuilder sb = new StringBuilder();
 
     sb.append("--\n")
-        .append("-- Name: ").append(CatalogUtil.denormalizeIdentifier(desc.getName())).append("; Type: INDEX;")
+        .append("-- Name: ").append(IdentifierUtil.denormalizeIdentifier(desc.getName())).append("; Type: INDEX;")
         .append(" Index Method: ").append(desc.getIndexMethod());
     sb.append("\n--\n");
-    sb.append("CREATE INDEX ").append(CatalogUtil.denormalizeIdentifier(desc.getName()));
-    sb.append(" on ").append(CatalogUtil.denormalizeIdentifier(desc.getTableName())).append(" ( ");
+    sb.append("CREATE INDEX ").append(IdentifierUtil.denormalizeIdentifier(desc.getName()));
+    sb.append(" on ").append(IdentifierUtil.denormalizeIdentifier(desc.getTableName())).append(" ( ");
 
     for (SortSpec sortSpec : desc.getKeySortSpecs()) {
       sb.append(sortSpec.getSortKey().getQualifiedName()).append(" ");
@@ -108,7 +109,7 @@ public class DDLBuilder {
         sb.append(", ");
       }
 
-      sb.append(CatalogUtil.denormalizeIdentifier(column.getSimpleName())).append(" ");
+      sb.append(IdentifierUtil.denormalizeIdentifier(column.getSimpleName())).append(" ");
       TypeDesc typeDesc = column.getTypeDesc();
       sb.append(typeDesc);
     }
@@ -177,7 +178,7 @@ public class DDLBuilder {
    */
   public static String buildDDLForAddPartition(TableDesc table, PartitionDescProto partition) {
     StringBuilder sb = new StringBuilder();
-    sb.append("ALTER TABLE ").append(CatalogUtil.denormalizeIdentifier(table.getName()))
+    sb.append("ALTER TABLE ").append(IdentifierUtil.denormalizeIdentifier(table.getName()))
       .append(" ADD IF NOT EXISTS PARTITION (");
 
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FieldConverter.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FieldConverter.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FieldConverter.java
index 616b44e..1b34429 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FieldConverter.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FieldConverter.java
@@ -21,16 +21,12 @@ package org.apache.tajo.catalog;
 import com.google.common.base.Function;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
-import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.exception.NotImplementedException;
 import org.apache.tajo.exception.TajoRuntimeException;
+import org.apache.tajo.schema.Field;
 import org.apache.tajo.schema.Identifier;
-import org.apache.tajo.schema.IdentifierPolicy;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.schema.QualifiedIdentifier;
-import org.apache.tajo.schema.Schema;
-import org.apache.tajo.schema.Schema.NamedPrimitiveType;
-import org.apache.tajo.schema.Schema.NamedStructType;
-import org.apache.tajo.type.*;
 
 import javax.annotation.Nullable;
 import java.util.Collection;
@@ -42,58 +38,20 @@ public class FieldConverter {
     final Collection<Identifier> identifiers = Collections2.transform(elems, new Function<String, Identifier>() {
       @Override
       public Identifier apply(@Nullable String input) {
-        boolean needQuote = CatalogUtil.isShouldBeQuoted(input);
-        return Identifier._(input, needQuote);
+        return Identifier._(input, IdentifierUtil.isShouldBeQuoted(input));
       }
     });
     return QualifiedIdentifier.$(identifiers);
   }
 
-  public static TypeDesc convert(Schema.NamedType src) {
-    if (src instanceof NamedStructType) {
-      NamedStructType structType = (NamedStructType) src;
-
-      ImmutableList.Builder<Column> fields = ImmutableList.builder();
-      for (Schema.NamedType t: structType.fields()) {
-        fields.add(new Column(t.name().raw(IdentifierPolicy.DefaultPolicy()), convert(t)));
-      }
-
-      return new TypeDesc(SchemaBuilder.builder().addAll(fields.build()).build());
-    } else {
-      final NamedPrimitiveType namedType = (NamedPrimitiveType) src;
-      final Type type = namedType.type();
-      if (type instanceof Char) {
-        Char charType = (Char) type;
-        return new TypeDesc(CatalogUtil.newDataTypeWithLen(TajoDataTypes.Type.CHAR, charType.length()));
-      } else if (type instanceof Varchar) {
-        Varchar varcharType = (Varchar) type;
-        return new TypeDesc(CatalogUtil.newDataTypeWithLen(TajoDataTypes.Type.VARCHAR, varcharType.length()));
-      } else if (type instanceof Numeric) {
-        Numeric numericType = (Numeric) type;
-        return new TypeDesc(CatalogUtil.newDataTypeWithLen(TajoDataTypes.Type.NUMERIC, numericType.precision()));
-      } else if (type instanceof Protobuf) {
-        Protobuf protobuf = (Protobuf) type;
-        return new TypeDesc(CatalogUtil.newDataType(TajoDataTypes.Type.PROTOBUF, protobuf.getMessageName()));
-      } else {
-        return new TypeDesc(TypeConverter.convert(namedType.type()));
-      }
+  public static Field convert(Column column) {
+    if (column.type.isStruct() && column.getTypeDesc().getNestedSchema() == null) {
+      throw new TajoRuntimeException(new NotImplementedException("record type projection"));
     }
+    return new Field(toQualifiedIdentifier(column.getQualifiedName()), column.type);
   }
 
-  public static Schema.NamedType convert(Column column) {
-    if (column.getTypeDesc().getDataType().getType() == TajoDataTypes.Type.RECORD) {
-
-      if (column.getTypeDesc().getNestedSchema() == null) {
-        throw new TajoRuntimeException(new NotImplementedException("record type projection"));
-      }
-
-      return new NamedStructType(toQualifiedIdentifier(column.getQualifiedName()),
-          TypeConverter.convert(column.getTypeDesc()));
-
-    } else {
-      return new NamedPrimitiveType(toQualifiedIdentifier(column.getQualifiedName()),
-          TypeConverter.convert(column.getDataType())
-      );
-    }
+  public static Column convert(Field field) {
+    return new Column(field.name().interned(), field.type());
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/ListSchemaBuilder.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/ListSchemaBuilder.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/ListSchemaBuilder.java
index e0c9d9e..8f77489 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/ListSchemaBuilder.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/ListSchemaBuilder.java
@@ -20,30 +20,30 @@ package org.apache.tajo.catalog;
 
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
-import org.apache.tajo.schema.Schema.NamedType;
+import org.apache.tajo.schema.Field;
 
 import java.util.Iterator;
 
 public class ListSchemaBuilder implements SchemaBuilder.SchemaCollector {
-  private final ImmutableList.Builder<NamedType> fields = new ImmutableList.Builder();
+  private final ImmutableList.Builder<Field> fields = new ImmutableList.Builder();
 
   @Override
-  public void add(NamedType namedType) {
-    fields.add(namedType);
+  public void add(Field field) {
+    fields.add(field);
   }
 
   @Override
-  public void addAll(Iterator<NamedType> fields) {
+  public void addAll(Iterator<Field> fields) {
     this.fields.addAll(fields);
   }
 
   @Override
-  public void addAll(Iterable<NamedType> fields) {
+  public void addAll(Iterable<Field> fields) {
     this.fields.addAll(fields);
   }
 
   @Override
-  public ImmutableCollection<NamedType> build() {
+  public ImmutableCollection<Field> build() {
     return fields.build();
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/NestedPathUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/NestedPathUtil.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/NestedPathUtil.java
index bf874b9..afe7e31 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/NestedPathUtil.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/NestedPathUtil.java
@@ -73,7 +73,7 @@ public class NestedPathUtil {
     Column found = null;
 
     if (currentColumn.getDataType().getType() == Type.RECORD) {
-      found = currentColumn.typeDesc.nestedRecordSchema.getColumn(paths[depth]);
+      found = TypeConverter.convert(currentColumn.type).nestedRecordSchema.getColumn(paths[depth]);
     }
 
     if (found != null) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaBuilder.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaBuilder.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaBuilder.java
index 35e38b5..582b5ee 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaBuilder.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaBuilder.java
@@ -22,18 +22,14 @@ import com.google.common.base.Function;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
 import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.schema.Field;
 import org.apache.tajo.schema.QualifiedIdentifier;
-import org.apache.tajo.schema.Schema.NamedPrimitiveType;
-import org.apache.tajo.schema.Schema.NamedStructType;
-import org.apache.tajo.schema.Schema.NamedType;
 import org.apache.tajo.type.Type;
 
 import javax.annotation.Nullable;
-import java.util.Collection;
 import java.util.Iterator;
 
 import static org.apache.tajo.catalog.FieldConverter.toQualifiedIdentifier;
-import static org.apache.tajo.schema.IdentifierPolicy.DefaultPolicy;
 
 /**
  * Builder for Schema
@@ -42,10 +38,10 @@ public class SchemaBuilder {
   private final SchemaCollector fields;
 
   public interface SchemaCollector {
-    void add(NamedType field);
-    void addAll(Iterator<NamedType> fields);
-    void addAll(Iterable<NamedType> fields);
-    ImmutableCollection<NamedType> build();
+    void add(Field field);
+    void addAll(Iterator<Field> fields);
+    void addAll(Iterable<Field> fields);
+    ImmutableCollection<Field> build();
   }
 
   public static SchemaLegacy empty() {
@@ -64,28 +60,19 @@ public class SchemaBuilder {
     this.fields = collector;
   }
 
-  public SchemaBuilder add(NamedType namedType) {
-    fields.add(namedType);
+  public SchemaBuilder add(Field field) {
+    fields.add(field);
     return this;
   }
 
   public SchemaBuilder add(QualifiedIdentifier id, Type type) {
-    add(new NamedPrimitiveType(id, type));
-    return this;
-  }
-
-  public SchemaBuilder addStruct(QualifiedIdentifier id, Collection<NamedType> fields) {
-    add(new NamedStructType(id, fields));
+    add(new Field(id, type));
     return this;
   }
 
   @Deprecated
   public SchemaBuilder add(String name, TypeDesc legacyType) {
-    if (legacyType.getDataType().getType() == TajoDataTypes.Type.RECORD) {
-      addStruct(toQualifiedIdentifier(name), TypeConverter.convert(legacyType));
-    } else {
-      add(toQualifiedIdentifier(name), TypeConverter.convert(legacyType.getDataType()));
-    }
+    add(toQualifiedIdentifier(name), TypeConverter.convert(legacyType));
     return this;
   }
 
@@ -109,9 +96,9 @@ public class SchemaBuilder {
 
   @Deprecated
   public SchemaBuilder addAll(Iterable<Column> columns) {
-    return addAll2(columns, new Function<Column, NamedType>() {
+    return addAll2(columns, new Function<Column, Field>() {
       @Override
-      public NamedType apply(@Nullable Column input) {
+      public Field apply(@Nullable Column input) {
         return FieldConverter.convert(input);
       }
     });
@@ -119,9 +106,9 @@ public class SchemaBuilder {
 
   @Deprecated
   public SchemaBuilder addAll(Column [] columns) {
-    return addAll2(columns, new Function<Column, NamedType>() {
+    return addAll2(columns, new Function<Column, Field>() {
       @Override
-      public NamedType apply(@Nullable Column input) {
+      public Field apply(@Nullable Column input) {
         return FieldConverter.convert(input);
       }
     });
@@ -152,21 +139,26 @@ public class SchemaBuilder {
     return this;
   }
 
-  public <T> SchemaBuilder addAll2(T [] fields, Function<T, NamedType> fn) {
+  public SchemaBuilder addAll2(Iterable<Field> fields) {
+    this.fields.addAll(fields);
+    return this;
+  }
+
+  public <T> SchemaBuilder addAll2(T [] fields, Function<T, Field> fn) {
     for (T t : fields) {
       add(fn.apply(t));
     }
     return this;
   }
 
-  public <T> SchemaBuilder addAll2(Iterable<T> fields, Function<T, NamedType> fn) {
+  public <T> SchemaBuilder addAll2(Iterable<T> fields, Function<T, Field> fn) {
     for (T t : fields) {
       add(fn.apply(t));
     }
     return this;
   }
 
-  public <T> SchemaBuilder addAll2(Iterator<T> fields, Function<T, NamedType> fn) {
+  public <T> SchemaBuilder addAll2(Iterator<T> fields, Function<T, Field> fn) {
     while(fields.hasNext()) {
       T t = fields.next();
       add(fn.apply(t));
@@ -177,8 +169,8 @@ public class SchemaBuilder {
   @Deprecated
   public SchemaLegacy build() {
     ImmutableList.Builder<Column> columns = new ImmutableList.Builder();
-    for (NamedType namedType : fields.build()) {
-      columns.add(new Column(namedType.name().raw(DefaultPolicy()), FieldConverter.convert(namedType)));
+    for (Field field : fields.build()) {
+      columns.add(new Column(field.name().interned(), field.type()));
     }
 
     return new SchemaLegacy(columns.build());

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaLegacy.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaLegacy.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaLegacy.java
index 2a16fa6..db1e566 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaLegacy.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaLegacy.java
@@ -18,23 +18,27 @@
 
 package org.apache.tajo.catalog;
 
+import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.SchemaUtil.ColumnVisitor;
 import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.ColumnProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.SchemaProto;
 import org.apache.tajo.common.ProtoObject;
-import org.apache.tajo.common.TajoDataTypes.DataType;
-import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.exception.DuplicateColumnException;
 import org.apache.tajo.exception.TajoRuntimeException;
 import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.util.StringUtils;
 
+import javax.annotation.Nullable;
 import java.util.*;
 
+import static com.google.common.collect.Collections2.transform;
+
+@Deprecated
 public class SchemaLegacy implements Schema, ProtoObject<SchemaProto>, Cloneable, GsonObject {
 
 	@Expose protected List<Column> fields = null;
@@ -55,47 +59,18 @@ public class SchemaLegacy implements Schema, ProtoObject<SchemaProto>, Cloneable
 	public SchemaLegacy(SchemaProto proto) {
     init();
 
-    List<Column> toBeAdded = new ArrayList<>();
-    for (int i = 0; i < proto.getFieldsCount(); i++) {
-      deserializeColumn(toBeAdded, proto.getFieldsList(), i);
-    }
+    Collection<Column> toBeAdded = transform(proto.getFieldsList(), new Function<ColumnProto, Column>() {
+      @Override
+      public Column apply(@Nullable ColumnProto proto) {
+        return new Column(proto);
+      }
+    });
 
     for (Column c : toBeAdded) {
       addColumn(c);
     }
   }
 
-  /**
-   * This method transforms a list of ColumnProtos into a schema tree.
-   * It assumes that <code>protos</code> contains a list of ColumnProtos in the depth-first order.
-   *
-   * @param tobeAdded
-   * @param protos
-   * @param serializedColumnIndex
-   */
-  private static void deserializeColumn(List<Column> tobeAdded, List<ColumnProto> protos, int serializedColumnIndex) {
-    ColumnProto columnProto = protos.get(serializedColumnIndex);
-    if (columnProto.getDataType().getType() == Type.RECORD) {
-
-      // Get the number of child fields
-      int childNum = columnProto.getDataType().getNumNestedFields();
-      // where is start index of nested fields?
-      int childStartIndex = tobeAdded.size() - childNum;
-      // Extract nested fields
-      List<Column> nestedColumns = new ArrayList<>(tobeAdded.subList(childStartIndex, childStartIndex + childNum));
-
-      // Remove nested fields from the the current level
-      for (int i = 0; i < childNum; i++) {
-        tobeAdded.remove(tobeAdded.size() - 1);
-      }
-
-      // Add the nested fields to the list as a single record column
-      tobeAdded.add(new Column(columnProto.getName(), new TypeDesc(new SchemaLegacy(nestedColumns))));
-    } else {
-      tobeAdded.add(new Column(protos.get(serializedColumnIndex)));
-    }
-  }
-
 	public SchemaLegacy(Schema schema) {
 	  new SchemaLegacy(schema.getRootColumns());
 	}
@@ -139,7 +114,7 @@ public class SchemaLegacy implements Schema, ProtoObject<SchemaProto>, Cloneable
 
     Column newColumn;
     for (Column c : columns) {
-      newColumn = new Column(qualifier + "." + c.getSimpleName(), c.typeDesc);
+      newColumn = new Column(qualifier + "." + c.getSimpleName(), c.type);
       addColumn(newColumn);
     }
   }
@@ -200,7 +175,7 @@ public class SchemaLegacy implements Schema, ProtoObject<SchemaProto>, Cloneable
 
       Column columnPath = new Column(
           column.getQualifiedName() + NestedPathUtil.makePath(paths, 1),
-          actualColumn.typeDesc);
+          actualColumn.type);
 
       return columnPath;
     } else {
@@ -424,13 +399,13 @@ public class SchemaLegacy implements Schema, ProtoObject<SchemaProto>, Cloneable
     return false;
   }
 
-  private SchemaLegacy addColumn(String name, TypeDesc typeDesc) {
+  private SchemaLegacy addColumn(String name, org.apache.tajo.type.Type type) {
     String normalized = name;
     if(fieldsByQualifiedName.containsKey(normalized)) {
       throw new TajoRuntimeException(new DuplicateColumnException(normalized));
     }
 
-    Column newCol = new Column(normalized, typeDesc);
+    Column newCol = new Column(normalized, type);
     fields.add(newCol);
     fieldsByQualifiedName.put(newCol.getQualifiedName(), fields.size() - 1);
     List<Integer> inputList = new ArrayList<>();
@@ -441,7 +416,7 @@ public class SchemaLegacy implements Schema, ProtoObject<SchemaProto>, Cloneable
   }
 
 	private synchronized void addColumn(Column column) {
-		addColumn(column.getQualifiedName(), column.typeDesc);
+		addColumn(column.getQualifiedName(), column.type);
 	}
 
   @Override
@@ -472,34 +447,15 @@ public class SchemaLegacy implements Schema, ProtoObject<SchemaProto>, Cloneable
 	@Override
 	public SchemaProto getProto() {
     SchemaProto.Builder builder = SchemaProto.newBuilder();
-    SchemaProtoBuilder recursiveBuilder = new SchemaProtoBuilder(builder);
-    SchemaUtil.visitSchema(this, recursiveBuilder);
+    builder.addAllFields(Iterables.transform(getRootColumns(), new Function<Column, ColumnProto>() {
+      @Override
+      public ColumnProto apply(@Nullable Column column) {
+        return column.getProto();
+      }
+    }));
     return builder.build();
 	}
 
-  private static class SchemaProtoBuilder implements ColumnVisitor {
-    private SchemaProto.Builder builder;
-    public SchemaProtoBuilder(SchemaProto.Builder builder) {
-      this.builder = builder;
-    }
-
-    @Override
-    public void visit(int depth, List<String> path, Column column) {
-
-      if (column.getDataType().getType() == Type.RECORD) {
-        DataType.Builder updatedType = DataType.newBuilder(column.getDataType());
-        updatedType.setNumNestedFields(column.typeDesc.nestedRecordSchema.size());
-
-        ColumnProto.Builder updatedColumn = ColumnProto.newBuilder(column.getProto());
-        updatedColumn.setDataType(updatedType);
-
-        builder.addFields(updatedColumn.build());
-      } else {
-        builder.addFields(column.getProto());
-      }
-    }
-  }
-
   @Override
 	public String toString() {
 	  StringBuilder sb = new StringBuilder();

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaUtil.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaUtil.java
index c0b60a3..fc6d353 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaUtil.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SchemaUtil.java
@@ -185,7 +185,7 @@ public class SchemaUtil {
                                              Column column) {
 
     if (column.getDataType().getType() == Type.RECORD) {
-      for (Column nestedColumn : column.typeDesc.nestedRecordSchema.getRootColumns()) {
+      for (Column nestedColumn : TypeConverter.convert(column.type).nestedRecordSchema.getRootColumns()) {
         List<String> newPath = new ArrayList<>(path);
         newPath.add(column.getQualifiedName());
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SetSchemaBuilder.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SetSchemaBuilder.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SetSchemaBuilder.java
index b66aac2..4a4099e 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SetSchemaBuilder.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/SetSchemaBuilder.java
@@ -20,47 +20,41 @@ package org.apache.tajo.catalog;
 
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
-import org.apache.commons.collections.collection.UnmodifiableCollection;
-import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.schema.QualifiedIdentifier;
-import org.apache.tajo.schema.Schema.NamedPrimitiveType;
-import org.apache.tajo.schema.Schema.NamedStructType;
-import org.apache.tajo.schema.Schema.NamedType;
-import org.apache.tajo.type.Type;
+import org.apache.tajo.schema.Field;
 
-import java.util.*;
-
-import static org.apache.tajo.catalog.FieldConverter.toQualifiedIdentifier;
-import static org.apache.tajo.schema.IdentifierPolicy.DefaultPolicy;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
 
 public class SetSchemaBuilder implements SchemaBuilder.SchemaCollector {
   private final Set<QualifiedIdentifier> nameSet = new HashSet<>();
-  private final ImmutableList.Builder<NamedType> fields = new ImmutableList.Builder();
+  private final ImmutableList.Builder<Field> fields = new ImmutableList.Builder();
 
   @Override
-  public void add(NamedType namedType) {
-    if (!nameSet.contains(namedType.name())) {
-      fields.add(namedType);
-      nameSet.add(namedType.name());
+  public void add(Field field) {
+    if (!nameSet.contains(field.name())) {
+      fields.add(field);
+      nameSet.add(field.name());
     }
   }
 
   @Override
-  public void addAll(Iterator<NamedType> fields) {
+  public void addAll(Iterator<Field> fields) {
     while (fields.hasNext()) {
       add(fields.next());
     }
   }
 
   @Override
-  public void addAll(Iterable<NamedType> fields) {
-    for (NamedType n : fields) {
+  public void addAll(Iterable<Field> fields) {
+    for (Field n : fields) {
       add(n);
     }
   }
 
   @Override
-  public ImmutableCollection<NamedType> build() {
+  public ImmutableCollection<Field> build() {
     return fields.build();
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TypeConverter.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TypeConverter.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TypeConverter.java
index f4164d4..387cf00 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TypeConverter.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TypeConverter.java
@@ -20,66 +20,25 @@ package org.apache.tajo.catalog;
 
 import com.google.common.collect.ImmutableList;
 import org.apache.tajo.common.TajoDataTypes;
-import org.apache.tajo.exception.NotImplementedException;
-import org.apache.tajo.exception.TajoRuntimeException;
-import org.apache.tajo.exception.UnsupportedException;
-import org.apache.tajo.schema.Schema;
+import org.apache.tajo.schema.Field;
 import org.apache.tajo.type.*;
 
-import java.util.Collection;
-
+import static org.apache.tajo.catalog.CatalogUtil.newDataTypeWithLen;
+import static org.apache.tajo.catalog.CatalogUtil.newSimpleDataType;
+import static org.apache.tajo.common.TajoDataTypes.Type.*;
 import static org.apache.tajo.type.Type.*;
 
 public class TypeConverter {
 
-  public static Collection<Schema.NamedType> convert(TypeDesc type) {
-    ImmutableList.Builder<Schema.NamedType> fields = ImmutableList.builder();
-    for (Column c : type.getNestedSchema().getRootColumns()) {
-      fields.add(FieldConverter.convert(c));
-    }
-    return fields.build();
-  }
-
-  public static Type convert(TajoDataTypes.Type legacyBaseType) {
-    switch (legacyBaseType) {
-    case BOOLEAN:
-      return Bool;
-    case INT1:
-      return Int1;
-    case INT2:
-      return Int2;
-    case INT4:
-      return Int4;
-    case INT8:
-      return Int8;
-    case FLOAT4:
-      return Float4;
-    case FLOAT8:
-      return Float8;
-    case DATE:
-      return Date;
-    case TIME:
-      return Time;
-    case TIMESTAMP:
-      return Timestamp;
-    case INTERVAL:
-      return Interval;
-    case CHAR:
-      return Char(1); // default len = 1
-    case TEXT:
-      return Text;
-    case BLOB:
-      return Blob;
-    case INET4:
-      return Inet4;
-    case RECORD:
-      throw new TajoRuntimeException(new NotImplementedException("record projection"));
-    case NULL_TYPE:
-      return Null;
-    case ANY:
-      return Any;
-    default:
-      throw new TajoRuntimeException(new UnsupportedException(legacyBaseType.name()));
+  public static Type convert(TypeDesc type) {
+    if (type.getDataType().getType() == TajoDataTypes.Type.RECORD) {
+      ImmutableList.Builder<Field> fields = ImmutableList.builder();
+      for (Column c : type.getNestedSchema().getRootColumns()) {
+        fields.add(FieldConverter.convert(c));
+      }
+      return Record(fields.build());
+    } else {
+      return convert(type.dataType);
     }
   }
 
@@ -96,26 +55,58 @@ public class TypeConverter {
     case PROTOBUF:
       return new Protobuf(legacyType.getCode());
     default:
-      return convert(legacyType.getType());
+      return TypeFactory.create(legacyType.getType());
     }
   }
 
-  public static TajoDataTypes.DataType convert(Type type) {
-    switch (type.baseType()) {
-      case CHAR:
-        Char charType = (Char) type;
-        return CatalogUtil.newDataTypeWithLen(TajoDataTypes.Type.CHAR, charType.length());
-      case VARCHAR:
-        Varchar varcharType = (Varchar) type;
-        return CatalogUtil.newDataTypeWithLen(TajoDataTypes.Type.VARCHAR, varcharType.length());
-      case PROTOBUF:
-        Protobuf protobuf = (Protobuf) type;
-        return CatalogUtil.newDataType(TajoDataTypes.Type.PROTOBUF, protobuf.getMessageName());
-      case NUMERIC:
-        Numeric numericType = (Numeric) type;
-        return CatalogUtil.newDataTypeWithLen(TajoDataTypes.Type.NUMERIC, numericType.precision());
+  public static TypeDesc convert(Field src) {
+    return convert(src.type());
+  }
+
+  public static TypeDesc convert(Type type) {
+    switch (type.kind()) {
+    case CHAR:
+      Char charType = (Char) type;
+      return new TypeDesc(newDataTypeWithLen(TajoDataTypes.Type.CHAR, charType.length()));
+    case VARCHAR:
+      Varchar varcharType = (Varchar) type;
+      return new TypeDesc(newDataTypeWithLen(TajoDataTypes.Type.VARCHAR, varcharType.length()));
+    case NUMERIC:
+      Numeric numericType = (Numeric) type;
+      return new TypeDesc(newDataTypeWithLen(TajoDataTypes.Type.NUMERIC, numericType.precision()));
+    case PROTOBUF:
+      Protobuf protobuf = (Protobuf) type;
+      return new TypeDesc(CatalogUtil.newDataType(TajoDataTypes.Type.PROTOBUF, protobuf.getMessageName()));
+    case RECORD:
+      Record record = (Record) type;
+      ImmutableList.Builder<Column> fields = ImmutableList.builder();
+      for (Field t: record.fields()) {
+        fields.add(new Column(t.name().interned(), convert(t)));
+      }
+      return new TypeDesc(SchemaBuilder.builder().addAll(fields.build()).build());
+
+    case ARRAY:
+      Array array = (Array) type;
+      Type elemType = array.elementType();
+      switch (elemType.kind()) {
+      case INT1:
+        return new TypeDesc(newSimpleDataType(INT1_ARRAY));
+      case INT2:
+        return new TypeDesc(newSimpleDataType(INT2_ARRAY));
+      case INT4:
+        return new TypeDesc(newSimpleDataType(INT4_ARRAY));
+      case INT8:
+        return new TypeDesc(newSimpleDataType(INT8_ARRAY));
+      case FLOAT4:
+        return new TypeDesc(newSimpleDataType(FLOAT4_ARRAY));
+      case FLOAT8:
+        return new TypeDesc(newSimpleDataType(FLOAT8_ARRAY));
       default:
-        return CatalogUtil.newSimpleDataType(type.baseType());
+        return new TypeDesc(newSimpleDataType(type.kind()));
+      }
+
+    default:
+      return new TypeDesc(newSimpleDataType(type.kind()));
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
index c145ecd..27c2309 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/json/CatalogGsonHelper.java
@@ -48,6 +48,7 @@ public class CatalogGsonHelper {
     adapters.put(Datum.class, new DatumAdapter());
     adapters.put(DataType.class, new DataTypeAdapter());
     adapters.put(Schema.class, new SchemaAdapter());
+    adapters.put(org.apache.tajo.type.Type.class, new TypeAdapter());
     return adapters;
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStats.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStats.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStats.java
index c66500d..47acb50 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStats.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/statistics/TableStats.java
@@ -26,6 +26,7 @@ import com.google.gson.Gson;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.TypeProto;
 import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableStatsProto;
@@ -35,6 +36,8 @@ import org.apache.tajo.util.TUtil;
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.apache.tajo.common.TajoDataTypes.Type.PROTOBUF;
+
 public class TableStats implements ProtoObject<TableStatsProto>, Cloneable, GsonObject {
   @Expose private Long numRows = null; // required
   @Expose private Long numBytes = null; // required
@@ -85,13 +88,17 @@ public class TableStats implements ProtoObject<TableStatsProto>, Cloneable, Gson
 
     this.columnStatses = new ArrayList<>();
     for (CatalogProtos.ColumnStatsProto colProto : proto.getColStatList()) {
-      if (colProto.getColumn().getDataType().getType() == TajoDataTypes.Type.PROTOBUF) {
+      if (peekType(colProto.getColumn().getType()) == PROTOBUF) {
         continue;
       }
       columnStatses.add(new ColumnStats(colProto));
     }
   }
 
+  private static TajoDataTypes.Type peekType(TypeProto proto) {
+    return proto.getElements(proto.getElementsCount() - 1).getKind();
+  }
+
   public Long getNumRows() {
     return this.numRows;
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto b/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
index d064c62..e79bc75 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
+++ b/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
@@ -66,7 +66,7 @@ enum AlterTableType {
 message ColumnProto {
   required string name = 1;
   optional int32 tid = 2;
-  required DataType data_type = 3;
+  required TypeProto type = 3;
 }
 
 message SchemaProto {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
index 0a7fd0a..c09909a 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
@@ -20,6 +20,7 @@ package org.apache.tajo.catalog;
 
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.function.FunctionUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -51,7 +52,7 @@ public class TestCatalogUtil {
   @Test
   public final void testNormalizeIdentifier() {
     for (int i = 0; i < sources.length; i++) {
-      assertEquals(normalized[i], CatalogUtil.normalizeIdentifier(sources[i]));
+      assertEquals(normalized[i], IdentifierUtil.normalizeIdentifier(sources[i]));
     }
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogStore.java b/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogStore.java
index 6aa0585..b855c77 100644
--- a/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogStore.java
+++ b/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogStore.java
@@ -57,7 +57,9 @@ import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.exception.*;
 import org.apache.tajo.plan.expr.AlgebraicUtil;
 import org.apache.tajo.plan.util.PartitionFilterAlgebraVisitor;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageConstants;
+import org.apache.tajo.type.TypeProtobufEncoder;
 import org.apache.tajo.util.KeyValueSet;
 import org.apache.thrift.TException;
 
@@ -165,8 +167,8 @@ public class HiveCatalogStore extends CatalogConstants implements CatalogStore {
         }
 
         if (!isPartitionKey) {
-          String fieldName = databaseName + CatalogConstants.IDENTIFIER_DELIMITER + tableName +
-              CatalogConstants.IDENTIFIER_DELIMITER + eachField.getName();
+          String fieldName = databaseName + IdentifierUtil.IDENTIFIER_DELIMITER + tableName +
+              IdentifierUtil.IDENTIFIER_DELIMITER + eachField.getName();
           TajoDataTypes.Type dataType = HiveCatalogUtil.getTajoFieldType(eachField.getType());
           schemaBuilder.add(fieldName, dataType);
         }
@@ -246,8 +248,8 @@ public class HiveCatalogStore extends CatalogConstants implements CatalogStore {
           for (int i = 0; i < partitionKeys.size(); i++) {
             FieldSchema fieldSchema = partitionKeys.get(i);
             TajoDataTypes.Type dataType = HiveCatalogUtil.getTajoFieldType(fieldSchema.getType());
-            String fieldName = databaseName + CatalogConstants.IDENTIFIER_DELIMITER + tableName +
-                CatalogConstants.IDENTIFIER_DELIMITER + fieldSchema.getName();
+            String fieldName = databaseName + IdentifierUtil.IDENTIFIER_DELIMITER + tableName +
+                IdentifierUtil.IDENTIFIER_DELIMITER + fieldSchema.getName();
             expressionSchema.add(new Column(fieldName, dataType));
             if (i > 0) {
               sb.append(",");
@@ -421,7 +423,7 @@ public class HiveCatalogStore extends CatalogConstants implements CatalogStore {
     HiveCatalogStoreClientPool.HiveCatalogStoreClient client = null;
 
     TableDesc tableDesc = new TableDesc(tableDescProto);
-    String[] splitted = CatalogUtil.splitFQTableName(tableDesc.getName());
+    String[] splitted = IdentifierUtil.splitFQTableName(tableDesc.getName());
     String databaseName = splitted[0];
     String tableName = splitted[1];
 
@@ -460,7 +462,7 @@ public class HiveCatalogStore extends CatalogConstants implements CatalogStore {
 
       for (Column eachField : columns) {
         cols.add(new FieldSchema(eachField.getSimpleName(),
-            HiveCatalogUtil.getHiveFieldType(eachField.getDataType()), ""));
+            HiveCatalogUtil.getHiveFieldType(eachField.getType()), ""));
       }
       sd.setCols(cols);
 
@@ -469,7 +471,7 @@ public class HiveCatalogStore extends CatalogConstants implements CatalogStore {
         List<FieldSchema> partitionKeys = new ArrayList<>();
         for (Column eachPartitionKey : tableDesc.getPartitionMethod().getExpressionSchema().getRootColumns()) {
           partitionKeys.add(new FieldSchema(eachPartitionKey.getSimpleName(),
-              HiveCatalogUtil.getHiveFieldType(eachPartitionKey.getDataType()), ""));
+              HiveCatalogUtil.getHiveFieldType(eachPartitionKey.getType()), ""));
         }
         table.setPartitionKeys(partitionKeys);
       }
@@ -605,7 +607,7 @@ public class HiveCatalogStore extends CatalogConstants implements CatalogStore {
       throws DuplicateTableException, DuplicateColumnException, DuplicatePartitionException,
       UndefinedPartitionException {
 
-    final String[] split = CatalogUtil.splitFQTableName(alterTableDescProto.getTableName());
+    final String[] split = IdentifierUtil.splitFQTableName(alterTableDescProto.getTableName());
 
     if (split.length == 1) {
       throw new IllegalArgumentException("alterTable() requires a qualified table name, but it is \""
@@ -713,7 +715,7 @@ public class HiveCatalogStore extends CatalogConstants implements CatalogStore {
       Table table = client.getHiveClient().getTable(databaseName, tableName);
       List<FieldSchema> columns = table.getSd().getCols();
       columns.add(new FieldSchema(columnProto.getName(),
-        HiveCatalogUtil.getHiveFieldType(columnProto.getDataType()), ""));
+        HiveCatalogUtil.getHiveFieldType(TypeProtobufEncoder.decode(columnProto.getType())), ""));
       client.getHiveClient().alter_table(databaseName, tableName, table);
 
 
@@ -812,8 +814,8 @@ public class HiveCatalogStore extends CatalogConstants implements CatalogStore {
           for (int i = 0; i < partitionKeys.size(); i++) {
             FieldSchema fieldSchema = partitionKeys.get(i);
             TajoDataTypes.Type dataType = HiveCatalogUtil.getTajoFieldType(fieldSchema.getType());
-            String fieldName = databaseName + CatalogConstants.IDENTIFIER_DELIMITER + tableName +
-                CatalogConstants.IDENTIFIER_DELIMITER + fieldSchema.getName();
+            String fieldName = databaseName + IdentifierUtil.IDENTIFIER_DELIMITER + tableName +
+                IdentifierUtil.IDENTIFIER_DELIMITER + fieldSchema.getName();
             expressionSchema.add(new Column(fieldName, dataType));
             if (i > 0) {
               sb.append(",");
@@ -1041,7 +1043,7 @@ public class HiveCatalogStore extends CatalogConstants implements CatalogStore {
           if (i > 0) {
             partitionName.append(File.separator);
           }
-          partitionName.append(CatalogUtil.extractSimpleName(parititonColumns.get(i).getName()));
+          partitionName.append(IdentifierUtil.extractSimpleName(parititonColumns.get(i).getName()));
           partitionName.append("=");
           partitionName.append(hivePartition.getValues().get(i));
         }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogUtil.java b/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogUtil.java
index 87b391e..faefd28 100644
--- a/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogUtil.java
+++ b/tajo-catalog/tajo-catalog-drivers/tajo-hive/src/main/java/org/apache/tajo/catalog/store/HiveCatalogUtil.java
@@ -39,6 +39,8 @@ import org.apache.tajo.exception.LMDNoMatchedDatatypeException;
 import org.apache.tajo.exception.TajoRuntimeException;
 import org.apache.tajo.exception.UnknownDataFormatException;
 import org.apache.tajo.exception.UnsupportedException;
+import org.apache.tajo.type.Type;
+import org.apache.tajo.type.TypeStringEncoder;
 import org.apache.thrift.TException;
 
 public class HiveCatalogUtil {
@@ -82,10 +84,10 @@ public class HiveCatalogUtil {
     }
   }
 
-  public static String getHiveFieldType(TajoDataTypes.DataType dataType) throws LMDNoMatchedDatatypeException {
-    Preconditions.checkNotNull(dataType);
+  public static String getHiveFieldType(Type type) throws LMDNoMatchedDatatypeException {
+    Preconditions.checkNotNull(type);
 
-    switch (dataType.getType()) {
+    switch (type.kind()) {
     case CHAR: return serdeConstants.CHAR_TYPE_NAME;
     case BOOLEAN: return serdeConstants.BOOLEAN_TYPE_NAME;
     case INT1: return serdeConstants.TINYINT_TYPE_NAME;
@@ -104,7 +106,7 @@ public class HiveCatalogUtil {
     case DATE: return serdeConstants.DATE_TYPE_NAME;
     case TIMESTAMP: return serdeConstants.TIMESTAMP_TYPE_NAME;
     default:
-      throw new LMDNoMatchedDatatypeException(dataType.getType().name());
+      throw new LMDNoMatchedDatatypeException(TypeStringEncoder.encode(type));
     }
   }
 


[4/7] tajo git commit: TAJO-2129: Apply new type implementation to Schema and Catalog.

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/TypeVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/TypeVisitor.java b/tajo-common/src/main/java/org/apache/tajo/type/TypeVisitor.java
new file mode 100644
index 0000000..8e437f4
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/type/TypeVisitor.java
@@ -0,0 +1,54 @@
+/**
+ * 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.type;
+
+import org.apache.tajo.schema.Field;
+
+public abstract class TypeVisitor {
+  public void visit(Type type) {
+    switch (type.kind) {
+    case ARRAY:
+      visitArray((Array) type);
+      break;
+    case RECORD:
+      visitRecord((Record) type);
+      break;
+    case MAP:
+      visitMap((Map) type);
+      break;
+    default:
+      visitPrimitive(type);
+    }
+  }
+
+  void visitPrimitive(Type type) {}
+
+  void visitMap(Map map) {
+    visit(map.keyType());
+    visit(map.valueType());
+  }
+  void visitArray(Array array) {
+    visit(array.elementType());
+  }
+  void visitRecord(Record record) {
+    for (Field field : record.fields()) {
+      visit(field.type());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/ValueParamterizedType.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/ValueParamterizedType.java b/tajo-common/src/main/java/org/apache/tajo/type/ValueParamterizedType.java
new file mode 100644
index 0000000..476629e
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/type/ValueParamterizedType.java
@@ -0,0 +1,79 @@
+/**
+ * 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.type;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.tajo.common.ProtoObject;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.TypeProto;
+import org.apache.tajo.util.StringUtils;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a type which takes value parameters (e.g., Numeric(10, 6))
+ */
+public abstract class ValueParamterizedType extends Type implements ProtoObject<TypeProto> {
+  protected ImmutableList<Integer> params;
+
+  public ValueParamterizedType(TajoDataTypes.Type type, ImmutableList<Integer> params) {
+    super(type);
+    this.params = params;
+  }
+
+  @Override
+  public boolean isValueParameterized() {
+    return true;
+  }
+
+  @Override
+  public List<Integer> getValueParameters() {
+    return params;
+  }
+
+  @Override
+  public boolean equals(Object object) {
+    if (object == this) {
+      return true;
+    }
+
+    if (object instanceof ValueParamterizedType) {
+      ValueParamterizedType other = (ValueParamterizedType) object;
+      return this.kind.equals(other.kind) && params.equals(other.params);
+    }
+
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(kind(), params);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(typeName(this.kind));
+    sb.append("(");
+    sb.append(StringUtils.join(params, ","));
+    sb.append(")");
+    return sb.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/Varchar.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/Varchar.java b/tajo-common/src/main/java/org/apache/tajo/type/Varchar.java
index fbfac17..61e4e85 100644
--- a/tajo-common/src/main/java/org/apache/tajo/type/Varchar.java
+++ b/tajo-common/src/main/java/org/apache/tajo/type/Varchar.java
@@ -18,47 +18,17 @@
 
 package org.apache.tajo.type;
 
-import org.apache.tajo.common.TajoDataTypes;
+import com.google.common.collect.ImmutableList;
 
-import java.util.Objects;
+import static org.apache.tajo.common.TajoDataTypes.Type.VARCHAR;
 
-public class Varchar extends Type {
-  private final int length;
+public class Varchar extends ValueParamterizedType {
 
   public Varchar(int length) {
-    this.length = length;
+    super(VARCHAR, ImmutableList.of(length));
   }
 
   public int length() {
-    return length;
-  }
-
-  @Override
-  public TajoDataTypes.Type baseType() {
-    return TajoDataTypes.Type.VARCHAR;
-  }
-
-  @Override
-  public boolean hasParam() {
-    return true;
-  }
-
-  @Override
-  public String toString() {
-    return "varchar(" + length + ")";
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(baseType(), length);
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object instanceof Varchar) {
-      return length == ((Varchar) object).length;
-    }
-
-    return false;
+    return params.get(0);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/java/org/apache/tajo/type/package-info.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/type/package-info.java b/tajo-common/src/main/java/org/apache/tajo/type/package-info.java
new file mode 100644
index 0000000..6ec63eb
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/type/package-info.java
@@ -0,0 +1,29 @@
+/**
+ * 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.
+ */
+
+/**
+ * Design Consideration:
+ * <ul>
+ *   <li>Parameterized Type</li>
+ * </ul>
+ *
+ * numeric (precise, scale)
+ * record (x int)
+ * map[int, text]
+ */
+package org.apache.tajo.type;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/main/proto/DataTypes.proto
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/proto/DataTypes.proto b/tajo-common/src/main/proto/DataTypes.proto
index 7cf09d3..360f595 100644
--- a/tajo-common/src/main/proto/DataTypes.proto
+++ b/tajo-common/src/main/proto/DataTypes.proto
@@ -116,3 +116,24 @@ message DataType {
   optional int32 num_nested_fields = 4;
 }
 
+message TypeProto {
+  repeated TypeElement elements = 1;
+}
+
+message TypeElement {
+ required Type kind = 1;
+ repeated int32 value_params = 2;
+ repeated string string_params = 3;
+ repeated QualifiedIdentifierProto field_names = 4;
+ optional int32 child_num = 5;
+}
+
+message QualifiedIdentifierProto {
+  repeated IdentifierProto names = 1;
+}
+
+message IdentifierProto {
+  required string name = 1;
+  required bool quoted = 2;
+}
+

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/test/java/org/apache/tajo/schema/TestSchema.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/schema/TestSchema.java b/tajo-common/src/test/java/org/apache/tajo/schema/TestSchema.java
index a843bd9..7d71630 100644
--- a/tajo-common/src/test/java/org/apache/tajo/schema/TestSchema.java
+++ b/tajo-common/src/test/java/org/apache/tajo/schema/TestSchema.java
@@ -20,11 +20,11 @@ package org.apache.tajo.schema;
 
 import org.junit.Test;
 
+import static org.apache.tajo.schema.Field.Field;
+import static org.apache.tajo.schema.Field.Record;
 import static org.apache.tajo.schema.Identifier._;
 import static org.apache.tajo.schema.QualifiedIdentifier.$;
-import static org.apache.tajo.schema.Schema.*;
 import static org.apache.tajo.schema.Schema.Schema;
-import static org.apache.tajo.schema.Schema.Struct;
 import static org.apache.tajo.type.Type.*;
 import static org.junit.Assert.assertEquals;
 
@@ -32,30 +32,30 @@ public class TestSchema {
 
   @Test
   public final void testSchema1() {
-    NamedType struct1 = Struct($("f12"), Field($("f1"), Int8), Field($("f2"), Int4));
-    NamedType struct2 = Struct($("f34"), Field($("f3"), Int8), Field($("f4"), Int4));
+    Field struct1 = Record($("f12"), Field($("f1"), Int8), Field($("f2"), Int4));
+    Field struct2 = Record($("f34"), Field($("f3"), Int8), Field($("f4"), Int4));
     Schema schema = Schema(struct1, struct2);
 
-    assertEquals(schema.toString(), "f12 record (f1 int8,f2 int4),f34 record (f3 int8,f4 int4)");
+    assertEquals("f12 (RECORD(f1 (INT8), f2 (INT4))), f34 (RECORD(f3 (INT8), f4 (INT4)))", schema.toString());
   }
 
   @Test
   public final void testSchema2() {
-    NamedType f1 = Field($("x"), Array(Int8));
-    NamedType f2 = Field($("y"), Int8);
-    NamedType f3 = Struct($("z"), Field($("z-1"), Time()), Field($("z-2"), Array(Int8)));
+    Field f1 = Field($("x"), Array(Int8));
+    Field f2 = Field($("y"), Int8);
+    Field f3 = Record($("z"), Field($("z-1"), Time), Field($("z-2"), Array(Int8)));
     Schema schema = Schema(f1, f2, f3);
 
-    assertEquals(schema.toString(), "x array<int8>,y int8,z record (z-1 time,z-2 array<int8>)");
+    assertEquals("x (ARRAY<INT8>), y (INT8), z (RECORD(z-1 (TIME), z-2 (ARRAY<INT8>)))", schema.toString());
   }
 
   @Test
   public final void testSchemaWithIdentifiers() {
-    NamedType f1 = Field($("x", "y"), Array(Int8));
-    NamedType f2 = Field($(_("y"), _("B", true)), Int8);
-    NamedType f3 = Struct($("z"), Field($("z-1"), Time), Field($("z-2"), Array(Int8)));
+    Field f1 = Field($("x", "y"), Array(Int8));
+    Field f2 = Field($(_("y"), _("B", true)), Int8);
+    Field f3 = Record($("z"), Field($("z-1"), Time), Field($("z-2"), Array(Int8)));
     Schema schema = Schema(f1, f2, f3);
 
-    assertEquals(schema.toString(), "x.y array<int8>,y.'B' int8,z record (z-1 time,z-2 array<int8>)");
+    assertEquals("x.y (ARRAY<INT8>), y.B (INT8), z (RECORD(z-1 (TIME), z-2 (ARRAY<INT8>)))", schema.toString());
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/test/java/org/apache/tajo/schema/TestTajoIdentifierPolicy.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/schema/TestTajoIdentifierPolicy.java b/tajo-common/src/test/java/org/apache/tajo/schema/TestTajoIdentifierPolicy.java
index 72027fe..cb777a7 100644
--- a/tajo-common/src/test/java/org/apache/tajo/schema/TestTajoIdentifierPolicy.java
+++ b/tajo-common/src/test/java/org/apache/tajo/schema/TestTajoIdentifierPolicy.java
@@ -45,10 +45,10 @@ public class TestTajoIdentifierPolicy {
   }
 
   public static void assertIdentifier(IdentifierPolicy p, Identifier id, String expected) {
-    assertEquals(expected, id.displayString(p));
+    assertEquals(expected, id.raw(p));
   }
 
   public static void assertQualifiedIdentifier(IdentifierPolicy p, QualifiedIdentifier id, String expected) {
-    assertEquals(expected, id.displayString(p));
+    assertEquals(expected, id.raw(p));
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/test/java/org/apache/tajo/type/TestType.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/type/TestType.java b/tajo-common/src/test/java/org/apache/tajo/type/TestType.java
index 910ba0d..1da0db7 100644
--- a/tajo-common/src/test/java/org/apache/tajo/type/TestType.java
+++ b/tajo-common/src/test/java/org/apache/tajo/type/TestType.java
@@ -21,84 +21,103 @@ package org.apache.tajo.type;
 import org.junit.Test;
 
 import static org.apache.tajo.common.TajoDataTypes.Type.*;
-import static org.apache.tajo.type.Type.*;
+import static org.apache.tajo.schema.Field.Field;
+import static org.apache.tajo.schema.QualifiedIdentifier.$;
+import static org.apache.tajo.type.Type.Array;
+import static org.apache.tajo.type.Type.Blob;
+import static org.apache.tajo.type.Type.Bool;
+import static org.apache.tajo.type.Type.Char;
+import static org.apache.tajo.type.Type.Date;
+import static org.apache.tajo.type.Type.Float4;
+import static org.apache.tajo.type.Type.Float8;
+import static org.apache.tajo.type.Type.Int1;
+import static org.apache.tajo.type.Type.Int2;
+import static org.apache.tajo.type.Type.Int4;
+import static org.apache.tajo.type.Type.Int8;
+import static org.apache.tajo.type.Type.Map;
+import static org.apache.tajo.type.Type.Numeric;
+import static org.apache.tajo.type.Type.Time;
+import static org.apache.tajo.type.Type.Timestamp;
+import static org.apache.tajo.type.Type.Varchar;
 import static org.junit.Assert.assertEquals;
 
 public class TestType {
   @Test
   public final void testPrimitiveTypes() {
-    assertEquals(Bool.baseType(), BOOLEAN);
-    assertEquals(Int1.baseType(), INT1);
-    assertEquals(Int2.baseType(), INT2);
-    assertEquals(Int4.baseType(), INT4);
-    assertEquals(Int8.baseType(), INT8);
-    assertEquals(Float4.baseType(), FLOAT4);
-    assertEquals(Float8.baseType(), FLOAT8);
-    assertEquals(Date.baseType(), DATE);
-    assertEquals(Time.baseType(), TIME);
-    assertEquals(Timestamp.baseType(), TIMESTAMP);
+    assertEquals(Bool.kind(), BOOLEAN);
+    assertEquals(Int1.kind(), INT1);
+    assertEquals(Int2.kind(), INT2);
+    assertEquals(Int4.kind(), INT4);
+    assertEquals(Int8.kind(), INT8);
+    assertEquals(Float4.kind(), FLOAT4);
+    assertEquals(Float8.kind(), FLOAT8);
+    assertEquals(Date.kind(), DATE);
+    assertEquals(Time.kind(), TIME);
+    assertEquals(Timestamp.kind(), TIMESTAMP);
 
     Numeric n = Numeric(4, 2);
-    assertEquals(n.baseType(), NUMERIC);
+    assertEquals(n.kind(), NUMERIC);
     assertEquals(n.precision(), 4);
     assertEquals(n.scale(), 2);
 
-    assertEquals(Blob().baseType(), BLOB);
+    assertEquals(Blob.kind(), BLOB);
 
     Char c = Char(2);
-    assertEquals(c.baseType(), CHAR);
+    assertEquals(c.kind(), CHAR);
     assertEquals(c.length(), 2);
 
     Varchar varchar = Varchar(2);
-    assertEquals(varchar.baseType(), VARCHAR);
+    assertEquals(varchar.kind(), VARCHAR);
     assertEquals(varchar.length(), 2);
 
-    Struct struct = Struct(Int8, Array(Float8));
-    assertEquals(struct.baseType(), RECORD);
-    assertEquals(struct.memberType(0).baseType(), INT8);
-    assertEquals(struct.memberType(1).baseType(), ARRAY);
+    Record record = Type.Record(Field("x", Int8), Field("y", Array(Float8)));
+    assertEquals(record.kind(), RECORD);
+    assertEquals(record.field(0).baseType(), INT8);
+    assertEquals(record.field(0).name(), $("x"));
+    assertEquals(record.field(1).baseType(), ARRAY);
+    assertEquals(record.field(1).name(), $("y"));
 
-    Map map = Map(Int8, Array(Timestamp()));
-    assertEquals(map.baseType(), MAP);
-    assertEquals(map.keyType().baseType(), INT8);
-    assertEquals(map.valueType().baseType(), ARRAY);
+    Map map = Map(Int8, Array(Timestamp));
+    assertEquals(map.kind(), MAP);
+    assertEquals(map.keyType().kind(), INT8);
+    assertEquals(map.valueType().kind(), ARRAY);
 
     Array array = Array(Int8);
-    assertEquals(array.baseType(), ARRAY);
-    assertEquals(array.elementType().baseType(), INT8);
+    assertEquals(array.kind(), ARRAY);
+    assertEquals(array.elementType().kind(), INT8);
   }
 
   @Test
   public final void testToString() {
-    assertEquals("boolean", Bool.toString());
-    assertEquals("int1", Int1.toString());
-    assertEquals("int2", Int2.toString());
-    assertEquals("int4", Int4.toString());
-    assertEquals("int8", Int8.toString());
-    assertEquals("float4", Float4.toString());
-    assertEquals("float8", Float8.toString());
-    assertEquals("date", Date.toString());
-    assertEquals("time", Time.toString());
-    assertEquals("timestamp", Timestamp.toString());
+    assertEquals("BOOLEAN", Bool.toString());
+    assertEquals("INT1", Int1.toString());
+    assertEquals("INT2", Int2.toString());
+    assertEquals("INT4", Int4.toString());
+    assertEquals("INT8", Int8.toString());
+    assertEquals("FLOAT4", Float4.toString());
+    assertEquals("FLOAT8", Float8.toString());
+    assertEquals("DATE", Date.toString());
+    assertEquals("TIME", Time.toString());
+    assertEquals("TIMESTAMP", Timestamp.toString());
 
     Numeric n = Numeric(4, 2);
-    assertEquals("numeric(4,2)", n.toString());
+    assertEquals("NUMERIC(4,2)", n.toString());
 
-    assertEquals("blob", Blob.toString());
+    assertEquals("BLOB", Blob.toString());
 
     Char c = Char(2);
-    assertEquals("char(2)", c.toString());
+    assertEquals("CHAR(2)", c.toString());
 
     Varchar varchar = Varchar(2);
-    assertEquals("varchar(2)", varchar.toString());
+    assertEquals("VARCHAR(2)", varchar.toString());
 
-    Struct struct = Struct(Int8, Array(Float8));
-    assertEquals("struct(int8,array<float8>)", struct.toString());
+    Record record = Type.Record(Field("x", Int8), Field("y", Array(Float8)));
+    assertEquals("RECORD(x (INT8), y (ARRAY<FLOAT8>))", record.toString());
 
     Map map = Map(Int8, Array(Timestamp));
-    assertEquals("map<int8,array<timestamp>>", map.toString());
+    assertEquals("MAP<INT8,ARRAY<TIMESTAMP>>", map.toString());
 
     Array array = Array(Int8);
-    assertEquals("array<int8>", array.toString());
+    assertEquals("ARRAY<INT8>", array.toString());
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/test/java/org/apache/tajo/type/TestTypeEncoder.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/type/TestTypeEncoder.java b/tajo-common/src/test/java/org/apache/tajo/type/TestTypeEncoder.java
new file mode 100644
index 0000000..abd427a
--- /dev/null
+++ b/tajo-common/src/test/java/org/apache/tajo/type/TestTypeEncoder.java
@@ -0,0 +1,124 @@
+/**
+ * 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.type;
+
+import com.google.common.base.Function;
+import org.apache.tajo.schema.Field;
+import org.junit.Test;
+
+import javax.annotation.Nullable;
+import java.util.List;
+
+import static org.apache.tajo.schema.Field.Field;
+import static org.apache.tajo.schema.Identifier._;
+import static org.apache.tajo.schema.QualifiedIdentifier.$;
+import static org.apache.tajo.type.Type.Array;
+import static org.apache.tajo.type.Type.Blob;
+import static org.apache.tajo.type.Type.Bool;
+import static org.apache.tajo.type.Type.Char;
+import static org.apache.tajo.type.Type.Float4;
+import static org.apache.tajo.type.Type.Float8;
+import static org.apache.tajo.type.Type.Inet4;
+import static org.apache.tajo.type.Type.Int1;
+import static org.apache.tajo.type.Type.Int2;
+import static org.apache.tajo.type.Type.Int4;
+import static org.apache.tajo.type.Type.Int8;
+import static org.apache.tajo.type.Type.Map;
+import static org.apache.tajo.type.Type.Numeric;
+import static org.apache.tajo.type.Type.Record;
+import static org.apache.tajo.type.Type.Text;
+import static org.apache.tajo.type.Type.Varchar;
+import static org.apache.tajo.type.TypeStringEncoder.*;
+import static org.junit.Assert.assertEquals;
+
+public abstract class TestTypeEncoder {
+
+  public static final Record RECORD_POINT = Record(Field($("x"), Float8), Field($("y"), Float8));
+  public static final Record RECORD_PERSON =
+      Record(
+          Field.Record($("name"), Field($(_("FirstName", true)), Text), Field($(_("LastName", true)), Text)),
+          Field($("age"), Int2),
+          Field.Record($("addr"), Field($("city"), Text), Field($("state"), Text))
+      );
+
+  @Test
+  public final void testTypesWithoutParams() {
+    assertSerialize(Bool);
+    assertSerialize(Int1);
+    assertSerialize(Int2);
+    assertSerialize(Int4);
+    assertSerialize(Int8);
+    assertSerialize(Float4);
+    assertSerialize(Float8);
+    assertSerialize(Text);
+    assertSerialize(Blob);
+    assertSerialize(Inet4);
+  }
+
+  @Test
+  public final void testValueParams() {
+    //assertSerialize(Numeric());
+    assertSerialize(Numeric(10));
+    assertSerialize(Numeric(10, 12));
+
+    assertSerialize(Char(256));
+    assertSerialize(Varchar(256));
+  }
+
+  @Test
+  public final void testTypeParams() {
+    assertSerialize(Array(Float8));
+    assertSerialize(Map(Text, Float8));
+
+    // nested
+    assertSerialize(Array(Array(Array(Float8))));
+    assertSerialize(Array(Map(Text, Array(Float8))));
+    assertSerialize(Map(Text, Array(Float8)));
+    assertSerialize(Map(Text, Array(RECORD_POINT)));
+  }
+
+  @Test
+  public final void testFieldParams() {
+    assertSerialize(RECORD_POINT);
+    assertSerialize(Record(Field.Record($("rectangle"),
+        Field($("left-bottom"), RECORD_POINT),
+        Field($("right-top"), RECORD_POINT))));
+
+    // nested with quoted identifiers
+    assertSerialize(RECORD_PERSON);
+    assertSerialize(Record(Field.Record($("couple"),
+        Field($("husband"), RECORD_PERSON),
+        Field($("wife"), RECORD_PERSON))));
+  }
+
+  @Test
+  public final void testParseTypeList() {
+    List<Type> types = parseList("TEXT,ARRAY<FLOAT8>", new Function<String, Type>() {
+      @Override
+      public Type apply(@Nullable String s) {
+        return decode(s);
+      }
+    });
+    assertEquals(2, types.size());
+    assertEquals(Text, types.get(0));
+    assertEquals(Array(Float8), types.get(1));
+  }
+
+  abstract void assertSerialize(Type type);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/test/java/org/apache/tajo/type/TestTypeProtobufEncoder.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/type/TestTypeProtobufEncoder.java b/tajo-common/src/test/java/org/apache/tajo/type/TestTypeProtobufEncoder.java
new file mode 100644
index 0000000..c2f6aa7
--- /dev/null
+++ b/tajo-common/src/test/java/org/apache/tajo/type/TestTypeProtobufEncoder.java
@@ -0,0 +1,30 @@
+/**
+ * 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.type;
+
+import static org.apache.tajo.type.TypeProtobufEncoder.decode;
+import static org.apache.tajo.type.TypeProtobufEncoder.encode;
+import static org.junit.Assert.assertEquals;
+
+public class TestTypeProtobufEncoder extends TestTypeEncoder {
+
+  public void assertSerialize(Type type) {
+    assertEquals(type, decode(encode(type)));
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-common/src/test/java/org/apache/tajo/type/TestTypeStringEncoder.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/type/TestTypeStringEncoder.java b/tajo-common/src/test/java/org/apache/tajo/type/TestTypeStringEncoder.java
new file mode 100644
index 0000000..56db01b
--- /dev/null
+++ b/tajo-common/src/test/java/org/apache/tajo/type/TestTypeStringEncoder.java
@@ -0,0 +1,29 @@
+/**
+ * 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.type;
+
+import static org.apache.tajo.type.TypeStringEncoder.decode;
+import static org.apache.tajo.type.TypeStringEncoder.encode;
+import static org.junit.Assert.assertEquals;
+
+public class TestTypeStringEncoder extends TestTypeEncoder {
+  public void assertSerialize(Type type) {
+    assertEquals(type, decode(encode(type)));
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/cli/tools/TestDDLBuilder.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tools/TestDDLBuilder.java b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tools/TestDDLBuilder.java
index 4bef226..1b5835b 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tools/TestDDLBuilder.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tools/TestDDLBuilder.java
@@ -26,6 +26,7 @@ import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageConstants;
 import org.apache.tajo.util.JavaResourceUtil;
 import org.junit.Test;
@@ -123,7 +124,7 @@ public class TestDDLBuilder {
     };
 
     for (String columnName : tobeUnquoted) {
-      assertFalse(CatalogUtil.isShouldBeQuoted(columnName));
+      assertFalse(IdentifierUtil.isShouldBeQuoted(columnName));
     }
 
     String [] quoted = {
@@ -137,7 +138,7 @@ public class TestDDLBuilder {
     };
 
     for (String columnName : quoted) {
-      assertTrue(CatalogUtil.isShouldBeQuoted(columnName));
+      assertTrue(IdentifierUtil.isShouldBeQuoted(columnName));
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCli.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCli.java b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCli.java
index fe2f867..47c5a35 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCli.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCli.java
@@ -28,7 +28,6 @@ import org.apache.tajo.ConfigKey;
 import org.apache.tajo.SessionVars;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.TpchTestBase;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.cli.tsql.commands.TajoShellCommand;
 import org.apache.tajo.client.ClientParameters;
@@ -36,6 +35,7 @@ import org.apache.tajo.client.QueryStatus;
 import org.apache.tajo.client.TajoClient;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.rpc.RpcConstants;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageUtil;
 import org.apache.tajo.storage.TablespaceManager;
 import org.apache.tajo.util.FileUtil;
@@ -550,7 +550,7 @@ public class TestTajoCli {
   // TODO: This should be removed at TAJO-1891
   @Test
   public void testAddPartitionNotimplementedException() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testAddPartitionNotimplementedException");
+    String tableName = IdentifierUtil.normalizeIdentifier("testAddPartitionNotimplementedException");
     tajoCli.executeScript("create table " + tableName + " (col1 int4, col2 int4) partition by column(key float8)");
     tajoCli.executeScript("alter table " + tableName + " add partition (key2 = 0.1)");
 
@@ -561,7 +561,7 @@ public class TestTajoCli {
 
   // TODO: This should be added at TAJO-1891
   public void testAlterTableAddDropPartition() throws Exception {
-    String tableName = CatalogUtil.normalizeIdentifier("testAlterTableAddPartition");
+    String tableName = IdentifierUtil.normalizeIdentifier("testAlterTableAddPartition");
 
     tajoCli.executeScript("create table " + tableName + " (col1 int4, col2 int4) partition by column(key float8)");
     tajoCli.executeScript("alter table " + tableName + " add partition (key2 = 0.1)");

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCliNegatives.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCliNegatives.java b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCliNegatives.java
index 0fd29d9..df66172 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCliNegatives.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCliNegatives.java
@@ -124,7 +124,7 @@ public class TestTajoCliNegatives extends QueryTestCaseBase {
       client.updateQuery("CREATE TABLE TestTajoCliNegatives.table12u79 ( name RECORD(last TEXT, first TEXT) )");
 
       assertScriptFailure("select name FROM TestTajoCliNegatives.table12u79",
-          "ERROR: org.apache.tajo.exception.NotImplementedException: not implemented feature: record projection\n");
+          "ERROR: not implemented feature: record projection\n");
 
     } finally {
       client.updateQuery("DROP TABLE IF EXISTS TestTajoCliNegatives.table12u79");

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/client/TestTajoClient.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/client/TestTajoClient.java b/tajo-core-tests/src/test/java/org/apache/tajo/client/TestTajoClient.java
index 1007642..828f60c 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/client/TestTajoClient.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/client/TestTajoClient.java
@@ -29,7 +29,6 @@ import org.apache.hadoop.fs.Path;
 import org.apache.tajo.*;
 import org.apache.tajo.TajoProtos.QueryState;
 import org.apache.tajo.annotation.NotThreadSafe;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
@@ -43,6 +42,7 @@ import org.apache.tajo.ipc.ClientProtos.QueryHistoryProto;
 import org.apache.tajo.ipc.ClientProtos.QueryInfoProto;
 import org.apache.tajo.ipc.ClientProtos.StageHistoryProto;
 import org.apache.tajo.rpc.NettyClientBase;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageConstants;
 import org.apache.tajo.storage.StorageUtil;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -91,7 +91,7 @@ public class TestTajoClient {
   public final void testCreateAndDropDatabases() throws TajoException {
     int currentNum = client.getAllDatabaseNames().size();
 
-    String prefix = CatalogUtil.normalizeIdentifier("testCreateDatabase_");
+    String prefix = IdentifierUtil.normalizeIdentifier("testCreateDatabase_");
     for (int i = 0; i < 10; i++) {
       // test allDatabaseNames
       assertEquals(currentNum + i, client.getAllDatabaseNames().size());
@@ -123,7 +123,7 @@ public class TestTajoClient {
     int currentNum = client.getAllDatabaseNames().size();
     assertEquals(TajoConstants.DEFAULT_DATABASE_NAME, client.getCurrentDatabase());
 
-    String databaseName = CatalogUtil.normalizeIdentifier("testcurrentdatabase");
+    String databaseName = IdentifierUtil.normalizeIdentifier("testcurrentdatabase");
     client.createDatabase(databaseName);
     assertEquals(currentNum + 1, client.getAllDatabaseNames().size());
     assertEquals(TajoConstants.DEFAULT_DATABASE_NAME, client.getCurrentDatabase());
@@ -153,7 +153,7 @@ public class TestTajoClient {
   @Test
   public final void testDropCurrentDatabase() throws IOException, TajoException, InterruptedException {
     int currentNum = client.getAllDatabaseNames().size();
-    String databaseName = CatalogUtil.normalizeIdentifier("testdropcurrentdatabase");
+    String databaseName = IdentifierUtil.normalizeIdentifier("testdropcurrentdatabase");
     client.createDatabase(databaseName);
     client.selectDatabase(databaseName);
     assertEquals(databaseName, client.getCurrentDatabase());
@@ -227,7 +227,7 @@ public class TestTajoClient {
 
   @Test
   public final void testUpdateQuery() throws IOException, TajoException {
-    final String tableName = CatalogUtil.normalizeIdentifier("testUpdateQuery");
+    final String tableName = IdentifierUtil.normalizeIdentifier("testUpdateQuery");
     Path tablePath = writeTmpTable(tableName);
 
     assertFalse(client.existTable(tableName));
@@ -279,7 +279,7 @@ public class TestTajoClient {
   @Test
   public final void testCreateAndDropExternalTableByExecuteQuery() throws IOException, TajoException {
     TajoConf conf = cluster.getConfiguration();
-    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndDropExternalTableByExecuteQuery");
+    final String tableName = IdentifierUtil.normalizeIdentifier("testCreateAndDropExternalTableByExecuteQuery");
 
     Path tablePath = writeTmpTable(tableName);
     assertFalse(client.existTable(tableName));
@@ -299,7 +299,7 @@ public class TestTajoClient {
   @Test
   public final void testCreateAndPurgeExternalTableByExecuteQuery() throws IOException, TajoException {
     TajoConf conf = cluster.getConfiguration();
-    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndPurgeExternalTableByExecuteQuery");
+    final String tableName = IdentifierUtil.normalizeIdentifier("testCreateAndPurgeExternalTableByExecuteQuery");
 
     Path tablePath = writeTmpTable(tableName);
     assertFalse(client.existTable(tableName));
@@ -319,7 +319,7 @@ public class TestTajoClient {
   @Test
   public final void testCreateAndDropTableByExecuteQuery() throws IOException, TajoException {
     TajoConf conf = cluster.getConfiguration();
-    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndDropTableByExecuteQuery");
+    final String tableName = IdentifierUtil.normalizeIdentifier("testCreateAndDropTableByExecuteQuery");
 
     assertFalse(client.existTable(tableName));
 
@@ -340,7 +340,7 @@ public class TestTajoClient {
   @Test
   public final void testCreateAndPurgeTableByExecuteQuery() throws IOException, TajoException {
     TajoConf conf = cluster.getConfiguration();
-    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndPurgeTableByExecuteQuery");
+    final String tableName = IdentifierUtil.normalizeIdentifier("testCreateAndPurgeTableByExecuteQuery");
 
     assertFalse(client.existTable(tableName));
 
@@ -360,7 +360,7 @@ public class TestTajoClient {
 
   @Test
   public final void testDDLByExecuteQuery() throws IOException, TajoException {
-    final String tableName = CatalogUtil.normalizeIdentifier("testDDLByExecuteQuery");
+    final String tableName = IdentifierUtil.normalizeIdentifier("testDDLByExecuteQuery");
     Path tablePath = writeTmpTable(tableName);
 
     assertFalse(client.existTable(tableName));
@@ -393,7 +393,7 @@ public class TestTajoClient {
 
   @Test
   public final void testGetTableDesc() throws IOException, TajoException {
-    final String tableName1 = CatalogUtil.normalizeIdentifier("table3");
+    final String tableName1 = IdentifierUtil.normalizeIdentifier("table3");
     Path tablePath = writeTmpTable(tableName1);
     LOG.error("Full path:" + tablePath.toUri().getRawPath());
     FileSystem fs = tablePath.getFileSystem(conf);
@@ -407,7 +407,7 @@ public class TestTajoClient {
 
     TableDesc desc = client.getTableDesc(tableName1);
     assertNotNull(desc);
-    assertEquals(CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, tableName1), desc.getName());
+    assertEquals(IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, tableName1), desc.getName());
     assertTrue(desc.getStats().getNumBytes() > 0);
   }
 
@@ -572,7 +572,7 @@ public class TestTajoClient {
   @Test
   public final void testCreateAndDropTablePartitionedColumnByExecuteQuery() throws IOException, TajoException {
     TajoConf conf = cluster.getConfiguration();
-    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndDropTablePartitionedColumnByExecuteQuery");
+    final String tableName = IdentifierUtil.normalizeIdentifier("testCreateAndDropTablePartitionedColumnByExecuteQuery");
 
     assertFalse(client.existTable(tableName));
 
@@ -614,7 +614,7 @@ public class TestTajoClient {
 
   @Test
   public final void testGetFinishedQueryList() throws SQLException, TajoException {
-    final String tableName = CatalogUtil.normalizeIdentifier("testGetFinishedQueryList");
+    final String tableName = IdentifierUtil.normalizeIdentifier("testGetFinishedQueryList");
     String sql = "create table " + tableName + " (deptname text, score int4)";
 
     client.updateQuery(sql);

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
index 723a87f..945e3d1 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
@@ -56,6 +56,12 @@ import org.apache.tajo.plan.verifier.VerificationState;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.text.CSVLineSerDe;
 import org.apache.tajo.storage.text.TextLineDeserializer;
+import org.apache.tajo.schema.IdentifierUtil;
+import org.apache.tajo.storage.LazyTuple;
+import org.apache.tajo.storage.TablespaceManager;
+import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.storage.VTuple;
+import org.apache.tajo.util.BytesUtils;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.apache.tajo.util.datetime.DateTimeUtil;
 import org.junit.AfterClass;
@@ -204,20 +210,20 @@ public class ExprTestBase {
 
   public void testEval(Schema schema, String tableName, String csvTuple, String query, String [] expected)
       throws TajoException {
-    testEval(null, schema, tableName != null ? CatalogUtil.normalizeIdentifier(tableName) : null, csvTuple, query,
+    testEval(null, schema, tableName != null ? IdentifierUtil.normalizeIdentifier(tableName) : null, csvTuple, query,
         expected, ',', true);
   }
 
   public void testEval(OverridableConf context, Schema schema, String tableName, String csvTuple, String query,
                        String [] expected)
       throws TajoException {
-    testEval(context, schema, tableName != null ? CatalogUtil.normalizeIdentifier(tableName) : null, csvTuple,
+    testEval(context, schema, tableName != null ? IdentifierUtil.normalizeIdentifier(tableName) : null, csvTuple,
         query, expected, ',', true);
   }
 
   public void testEval(Schema schema, String tableName, String csvTuple, String query,
                        String [] expected, char delimiter, boolean condition) throws TajoException {
-    testEval(null, schema, tableName != null ? CatalogUtil.normalizeIdentifier(tableName) : null, csvTuple,
+    testEval(null, schema, tableName != null ? IdentifierUtil.normalizeIdentifier(tableName) : null, csvTuple,
         query, expected, delimiter, condition);
   }
 
@@ -233,8 +239,8 @@ public class ExprTestBase {
 
     VTuple vtuple  = null;
     String qualifiedTableName =
-        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME,
-            tableName != null ? CatalogUtil.normalizeIdentifier(tableName) : null);
+        IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME,
+            tableName != null ? IdentifierUtil.normalizeIdentifier(tableName) : null);
     Schema inputSchema = null;
 
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java
index 26e0615..c42e356 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java
@@ -18,10 +18,7 @@
 
 package org.apache.tajo.engine.eval;
 
-import org.apache.tajo.catalog.CatalogUtil;
-import org.apache.tajo.catalog.Column;
-import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.catalog.SchemaBuilder;
+import org.apache.tajo.catalog.*;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
@@ -29,9 +26,11 @@ import org.apache.tajo.plan.expr.*;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.VTuple;
 import org.apache.tajo.type.Type;
+import org.apache.tajo.type.TypeFactory;
 import org.junit.Test;
 
 import static org.apache.tajo.common.TajoDataTypes.Type.INT4;
+import static org.apache.tajo.common.TajoDataTypes.Type.TEXT;
 import static org.junit.Assert.*;
 
 public class TestEvalTree extends ExprTestBase {
@@ -383,6 +382,7 @@ public class TestEvalTree extends ExprTestBase {
   private void assertCloneEqual(EvalNode eval) throws CloneNotSupportedException {
     EvalNode copy = (EvalNode) eval.clone();
     assertEquals(eval, copy);
+    assertEquals(eval.hashCode(), copy.hashCode());
     assertFalse(eval == copy);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
index a0cb924..58adc3e 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
@@ -44,6 +44,7 @@ import org.apache.tajo.plan.function.GeneralFunction;
 import org.apache.tajo.plan.logical.GroupbyNode;
 import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.plan.nameresolver.NameResolvingMode;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.TablespaceManager;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -106,7 +107,7 @@ public class TestEvalTreeUtil {
 
     TableMeta meta = CatalogUtil.newTableMeta(BuiltinStorages.TEXT, util.getConfiguration());
     TableDesc desc = new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "people"), schema, meta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "people"), schema, meta,
         CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(desc);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestEvalNodeToExprConverter.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestEvalNodeToExprConverter.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestEvalNodeToExprConverter.java
index 454ae6c..b0e2b19 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestEvalNodeToExprConverter.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestEvalNodeToExprConverter.java
@@ -38,6 +38,7 @@ import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.plan.logical.ScanNode;
 import org.apache.tajo.plan.util.EvalNodeToExprConverter;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.session.Session;
 import org.apache.tajo.storage.TablespaceManager;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -81,7 +82,7 @@ public class TestEvalNodeToExprConverter {
     for (String table : tpchTables) {
       TableMeta m = CatalogUtil.newTableMeta(BuiltinStorages.TEXT, util.getConfiguration());
       TableDesc d = CatalogUtil.newTableDesc(
-        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, table), tpch.getSchema(table), m,
+        IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, table), tpch.getSchema(table), m,
         CommonTestingUtil.getTestDir());
       catalog.createTable(d);
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestJoinOrderAlgorithm.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestJoinOrderAlgorithm.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestJoinOrderAlgorithm.java
index 0805151..d6e240f 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestJoinOrderAlgorithm.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestJoinOrderAlgorithm.java
@@ -39,6 +39,7 @@ import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.plan.logical.ScanNode;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.TablespaceManager;
 import org.apache.tajo.unit.StorageUnit;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -91,19 +92,19 @@ public class TestJoinOrderAlgorithm {
 
     TableMeta meta = CatalogUtil.newTableMeta(BuiltinStorages.TEXT, util.getConfiguration());
     TableDesc people = new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
         CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(people);
 
     TableDesc student =
         new TableDesc(
-            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, "TEXT", new KeyValueSet(),
+            IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, "TEXT", new KeyValueSet(),
             CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(student);
 
     TableDesc score =
         new TableDesc(
-            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, "TEXT", new KeyValueSet(),
+            IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, "TEXT", new KeyValueSet(),
             CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(score);
 
@@ -123,7 +124,7 @@ public class TestJoinOrderAlgorithm {
       fs.create(tablePath);
       largeDept =
           new TableDesc(
-              CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "large_dept"+(i+1)), schema4, largeTableMeta,
+              IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "large_dept"+(i+1)), schema4, largeTableMeta,
               tablePath.toUri());
       largeTableStats = new TableStats();
       largeTableStats.setNumBytes(StorageUnit.PB * (i+1));  //1 PB * i

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java
index 1ff7c87..8e0da46 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java
@@ -35,6 +35,7 @@ import org.apache.tajo.plan.LogicalOptimizer;
 import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.LogicalPlanner;
 import org.apache.tajo.plan.logical.*;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.TablespaceManager;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.apache.tajo.util.KeyValueSet;
@@ -85,19 +86,19 @@ public class TestLogicalOptimizer {
 
     TableMeta meta = CatalogUtil.newTableMeta(BuiltinStorages.TEXT, util.getConfiguration());
     TableDesc people = new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
         CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(people);
 
     TableDesc student =
         new TableDesc(
-            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, "TEXT", new KeyValueSet(),
+            IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, "TEXT", new KeyValueSet(),
             CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(student);
 
     TableDesc score =
         new TableDesc(
-            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, "TEXT", new KeyValueSet(),
+            IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, "TEXT", new KeyValueSet(),
             CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(score);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
index c50a21d..142b2c3 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
@@ -35,7 +35,6 @@ import org.apache.tajo.datum.Int4Datum;
 import org.apache.tajo.datum.TextDatum;
 import org.apache.tajo.engine.function.FunctionLoader;
 import org.apache.tajo.engine.function.builtin.SumInt;
-import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.engine.query.QueryContext;
 import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.parser.sql.SQLAnalyzer;
@@ -46,6 +45,7 @@ import org.apache.tajo.plan.Target;
 import org.apache.tajo.plan.expr.*;
 import org.apache.tajo.plan.logical.*;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.session.Session;
 import org.apache.tajo.storage.TablespaceManager;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -101,17 +101,17 @@ public class TestLogicalPlanner {
 
     TableMeta meta = CatalogUtil.newTableMeta(BuiltinStorages.TEXT, util.getConfiguration());
     TableDesc people = new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
         CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(people);
 
     TableDesc student = new TableDesc(
-        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, "TEXT", new KeyValueSet(),
+        IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, "TEXT", new KeyValueSet(),
         CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(student);
 
     TableDesc score = new TableDesc(
-        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, "TEXT", new KeyValueSet(),
+        IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, "TEXT", new KeyValueSet(),
         CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(score);
 
@@ -130,7 +130,7 @@ public class TestLogicalPlanner {
     for (String table : tpchTables) {
       TableMeta m = CatalogUtil.newTableMeta(BuiltinStorages.TEXT, util.getConfiguration());
       TableDesc d = CatalogUtil.newTableDesc(
-          CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, table), tpch.getSchema(table), m,
+          IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, table), tpch.getSchema(table), m,
           CommonTestingUtil.getTestDir());
       catalog.createTable(d);
     }
@@ -193,7 +193,7 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, selNode.getChild().getType());
     ScanNode scanNode = selNode.getChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
   }
 
   public static void assertSchema(Schema expected, Schema schema) {
@@ -239,10 +239,10 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, joinNode.getLeftChild().getType());
     ScanNode leftNode = joinNode.getLeftChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), leftNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), leftNode.getTableName());
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
     ScanNode rightNode = joinNode.getRightChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), rightNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), rightNode.getTableName());
 
     // three relations
     expr = sqlAnalyzer.parse(QUERIES[2]);
@@ -267,18 +267,18 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
     ScanNode scan1 = joinNode.getRightChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), scan1.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), scan1.getTableName());
 
     JoinNode leftNode2 = joinNode.getLeftChild();
     assertEquals(NodeType.JOIN, leftNode2.getType());
 
     assertEquals(NodeType.SCAN, leftNode2.getLeftChild().getType());
     ScanNode leftScan = leftNode2.getLeftChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), leftScan.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), leftScan.getTableName());
 
     assertEquals(NodeType.SCAN, leftNode2.getRightChild().getType());
     ScanNode rightScan = leftNode2.getRightChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), rightScan.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), rightScan.getTableName());
   }
 
 
@@ -706,10 +706,10 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, joinNode.getLeftChild().getType());
     ScanNode leftNode = joinNode.getLeftChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), leftNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), leftNode.getTableName());
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
     ScanNode rightNode = joinNode.getRightChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), rightNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), rightNode.getTableName());
   }
 
 
@@ -753,10 +753,10 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, joinNode.getLeftChild().getType());
     ScanNode leftNode = joinNode.getLeftChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), leftNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), leftNode.getTableName());
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
     ScanNode rightNode = joinNode.getRightChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), rightNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), rightNode.getTableName());
   }
 
   @Test
@@ -796,7 +796,7 @@ public class TestLogicalPlanner {
     SelectionNode selNode = projNode.getChild();
     assertEquals(NodeType.SCAN, selNode.getChild().getType());
     ScanNode scanNode = selNode.getChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
   }
 
 
@@ -877,7 +877,7 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, selNode.getChild().getType());
     ScanNode scanNode = selNode.getChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
   }
 
   @Test
@@ -900,7 +900,7 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, selNode.getChild().getType());
     ScanNode scanNode = selNode.getChild();
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
   }
 
   static final String ALIAS [] = {
@@ -1115,7 +1115,7 @@ public class TestLogicalPlanner {
     InsertNode insertNode = getInsertNode(plan);
     assertFalse(insertNode.isOverwrite());
     assertTrue(insertNode.hasTargetTable());
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), insertNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), insertNode.getTableName());
   }
 
   @Test
@@ -1127,7 +1127,7 @@ public class TestLogicalPlanner {
     assertEquals(1, plan.getQueryBlocks().size());
     InsertNode insertNode = getInsertNode(plan);
     assertFalse(insertNode.isOverwrite());
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), insertNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), insertNode.getTableName());
   }
 
   @Test
@@ -1139,7 +1139,7 @@ public class TestLogicalPlanner {
     assertEquals(1, plan.getQueryBlocks().size());
     InsertNode insertNode = getInsertNode(plan);
     assertFalse(insertNode.isOverwrite());
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), insertNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), insertNode.getTableName());
     assertTrue(insertNode.hasTargetSchema());
     assertEquals(insertNode.getTargetSchema().getColumn(0).getSimpleName(), "name");
     assertEquals(insertNode.getTargetSchema().getColumn(1).getSimpleName(), "deptname");
@@ -1167,7 +1167,7 @@ public class TestLogicalPlanner {
     InsertNode insertNode = getInsertNode(plan);
     assertTrue(insertNode.isOverwrite());
     assertTrue(insertNode.hasTargetTable());
-    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), insertNode.getTableName());
+    assertEquals(IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), insertNode.getTableName());
     assertTrue(insertNode.hasTargetSchema());
     assertEquals(insertNode.getTargetSchema().getColumn(0).getSimpleName(), "name");
     assertEquals(insertNode.getTargetSchema().getColumn(1).getSimpleName(), "deptname");
@@ -1235,8 +1235,8 @@ public class TestLogicalPlanner {
 
   // TODO: This should be added at TAJO-1891
   public final void testAddPartitionAndDropPartition() throws TajoException {
-    String tableName = CatalogUtil.normalizeIdentifier("partitioned_table");
-    String qualifiedTableName = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName);
+    String tableName = IdentifierUtil.normalizeIdentifier("partitioned_table");
+    String qualifiedTableName = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName);
 
     Schema schema = SchemaBuilder.builder()
         .add("id", Type.INT4)

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java
index 7fd249d..13e26ae 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java
@@ -40,6 +40,7 @@ import org.apache.tajo.plan.LogicalPlanner;
 import org.apache.tajo.plan.expr.*;
 import org.apache.tajo.plan.logical.*;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.TablespaceManager;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.TupleComparator;
@@ -88,19 +89,19 @@ public class TestPlannerUtil {
 
     TableMeta meta = CatalogUtil.newTableMeta(BuiltinStorages.TEXT, util.getConfiguration());
     TableDesc people = new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
         CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(people);
 
     TableDesc student =
         new TableDesc(
-            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, "TEXT",
+            IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, "TEXT",
             new KeyValueSet(), CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(student);
 
     TableDesc score =
         new TableDesc(
-            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, "TEXT",
+            IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, "TEXT",
             new KeyValueSet(), CommonTestingUtil.getTestDir().toUri());
     catalog.createTable(score);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java
index 5c56aef..dc14336 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java
@@ -39,6 +39,7 @@ import org.apache.tajo.plan.logical.JoinNode;
 import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.Appender;
 import org.apache.tajo.storage.FileTablespace;
 import org.apache.tajo.storage.TablespaceManager;
@@ -73,10 +74,10 @@ public class TestFullOuterHashJoinExec {
   private TableDesc emp3;
   private TableDesc phone3;
 
-  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
-  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
-  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
-  private final String PHONE3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
+  private final String DEP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String JOB3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String PHONE3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
 
   @Before
   public void setUp() throws Exception {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java
index 605ad6e..49f9651 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java
@@ -40,6 +40,7 @@ import org.apache.tajo.plan.logical.JoinNode;
 import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.Appender;
 import org.apache.tajo.storage.FileTablespace;
 import org.apache.tajo.storage.TablespaceManager;
@@ -75,11 +76,11 @@ public class TestFullOuterMergeJoinExec {
   private TableDesc emp3;
   private TableDesc phone3;
 
-  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
-  private final String DEP4_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep4");
-  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
-  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
-  private final String PHONE3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
+  private final String DEP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String DEP4_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep4");
+  private final String JOB3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String PHONE3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
 
   @Before
   public void setUp() throws Exception {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java
index fa20941..cda9bfd 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java
@@ -39,6 +39,7 @@ import org.apache.tajo.plan.logical.JoinNode;
 import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -71,10 +72,10 @@ public class TestLeftOuterHashJoinExec {
   private TableDesc emp3;
   private TableDesc phone3;
 
-  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
-  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
-  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
-  private final String PHONE3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
+  private final String DEP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String JOB3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String PHONE3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
 
   @Before
   public void setUp() throws Exception {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java
index c3a669e..14f3e98 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java
@@ -49,6 +49,7 @@ import org.apache.tajo.plan.expr.AggregationFunctionCallEval;
 import org.apache.tajo.plan.logical.*;
 import org.apache.tajo.plan.serder.PlanProto.ShuffleType;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
@@ -133,7 +134,7 @@ public class TestPhysicalPlanner {
     appender.close();
 
     employee = new TableDesc(
-        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), employeeSchema, employeeMeta,
+        IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), employeeSchema, employeeMeta,
         employeePath.toUri());
     catalog.createTable(employee);
 
@@ -142,7 +143,7 @@ public class TestPhysicalPlanner {
     appender = sm.getAppender(scoreMeta, scoreSchema, scorePath);
     appender.init();
     score = new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "score"), scoreSchema, scoreMeta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "score"), scoreSchema, scoreMeta,
         scorePath.toUri());
     tuple = new VTuple(scoreSchema.size());
     int m = 0;
@@ -186,7 +187,7 @@ public class TestPhysicalPlanner {
     appender.enableStats();
     appender.init();
     largeScore = new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "score_large"), scoreSchmea, scoreLargeMeta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "score_large"), scoreSchmea, scoreLargeMeta,
         scoreLargePath.toUri());
 
     VTuple tuple = new VTuple(scoreSchmea.size());

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java
index f88e2ef..77b1709 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java
@@ -37,6 +37,7 @@ import org.apache.tajo.parser.sql.SQLAnalyzer;
 import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.LogicalPlanner;
 import org.apache.tajo.plan.logical.LogicalNode;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.unit.StorageUnit;
@@ -106,7 +107,7 @@ public class TestProgressExternalSortExec {
 
     testDataStats = appender.getStats();
     employee = new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, employeeMeta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, employeeMeta,
         employeePath.toUri());
     catalog.createTable(employee);
     analyzer = new SQLAnalyzer();

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java
index 015cf73..d431f2b 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java
@@ -36,6 +36,7 @@ import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.parser.sql.SQLAnalyzer;
 import org.apache.tajo.plan.LogicalPlanner;
 import org.apache.tajo.plan.logical.LogicalNode;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -66,9 +67,9 @@ public class TestRightOuterHashJoinExec {
   private TableDesc job3;
   private TableDesc emp3;
 
-  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
-  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
-  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String DEP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String JOB3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
 
   @Before
   public void setUp() throws Exception {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java
index a6b5d4f..00d968c 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java
@@ -39,6 +39,7 @@ import org.apache.tajo.plan.logical.JoinNode;
 import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.logical.NodeType;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.Appender;
 import org.apache.tajo.storage.FileTablespace;
 import org.apache.tajo.storage.TablespaceManager;
@@ -75,11 +76,11 @@ public class TestRightOuterMergeJoinExec {
   private TableDesc emp3;
   private TableDesc phone3;
 
-  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
-  private final String DEP4_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep4");
-  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
-  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
-  private final String PHONE3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
+  private final String DEP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String DEP4_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep4");
+  private final String JOB3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String PHONE3_NAME = IdentifierUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
 
   @Before
   public void setUp() throws Exception {

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java
index 235d126..0fe4b54 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java
@@ -40,6 +40,7 @@ import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.LogicalPlanner;
 import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -104,7 +105,7 @@ public class TestSortExec {
     appender.close();
 
     TableDesc desc = new TableDesc(
-        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, employeeMeta,
+        IdentifierUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, employeeMeta,
         tablePath.toUri());
     catalog.createTable(desc);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/8d2bf407/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestAlterTable.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestAlterTable.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestAlterTable.java
index 3b47bff..30490f4 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestAlterTable.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestAlterTable.java
@@ -22,11 +22,11 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
-import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.exception.*;
+import org.apache.tajo.schema.IdentifierUtil;
 import org.apache.tajo.storage.StorageConstants;
 import org.junit.After;
 import org.junit.Before;
@@ -35,7 +35,6 @@ import org.junit.experimental.categories.Category;
 
 import java.io.File;
 import java.sql.ResultSet;
-import java.sql.SQLException;
 import java.util.List;
 
 import static org.junit.Assert.*;
@@ -93,7 +92,7 @@ public class TestAlterTable extends QueryTestCaseBase {
   public final void testAlterTableAddPartition() throws Exception {
     executeDDL("create_partitioned_table.sql", null);
 
-    String tableName = CatalogUtil.buildFQName("TestAlterTable", "partitioned_table");
+    String tableName = IdentifierUtil.buildFQName("TestAlterTable", "partitioned_table");
     assertTrue(catalog.existsTable(tableName));
 
     TableDesc retrieved = catalog.getTableDesc(tableName);
@@ -137,7 +136,7 @@ public class TestAlterTable extends QueryTestCaseBase {
     executeDDL("create_partitioned_table2.sql", null);
 
     String simpleTableName = "partitioned_table2";
-    String tableName = CatalogUtil.buildFQName(getCurrentDatabase(), simpleTableName);
+    String tableName = IdentifierUtil.buildFQName(getCurrentDatabase(), simpleTableName);
     assertTrue(catalog.existsTable(tableName));
 
     TableDesc tableDesc = catalog.getTableDesc(tableName);
@@ -222,7 +221,7 @@ public class TestAlterTable extends QueryTestCaseBase {
   public final void testRepairPartitionWithDatabaseNameIncludeTableName() throws Exception {
     String databaseName = "test_repair_partition";
     String tableName = "part";
-    String canonicalTableName = CatalogUtil.getCanonicalTableName(databaseName, tableName);
+    String canonicalTableName = IdentifierUtil.getCanonicalTableName(databaseName, tableName);
 
     executeString("create database " + databaseName).close();
     executeString("create table " + canonicalTableName + "(col1 int4, col2 int4) partition by column(key float8) "
@@ -270,7 +269,7 @@ public class TestAlterTable extends QueryTestCaseBase {
   public void testRepairPartitionWithAbnormalDirectories()  throws Exception {
     String databaseName = getCurrentDatabase().toLowerCase();
     String tableName = "testRepairPartitionWithAbnormalDirectories".toLowerCase();
-    String canonicalTableName = CatalogUtil.getCanonicalTableName(databaseName, tableName);
+    String canonicalTableName = IdentifierUtil.getCanonicalTableName(databaseName, tableName);
 
     executeString("create table " + canonicalTableName + "(col1 int4, col2 int4) partition by column(key float8) "
       + " as select l_orderkey, l_partkey, l_quantity from default.lineitem").close();
@@ -327,7 +326,7 @@ public class TestAlterTable extends QueryTestCaseBase {
   public void testRepairPartitionWithDatePartitionColumn()  throws Exception {
     String databaseName = getCurrentDatabase().toLowerCase();
     String tableName = "testRepairPartitionWithDatePartitionColumn".toLowerCase();
-    String canonicalTableName = CatalogUtil.getCanonicalTableName(databaseName, tableName);
+    String canonicalTableName = IdentifierUtil.getCanonicalTableName(databaseName, tableName);
 
     executeString(
       "create table " + canonicalTableName + "(col1 int4, col2 int4) partition by column(key date) "
@@ -374,7 +373,7 @@ public class TestAlterTable extends QueryTestCaseBase {
   public void testRepairPartitionWithTimestampPartitionColumn()  throws Exception {
     String databaseName = getCurrentDatabase().toLowerCase();
     String tableName = "testRepairPartitionWithTimestampPartitionColumn".toLowerCase();
-    String canonicalTableName = CatalogUtil.getCanonicalTableName(databaseName, tableName);
+    String canonicalTableName = IdentifierUtil.getCanonicalTableName(databaseName, tableName);
 
     executeString(
       "create table " + canonicalTableName + "(col1 int4, col2 int4) partition by column(key timestamp) "
@@ -421,7 +420,7 @@ public class TestAlterTable extends QueryTestCaseBase {
   public void testRepairPartitionWithTimesPartitionColumn()  throws Exception {
     String databaseName = getCurrentDatabase().toLowerCase();
     String tableName = "testRepairPartitionWithTimesPartitionColumn".toLowerCase();
-    String canonicalTableName = CatalogUtil.getCanonicalTableName(databaseName, tableName);
+    String canonicalTableName = IdentifierUtil.getCanonicalTableName(databaseName, tableName);
 
     executeString(
       "create table " + canonicalTableName + "(col1 int4, col2 int4) partition by column(key time) "
@@ -474,7 +473,7 @@ public class TestAlterTable extends QueryTestCaseBase {
   public void testRepairPartitionWithMutiplePartitionColumn()  throws Exception {
     String databaseName = getCurrentDatabase().toLowerCase();
     String tableName = "testRepairPartitionWithMutiplePartitionColumn".toLowerCase();
-    String canonicalTableName = CatalogUtil.getCanonicalTableName(databaseName, tableName);
+    String canonicalTableName = IdentifierUtil.getCanonicalTableName(databaseName, tableName);
 
     executeString("create table " + canonicalTableName + " (col4 text) "
       + " partition by column(col1 int4, col2 int4, col3 float8) as select l_returnflag, l_orderkey, l_partkey, " +
@@ -535,7 +534,7 @@ public class TestAlterTable extends QueryTestCaseBase {
 
   private void dropPartitions(String databaseName, String tableName, List<Column> colums)
     throws Exception {
-    String canonicalTableName = CatalogUtil.getCanonicalTableName(databaseName, tableName);
+    String canonicalTableName = IdentifierUtil.getCanonicalTableName(databaseName, tableName);
     List<CatalogProtos.PartitionDescProto> partitions = catalog.getPartitionsOfTable(databaseName, tableName);
 
     StringBuilder sb = new StringBuilder();