tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jihoon...@apache.org
Subject [23/50] [abbrv] git commit: TAJO-338 - Add Query Optimization Part for Column-Partitioned Tables. (hyunsik)
Date Sat, 28 Dec 2013 06:36:20 GMT
TAJO-338 - Add Query Optimization Part for Column-Partitioned Tables. (hyunsik)


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

Branch: refs/heads/DAG-execplan
Commit: f58f6ee827139c01253902f0b1076b47fde9d5e6
Parents: 4dbecf9
Author: Hyunsik Choi <hyunsik@apache.org>
Authored: Wed Dec 18 21:39:30 2013 +0900
Committer: Hyunsik Choi <hyunsik@apache.org>
Committed: Thu Dec 19 11:36:10 2013 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |   3 +
 .../org/apache/tajo/algebra/CreateTable.java    |  30 +-
 .../tajo/catalog/AbstractCatalogClient.java     |   2 +-
 .../org/apache/tajo/catalog/DDLBuilder.java     |  20 +-
 .../java/org/apache/tajo/catalog/Schema.java    |  57 ++-
 .../java/org/apache/tajo/catalog/TableDesc.java |  30 +-
 .../tajo/catalog/partition/PartitionDesc.java   | 194 ++++++++++
 .../tajo/catalog/partition/Partitions.java      | 349 -----------------
 .../src/main/proto/CatalogProtos.proto          |   7 +-
 .../org/apache/tajo/catalog/TestSchema.java     |  26 ++
 .../tajo/catalog/store/HCatalogStore.java       |   6 +-
 .../tajo/catalog/store/TestHCatalogStore.java   |   2 +-
 .../tajo/catalog/store/AbstractDBStore.java     |  42 +--
 .../apache/tajo/catalog/store/DerbyStore.java   |  42 +--
 .../org/apache/tajo/catalog/TestCatalog.java    |  72 ++--
 .../org/apache/tajo/catalog/TestDBStore.java    |  62 ++--
 .../org/apache/tajo/datum/BooleanDatum.java     |   2 +
 .../org/apache/tajo/datum/DatumFactory.java     |  34 ++
 .../main/java/org/apache/tajo/util/TUtil.java   |   2 +-
 .../org/apache/tajo/engine/parser/SQLLexer.g4   |   3 +-
 .../org/apache/tajo/engine/parser/SQLParser.g4  |   2 +-
 .../apache/tajo/engine/eval/AlgebraicUtil.java  | 134 ++++++-
 .../apache/tajo/engine/eval/EvalTreeUtil.java   |  62 +---
 .../org/apache/tajo/engine/eval/InEval.java     |   2 +-
 .../tajo/engine/eval/LikePredicateEval.java     |   4 +
 .../apache/tajo/engine/parser/SQLAnalyzer.java  |  10 +-
 .../engine/planner/BasicLogicalPlanVisitor.java |   8 +
 .../tajo/engine/planner/LogicalOptimizer.java   |  11 +-
 .../tajo/engine/planner/LogicalPlanVisitor.java |   2 +
 .../tajo/engine/planner/LogicalPlanner.java     |  72 ++--
 .../engine/planner/PhysicalPlannerImpl.java     |   4 +-
 .../apache/tajo/engine/planner/PlannerUtil.java |   2 +-
 .../org/apache/tajo/engine/planner/Target.java  |   4 +
 .../engine/planner/global/ExecutionBlock.java   |   4 +
 .../engine/planner/global/GlobalPlanner.java    |   2 +-
 .../engine/planner/logical/CreateTableNode.java |  20 +-
 .../tajo/engine/planner/logical/NodeType.java   |   1 +
 .../logical/PartitionedTableScanNode.java       | 180 +++++++++
 .../engine/planner/logical/RelationNode.java    |   2 +-
 .../tajo/engine/planner/logical/ScanNode.java   |  19 +-
 .../engine/planner/logical/StoreTableNode.java  |  24 +-
 .../planner/logical/TableSubQueryNode.java      |   2 +-
 .../join/GreedyHeuristicJoinOrderAlgorithm.java |   8 +-
 .../engine/planner/logical/join/JoinGraph.java  |   3 +-
 .../ColumnPartitionedTableStoreExec.java        |  65 +++-
 .../engine/planner/physical/PhysicalExec.java   |   6 +-
 .../engine/planner/physical/SeqScanExec.java    |  69 +++-
 .../planner/rewrite/FilterPushDownRule.java     |  21 +-
 .../rewrite/PartitionedTableRewriter.java       | 371 +++++++++++++++++++
 .../planner/rewrite/ProjectionPushDownRule.java |   2 +-
 .../org/apache/tajo/engine/utils/TupleUtil.java | 106 ++++++
 .../tajo/master/DefaultTaskScheduler.java       |  19 +-
 .../org/apache/tajo/master/GlobalEngine.java    |  12 +-
 .../tajo/master/TajoMasterClientService.java    |  10 +-
 .../master/querymaster/QueryMasterTask.java     |  10 +-
 .../tajo/master/querymaster/SubQuery.java       |  44 ++-
 .../src/main/proto/ClientProtos.proto           |   2 +-
 .../org/apache/tajo/client/TestTajoClient.java  |   4 +-
 .../apache/tajo/engine/eval/ExprTestBase.java   |   2 +-
 .../tajo/engine/eval/TestEvalTreeUtil.java      |  24 +-
 .../tajo/engine/parser/TestSQLAnalyzer.java     |   7 +-
 .../engine/planner/TestLogicalOptimizer.java    |   2 +-
 .../tajo/engine/planner/TestLogicalPlan.java    |   2 +-
 .../planner/physical/TestBSTIndexExec.java      |   2 +-
 .../planner/physical/TestHashAntiJoinExec.java  |   2 +-
 .../planner/physical/TestHashSemiJoinExec.java  |   2 +-
 .../planner/physical/TestPhysicalPlanner.java   |   2 +-
 .../engine/planner/physical/TestSortExec.java   |   2 +-
 .../tajo/engine/query/TestInsertQuery.java      | 201 ----------
 .../tajo/engine/query/TestTablePartitions.java  | 360 ++++++++++++++++++
 .../apache/tajo/engine/util/TestTupleUtil.java  |  52 ++-
 .../tajo/master/TestExecutionBlockCursor.java   |   2 +-
 .../apache/tajo/master/TestGlobalPlanner.java   |   2 +-
 .../tajo/worker/TestRangeRetrieverHandler.java  |   2 +-
 .../create_table_partition_by_column.sql        |   2 +-
 75 files changed, 2000 insertions(+), 976 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 5d6ba59..cceb1cb 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,9 @@ Release 0.8.0 - unreleased
 
   NEW FEATURES
 
+    TAJO-338 - Add Query Optimization Part for Column-Partitioned Tables.
+    (hyunsik)
+
     TAJO-333: Add metric system to Tajo. (hyoungjunkim via jihoon)
 
     TAJO-413: Implement pi function. (DaeMyung Kang via jihoon)

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
index a6bc1e7..a85e366 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
@@ -31,7 +31,7 @@ public class CreateTable extends Expr {
   private String location;
   private Expr subquery;
   private Map<String, String> params;
-  private PartitionOption partition;
+  private PartitionDescExpr partition;
 
   public CreateTable(final String tableName) {
     super(OpType.CreateTable);
@@ -107,11 +107,11 @@ public class CreateTable extends Expr {
     return partition != null;
   }
 
-  public void setPartition(PartitionOption partition) {
+  public void setPartition(PartitionDescExpr partition) {
     this.partition = partition;
   }
 
-  public <T extends PartitionOption> T getPartition() {
+  public <T extends PartitionDescExpr> T getPartition() {
     return (T) this.partition;
   }
 
@@ -178,10 +178,10 @@ public class CreateTable extends Expr {
     COLUMN
   }
 
-  public static abstract class PartitionOption {
+  public static abstract class PartitionDescExpr {
     PartitionType type;
 
-    public PartitionOption(PartitionType type) {
+    public PartitionDescExpr(PartitionType type) {
       this.type = type;
     }
 
@@ -190,7 +190,7 @@ public class CreateTable extends Expr {
     }
   }
 
-  public static class RangePartition extends PartitionOption {
+  public static class RangePartition extends PartitionDescExpr {
     ColumnReferenceExpr [] columns;
     List<RangePartitionSpecifier> specifiers;
 
@@ -209,7 +209,7 @@ public class CreateTable extends Expr {
     }
   }
 
-  public static class HashPartition extends PartitionOption {
+  public static class HashPartition extends PartitionDescExpr {
     ColumnReferenceExpr [] columns;
     Expr quantity;
     List<PartitionSpecifier> specifiers;
@@ -246,7 +246,7 @@ public class CreateTable extends Expr {
     }
   }
 
-  public static class ListPartition extends PartitionOption {
+  public static class ListPartition extends PartitionDescExpr {
     ColumnReferenceExpr [] columns;
     List<ListPartitionSpecifier> specifiers;
 
@@ -265,17 +265,23 @@ public class CreateTable extends Expr {
     }
   }
 
-  public static class ColumnPartition extends PartitionOption {
-    ColumnReferenceExpr [] columns;
+  public static class ColumnPartition extends PartitionDescExpr {
+    private ColumnDefinition [] columns;
+    private boolean isOmitValues;
 
-    public ColumnPartition(ColumnReferenceExpr [] columns) {
+    public ColumnPartition(ColumnDefinition [] columns, boolean isOmitValues) {
       super(PartitionType.COLUMN);
       this.columns = columns;
+      this.isOmitValues = isOmitValues;
     }
 
-    public ColumnReferenceExpr [] getColumns() {
+    public ColumnDefinition [] getColumns() {
       return columns;
     }
+
+    public boolean isOmitValues() {
+      return isOmitValues;
+    }
   }
 
   public static class RangePartitionSpecifier extends PartitionSpecifier {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/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 5f79f10..44ac8f4 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
@@ -122,7 +122,7 @@ public abstract class AbstractCatalogClient implements CatalogService {
       return new ServerCallable<Boolean>(conf, catalogServerAddr, CatalogProtocol.class, false) {
         public Boolean call(NettyClientBase client) throws ServiceException {
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return stub.addTable(null, (TableDescProto) desc.getProto()).getValue();
+          return stub.addTable(null, desc.getProto()).getValue();
         }
       }.withRetries();
     } catch (ServiceException e) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/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 a9d0f03..c818be7 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
@@ -18,7 +18,7 @@
 
 package org.apache.tajo.catalog;
 
-import org.apache.tajo.catalog.partition.Partitions;
+import org.apache.tajo.catalog.partition.PartitionDesc;
 import org.apache.tajo.catalog.partition.Specifier;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.common.TajoDataTypes;
@@ -96,15 +96,15 @@ public class DDLBuilder {
   }
 
   private static void buildPartitionClause(StringBuilder sb, TableDesc desc) {
-    Partitions partitions = desc.getPartitions();
+    PartitionDesc partitionDesc = desc.getPartitions();
 
     sb.append(" PARTITION BY ");
-    sb.append(partitions.getPartitionsType().name());
+    sb.append(partitionDesc.getPartitionsType().name());
 
     // columns
     sb.append("(");
     int columnCount = 0;
-    for(Column column: partitions.getColumns()) {
+    for(Column column: partitionDesc.getColumns()) {
       for(Column targetColumn: desc.getSchema().getColumns()) {
         if (column.getColumnName().equals(targetColumn.getColumnName()))  {
           if (columnCount > 0)
@@ -118,12 +118,12 @@ public class DDLBuilder {
     sb.append(")");
 
     // specifier
-    if (partitions.getSpecifiers() != null
-        && !partitions.getPartitionsType().equals(CatalogProtos.PartitionsType.COLUMN)) {
+    if (partitionDesc.getSpecifiers() != null
+        && !partitionDesc.getPartitionsType().equals(CatalogProtos.PartitionsType.COLUMN)) {
 
       sb.append(" (");
-      for(int i = 0; i < partitions.getSpecifiers().size(); i++) {
-        Specifier specifier = partitions.getSpecifiers().get(i);
+      for(int i = 0; i < partitionDesc.getSpecifiers().size(); i++) {
+        Specifier specifier = partitionDesc.getSpecifiers().get(i);
         if (i > 0)
           sb.append(",");
 
@@ -132,7 +132,7 @@ public class DDLBuilder {
         if (!specifier.getName().isEmpty())
           sb.append(" ").append(specifier.getName());
 
-        if (partitions.getPartitionsType().equals(CatalogProtos.PartitionsType.LIST)) {
+        if (partitionDesc.getPartitionsType().equals(CatalogProtos.PartitionsType.LIST)) {
           if (!specifier.getExpressions().isEmpty()) {
             sb.append(" VALUES (");
             String[] expressions = specifier.getExpressions().split("\\,");
@@ -144,7 +144,7 @@ public class DDLBuilder {
             sb.append(")");
 
           }
-        } else if (partitions.getPartitionsType().equals(CatalogProtos.PartitionsType.RANGE))  {
+        } else if (partitionDesc.getPartitionsType().equals(CatalogProtos.PartitionsType.RANGE))  {
           sb.append(" VALUES LESS THAN (");
           if (!specifier.getExpressions().isEmpty()) {
             sb.append(specifier.getExpressions());

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java
index 8a2d028..4ea3b81 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Schema.java
@@ -39,26 +39,24 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable, GsonObject {
 	private	SchemaProto.Builder builder = SchemaProto.newBuilder();
 
 	@Expose protected List<Column> fields = null;
-	@Expose protected Map<String, Integer> fieldsByQialifiedName = null;
+	@Expose protected Map<String, Integer> fieldsByQualifiedName = null;
   @Expose protected Map<String, List<Integer>> fieldsByName = null;
 
 	public Schema() {
-    this.fields = new ArrayList<Column>();
-    this.fieldsByQialifiedName = new TreeMap<String, Integer>();
-    this.fieldsByName = new HashMap<String, List<Integer>>();
+    init();
 	}
 	
 	public Schema(SchemaProto proto) {
     this.fields = new ArrayList<Column>();
-    this.fieldsByQialifiedName = new HashMap<String, Integer>();
+    this.fieldsByQualifiedName = new HashMap<String, Integer>();
     this.fieldsByName = new HashMap<String, List<Integer>>();
     for(ColumnProto colProto : proto.getFieldsList()) {
       Column tobeAdded = new Column(colProto);
       fields.add(tobeAdded);
       if (tobeAdded.hasQualifier()) {
-        fieldsByQialifiedName.put(tobeAdded.getQualifier() + "." + tobeAdded.getColumnName(), fields.size() - 1);
+        fieldsByQualifiedName.put(tobeAdded.getQualifier() + "." + tobeAdded.getColumnName(), fields.size() - 1);
       } else {
-        fieldsByQialifiedName.put(tobeAdded.getColumnName(), fields.size() - 1);
+        fieldsByQualifiedName.put(tobeAdded.getColumnName(), fields.size() - 1);
       }
       if (fieldsByName.containsKey(tobeAdded.getColumnName())) {
         fieldsByName.get(tobeAdded.getColumnName()).add(fields.size() - 1);
@@ -71,17 +69,23 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable, GsonObject {
 	public Schema(Schema schema) {
 	  this();
 		this.fields.addAll(schema.fields);
-		this.fieldsByQialifiedName.putAll(schema.fieldsByQialifiedName);
+		this.fieldsByQualifiedName.putAll(schema.fieldsByQualifiedName);
     this.fieldsByName.putAll(schema.fieldsByName);
 	}
-	
+
 	public Schema(Column [] columns) {
-    this();
+    init();
     for(Column c : columns) {
       addColumn(c);
     }
   }
 
+  private void init() {
+    this.fields = new ArrayList<Column>();
+    this.fieldsByQualifiedName = new HashMap<String, Integer>();
+    this.fieldsByName = new HashMap<String, List<Integer>>();
+  }
+
   /**
    * Set a qualifier to this schema.
    * This changes the qualifier of all columns except for not-qualified columns.
@@ -89,26 +93,10 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable, GsonObject {
    * @param qualifier The qualifier
    */
   public void setQualifier(String qualifier) {
-    setQualifier(qualifier, false);
-  }
-
-  /**
-   * Set a qualifier to this schema. This changes the qualifier of all columns if force is true.
-   * Otherwise, it changes the qualifier of all columns except for non-qualified columns
-   *
-   * @param qualifier The qualifier
-   * @param force If true, all columns' qualifiers will be changed. Otherwise, only qualified columns' qualifiers will
-   *              be changed.
-   */
-  public void setQualifier(String qualifier, boolean force) {
-    fieldsByQialifiedName.clear();
-
+    fieldsByQualifiedName.clear();
     for (int i = 0; i < getColumnNum(); i++) {
-      if (!force && fields.get(i).hasQualifier()) {
-        continue;
-      }
       fields.get(i).setQualifier(qualifier);
-      fieldsByQialifiedName.put(fields.get(i).getQualifiedName(), i);
+      fieldsByQualifiedName.put(fields.get(i).getQualifiedName(), i);
     }
   }
 	
@@ -121,7 +109,7 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable, GsonObject {
   }
 
 	public Column getColumnByFQN(String qualifiedName) {
-		Integer cid = fieldsByQialifiedName.get(qualifiedName.toLowerCase());
+		Integer cid = fieldsByQualifiedName.get(qualifiedName.toLowerCase());
 		return cid != null ? fields.get(cid) : null;
 	}
 	
@@ -151,13 +139,14 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable, GsonObject {
 	}
 	
 	public int getColumnId(String qualifiedName) {
-	  return fieldsByQialifiedName.get(qualifiedName.toLowerCase());
+	  return fieldsByQualifiedName.get(qualifiedName.toLowerCase());
 	}
 
   public int getColumnIdByName(String colName) {
     for (Column col : fields) {
       if (col.getColumnName().equals(colName.toLowerCase())) {
-        return fieldsByQialifiedName.get(col.getQualifiedName());
+        String qualifiedName = col.getQualifiedName();
+        return fieldsByQualifiedName.get(qualifiedName);
       }
     }
     return -1;
@@ -168,7 +157,7 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable, GsonObject {
 	}
 	
 	public boolean contains(String colName) {
-		return fieldsByQialifiedName.containsKey(colName.toLowerCase());
+		return fieldsByQualifiedName.containsKey(colName.toLowerCase());
 
 	}
 
@@ -189,14 +178,14 @@ public class Schema implements ProtoObject<SchemaProto>, Cloneable, GsonObject {
 
   public synchronized Schema addColumn(String name, DataType dataType) {
 		String normalized = name.toLowerCase();
-		if(fieldsByQialifiedName.containsKey(normalized)) {
+		if(fieldsByQualifiedName.containsKey(normalized)) {
 		  LOG.error("Already exists column " + normalized);
 			throw new AlreadyExistsFieldException(normalized);
 		}
 			
 		Column newCol = new Column(normalized, dataType);
 		fields.add(newCol);
-		fieldsByQialifiedName.put(newCol.getQualifiedName(), fields.size() - 1);
+		fieldsByQualifiedName.put(newCol.getQualifiedName(), fields.size() - 1);
     fieldsByName.put(newCol.getColumnName(), TUtil.newList(fields.size() - 1));
 		
 		return this;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java
index 458a99a..8fffc6e 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/TableDesc.java
@@ -25,12 +25,13 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.catalog.json.CatalogGsonHelper;
-import org.apache.tajo.catalog.partition.Partitions;
+import org.apache.tajo.catalog.partition.PartitionDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableDescProto;
 import org.apache.tajo.catalog.statistics.TableStats;
 import org.apache.tajo.common.ProtoObject;
 import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.util.TUtil;
 
 public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Cloneable {
   private final Log LOG = LogFactory.getLog(TableDesc.class);
@@ -42,7 +43,7 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
   @Expose protected TableMeta meta; // required
   @Expose protected Path uri; // required
   @Expose	protected TableStats stats; // optional
-  @Expose protected Partitions partitions; //optional
+  @Expose protected PartitionDesc partitionDesc; //optional
   
 	public TableDesc() {
 		builder = TableDescProto.newBuilder();
@@ -65,7 +66,7 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
 	  this(proto.getId(), new Schema(proto.getSchema()), new TableMeta(proto.getMeta()), new Path(proto.getPath()));
     this.stats = new TableStats(proto.getStats());
     if (proto.getPartitions() != null && !proto.getPartitions().toString().isEmpty()) {
-      this.partitions = new Partitions(proto.getPartitions());
+      this.partitionDesc = new PartitionDesc(proto.getPartitions());
     }
 	}
 	
@@ -115,22 +116,27 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
   }
 
   public boolean hasPartitions() {
-    return this.partitions != null;
+    return this.partitionDesc != null;
   }
 
-  public Partitions getPartitions() {
-    return partitions;
+  public PartitionDesc getPartitions() {
+    return partitionDesc;
   }
 
-  public void setPartitions(Partitions partitions) {
-    this.partitions = partitions;
+  public void setPartitions(PartitionDesc partitionDesc) {
+    this.partitionDesc = partitionDesc;
   }
 
   public boolean equals(Object object) {
     if(object instanceof TableDesc) {
       TableDesc other = (TableDesc) object;
       
-      return this.getProto().equals(other.getProto());
+      boolean eq = tableName.equals(other.tableName);
+      eq = eq && schema.equals(other.schema);
+      eq = eq && meta.equals(other.meta);
+      eq = eq && uri.equals(other.uri);
+      eq = eq && TUtil.checkEquals(partitionDesc, other.partitionDesc);
+      return eq && TUtil.checkEquals(stats, other.stats);
     }
     
     return false;   
@@ -144,7 +150,7 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
     desc.meta = (TableMeta) meta.clone();
     desc.uri = uri;
     desc.stats = stats != null ? (TableStats) stats.clone() : null;
-    desc.partitions = partitions != null ? (Partitions) partitions.clone() : null;
+    desc.partitionDesc = partitionDesc != null ? (PartitionDesc) partitionDesc.clone() : null;
 	  
 	  return desc;
 	}
@@ -178,8 +184,8 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
     if (this.stats != null) {
       builder.setStats(this.stats.getProto());
     }
-    if (this.partitions != null) {
-      builder.setPartitions(this.partitions.getProto());
+    if (this.partitionDesc != null) {
+      builder.setPartitions(this.partitionDesc.getProto());
     }
     return builder.build();
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/PartitionDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/PartitionDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/PartitionDesc.java
new file mode 100644
index 0000000..fbec807
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/PartitionDesc.java
@@ -0,0 +1,194 @@
+/**
+ * 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.catalog.partition;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.catalog.json.CatalogGsonHelper;
+import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.common.ProtoObject;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.util.TUtil;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class PartitionDesc implements ProtoObject<CatalogProtos.PartitionDescProto>, Cloneable, GsonObject {
+  @Expose protected CatalogProtos.PartitionsType partitionsType; //required
+  @Expose protected Schema schema;
+  @Expose protected int numPartitions; //optional
+  @Expose protected List<Specifier> specifiers; //optional
+  @Expose protected boolean isOmitValues = false; // optional;
+
+  private CatalogProtos.PartitionDescProto.Builder builder = CatalogProtos.PartitionDescProto.newBuilder();
+
+  public PartitionDesc() {
+  }
+
+  public PartitionDesc(PartitionDesc partition) {
+    this();
+    this.partitionsType = partition.partitionsType;
+    this.schema = partition.schema;
+    this.numPartitions = partition.numPartitions;
+    this.specifiers = partition.specifiers;
+  }
+
+  public PartitionDesc(CatalogProtos.PartitionsType partitionsType, Column[] columns, int numPartitions,
+                       List<Specifier> specifiers) {
+    this();
+    this.partitionsType = partitionsType;
+    for (Column c : columns) {
+      addColumn(c);
+    }
+    this.numPartitions = numPartitions;
+    this.specifiers = specifiers;
+  }
+
+  public PartitionDesc(CatalogProtos.PartitionDescProto proto) {
+    this.partitionsType = proto.getPartitionsType();
+    this.schema = new Schema(proto.getSchema());
+    this.numPartitions = proto.getNumPartitions();
+    this.isOmitValues = proto.getIsOmitValues();
+    if(proto.getSpecifiersList() != null) {
+      this.specifiers = TUtil.newList();
+      for(CatalogProtos.SpecifierProto specifier: proto.getSpecifiersList()) {
+        this.specifiers.add(new Specifier(specifier));
+      }
+    }
+  }
+
+  public Schema getSchema() {
+    return schema;
+  }
+
+  public List<Column> getColumns() {
+    return ImmutableList.copyOf(schema.toArray());
+  }
+
+  public void setColumns(Collection<Column> columns) {
+    this.schema = new Schema(columns.toArray(new Column[columns.size()]));
+  }
+
+  public synchronized void addColumn(Column column) {
+    if (schema == null) {
+      schema = new Schema();
+    }
+    schema.addColumn(column);
+  }
+
+  public synchronized void addSpecifier(Specifier specifier) {
+    if(specifiers == null)
+      specifiers = TUtil.newList();
+
+    specifiers.add(specifier);
+  }
+
+  public CatalogProtos.PartitionsType getPartitionsType() {
+    return partitionsType;
+  }
+
+  public void setPartitionsType(CatalogProtos.PartitionsType partitionsType) {
+    this.partitionsType = partitionsType;
+  }
+
+  public int getNumPartitions() {
+    return numPartitions;
+  }
+
+  public void setNumPartitions(int numPartitions) {
+    this.numPartitions = numPartitions;
+  }
+
+  public List<Specifier> getSpecifiers() {
+    return specifiers;
+  }
+
+  public void setSpecifiers(List<Specifier> specifiers) {
+    this.specifiers = specifiers;
+  }
+
+  public void setOmitValues(boolean flag) {
+    isOmitValues = flag;
+  }
+
+  public boolean isOmitValues() {
+    return isOmitValues;
+  }
+
+  public boolean equals(Object o) {
+    if (o instanceof PartitionDesc) {
+      PartitionDesc another = (PartitionDesc) o;
+      boolean eq = partitionsType == another.partitionsType;
+      eq = eq && schema.equals(another.schema);
+      eq = eq && numPartitions == another.numPartitions;
+      eq = eq && TUtil.checkEquals(specifiers, another.specifiers);
+      eq = eq && isOmitValues == another.isOmitValues;
+      return eq;
+    }
+    return false;
+  }
+
+  public Object clone() throws CloneNotSupportedException {
+    PartitionDesc copy = (PartitionDesc) super.clone();
+    copy.builder = CatalogProtos.PartitionDescProto.newBuilder();
+    copy.setPartitionsType(this.partitionsType);
+    copy.schema = new Schema(schema.getProto());
+    copy.setNumPartitions(this.numPartitions);
+    copy.specifiers = new ArrayList<Specifier>(this.specifiers);
+    copy.isOmitValues = isOmitValues;
+
+    return copy;
+  }
+
+  @Override
+  public CatalogProtos.PartitionDescProto getProto() {
+    if (builder == null) {
+      builder = CatalogProtos.PartitionDescProto.newBuilder();
+    }
+    if (this.partitionsType != null) {
+      builder.setPartitionsType(this.partitionsType);
+    }
+    builder.setSchema(schema.getProto());
+    builder.setNumPartitions(numPartitions);
+    builder.setIsOmitValues(isOmitValues);
+    if (this.specifiers != null) {
+      for(Specifier specifier: specifiers) {
+        builder.addSpecifiers(specifier.getProto());
+      }
+    }
+    return builder.build();
+  }
+
+  public String toString() {
+    Gson gson = new GsonBuilder().setPrettyPrinting().
+        excludeFieldsWithoutExposeAnnotation().create();
+    return gson.toJson(this);
+  }
+
+  @Override
+  public String toJson() {
+    return CatalogGsonHelper.toJson(this, PartitionDesc.class);
+
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/Partitions.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/Partitions.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/Partitions.java
deleted file mode 100644
index c82f0cb..0000000
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/Partitions.java
+++ /dev/null
@@ -1,349 +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.catalog.partition;
-
-import com.google.common.collect.ImmutableList;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.annotations.Expose;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.tajo.catalog.CatalogUtil;
-import org.apache.tajo.catalog.Column;
-import org.apache.tajo.catalog.exception.AlreadyExistsFieldException;
-import org.apache.tajo.catalog.json.CatalogGsonHelper;
-import org.apache.tajo.catalog.proto.CatalogProtos;
-import org.apache.tajo.common.ProtoObject;
-import org.apache.tajo.common.TajoDataTypes;
-import org.apache.tajo.json.GsonObject;
-import org.apache.tajo.util.TUtil;
-
-import java.util.*;
-
-public class Partitions implements ProtoObject<CatalogProtos.PartitionsProto>, Cloneable, GsonObject {
-
-  private static final Log LOG = LogFactory.getLog(Partitions.class);
-
-  @Expose protected CatalogProtos.PartitionsType partitionsType; //required
-  @Expose protected List<Column> columns; //required
-  @Expose protected int numPartitions; //optional
-  @Expose protected List<Specifier> specifiers; //optional
-  @Expose protected Map<String, Integer> columnsByQialifiedName = null;
-  @Expose protected Map<String, List<Integer>> columnsByName = null;
-
-  private CatalogProtos.PartitionsProto.Builder builder = CatalogProtos.PartitionsProto.newBuilder();
-
-  public Partitions() {
-    this.columns = new ArrayList<Column>();
-    this.columnsByQialifiedName = new TreeMap<String, Integer>();
-    this.columnsByName = new HashMap<String, List<Integer>>();
-  }
-
-  public Partitions(Partitions partition) {
-    this();
-    this.partitionsType = partition.partitionsType;
-    this.columns.addAll(partition.columns);
-    this.columnsByQialifiedName.putAll(partition.columnsByQialifiedName);
-    this.columnsByName.putAll(partition.columnsByName);
-    this.numPartitions = partition.numPartitions;
-    this.specifiers = partition.specifiers;
-  }
-
-  public Partitions(CatalogProtos.PartitionsType partitionsType, Column[] columns, int numPartitions,
-                   List<Specifier> specifiers) {
-    this();
-    this.partitionsType = partitionsType;
-    for (Column c : columns) {
-      addColumn(c);
-    }
-    this.numPartitions = numPartitions;
-    this.specifiers = specifiers;
-  }
-
-  public Partitions(CatalogProtos.PartitionsProto proto) {
-    this.partitionsType = proto.getPartitionsType();
-    this.columns = new ArrayList<Column>();
-    this.columnsByQialifiedName = new HashMap<String, Integer>();
-    this.columnsByName = new HashMap<String, List<Integer>>();
-    for (CatalogProtos.ColumnProto colProto : proto.getColumnsList()) {
-      Column tobeAdded = new Column(colProto);
-      columns.add(tobeAdded);
-      if (tobeAdded.hasQualifier()) {
-        columnsByQialifiedName.put(tobeAdded.getQualifier() + "." + tobeAdded.getColumnName(),
-            columns.size() - 1);
-      } else {
-        columnsByQialifiedName.put(tobeAdded.getColumnName(), columns.size() - 1);
-      }
-      if (columnsByName.containsKey(tobeAdded.getColumnName())) {
-        columnsByName.get(tobeAdded.getColumnName()).add(columns.size() - 1);
-      } else {
-        columnsByName.put(tobeAdded.getColumnName(), TUtil.newList(columns.size() - 1));
-      }
-    }
-    this.numPartitions = proto.getNumPartitions();
-    if(proto.getSpecifiersList() != null) {
-      this.specifiers = TUtil.newList();
-      for(CatalogProtos.SpecifierProto specifier: proto.getSpecifiersList()) {
-        this.specifiers.add(new Specifier(specifier));
-      }
-    }
-  }
-
-  /**
-   * Set a qualifier to this schema.
-   * This changes the qualifier of all columns except for not-qualified columns.
-   *
-   * @param qualifier The qualifier
-   */
-  public void setQualifier(String qualifier) {
-    setQualifier(qualifier, false);
-  }
-
-  /**
-   * Set a qualifier to this schema. This changes the qualifier of all columns if force is true.
-   * Otherwise, it changes the qualifier of all columns except for non-qualified columns
-   *
-   * @param qualifier The qualifier
-   * @param force     If true, all columns' qualifiers will be changed. Otherwise,
-   *                  only qualified columns' qualifiers will
-   *                  be changed.
-   */
-  public void setQualifier(String qualifier, boolean force) {
-    columnsByQialifiedName.clear();
-
-    for (int i = 0; i < getColumnNum(); i++) {
-      if (!force && columns.get(i).hasQualifier()) {
-        continue;
-      }
-      columns.get(i).setQualifier(qualifier);
-      columnsByQialifiedName.put(columns.get(i).getQualifiedName(), i);
-    }
-  }
-
-  public int getColumnNum() {
-    return this.columns.size();
-  }
-
-  public Column getColumn(int id) {
-    return columns.get(id);
-  }
-
-  public Column getColumnByFQN(String qualifiedName) {
-    Integer cid = columnsByQialifiedName.get(qualifiedName.toLowerCase());
-    return cid != null ? columns.get(cid) : null;
-  }
-
-  public Column getColumnByName(String colName) {
-    String normalized = colName.toLowerCase();
-    List<Integer> list = columnsByName.get(normalized);
-
-    if (list == null || list.size() == 0) {
-      return null;
-    }
-
-    if (list.size() == 1) {
-      return columns.get(list.get(0));
-    } else {
-      StringBuilder sb = new StringBuilder();
-      boolean first = true;
-      for (Integer id : list) {
-        if (first) {
-          first = false;
-        } else {
-          sb.append(", ");
-        }
-        sb.append(columns.get(id));
-      }
-      throw new RuntimeException("Ambiguous Column Name: " + sb.toString());
-    }
-  }
-
-  public int getColumnId(String qualifiedName) {
-    return columnsByQialifiedName.get(qualifiedName.toLowerCase());
-  }
-
-  public int getColumnIdByName(String colName) {
-    for (Column col : columns) {
-      if (col.getColumnName().equals(colName.toLowerCase())) {
-        return columnsByQialifiedName.get(col.getQualifiedName());
-      }
-    }
-    return -1;
-  }
-
-  public List<Column> getColumns() {
-    return ImmutableList.copyOf(columns);
-  }
-
-  public void setColumns(List<Column> columns) {
-    this.columns = columns;
-  }
-
-  public boolean contains(String colName) {
-    return columnsByQialifiedName.containsKey(colName.toLowerCase());
-
-  }
-
-  public boolean containsAll(Collection<Column> columns) {
-    return columns.containsAll(columns);
-  }
-
-  public synchronized Partitions addColumn(String name, TajoDataTypes.Type type) {
-    if (type == TajoDataTypes.Type.CHAR) {
-      return addColumn(name, CatalogUtil.newDataTypeWithLen(type, 1));
-    }
-    return addColumn(name, CatalogUtil.newSimpleDataType(type));
-  }
-
-  public synchronized Partitions addColumn(String name, TajoDataTypes.Type type, int length) {
-    return addColumn(name, CatalogUtil.newDataTypeWithLen(type, length));
-  }
-
-  public synchronized Partitions addColumn(String name, TajoDataTypes.DataType dataType) {
-    String normalized = name.toLowerCase();
-    if (columnsByQialifiedName.containsKey(normalized)) {
-      LOG.error("Already exists column " + normalized);
-      throw new AlreadyExistsFieldException(normalized);
-    }
-
-    Column newCol = new Column(normalized, dataType);
-    columns.add(newCol);
-    columnsByQialifiedName.put(newCol.getQualifiedName(), columns.size() - 1);
-    columnsByName.put(newCol.getColumnName(), TUtil.newList(columns.size() - 1));
-
-    return this;
-  }
-
-  public synchronized void addColumn(Column column) {
-    addColumn(column.getQualifiedName(), column.getDataType());
-  }
-
-  public synchronized void addColumns(Partitions schema) {
-    for (Column column : schema.getColumns()) {
-      addColumn(column);
-    }
-  }
-
-  public synchronized void addSpecifier(Specifier specifier) {
-    if(specifiers == null)
-      specifiers = TUtil.newList();
-
-    specifiers.add(specifier);
-  }
-
-  public CatalogProtos.PartitionsType getPartitionsType() {
-    return partitionsType;
-  }
-
-  public void setPartitionsType(CatalogProtos.PartitionsType partitionsType) {
-    this.partitionsType = partitionsType;
-  }
-
-  public int getNumPartitions() {
-    return numPartitions;
-  }
-
-  public void setNumPartitions(int numPartitions) {
-    this.numPartitions = numPartitions;
-  }
-
-  public List<Specifier> getSpecifiers() {
-    return specifiers;
-  }
-
-  public void setSpecifiers(List<Specifier> specifiers) {
-    this.specifiers = specifiers;
-  }
-
-  public Map<String, Integer> getColumnsByQialifiedName() {
-    return columnsByQialifiedName;
-  }
-
-  public void setColumnsByQialifiedName(Map<String, Integer> columnsByQialifiedName) {
-    this.columnsByQialifiedName = columnsByQialifiedName;
-  }
-
-  public Map<String, List<Integer>> getColumnsByName() {
-    return columnsByName;
-  }
-
-  public void setColumnsByName(Map<String, List<Integer>> columnsByName) {
-    this.columnsByName = columnsByName;
-  }
-
-  public boolean equals(Object o) {
-    if (o instanceof Partitions) {
-      Partitions other = (Partitions) o;
-      return getProto().equals(other.getProto());
-    }
-    return false;
-  }
-
-  public Object clone() throws CloneNotSupportedException {
-    Partitions clone = (Partitions) super.clone();
-    clone.builder = CatalogProtos.PartitionsProto.newBuilder();
-    clone.setPartitionsType(this.partitionsType);
-    clone.setColumns(this.columns);
-    clone.setNumPartitions(this.numPartitions);
-    clone.specifiers = new ArrayList<Specifier>(this.specifiers);
-
-    return clone;
-  }
-
-  @Override
-  public CatalogProtos.PartitionsProto getProto() {
-    if (builder == null) {
-      builder = CatalogProtos.PartitionsProto.newBuilder();
-    }
-    if (this.partitionsType != null) {
-      builder.setPartitionsType(this.partitionsType);
-    }
-    builder.clearColumns();
-    if (this.columns != null) {
-      for (Column col : columns) {
-        builder.addColumns(col.getProto());
-      }
-    }
-    builder.setNumPartitions(numPartitions);
-
-    if (this.specifiers != null) {
-      for(Specifier specifier: specifiers) {
-        builder.addSpecifiers(specifier.getProto());
-      }
-    }
-    return builder.build();
-  }
-
-  public String toString() {
-    Gson gson = new GsonBuilder().setPrettyPrinting().
-        excludeFieldsWithoutExposeAnnotation().create();
-    return gson.toJson(this);
-  }
-
-  @Override
-  public String toJson() {
-    return CatalogGsonHelper.toJson(this, Partitions.class);
-
-  }
-
-  public Column[] toArray() {
-    return this.columns.toArray(new Column[this.columns.size()]);
-  }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/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 e5af491..ad6ef3e 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
+++ b/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
@@ -113,7 +113,7 @@ message TableDescProto {
 	required TableProto meta = 3;
 	required SchemaProto schema = 4;
 	optional TableStatsProto stats = 5;
-	optional PartitionsProto partitions = 6;
+	optional PartitionDescProto partitions = 6;
 }
 
 enum FunctionType {
@@ -234,11 +234,12 @@ message SortSpecProto {
   optional bool nullFirst = 3 [default = false];
 }
 
-message PartitionsProto {
+message PartitionDescProto {
   required PartitionsType partitionsType = 1;
-  repeated ColumnProto columns = 2;
+  optional SchemaProto schema = 2;
   optional int32 numPartitions = 3;
   repeated SpecifierProto specifiers = 4;
+  optional bool isOmitValues = 5;
 }
 
 message SpecifierProto {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java
index 1747e68..1422cf2 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestSchema.java
@@ -140,7 +140,33 @@ public class TestSchema {
     Schema schema2 = new Schema(schema.getProto());
     schema2.setQualifier("test1");
     Column column = schema2.getColumn(1);
+    assertEquals(1, schema2.getColumnIdByName("age"));
     assertEquals(column, schema2.getColumnByName("age"));
     assertEquals(column, schema2.getColumnByFQN("test1.age"));
+
+    Schema schema3 = new Schema();
+    schema3.addColumn("tb1.col1", Type.INT4);
+    schema3.addColumn("col2", Type.INT4);
+    assertEquals("tb1", schema3.getColumn(0).getQualifier());
+    assertEquals("tb1.col1", schema3.getColumn(0).getQualifiedName());
+    assertEquals("col1", schema3.getColumn(0).getColumnName());
+    assertEquals("col2", schema3.getColumn(1).getQualifiedName());
+
+    assertEquals(schema3.getColumn(0), schema3.getColumnByName("col1"));
+    assertEquals(schema3.getColumn(0), schema3.getColumnByFQN("tb1.col1"));
+    assertEquals(schema3.getColumn(1), schema3.getColumnByName("col2"));
+    assertEquals(schema3.getColumn(1), schema3.getColumnByFQN("col2"));
+
+    schema3.setQualifier("tb2");
+    assertEquals("tb2", schema3.getColumn(0).getQualifier());
+    assertEquals("tb2.col1", schema3.getColumn(0).getQualifiedName());
+    assertEquals("col1", schema3.getColumn(0).getColumnName());
+    assertEquals("tb2.col2", schema3.getColumn(1).getQualifiedName());
+
+    assertEquals(schema3.getColumn(0), schema3.getColumnByName("col1"));
+    assertEquals(schema3.getColumn(0), schema3.getColumnByFQN("tb2.col1"));
+    assertEquals(schema3.getColumn(1), schema3.getColumnByName("col2"));
+    assertEquals(schema3.getColumn(1), schema3.getColumnByFQN("tb2.col2"));
+
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStore.java b/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStore.java
index e7a862a..74c7cb5 100644
--- a/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStore.java
+++ b/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStore.java
@@ -30,7 +30,7 @@ import org.apache.hcatalog.data.Pair;
 import org.apache.hcatalog.data.schema.HCatFieldSchema;
 import org.apache.hcatalog.data.schema.HCatSchema;
 import org.apache.tajo.catalog.*;
-import org.apache.tajo.catalog.partition.Partitions;
+import org.apache.tajo.catalog.partition.PartitionDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.statistics.TableStats;
 import org.apache.tajo.common.TajoDataTypes;
@@ -106,7 +106,7 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
     org.apache.tajo.catalog.Schema schema = null;
     Options options = null;
     TableStats stats = null;
-    Partitions partitions = null;
+    PartitionDesc partitions = null;
 
     // get db name and table name.
     try {
@@ -178,7 +178,7 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
       // set partition keys
       if (table.getPartitionKeys() != null) {
         if (table.getPartitionKeys().size() > 0) {
-          partitions = new Partitions();
+          partitions = new PartitionDesc();
           List<FieldSchema> partitionKeys = table.getPartitionKeys();
           for(int i = 0; i < partitionKeys.size(); i++) {
             FieldSchema fieldSchema = partitionKeys.get(i);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/test/java/org/apache/tajo/catalog/store/TestHCatalogStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/test/java/org/apache/tajo/catalog/store/TestHCatalogStore.java b/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/test/java/org/apache/tajo/catalog/store/TestHCatalogStore.java
index d8ee85e..9ab208f 100644
--- a/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/test/java/org/apache/tajo/catalog/store/TestHCatalogStore.java
+++ b/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/test/java/org/apache/tajo/catalog/store/TestHCatalogStore.java
@@ -265,7 +265,7 @@ public class TestHCatalogStore {
     assertEquals("type", columns.get(4).getColumnName());
     assertEquals(TajoDataTypes.Type.TEXT, columns.get(4).getDataType().getType());
     assertNotNull(table.getPartitions());
-    assertEquals("type", table.getPartitions().getColumn(0).getColumnName());
+    assertEquals("type", table.getPartitions().getSchema().getColumn(0).getColumnName());
     assertEquals(CatalogProtos.PartitionsType.COLUMN, table.getPartitions().getPartitionsType());
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/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 3414e83..60c88e9 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
@@ -26,7 +26,7 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.catalog.*;
-import org.apache.tajo.catalog.partition.Partitions;
+import org.apache.tajo.catalog.partition.PartitionDesc;
 import org.apache.tajo.catalog.partition.Specifier;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.ColumnProto;
@@ -284,8 +284,8 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       //Partition
       if (table.getPartitions() != null && !table.getPartitions().toString().isEmpty()) {
         try {
-          Partitions partitions = table.getPartitions();
-          List<Column> columnList = partitions.getColumns();
+          PartitionDesc partitionDesc = table.getPartitions();
+          List<Column> columnList = partitionDesc.getColumns();
 
           // Find columns which used for a partitioned table.
           StringBuffer columns = new StringBuffer();
@@ -320,19 +320,19 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
           }
 
           // Find information for subpartitions
-          if (partitions.getSpecifiers() != null) {
+          if (partitionDesc.getSpecifiers() != null) {
             int count = 1;
-            if (partitions.getSpecifiers().size() == 0) {
+            if (partitionDesc.getSpecifiers().size() == 0) {
               pstmt.clearParameters();
               pstmt.setString(1, null);
               pstmt.setInt(2, tid);
-              pstmt.setString(3, partitions.getPartitionsType().name());
-              pstmt.setInt(4, partitions.getNumPartitions());
+              pstmt.setString(3, partitionDesc.getPartitionsType().name());
+              pstmt.setInt(4, partitionDesc.getNumPartitions());
               pstmt.setString(5, columns.toString());
               pstmt.setString(6, null);
               pstmt.addBatch();
             } else {
-              for(Specifier specifier: partitions.getSpecifiers()) {
+              for(Specifier specifier: partitionDesc.getSpecifiers()) {
                 pstmt.clearParameters();
                 if (specifier.getName() != null && !specifier.getName().equals("")) {
                   pstmt.setString(1, specifier.getName());
@@ -340,8 +340,8 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
                   pstmt.setString(1, null);
                 }
                 pstmt.setInt(2, tid);
-                pstmt.setString(3, partitions.getPartitionsType().name());
-                pstmt.setInt(4, partitions.getNumPartitions());
+                pstmt.setString(3, partitionDesc.getPartitionsType().name());
+                pstmt.setInt(4, partitionDesc.getNumPartitions());
                 pstmt.setString(5, columns.toString());
                 pstmt.setString(6, specifier.getExpressions());
                 pstmt.addBatch();
@@ -352,8 +352,8 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
             pstmt.clearParameters();
             pstmt.setString(1, null);
             pstmt.setInt(2, tid);
-            pstmt.setString(3, partitions.getPartitionsType().name());
-            pstmt.setInt(4, partitions.getNumPartitions());
+            pstmt.setString(3, partitionDesc.getPartitionsType().name());
+            pstmt.setInt(4, partitionDesc.getNumPartitions());
             pstmt.setString(5, columns.toString());
             pstmt.setString(6, null);
             pstmt.addBatch();
@@ -496,7 +496,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     StoreType storeType = null;
     Options options;
     TableStats stat = null;
-    Partitions partitions = null;
+    PartitionDesc partitionDesc = null;
     int tid = 0;
 
     try {
@@ -602,18 +602,18 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       res = stmt.executeQuery(sql);
 
       while (res.next()) {
-        if (partitions == null) {
-          partitions = new Partitions();
+        if (partitionDesc == null) {
+          partitionDesc = new PartitionDesc();
           String[] columns = res.getString("columns").split(",");
           for(String eachColumn: columns) {
-            partitions.addColumn(getColumn(tableName, tid, eachColumn));
+            partitionDesc.addColumn(getColumn(tableName, tid, eachColumn));
           }
-          partitions.setPartitionsType(CatalogProtos.PartitionsType.valueOf(res.getString("type")));
-          partitions.setNumPartitions(res.getInt("quantity"));
+          partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.valueOf(res.getString("type")));
+          partitionDesc.setNumPartitions(res.getInt("quantity"));
         }
 
         Specifier specifier = new Specifier(res.getString("name"), res.getString("expressions"));
-        partitions.addSpecifier(specifier);
+        partitionDesc.addSpecifier(specifier);
       }
 
     } catch (SQLException se) {
@@ -628,8 +628,8 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       table.setStats(stat);
     }
 
-    if (partitions != null) {
-      table.setPartitions(partitions);
+    if (partitionDesc != null) {
+      table.setPartitions(partitionDesc);
     }
 
     return table;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/DerbyStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/DerbyStore.java b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/DerbyStore.java
index 06a701b..f21ab0e 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/DerbyStore.java
+++ b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/DerbyStore.java
@@ -24,7 +24,7 @@ package org.apache.tajo.catalog.store;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.catalog.*;
-import org.apache.tajo.catalog.partition.Partitions;
+import org.apache.tajo.catalog.partition.PartitionDesc;
 import org.apache.tajo.catalog.partition.Specifier;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.ColumnProto;
@@ -375,8 +375,8 @@ public class DerbyStore extends AbstractDBStore {
       //Partition
       if (table.getPartitions() != null && !table.getPartitions().toString().isEmpty()) {
         try {
-          Partitions partitions = table.getPartitions();
-          List<Column> columnList = partitions.getColumns();
+          PartitionDesc partitionDesc = table.getPartitions();
+          List<Column> columnList = partitionDesc.getColumns();
 
           // Find columns which used for a partitioned table.
           StringBuffer columns = new StringBuffer();
@@ -411,19 +411,19 @@ public class DerbyStore extends AbstractDBStore {
           }
 
           // Find information for subpartitions
-          if (partitions.getSpecifiers() != null) {
+          if (partitionDesc.getSpecifiers() != null) {
             int count = 1;
-            if (partitions.getSpecifiers().size() == 0) {
+            if (partitionDesc.getSpecifiers().size() == 0) {
               pstmt.clearParameters();
               pstmt.setString(1, null);
               pstmt.setInt(2, tid);
-              pstmt.setString(3, partitions.getPartitionsType().name());
-              pstmt.setInt(4, partitions.getNumPartitions());
+              pstmt.setString(3, partitionDesc.getPartitionsType().name());
+              pstmt.setInt(4, partitionDesc.getNumPartitions());
               pstmt.setString(5, columns.toString());
               pstmt.setString(6, null);
               pstmt.addBatch();
             } else {
-              for(Specifier eachValue: partitions.getSpecifiers()) {
+              for(Specifier eachValue: partitionDesc.getSpecifiers()) {
                 pstmt.clearParameters();
                 if (eachValue.getName() != null && !eachValue.getName().equals("")) {
                   pstmt.setString(1, eachValue.getName());
@@ -431,8 +431,8 @@ public class DerbyStore extends AbstractDBStore {
                   pstmt.setString(1, null);
                 }
                 pstmt.setInt(2, tid);
-                pstmt.setString(3, partitions.getPartitionsType().name());
-                pstmt.setInt(4, partitions.getNumPartitions());
+                pstmt.setString(3, partitionDesc.getPartitionsType().name());
+                pstmt.setInt(4, partitionDesc.getNumPartitions());
                 pstmt.setString(5, columns.toString());
                 pstmt.setString(6, eachValue.getExpressions());
                 pstmt.addBatch();
@@ -443,8 +443,8 @@ public class DerbyStore extends AbstractDBStore {
             pstmt.clearParameters();
             pstmt.setString(1, null);
             pstmt.setInt(2, tid);
-            pstmt.setString(3, partitions.getPartitionsType().name());
-            pstmt.setInt(4, partitions.getNumPartitions());
+            pstmt.setString(3, partitionDesc.getPartitionsType().name());
+            pstmt.setInt(4, partitionDesc.getNumPartitions());
             pstmt.setString(5, columns.toString());
             pstmt.setString(6, null);
             pstmt.addBatch();
@@ -596,7 +596,7 @@ public class DerbyStore extends AbstractDBStore {
     StoreType storeType = null;
     Options options;
     TableStats stat = null;
-    Partitions partitions = null;
+    PartitionDesc partitionDesc = null;
     int tid = 0;
 
     try {
@@ -706,19 +706,19 @@ public class DerbyStore extends AbstractDBStore {
         res = stmt.executeQuery(sql);
 
         while (res.next()) {
-          if (partitions == null) {
-            partitions = new Partitions();
+          if (partitionDesc == null) {
+            partitionDesc = new PartitionDesc();
             String[] columns = res.getString("columns").split(",");
             for(String eachColumn: columns) {
-              partitions.addColumn(getColumn(tableName, tid, eachColumn));
+              partitionDesc.addColumn(getColumn(tableName, tid, eachColumn));
             }
-            partitions.setPartitionsType(CatalogProtos.PartitionsType.valueOf(res.getString
+            partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.valueOf(res.getString
                 ("type")));
-            partitions.setNumPartitions(res.getInt("quantity"));
+            partitionDesc.setNumPartitions(res.getInt("quantity"));
           }
 
           Specifier specifier = new Specifier(res.getString("name"), res.getString("expressions"));
-          partitions.addSpecifier(specifier);
+          partitionDesc.addSpecifier(specifier);
         }
 
       } catch (SQLException se) {
@@ -733,8 +733,8 @@ public class DerbyStore extends AbstractDBStore {
         table.setStats(stat);
       }
 
-      if (partitions != null) {
-        table.setPartitions(partitions);
+      if (partitionDesc != null) {
+        table.setPartitions(partitionDesc);
       }
 
       return table;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/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 d174e72..3abbb81 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
@@ -20,7 +20,7 @@ package org.apache.tajo.catalog;
 
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.catalog.function.Function;
-import org.apache.tajo.catalog.partition.Partitions;
+import org.apache.tajo.catalog.partition.PartitionDesc;
 import org.apache.tajo.catalog.partition.Specifier;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.FunctionType;
@@ -214,13 +214,13 @@ public class TestCatalog {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.HASH);
-    partitions.setNumPartitions(2);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.HASH);
+    partitionDesc.setNumPartitions(2);
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
 
     assertFalse(catalog.existsTable(tableName));
     catalog.addTable(desc);
@@ -229,7 +229,7 @@ public class TestCatalog {
 
     assertEquals(retrieved.getName(), tableName);
     assertEquals(retrieved.getPartitions().getPartitionsType(), CatalogProtos.PartitionsType.HASH);
-    assertEquals(retrieved.getPartitions().getColumn(0).getColumnName(), "id");
+    assertEquals(retrieved.getPartitions().getSchema().getColumn(0).getColumnName(), "id");
     assertEquals(retrieved.getPartitions().getNumPartitions(), 2);
 
     catalog.deleteTable(tableName);
@@ -250,17 +250,17 @@ public class TestCatalog {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.HASH);
-    partitions.setNumPartitions(2);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.HASH);
+    partitionDesc.setNumPartitions(2);
 
-    partitions.addSpecifier(new Specifier("sub_part1"));
-    partitions.addSpecifier(new Specifier("sub_part2"));
-    partitions.addSpecifier(new Specifier("sub_part3"));
+    partitionDesc.addSpecifier(new Specifier("sub_part1"));
+    partitionDesc.addSpecifier(new Specifier("sub_part2"));
+    partitionDesc.addSpecifier(new Specifier("sub_part3"));
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
     assertFalse(catalog.existsTable(tableName));
     catalog.addTable(desc);
     assertTrue(catalog.existsTable(tableName));
@@ -269,7 +269,7 @@ public class TestCatalog {
 
     assertEquals(retrieved.getName(), tableName);
     assertEquals(retrieved.getPartitions().getPartitionsType(), CatalogProtos.PartitionsType.HASH);
-    assertEquals(retrieved.getPartitions().getColumn(0).getColumnName(), "id");
+    assertEquals(retrieved.getPartitions().getSchema().getColumn(0).getColumnName(), "id");
     assertEquals(retrieved.getPartitions().getNumPartitions(), 2);
     assertEquals(retrieved.getPartitions().getSpecifiers().get(0).getName(),
         "sub_part1");
@@ -295,15 +295,15 @@ public class TestCatalog {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.LIST);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.LIST);
 
-    partitions.addSpecifier(new Specifier("sub_part1", "Seoul,서울"));
-    partitions.addSpecifier(new Specifier("sub_part2", "Busan,부산"));
+    partitionDesc.addSpecifier(new Specifier("sub_part1", "Seoul,서울"));
+    partitionDesc.addSpecifier(new Specifier("sub_part2", "Busan,부산"));
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
     assertFalse(catalog.existsTable(tableName));
     catalog.addTable(desc);
     assertTrue(catalog.existsTable(tableName));
@@ -312,7 +312,7 @@ public class TestCatalog {
 
     assertEquals(retrieved.getName(), tableName);
     assertEquals(retrieved.getPartitions().getPartitionsType(), CatalogProtos.PartitionsType.LIST);
-    assertEquals(retrieved.getPartitions().getColumn(0).getColumnName(), "id");
+    assertEquals(retrieved.getPartitions().getSchema().getColumn(0).getColumnName(), "id");
     assertEquals(retrieved.getPartitions().getSpecifiers().get(0).getName(),
         "sub_part1");
     assertEquals(retrieved.getPartitions().getSpecifiers().get(0).getExpressions(),
@@ -339,16 +339,16 @@ public class TestCatalog {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.RANGE);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.RANGE);
 
-    partitions.addSpecifier(new Specifier("sub_part1", "2"));
-    partitions.addSpecifier(new Specifier("sub_part2", "5"));
-    partitions.addSpecifier(new Specifier("sub_part3"));
+    partitionDesc.addSpecifier(new Specifier("sub_part1", "2"));
+    partitionDesc.addSpecifier(new Specifier("sub_part2", "5"));
+    partitionDesc.addSpecifier(new Specifier("sub_part3"));
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
     assertFalse(catalog.existsTable(tableName));
     catalog.addTable(desc);
     assertTrue(catalog.existsTable(tableName));
@@ -357,7 +357,7 @@ public class TestCatalog {
 
     assertEquals(retrieved.getName(), tableName);
     assertEquals(retrieved.getPartitions().getPartitionsType(), CatalogProtos.PartitionsType.RANGE);
-    assertEquals(retrieved.getPartitions().getColumn(0).getColumnName(), "id");
+    assertEquals(retrieved.getPartitions().getSchema().getColumn(0).getColumnName(), "id");
     assertEquals(retrieved.getPartitions().getSpecifiers().get(0).getName(),
         "sub_part1");
     assertEquals(retrieved.getPartitions().getSpecifiers().get(0).getExpressions(),
@@ -388,12 +388,12 @@ public class TestCatalog {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.COLUMN);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.COLUMN);
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
     assertFalse(catalog.existsTable(tableName));
     catalog.addTable(desc);
     assertTrue(catalog.existsTable(tableName));
@@ -402,7 +402,7 @@ public class TestCatalog {
 
     assertEquals(retrieved.getName(), tableName);
     assertEquals(retrieved.getPartitions().getPartitionsType(), CatalogProtos.PartitionsType.COLUMN);
-    assertEquals(retrieved.getPartitions().getColumn(0).getColumnName(), "id");
+    assertEquals(retrieved.getPartitions().getSchema().getColumn(0).getColumnName(), "id");
 
     catalog.deleteTable(tableName);
     assertFalse(catalog.existsTable(tableName));

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestDBStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestDBStore.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestDBStore.java
index d3671b3..1949afc 100644
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestDBStore.java
+++ b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestDBStore.java
@@ -22,7 +22,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
-import org.apache.tajo.catalog.partition.Partitions;
+import org.apache.tajo.catalog.partition.PartitionDesc;
 import org.apache.tajo.catalog.partition.Specifier;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
@@ -236,13 +236,13 @@ public class TestDBStore {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.HASH);
-    partitions.setNumPartitions(2);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.HASH);
+    partitionDesc.setNumPartitions(2);
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
     assertFalse(store.existTable(tableName));
     store.addTable(desc);
     assertTrue(store.existTable(tableName));
@@ -268,17 +268,17 @@ public class TestDBStore {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.HASH);
-    partitions.setNumPartitions(2);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.HASH);
+    partitionDesc.setNumPartitions(2);
 
-    partitions.addSpecifier(new Specifier("sub_part1"));
-    partitions.addSpecifier(new Specifier("sub_part2"));
-    partitions.addSpecifier(new Specifier("sub_part3"));
+    partitionDesc.addSpecifier(new Specifier("sub_part1"));
+    partitionDesc.addSpecifier(new Specifier("sub_part2"));
+    partitionDesc.addSpecifier(new Specifier("sub_part3"));
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
     assertFalse(store.existTable(tableName));
     store.addTable(desc);
     assertTrue(store.existTable(tableName));
@@ -304,15 +304,15 @@ public class TestDBStore {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.LIST);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.LIST);
 
-    partitions.addSpecifier(new Specifier("sub_part1", "Seoul,서울"));
-    partitions.addSpecifier(new Specifier("sub_part2", "Busan,부산"));
+    partitionDesc.addSpecifier(new Specifier("sub_part1", "Seoul,서울"));
+    partitionDesc.addSpecifier(new Specifier("sub_part2", "Busan,부산"));
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
     assertFalse(store.existTable(tableName));
     store.addTable(desc);
     assertTrue(store.existTable(tableName));
@@ -338,16 +338,16 @@ public class TestDBStore {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.RANGE);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.RANGE);
 
-    partitions.addSpecifier(new Specifier("sub_part1", "2"));
-    partitions.addSpecifier(new Specifier("sub_part2", "5"));
-    partitions.addSpecifier(new Specifier("sub_part3"));
+    partitionDesc.addSpecifier(new Specifier("sub_part1", "2"));
+    partitionDesc.addSpecifier(new Specifier("sub_part2", "5"));
+    partitionDesc.addSpecifier(new Specifier("sub_part3"));
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
     assertFalse(store.existTable(tableName));
     store.addTable(desc);
     assertTrue(store.existTable(tableName));
@@ -373,12 +373,12 @@ public class TestDBStore {
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    Partitions partitions = new Partitions();
-    partitions.addColumn(new Column("id", Type.INT4));
-    partitions.setPartitionsType(CatalogProtos.PartitionsType.COLUMN);
+    PartitionDesc partitionDesc = new PartitionDesc();
+    partitionDesc.addColumn(new Column("id", Type.INT4));
+    partitionDesc.setPartitionsType(CatalogProtos.PartitionsType.COLUMN);
 
     TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitions(partitions);
+    desc.setPartitions(partitionDesc);
     assertFalse(store.existTable(tableName));
     store.addTable(desc);
     assertTrue(store.existTable(tableName));

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
index bf4d83d..56fd3b5 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
@@ -24,6 +24,8 @@ import org.apache.tajo.datum.exception.InvalidOperationException;
 
 public class BooleanDatum extends Datum {
 	@Expose private boolean val;
+  public static final String TRUE="t";
+  public static final String FALSE="f";
 
   public BooleanDatum() {
     super(TajoDataTypes.Type.BOOLEAN);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java b/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java
index 343bbfe..2082225 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java
@@ -69,6 +69,40 @@ public class DatumFactory {
     }
   }
 
+  public static Datum createFromString(DataType dataType, String value) {
+    switch (dataType.getType()) {
+
+    case BOOLEAN:
+      return createBool(value.equals(BooleanDatum.TRUE));
+    case INT2:
+      return createInt2(value);
+    case INT4:
+      return createInt4(value);
+    case INT8:
+      return createInt8(value);
+    case FLOAT4:
+      return createFloat4(value);
+    case FLOAT8:
+      return createFloat8(value);
+    case CHAR:
+      return createChar(value);
+    case TEXT:
+      return createText(value);
+    case DATE:
+      return createDate(value);
+    case TIME:
+      return createTime(value);
+    case TIMESTAMP:
+      return createTimeStamp(value);
+    case BLOB:
+      return createBlob(value);
+    case INET4:
+      return createInet4(value);
+    default:
+      throw new UnsupportedOperationException(dataType.toString());
+    }
+  }
+
   public static Datum createFromBytes(DataType dataType, byte[] bytes) {
     switch (dataType.getType()) {
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java b/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
index 5b5a406..2f81ef4 100644
--- a/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
+++ b/tajo-common/src/main/java/org/apache/tajo/util/TUtil.java
@@ -183,7 +183,7 @@ public class TUtil {
   }
 
   public static String arrayToString(Object [] objects) {
-    boolean first = false;
+    boolean first = true;
     StringBuilder sb = new StringBuilder();
     for(Object object : objects) {
       if (first) {

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4 b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
index a19f3e9..3bc9ff4 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
+++ b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
@@ -290,7 +290,6 @@ Nonreserved_keywords
 
   | MAXVALUE
 
-  | VALUES
   | PARTITION
   | PARTITIONS
   | ROLLUP
@@ -305,6 +304,8 @@ Nonreserved_keywords
   | THAN
   | TRIM
   | TO
+
+  | VALUES
   ;
 
 /*

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4 b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
index 0728008..54e43c7 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
+++ b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
@@ -152,7 +152,7 @@ list_value_partition
   ;
 
 column_partitions
-  : PARTITION BY COLUMN LEFT_PAREN column_reference_list RIGHT_PAREN
+  : PARTITION BY COLUMN table_elements
   ;
 
 partition_name

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/f58f6ee8/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
index a5ee425..e933ddb 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
@@ -20,6 +20,8 @@ package org.apache.tajo.engine.eval;
 
 import org.apache.tajo.catalog.Column;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 public class AlgebraicUtil {
@@ -51,7 +53,7 @@ public class AlgebraicUtil {
   }
   
   private static EvalNode _transpose(EvalNode _expr, Column target) {
-     EvalNode expr = simplify(_expr);
+     EvalNode expr = eliminateConstantExprs(_expr);
      
      if (isSingleVar(expr.getLeftExpr())) {
        return expr;
@@ -128,7 +130,7 @@ public class AlgebraicUtil {
    * @param expr to be simplified
    * @return the simplified expr
    */
-  public static EvalNode simplify(EvalNode expr) {
+  public static EvalNode eliminateConstantExprs(EvalNode expr) {
     EvalNode left = expr.getLeftExpr();
     EvalNode right = expr.getRightExpr();
     
@@ -136,31 +138,27 @@ public class AlgebraicUtil {
     case AND:
     case OR:
     case EQUAL:
+    case NOT_EQUAL:
     case LTH:
     case LEQ:
     case GTH:
     case GEQ:
-      left = simplify(left);
-      right = simplify(right);      
-      return new BinaryEval(expr.getType(), left, right);    
-    
     case PLUS:
     case MINUS:
     case MULTIPLY:
     case DIVIDE:
-      left = simplify(left);
-      right = simplify(right);
-      
-      // If both are constants, they can be evaluated immediately.
-      if (left.getType() == EvalType.CONST
-          && right.getType() == EvalType.CONST) {
+    case MODULAR:
+      left = eliminateConstantExprs(left);
+      right = eliminateConstantExprs(right);
+
+      if (left.getType() == EvalType.CONST && right.getType() == EvalType.CONST) {
         EvalContext exprCtx = expr.newContext();
         expr.eval(exprCtx, null, null);
         return new ConstEval(expr.terminate(exprCtx));
       } else {
-        return new BinaryEval(expr.getType(), left, right);            
+        return new BinaryEval(expr.getType(), left, right);
       }
-      
+
     case CONST:
       return expr;
       
@@ -286,4 +284,112 @@ public class AlgebraicUtil {
     
     return expr;
   }
+
+  public static boolean isComparisonOperator(EvalNode expr) {
+    return expr.getType() == EvalType.EQUAL ||
+        expr.getType() == EvalType.LEQ ||
+        expr.getType() == EvalType.LTH ||
+        expr.getType() == EvalType.GEQ ||
+        expr.getType() == EvalType.GTH ||
+        expr.getType() == EvalType.BETWEEN;
+  }
+
+  public static boolean isIndexableOperator(EvalNode expr) {
+    return expr.getType() == EvalType.EQUAL ||
+        expr.getType() == EvalType.LEQ ||
+        expr.getType() == EvalType.LTH ||
+        expr.getType() == EvalType.GEQ ||
+        expr.getType() == EvalType.GTH ||
+        expr.getType() == EvalType.BETWEEN ||
+        expr.getType() == EvalType.IN ||
+        (expr.getType() == EvalType.LIKE && !((LikePredicateEval)expr).isLeadingWildCard());
+  }
+
+  /**
+   * Convert a list of conjunctive normal forms into a singleton expression.
+   *
+   * @param cnfExprs
+   * @return The EvalNode object that merges all CNF-formed expressions.
+   */
+  public static EvalNode createSingletonExprFromCNF(EvalNode... cnfExprs) {
+    if (cnfExprs.length == 1) {
+      return cnfExprs[0];
+    }
+
+    return createSingletonExprFromCNFRecursive(cnfExprs, 0);
+  }
+
+  private static EvalNode createSingletonExprFromCNFRecursive(EvalNode[] evalNode, int idx) {
+    if (idx == evalNode.length - 2) {
+      return new BinaryEval(EvalType.AND, evalNode[idx], evalNode[idx + 1]);
+    } else {
+      return new BinaryEval(EvalType.AND, evalNode[idx], createSingletonExprFromCNFRecursive(evalNode, idx + 1));
+    }
+  }
+
+  /**
+   * Transforms a expression to an array of conjunctive normal formed expressions.
+   *
+   * @param expr The expression to be transformed to an array of CNF-formed expressions.
+   * @return An array of CNF-formed expressions
+   */
+  public static EvalNode [] toConjunctiveNormalFormArray(EvalNode expr) {
+    List<EvalNode> list = new ArrayList<EvalNode>();
+    toConjunctiveNormalFormArrayRecursive(expr, list);
+    return list.toArray(new EvalNode[list.size()]);
+  }
+
+  private static void toConjunctiveNormalFormArrayRecursive(EvalNode node, List<EvalNode> found) {
+    if (node.getType() == EvalType.AND) {
+      toConjunctiveNormalFormArrayRecursive(node.getLeftExpr(), found);
+      toConjunctiveNormalFormArrayRecursive(node.getRightExpr(), found);
+    } else {
+      found.add(node);
+    }
+  }
+
+  /**
+   * Convert a list of conjunctive normal forms into a singleton expression.
+   *
+   * @param cnfExprs
+   * @return The EvalNode object that merges all CNF-formed expressions.
+   */
+  public static EvalNode createSingletonExprFromDNF(EvalNode... cnfExprs) {
+    if (cnfExprs.length == 1) {
+      return cnfExprs[0];
+    }
+
+    return createSingletonExprFromDNFRecursive(cnfExprs, 0);
+  }
+
+  private static EvalNode createSingletonExprFromDNFRecursive(EvalNode[] evalNode, int idx) {
+    if (idx == evalNode.length - 2) {
+      return new BinaryEval(EvalType.OR, evalNode[idx], evalNode[idx + 1]);
+    } else {
+      return new BinaryEval(EvalType.OR, evalNode[idx], createSingletonExprFromDNFRecursive(evalNode, idx + 1));
+    }
+  }
+
+  /**
+   * Transforms a expression to an array of disjunctive normal formed expressions.
+   *
+   * @param exprs The expressions to be transformed to an array of CNF-formed expressions.
+   * @return An array of CNF-formed expressions
+   */
+  public static EvalNode [] toDisjunctiveNormalFormArray(EvalNode...exprs) {
+    List<EvalNode> list = new ArrayList<EvalNode>();
+    for (EvalNode expr : exprs) {
+      toDisjunctiveNormalFormArrayRecursive(expr, list);
+    }
+    return list.toArray(new EvalNode[list.size()]);
+  }
+
+  private static void toDisjunctiveNormalFormArrayRecursive(EvalNode node, List<EvalNode> found) {
+    if (node.getType() == EvalType.OR) {
+      toDisjunctiveNormalFormArrayRecursive(node.getLeftExpr(), found);
+      toDisjunctiveNormalFormArrayRecursive(node.getRightExpr(), found);
+    } else {
+      found.add(node);
+    }
+  }
 }


Mime
View raw message