TAJO-1300: Merge the index branch into the master branch.

Closes #651


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

Branch: refs/heads/master
Commit: 9840d378522ae921d32c04f21b3e0673fc9dd90c
Parents: 97e61e6
Author: Jihoon Son <[email protected]>
Authored: Thu Jul 30 13:37:40 2015 +0900
Committer: Jihoon Son <[email protected]>
Committed: Thu Jul 30 13:37:40 2015 +0900

----------------------------------------------------------------------
 CHANGES                                         |  13 ++
 .../org/apache/tajo/algebra/CreateDatabase.java |   2 +-
 .../org/apache/tajo/algebra/CreateIndex.java    | 146 +++++++++++++
 .../org/apache/tajo/algebra/CreateTable.java    |   2 +-
 .../java/org/apache/tajo/algebra/DropIndex.java |  54 +++++
 .../java/org/apache/tajo/algebra/Insert.java    |   2 +-
 .../java/org/apache/tajo/algebra/OpType.java    |   2 +
 .../tajo/catalog/AbstractCatalogClient.java     | 122 ++++++++---
 .../src/main/proto/CatalogProtocol.proto        |  18 +-
 .../apache/tajo/catalog/CatalogConstants.java   |   1 +
 .../org/apache/tajo/catalog/CatalogService.java |  24 ++-
 .../org/apache/tajo/catalog/CatalogUtil.java    |  46 ++++-
 .../org/apache/tajo/catalog/DDLBuilder.java     |  22 ++
 .../java/org/apache/tajo/catalog/IndexDesc.java | 126 +++++++-----
 .../java/org/apache/tajo/catalog/IndexMeta.java | 180 ++++++++++++++++
 .../java/org/apache/tajo/catalog/TableDesc.java |   5 -
 .../exception/UndefinedIndexException.java      |   2 +-
 .../src/main/proto/CatalogProtos.proto          |  48 ++---
 .../org/apache/tajo/catalog/TestIndexDesc.java  |  59 ++++--
 .../tajo/catalog/store/HiveCatalogStore.java    |  50 +++--
 .../org/apache/tajo/catalog/CatalogServer.java  | 148 +++++++++----
 .../dictionary/IndexesTableDescriptor.java      |   8 +-
 .../tajo/catalog/store/AbstractDBStore.java     | 184 ++++++++++-------
 .../apache/tajo/catalog/store/CatalogStore.java |  29 +--
 .../org/apache/tajo/catalog/store/MemStore.java | 113 ++++++----
 .../src/main/resources/schemas/derby/derby.xml  |  32 +--
 .../main/resources/schemas/mariadb/mariadb.xml  |  20 +-
 .../src/main/resources/schemas/mysql/mysql.xml  |  20 +-
 .../main/resources/schemas/oracle/oracle.xml    |  30 +--
 .../resources/schemas/postgresql/postgresql.xml |  32 +--
 .../org/apache/tajo/catalog/TestCatalog.java    |  89 ++++----
 .../org/apache/tajo/cli/tools/TajoDump.java     |  14 +-
 .../cli/tsql/commands/DescTableCommand.java     |  19 ++
 .../apache/tajo/client/CatalogAdminClient.java  |  15 ++
 .../tajo/client/CatalogAdminClientImpl.java     | 110 +++++++++-
 .../org/apache/tajo/client/QueryClientImpl.java |   4 +-
 .../apache/tajo/client/SessionConnection.java   |   1 -
 .../org/apache/tajo/client/TajoClientImpl.java  |  36 ++++
 tajo-client/src/main/proto/ClientProtos.proto   |  10 +
 .../main/proto/TajoMasterClientProtocol.proto   |   9 +
 .../java/org/apache/tajo/OverridableConf.java   |   2 +-
 .../main/java/org/apache/tajo/SessionVars.java  |   5 +
 .../java/org/apache/tajo/conf/TajoConf.java     |   6 +-
 .../apache/tajo/exception/ErrorMessages.java    |   3 +
 .../apache/tajo/exception/ReturnStateUtil.java  |  11 +-
 .../main/java/org/apache/tajo/util/TUtil.java   |  10 +
 tajo-common/src/main/proto/errors.proto         |  11 +-
 .../org/apache/tajo/engine/parser/SQLParser.g4  |  13 +-
 .../engine/codegen/ExecutorPreCompiler.java     |   7 +
 .../apache/tajo/engine/parser/SQLAnalyzer.java  |  47 +++++
 .../engine/planner/PhysicalPlannerImpl.java     |  34 ++-
 .../engine/planner/global/GlobalPlanner.java    |  23 +++
 .../planner/physical/BSTIndexScanExec.java      | 173 +++++++++++++---
 .../engine/planner/physical/ProjectionExec.java |   4 +-
 .../engine/planner/physical/StoreIndexExec.java | 102 +++++++++
 .../utils/test/ErrorInjectionRewriter.java      |   7 +-
 .../org/apache/tajo/master/GlobalEngine.java    |   3 +-
 .../tajo/master/TajoMasterClientService.java    | 204 +++++++++++++++++-
 .../apache/tajo/master/exec/DDLExecutor.java    | 134 +++++++++---
 .../NonForwardQueryResultSystemScanner.java     |  40 ++--
 .../apache/tajo/master/exec/QueryExecutor.java  |  42 +++-
 .../java/org/apache/tajo/querymaster/Query.java |  46 +++++
 .../tajo/querymaster/QueryMasterTask.java       |  13 +-
 .../java/org/apache/tajo/util/IndexUtil.java    | 152 --------------
 .../tajo/worker/TajoWorkerClientService.java    |   2 +-
 .../apache/tajo/worker/TaskAttemptContext.java  |  13 +-
 .../java/org/apache/tajo/worker/TaskImpl.java   |  29 ++-
 .../tajo/ws/rs/resources/QueryResource.java     |   4 +-
 .../java/org/apache/tajo/QueryTestCaseBase.java |   3 +
 .../org/apache/tajo/cli/tools/TestTajoDump.java |  95 +++++++--
 .../apache/tajo/engine/eval/ExprTestBase.java   |  12 +-
 .../engine/planner/TestJoinOrderAlgorithm.java  |   2 +-
 .../engine/planner/TestLogicalOptimizer.java    |   3 +-
 .../tajo/engine/planner/TestLogicalPlanner.java |  36 +++-
 .../planner/physical/TestBSTIndexExec.java      | 206 -------------------
 .../planner/physical/TestHashAntiJoinExec.java  |   6 +-
 .../planner/physical/TestHashSemiJoinExec.java  |   6 +-
 .../planner/physical/TestPhysicalPlanner.java   |  18 +-
 .../engine/planner/physical/TestSortExec.java   |   6 +-
 .../planner/physical/TestSortIntersectExec.java |   2 +-
 .../tajo/engine/query/TestCreateIndex.java      | 113 ++++++++++
 .../apache/tajo/engine/query/TestIndexScan.java | 144 +++++++++++++
 .../tajo/engine/query/TestTablePartitions.java  |   8 +-
 .../tajo/master/TestExecutionBlockCursor.java   |   2 +-
 .../apache/tajo/querymaster/TestKillQuery.java  |   4 +-
 .../queries/TestCreateIndex/testCreateIndex.sql |   1 +
 .../testCreateIndexOnExpression.sql             |   1 +
 .../testCreateIndexOnLocation.sql               |   1 +
 .../testCreateIndexOnMultiAttrs.sql             |   1 +
 .../testCreateIndexOnMultiExprs.sql             |   1 +
 .../testCreateIndexWithCondition.sql            |   1 +
 .../TestIndexScan/testOnMultipleExprs.result    |   3 +
 .../TestIndexScan/testOnMultipleKeys.result     |   3 +
 .../TestIndexScan/testOnMultipleKeys2.result    |   3 +
 .../testOnSortedNonUniqueKeys.result            |   4 +
 .../TestIndexScan/testOnUnsortedTextKeys.result |   3 +
 .../TestIndexScan/testWithGroupBy.result        |   3 +
 .../results/TestIndexScan/testWithJoin.result   |   4 +
 .../results/TestIndexScan/testWithSort.result   |   4 +
 .../TestTajoCli/testHelpSessionVars.result      |   2 +
 .../results/TestTajoDump/testDump3.result       |  20 ++
 tajo-docs/src/main/sphinx/index/how_to_use.rst  |   2 +-
 .../org/apache/tajo/jdbc/TajoStatement.java     |   3 +-
 .../org/apache/tajo/plan/LogicalOptimizer.java  |  12 +-
 .../java/org/apache/tajo/plan/LogicalPlan.java  |  28 +++
 .../tajo/plan/LogicalPlanPreprocessor.java      |  17 ++
 .../org/apache/tajo/plan/LogicalPlanner.java    |  93 ++++++++-
 .../org/apache/tajo/plan/NamedExprsManager.java |   1 +
 .../tajo/plan/algebra/AlgebraVisitor.java       |   2 +
 .../tajo/plan/algebra/BaseAlgebraVisitor.java   |  17 ++
 .../apache/tajo/plan/expr/AlgebraicUtil.java    |  70 +++++++
 .../org/apache/tajo/plan/expr/EvalTreeUtil.java |   6 +-
 .../tajo/plan/logical/CreateIndexNode.java      | 161 +++++++++++++++
 .../apache/tajo/plan/logical/DropIndexNode.java |  92 +++++++++
 .../apache/tajo/plan/logical/IndexScanNode.java |  92 ++++-----
 .../org/apache/tajo/plan/logical/NodeType.java  |   4 +-
 .../rewrite/BaseLogicalPlanRewriteEngine.java   |   9 +-
 .../BaseLogicalPlanRewriteRuleProvider.java     |   4 +-
 .../plan/rewrite/LogicalPlanRewriteEngine.java  |   3 +-
 .../plan/rewrite/LogicalPlanRewriteRule.java    |   6 +-
 .../rewrite/LogicalPlanRewriteRuleContext.java  |  65 ++++++
 .../tajo/plan/rewrite/rules/AccessPathInfo.java |  52 +++++
 .../plan/rewrite/rules/AccessPathRewriter.java  | 129 ++++++++++++
 .../plan/rewrite/rules/FilterPushDownRule.java  |  95 ++++++++-
 .../tajo/plan/rewrite/rules/IndexScanInfo.java  | 113 ++++++++++
 .../rules/LogicalPlanEqualityTester.java        |   9 +-
 .../rewrite/rules/PartitionedTableRewriter.java |  10 +-
 .../rewrite/rules/ProjectionPushDownRule.java   |  21 +-
 .../tajo/plan/rewrite/rules/SeqScanInfo.java    |  43 ++++
 .../plan/serder/LogicalNodeDeserializer.java    |  69 +++++++
 .../tajo/plan/serder/LogicalNodeSerializer.java |  75 +++++++
 .../org/apache/tajo/plan/util/IndexUtil.java    |  72 +++++++
 .../org/apache/tajo/plan/util/PlannerUtil.java  |  35 +++-
 .../plan/visitor/BasicLogicalPlanVisitor.java   |  32 ++-
 .../plan/visitor/ExplainLogicalPlanVisitor.java |  14 +-
 .../tajo/plan/visitor/LogicalPlanVisitor.java   |  10 +-
 .../tajo/plan/visitor/SimpleAlgebraVisitor.java |   1 -
 tajo-plan/src/main/proto/Plan.proto             |  86 +++++---
 .../apache/tajo/storage/OldStorageManager.java  |  16 --
 .../org/apache/tajo/storage/Tablespace.java     |  15 ++
 .../tajo/storage/hbase/HBaseTablespace.java     |   5 +-
 .../storage/hbase/SortedInsertRewriter.java     |  11 +-
 .../apache/tajo/storage/index/TestBSTIndex.java |  48 +++--
 .../index/TestSingleCSVFileBSTIndex.java        |  12 +-
 144 files changed, 4163 insertions(+), 1205 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 2b9ea92..4c44aec 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,6 @@
 Tajo Change Log 
 
+
 Release 0.11.0 - unreleased
 
   NEW FEATURES
@@ -200,6 +201,14 @@ Release 0.11.0 - unreleased
 
   BUG FIXES
 
+    TAJO-1608: Fix test failure in index_support branch. (jihoon)
+
+    TAJO-1594: Catalog schema is invalid for some databases. (jihoon)
+
+    TAJO-1657: Tajo Rest API /database/{database-name]/tables should return 
table 
+    names only without invalid external table info. 
+    (Contributed by DaeMyung Kang, Committed by jihoon)
+
     TAJO-1552: NPE occurs when GreedyHeuristicJoinOrderAlgorithm.getCost() 
returns 
     infinity. (Contributed by Hyoungjun Kim, Committed by jihoon)
 
@@ -373,6 +382,8 @@ Release 0.11.0 - unreleased
   
   TASKS
 
+    TAJO-1300: Merge the index branch into the master branch. (jihoon)
+
     TAJO-1713: Change the type of edge cache in JoinGraphContext from 
     HashMap to LRUMap. (jihoon)
 
@@ -432,6 +443,8 @@ Release 0.11.0 - unreleased
 
   SUB TASKS
 
+    TAJO-1302: Support index metadata backup and restore. (jihoon)
+
     TAJO-1484 Apply on ColPartitionStoreExec. (Contributed by Navis, 
     committed by hyunsik)
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateDatabase.java
----------------------------------------------------------------------
diff --git 
a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateDatabase.java 
b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateDatabase.java
index 1144b6e..6e74d3d 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateDatabase.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateDatabase.java
@@ -32,7 +32,7 @@ public class CreateDatabase extends Expr {
   private String tablespaceName;
   @Expose @SerializedName("IfNotExists")
   private boolean ifNotExists;
-  @Expose @SerializedName("DatabaseProperties")
+  @Expose @SerializedName("Properties")
   private Map<String, String> params;
 
   public CreateDatabase(final String databaseName, final String 
tablespaceName, final boolean ifNotExists) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateIndex.java
----------------------------------------------------------------------
diff --git 
a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateIndex.java 
b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateIndex.java
new file mode 100644
index 0000000..a9f734d
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateIndex.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.algebra;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import org.apache.tajo.algebra.Sort.SortSpec;
+import org.apache.tajo.util.TUtil;
+
+import java.util.Map;
+
+public class CreateIndex extends UnaryOperator {
+  @Expose @SerializedName("IsUnique")
+  private boolean unique = false;
+  @Expose @SerializedName("IndexName")
+  private String indexName;
+  @Expose @SerializedName("SortSpecs")
+  private SortSpec[] sortSpecs;
+  @Expose @SerializedName("Properties")
+  private Map<String, String> params;
+  @Expose @SerializedName("IndexMethodSpec")
+  private IndexMethodSpec methodSpec;
+  private boolean external = false;
+  @Expose @SerializedName("IndexPath")
+  private String indexPath;
+
+  public CreateIndex(final String indexName, final SortSpec[] sortSpecs) {
+    super(OpType.CreateIndex);
+    this.indexName = indexName;
+    this.sortSpecs = sortSpecs;
+    this.methodSpec = new IndexMethodSpec("TWO_LEVEL_BIN_TREE");
+  }
+
+  public void setUnique(boolean unique) {
+    this.unique = unique;
+  }
+
+  public boolean isUnique() {
+    return this.unique;
+  }
+
+  public void setIndexName(String indexName) {
+    this.indexName = indexName;
+  }
+
+  public String getIndexName() {
+    return indexName;
+  }
+
+  public void setSortSpecs(SortSpec[] sortSpecs) {
+    this.sortSpecs = sortSpecs;
+  }
+
+  public SortSpec[] getSortSpecs() {
+    return sortSpecs;
+  }
+
+  public void setParams(Map<String, String> params) {
+    this.params = params;
+  }
+
+  public Map<String, String> getParams() {
+    return this.params;
+  }
+
+  public void setMethodSpec(IndexMethodSpec methodSpec) {
+    this.methodSpec = methodSpec;
+  }
+
+  public IndexMethodSpec getMethodSpec() {
+    return this.methodSpec;
+  }
+
+  public void setIndexPath(String indexPath) {
+    this.external = true;
+    this.indexPath = indexPath;
+  }
+
+  public boolean isExternal() {
+    return this.external;
+  }
+
+  public String getIndexPath() {
+    return this.indexPath;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(unique, indexName,  sortSpecs, params, methodSpec, 
external);
+  }
+
+  @Override
+  boolean equalsTo(Expr expr) {
+    CreateIndex other = (CreateIndex) expr;
+    return this.unique == other.unique &&
+        this.indexName.equals(other.indexName) &&
+        TUtil.checkEquals(this.sortSpecs, other.sortSpecs) &&
+        TUtil.checkEquals(this.params, other.params) &&
+        this.methodSpec.equals(other.methodSpec) &&
+        this.external == other.external;
+  }
+
+  public static class IndexMethodSpec {
+    @Expose @SerializedName("IndexMethodName")
+    private String name;
+
+    public IndexMethodSpec(final String name) {
+      this.name = name;
+    }
+
+    public String getName() {
+      return this.name;
+    }
+
+    @Override
+    public int hashCode() {
+      return name.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (o instanceof IndexMethodSpec) {
+        IndexMethodSpec other = (IndexMethodSpec) o;
+        return this.name.equals(other.name);
+      }
+      return false;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/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 5d1599d..ef10c4c 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
@@ -46,7 +46,7 @@ public class CreateTable extends Expr {
   private String location;
   @Expose @SerializedName("SubPlan")
   private Expr subquery;
-  @Expose @SerializedName("TableProperties")
+  @Expose @SerializedName("Properties")
   private Map<String, String> params;
   @Expose @SerializedName("PartitionMethodDesc")
   private PartitionMethodDescExpr partition;

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropIndex.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropIndex.java 
b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropIndex.java
new file mode 100644
index 0000000..5a75e78
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropIndex.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.algebra;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+public class DropIndex extends Expr {
+  @Expose @SerializedName("IndexName")
+  private String indexName;
+
+  public DropIndex(final String indexName) {
+    super(OpType.DropIndex);
+    this.indexName = indexName;
+  }
+
+  @Override
+  public int hashCode() {
+    return indexName.hashCode();
+  }
+
+  @Override
+  boolean equalsTo(Expr expr) {
+    DropIndex other = (DropIndex) expr;
+    return this.indexName.equals(other.indexName);
+  }
+
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    DropIndex clone = (DropIndex) super.clone();
+    clone.indexName = indexName;
+    return clone;
+  }
+
+  public String getIndexName() {
+    return indexName;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-algebra/src/main/java/org/apache/tajo/algebra/Insert.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/Insert.java 
b/tajo-algebra/src/main/java/org/apache/tajo/algebra/Insert.java
index 0826d90..f0cd5f9 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/Insert.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/Insert.java
@@ -39,7 +39,7 @@ public class Insert extends Expr {
   private String location;
   @Expose @SerializedName("SubPlan")
   private Expr subquery;
-  @Expose @SerializedName("InsertParams")
+  @Expose @SerializedName("Properties")
   private Map<String, String> params;
 
   public Insert() {

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java 
b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
index 3e7d277..47fea64 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
@@ -53,6 +53,8 @@ public enum OpType {
   DropTable(DropTable.class),
   AlterTablespace(AlterTablespace.class),
   AlterTable(AlterTable.class),
+  CreateIndex(CreateIndex.class),
+  DropIndex(DropIndex.class),
   TruncateTable(TruncateTable.class),
 
   // Insert or Update

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/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 f7f7785..402df0f 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
@@ -34,8 +34,10 @@ import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.error.Errors.ResultCode;
 import org.apache.tajo.exception.ReturnStateUtil;
 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.util.ProtoUtil;
+import org.apache.tajo.util.TUtil;
 
 import java.io.Closeable;
 import java.util.ArrayList;
@@ -315,6 +317,18 @@ public abstract class AbstractCatalogClient implements 
CatalogService, Closeable
   }
 
   @Override
+  public List<IndexDescProto> getAllIndexes() {
+    try {
+      CatalogProtocolService.BlockingInterface stub = getStub();
+      IndexListResponse response = stub.getAllIndexes(null, 
ProtoUtil.NULL_PROTO);
+      return response.getIndexDescList();
+    } catch (ServiceException e) {
+      LOG.error(e.getMessage(), e);
+      return null;
+    }
+  }
+
+  @Override
   public final PartitionMethodDesc getPartitionMethod(final String 
databaseName, final String tableName) {
 
     try {
@@ -496,7 +510,13 @@ public abstract class AbstractCatalogClient implements 
CatalogService, Closeable
     try {
       final BlockingInterface stub = getStub();
 
-      return isSuccess(stub.createIndex(null, index.getProto()));
+      final ReturnState state = stub.createIndex(null, index.getProto());
+      if (isSuccess(state)) {
+        return true;
+      } else {
+        // TODO
+        return false;
+      }
 
     } catch (ServiceException e) {
       throw new RuntimeException(e);
@@ -521,18 +541,35 @@ public abstract class AbstractCatalogClient implements 
CatalogService, Closeable
   }
 
   @Override
-  public boolean existIndexByColumn(final String databaseName, final String 
tableName, final String columnName) {
+  public boolean existIndexByColumns(final String databaseName, final String 
tableName, final Column [] columns) {
+    return existIndexByColumnNames(databaseName, tableName, 
extractColumnNames(columns));
+  }
+
+  @Override
+  public boolean existIndexByColumnNames(final String databaseName, final 
String tableName, final String [] columnNames) {
     try {
 
-      final GetIndexByColumnRequest request = 
GetIndexByColumnRequest.newBuilder()
-          .setTableIdentifier(buildTableIdentifier(databaseName, tableName))
-          .setColumnName(columnName)
-          .build();
+      GetIndexByColumnNamesRequest.Builder builder = 
GetIndexByColumnNamesRequest.newBuilder();
+      
builder.setTableIdentifier(CatalogUtil.buildTableIdentifier(databaseName, 
tableName));
+      for (String colunName : columnNames) {
+        builder.addColumnNames(colunName);
+      }
 
       final BlockingInterface stub = getStub();
 
-      return isSuccess(stub.existIndexByColumn(null, request));
+      return isSuccess(stub.existIndexByColumnNames(null, builder.build()));
+    } catch (ServiceException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  @Override
+  public boolean existIndexesByTable(final String databaseName, final String 
tableName) {
+    try {
+      final BlockingInterface stub = getStub();
 
+      return isSuccess(
+          stub.existIndexesByTable(null, 
CatalogUtil.buildTableIdentifier(databaseName, tableName)));
     } catch (ServiceException e) {
       throw new RuntimeException(e);
     }
@@ -548,64 +585,83 @@ public abstract class AbstractCatalogClient implements 
CatalogService, Closeable
           .build();
 
       final BlockingInterface stub = getStub();
-      final GetIndexResponse response = stub.getIndexByName(null, request);
+      final IndexResponse response = stub.getIndexByName(null, request);
       ensureOk(response.getState());
 
-      return new IndexDesc(response.getIndex());
+      return new IndexDesc(response.getIndexDesc());
 
     } catch (ServiceException e) {
       throw new RuntimeException(e);
     }
   }
 
+  private static String[] extractColumnNames(Column[] columns) {
+    String[] columnNames = new String [columns.length];
+    for (int i = 0; i < columnNames.length; i++) {
+      columnNames[i] = columns[i].getSimpleName();
+    }
+    return columnNames;
+  }
+
   @Override
-  public final IndexDesc getIndexByColumn(final String databaseName,
-                                          final String tableName,
-                                          final String columnName) {
-    try {
+  public final IndexDesc getIndexByColumns(final String databaseName,
+                                               final String tableName,
+                                               final Column [] columns) {
+    return getIndexByColumnNames(databaseName, tableName, 
extractColumnNames(columns));
+  }
 
-      final GetIndexByColumnRequest request = 
GetIndexByColumnRequest.newBuilder()
-          .setTableIdentifier(buildTableIdentifier(databaseName, tableName))
-          .setColumnName(columnName)
-          .build();
+  @Override
+  public final IndexDesc getIndexByColumnNames(final String databaseName,
+                                           final String tableName,
+                                           final String [] columnNames) {
+    try {
+      GetIndexByColumnNamesRequest.Builder builder = 
GetIndexByColumnNamesRequest.newBuilder();
+      
builder.setTableIdentifier(CatalogUtil.buildTableIdentifier(databaseName, 
tableName));
+      for (String columnName : columnNames) {
+        builder.addColumnNames(columnName);
+      }
 
       final BlockingInterface stub = getStub();
-      final GetIndexResponse response = stub.getIndexByColumn(null, request);
-      ensureOk(response.getState());;
-
-      return new IndexDesc(response.getIndex());
+      final IndexResponse response = stub.getIndexByColumnNames(null, 
builder.build());
+      ensureOk(response.getState());
 
+      return new IndexDesc(response.getIndexDesc());
     } catch (ServiceException e) {
       throw new RuntimeException(e);
     }
   }
 
   @Override
-  public boolean dropIndex(final String dbName, final String indexName) {
+  public final Collection<IndexDesc> getAllIndexesByTable(final String 
databaseName,
+                                                          final String 
tableName) {
     try {
-      final IndexNameProto request = IndexNameProto.newBuilder()
-          .setDatabaseName(dbName)
-          .setIndexName(indexName)
-          .build();
+      TableIdentifierProto proto = 
CatalogUtil.buildTableIdentifier(databaseName, tableName);
 
       final BlockingInterface stub = getStub();
+      final IndexListResponse response = stub.getAllIndexesByTable(null, 
proto);
+      ensureOk(response.getState());
 
-      return isSuccess(stub.dropIndex(null, request));
-
+      List<IndexDesc> indexDescs = TUtil.newList();
+      for (IndexDescProto descProto : response.getIndexDescList()) {
+        indexDescs.add(new IndexDesc(descProto));
+      }
+      return indexDescs;
     } catch (ServiceException e) {
       throw new RuntimeException(e);
     }
   }
 
   @Override
-  public List<IndexProto> getAllIndexes() {
-
+  public boolean dropIndex(final String dbName, final String indexName) {
     try {
+      final IndexNameProto request = IndexNameProto.newBuilder()
+          .setDatabaseName(dbName)
+          .setIndexName(indexName)
+          .build();
+
       final BlockingInterface stub = getStub();
-      final GetIndexesResponse response = stub.getAllIndexes(null, 
ProtoUtil.NULL_PROTO);
-      ensureOk(response.getState());
 
-      return response.getIndexList();
+      return isSuccess(stub.dropIndex(null, request));
 
     } catch (ServiceException e) {
       throw new RuntimeException(e);

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-catalog/tajo-catalog-client/src/main/proto/CatalogProtocol.proto
----------------------------------------------------------------------
diff --git 
a/tajo-catalog/tajo-catalog-client/src/main/proto/CatalogProtocol.proto 
b/tajo-catalog/tajo-catalog-client/src/main/proto/CatalogProtocol.proto
index 8d0eef6..ee74aa0 100644
--- a/tajo-catalog/tajo-catalog-client/src/main/proto/CatalogProtocol.proto
+++ b/tajo-catalog/tajo-catalog-client/src/main/proto/CatalogProtocol.proto
@@ -69,14 +69,14 @@ message GetPartitionDescResponse {
   optional PartitionDescProto partition = 2;
 }
 
-message GetIndexResponse {
+message GetIndexeDescResponse {
   required ReturnState state = 1;
   optional IndexDescProto index = 2;
 }
 
-message GetIndexesResponse {
-  required ReturnState state = 1;
-  repeated IndexProto index = 2;
+message GetIndexByColumnNamesRequest {
+  required TableIdentifierProto tableIdentifier = 1;
+  repeated string columnNames = 2;
 }
 
 message GetPartitionsResponse {
@@ -128,10 +128,12 @@ service CatalogProtocolService {
   rpc createIndex(IndexDescProto) returns (ReturnState);
   rpc dropIndex(IndexNameProto) returns (ReturnState);
   rpc existIndexByName(IndexNameProto) returns (ReturnState);
-  rpc existIndexByColumn(GetIndexByColumnRequest) returns (ReturnState);
-  rpc getIndexByName(IndexNameProto) returns (GetIndexResponse);
-  rpc getIndexByColumn(GetIndexByColumnRequest) returns (GetIndexResponse);
-  rpc getAllIndexes(NullProto) returns (GetIndexesResponse);
+  rpc existIndexByColumnNames(GetIndexByColumnNamesRequest) returns 
(ReturnState);
+  rpc existIndexesByTable(TableIdentifierProto) returns (ReturnState);
+  rpc getIndexByName(IndexNameProto) returns (IndexResponse);
+  rpc getIndexByColumnNames(GetIndexByColumnNamesRequest) returns 
(IndexResponse);
+  rpc getAllIndexesByTable(TableIdentifierProto) returns (IndexListResponse);
+  rpc getAllIndexes(NullProto) returns (IndexListResponse);
 
   rpc createFunction(FunctionDescProto) returns (ReturnState);
   rpc dropFunction(UnregisterFunctionRequest) returns (ReturnState);

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/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 8265e38..721bcf1 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
@@ -53,6 +53,7 @@ public class CatalogConstants {
   public static final String COL_TABLESPACE_PK = "SPACE_ID";
   public static final String COL_DATABASES_PK = "DB_ID";
   public static final String COL_TABLES_PK = "TID";
+  public static final String COL_INDEXES_PK = "INDEX_ID";
   public static final String COL_TABLES_NAME = "TABLE_NAME";
 
   public static final String COL_PARTITIONS_PK = "PARTITION_ID";

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogService.java
----------------------------------------------------------------------
diff --git 
a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogService.java
 
b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogService.java
index f1bfe6a..7704191 100644
--- 
a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogService.java
+++ 
b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogService.java
@@ -21,16 +21,12 @@ package org.apache.tajo.catalog;
 import org.apache.tajo.catalog.exception.UndefinedFunctionException;
 import org.apache.tajo.catalog.exception.UndefinedPartitionException;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
-import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.*;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 
 import java.util.Collection;
 import java.util.List;
 
-import static org.apache.tajo.catalog.proto.CatalogProtos.*;
-
-
 public interface CatalogService {
 
   /**
@@ -148,6 +144,8 @@ public interface CatalogService {
    */
   List<ColumnProto> getAllColumns();
 
+  List<IndexDescProto> getAllIndexes();
+
   /**
    *
    * @return All FunctionDescs
@@ -178,10 +176,10 @@ public interface CatalogService {
 
   boolean existPartitionMethod(String databaseName, String tableName);
 
-  CatalogProtos.PartitionDescProto getPartition(String databaseName, String 
tableName, String partitionName)
+  PartitionDescProto getPartition(String databaseName, String tableName, 
String partitionName)
       throws UndefinedPartitionException;
 
-  List<CatalogProtos.PartitionDescProto> getPartitions(String databaseName, 
String tableName);
+  List<PartitionDescProto> getPartitions(String databaseName, String 
tableName);
 
   List<TablePartitionProto> getAllPartitions();
 
@@ -189,15 +187,21 @@ public interface CatalogService {
 
   boolean existIndexByName(String databaseName, String indexName);
 
-  boolean existIndexByColumn(String databaseName, String tableName, String 
columnName);
+  boolean existIndexByColumns(String databaseName, String tableName, Column[] 
columns);
+
+  boolean existIndexByColumnNames(String databaseName, String tableName, 
String [] columnNames);
+
+  boolean existIndexesByTable(String databaseName, String tableName);
 
   IndexDesc getIndexByName(String databaseName, String indexName);
 
-  IndexDesc getIndexByColumn(String databaseName, String tableName, String 
columnName);
+  IndexDesc getIndexByColumns(String databaseName, String tableName, Column [] 
columns);
+
+  IndexDesc getIndexByColumnNames(String databaseName, String tableName, 
String [] columnNames);
+
+  Collection<IndexDesc> getAllIndexesByTable(String databaseName, String 
tableName);
 
   boolean dropIndex(String databaseName, String indexName);
-  
-  List<IndexProto> getAllIndexes();
 
   boolean createFunction(FunctionDesc funcDesc);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/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 8205e9b..378bbcb 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
@@ -29,6 +29,7 @@ import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.PartitionKeyProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.SchemaProto;
+import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableDescProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableIdentifierProto;
 import org.apache.tajo.common.TajoDataTypes;
@@ -46,12 +47,8 @@ import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
-import static org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import static org.apache.tajo.common.TajoDataTypes.Type;
 
 public class CatalogUtil {
@@ -967,4 +964,43 @@ public class CatalogUtil {
 
     return options;
   }
+
+  /**
+   * Make a unique name by concatenating column names.
+   * The concatenation is performed in sequence of columns' occurrence in the 
relation schema.
+   *
+   * @param originalSchema original relation schema
+   * @param columnNames column names which will be unified
+   * @return unified name
+   */
+  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);
+      simpleNames[i] = identifiers[identifiers.length-1];
+    }
+    Arrays.sort(simpleNames, new ColumnPosComparator(originalSchema));
+    StringBuilder sb = new StringBuilder();
+    for (String colName : simpleNames) {
+      sb.append(colName).append("_");
+    }
+    sb.deleteCharAt(sb.length()-1);
+    return sb.toString();
+  }
+
+  /**
+   * Given column names, compare the position of columns in the relation 
schema.
+   */
+  public static class ColumnPosComparator implements Comparator<String> {
+
+    private Schema originlSchema;
+    public ColumnPosComparator(Schema originalSchema) {
+      this.originlSchema = originalSchema;
+    }
+
+    @Override
+    public int compare(String o1, String o2) {
+      return originlSchema.getColumnId(o1) - originlSchema.getColumnId(o2);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/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 f313aa5..2923654 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
@@ -68,6 +68,28 @@ public class DDLBuilder {
     return sb.toString();
   }
 
+  public static String buildDDLForIndex(IndexDesc desc) {
+    StringBuilder sb = new StringBuilder();
+
+    sb.append("--\n")
+        .append("-- Name: 
").append(CatalogUtil.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(" ( ");
+
+    for (SortSpec sortSpec : desc.getKeySortSpecs()) {
+      sb.append(sortSpec.getSortKey().getQualifiedName()).append(" ");
+      sb.append(sortSpec.isAscending() ? "asc" : "desc").append(" ");
+      sb.append(sortSpec.isNullFirst() ? "null first" : "null last").append(", 
");
+    }
+    sb.replace(sb.length()-2, sb.length()-1, " )");
+
+    sb.append(" location '").append(desc.getIndexPath()).append("';");
+
+    return sb.toString();
+  }
+
   public static void buildSchema(StringBuilder sb, Schema schema) {
     boolean first = true;
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java
----------------------------------------------------------------------
diff --git 
a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java
 
b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java
index 151b919..9f64913 100644
--- 
a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java
+++ 
b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexDesc.java
@@ -26,66 +26,86 @@ import 
org.apache.tajo.catalog.proto.CatalogProtos.IndexDescProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.IndexMethod;
 import org.apache.tajo.common.ProtoObject;
 
+import java.net.URI;
+import java.net.URISyntaxException;
+
 public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
-  private String indexName;            // required
   private String databaseName;         // required
   private String tableName;            // required
-  private Column column;               // required
-  private IndexMethod indexMethod;     // required
-  private boolean isUnique = false;    // optional [default = false]
-  private boolean isClustered = false; // optional [default = false]
-  private boolean isAscending = false; // optional [default = false]
-  
+  private IndexMeta indexMeta;         // required
+
   public IndexDesc() {
   }
   
-  public IndexDesc(String idxName, String databaseName, String tableName, 
Column column,
-                   IndexMethod type,  boolean isUnique, boolean isClustered, 
boolean isAscending) {
+  public IndexDesc(String databaseName, String tableName, String indexName, 
URI indexPath, SortSpec[] keySortSpecs,
+                   IndexMethod type,  boolean isUnique, boolean isClustered, 
Schema targetRelationSchema) {
     this();
-    this.indexName = idxName;
-    this.databaseName = databaseName;
-    this.tableName = tableName;
-    this.column = column;
-    this.indexMethod = type;
-    this.isUnique = isUnique;
-    this.isClustered = isClustered;
-    this.isAscending = isAscending;
+    this.set(databaseName, tableName, indexName, indexPath, keySortSpecs, 
type, isUnique, isClustered,
+        targetRelationSchema);
   }
   
   public IndexDesc(IndexDescProto proto) {
-    this(proto.getIndexName(),
-        proto.getTableIdentifier().getDatabaseName(),
-        proto.getTableIdentifier().getTableName(),
-        new Column(proto.getColumn()),
-        proto.getIndexMethod(), proto.getIsUnique(), proto.getIsClustered(), 
proto.getIsAscending());
+    this();
+
+    SortSpec[] keySortSpecs = new SortSpec[proto.getKeySortSpecsCount()];
+    for (int i = 0; i < keySortSpecs.length; i++) {
+      keySortSpecs[i] = new SortSpec(proto.getKeySortSpecs(i));
+    }
+
+    try {
+      this.set(proto.getTableIdentifier().getDatabaseName(),
+          proto.getTableIdentifier().getTableName(),
+          proto.getIndexName(), new URI(proto.getIndexPath()),
+          keySortSpecs,
+          proto.getIndexMethod(), proto.getIsUnique(), proto.getIsClustered(),
+          new Schema(proto.getTargetRelationSchema()));
+    } catch (URISyntaxException e) {
+      e.printStackTrace();
+    }
   }
-  
-  public String getIndexName() {
-    return indexName;
+
+  public void set(String databaseName, String tableName, String indexName, URI 
indexPath, SortSpec[] keySortSpecs,
+                  IndexMethod type,  boolean isUnique, boolean isClustered, 
Schema targetRelationSchema) {
+    this.databaseName = databaseName;
+    this.tableName = tableName;
+    this.indexMeta = new IndexMeta(indexName, indexPath, keySortSpecs, type, 
isUnique, isClustered,
+        targetRelationSchema);
   }
-  
+
+  public String getDatabaseName() {
+    return databaseName;
+  }
+
   public String getTableName() {
     return tableName;
   }
+
+  public String getName() {
+    return indexMeta.getIndexName();
+  }
   
-  public Column getColumn() {
-    return column;
+  public URI getIndexPath() {
+    return indexMeta.getIndexPath();
+  }
+
+  public SortSpec[] getKeySortSpecs() {
+    return indexMeta.getKeySortSpecs();
   }
   
   public IndexMethod getIndexMethod() {
-    return this.indexMethod;
+    return indexMeta.getIndexMethod();
   }
   
   public boolean isClustered() {
-    return this.isClustered;
+    return indexMeta.isClustered();
   }
   
   public boolean isUnique() {
-    return this.isUnique;
+    return indexMeta.isUnique();
   }
-  
-  public boolean isAscending() {
-    return this.isAscending;
+
+  public Schema getTargetRelationSchema() {
+    return indexMeta.getTargetRelationSchema();
   }
 
   @Override
@@ -101,12 +121,15 @@ public class IndexDesc implements 
ProtoObject<IndexDescProto>, Cloneable {
     }
 
     builder.setTableIdentifier(tableIdentifierBuilder.build());
-    builder.setIndexName(this.indexName);
-    builder.setColumn(this.column.getProto());
-    builder.setIndexMethod(indexMethod);
-    builder.setIsUnique(this.isUnique);
-    builder.setIsClustered(this.isClustered);
-    builder.setIsAscending(this.isAscending);
+    builder.setIndexName(indexMeta.getIndexName());
+    builder.setIndexPath(indexMeta.getIndexPath().toString());
+    for (SortSpec colSpec : indexMeta.getKeySortSpecs()) {
+      builder.addKeySortSpecs(colSpec.getProto());
+    }
+    builder.setIndexMethod(indexMeta.getIndexMethod());
+    builder.setIsUnique(indexMeta.isUnique());
+    builder.setIsClustered(indexMeta.isClustered());
+    
builder.setTargetRelationSchema(indexMeta.getTargetRelationSchema().getProto());
 
     return builder.build();
   }
@@ -114,32 +137,23 @@ public class IndexDesc implements 
ProtoObject<IndexDescProto>, Cloneable {
   public boolean equals(Object obj) {
     if (obj instanceof IndexDesc) {
       IndexDesc other = (IndexDesc) obj;
-      return getIndexName().equals(other.getIndexName())
+      return getDatabaseName().equals(other.getDatabaseName())
           && getTableName().equals(other.getTableName())
-          && getColumn().equals(other.getColumn())
-          && getIndexMethod().equals(other.getIndexMethod())
-          && isUnique() == other.isUnique()
-          && isClustered() == other.isClustered()
-          && isAscending() == other.isAscending();
+          && this.indexMeta.equals(other.indexMeta);
     } else {
       return false;
     }
   }
   
   public int hashCode() {
-    return Objects.hashCode(getIndexName(), getTableName(), getColumn(),
-        getIndexMethod(), isUnique(), isClustered(), isAscending());
+    return Objects.hashCode(databaseName, tableName, indexMeta);
   }
 
   public Object clone() throws CloneNotSupportedException {
     IndexDesc desc = (IndexDesc) super.clone();
-    desc.indexName = indexName;
-    desc.tableName = tableName;
-    desc.column = column;
-    desc.indexMethod = indexMethod;
-    desc.isUnique = isUnique;
-    desc.isClustered = isClustered;
-    desc.isAscending = isAscending;
+    desc.databaseName = this.databaseName;
+    desc.tableName = this.tableName;
+    desc.indexMeta = (IndexMeta) this.indexMeta.clone();
     return desc;
   }
   
@@ -147,4 +161,4 @@ public class IndexDesc implements 
ProtoObject<IndexDescProto>, Cloneable {
     Gson gson = new GsonBuilder().setPrettyPrinting().create();
     return gson.toJson(this);
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexMeta.java
----------------------------------------------------------------------
diff --git 
a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexMeta.java
 
b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexMeta.java
new file mode 100644
index 0000000..a911055
--- /dev/null
+++ 
b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/IndexMeta.java
@@ -0,0 +1,180 @@
+/**
+ * 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;
+
+import com.google.common.base.Objects;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.proto.CatalogProtos.IndexMethod;
+import org.apache.tajo.util.KeyValueSet;
+import org.apache.tajo.util.TUtil;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * IndexMeta contains meta information of an index.
+ * Meta information is the name, an index method, a path to the stored 
location, index keys, and so on.
+ */
+public class IndexMeta implements Cloneable {
+  @Expose private String indexName;              // index name
+  @Expose private IndexMethod indexMethod;       // index method
+  @Expose private URI indexPath;                 // path to the location
+  @Expose private SortSpec[] keySortSpecs;       // index keys. This array 
should always be sorted
+                                                 // according to the position 
in the targetRelationSchema
+  @Expose private boolean isUnique = false;      // unique key or not
+  @Expose private boolean isClustered = false;   // clustered index or not
+  @Expose private Schema targetRelationSchema;   // schema of the indexed 
relation
+  @Expose private KeyValueSet options;           // index options. TODO: will 
be added
+
+  public IndexMeta() {}
+
+  public IndexMeta(String indexName, URI indexPath, SortSpec[] keySortSpecs,
+                   IndexMethod type,  boolean isUnique, boolean isClustered,
+                   Schema targetRelationSchema) {
+    this.indexName = indexName;
+    this.indexPath = indexPath;
+    this.indexMethod = type;
+    this.isUnique = isUnique;
+    this.isClustered = isClustered;
+    this.targetRelationSchema = targetRelationSchema;
+    initKeySortSpecs(targetRelationSchema, keySortSpecs);
+  }
+
+  private void initKeySortSpecs(final Schema targetRelationSchema, final 
SortSpec[] keySortSpecs) {
+    this.targetRelationSchema = targetRelationSchema;
+    this.keySortSpecs = new SortSpec[keySortSpecs.length];
+    for (int i = 0; i < keySortSpecs.length; i++) {
+      this.keySortSpecs[i] = new SortSpec(keySortSpecs[i].getSortKey(), 
keySortSpecs[i].isAscending(),
+          keySortSpecs[i].isNullFirst());
+    }
+    Arrays.sort(this.keySortSpecs, new Comparator<SortSpec>() {
+      @Override
+      public int compare(SortSpec o1, SortSpec o2) {
+        return 
targetRelationSchema.getColumnId(o1.getSortKey().getSimpleName())
+            - 
targetRelationSchema.getColumnId(o2.getSortKey().getSimpleName());
+      }
+    });
+  }
+
+  public String getIndexName() {
+    return indexName;
+  }
+
+  public void setIndexName(final String indexName) {
+    this.indexName = indexName;
+  }
+
+  public IndexMethod getIndexMethod() {
+    return indexMethod;
+  }
+
+  public void setIndexMethod(final IndexMethod type) {
+    this.indexMethod = type;
+  }
+
+  public URI getIndexPath() {
+    return indexPath;
+  }
+
+  public void setIndexPath(final URI indexPath) {
+    this.indexPath = indexPath;
+  }
+
+  public SortSpec[] getKeySortSpecs() {
+    return keySortSpecs;
+  }
+
+  public void setKeySortSpecs(final Schema targetRelationSchema, final 
SortSpec[] keySortSpecs) {
+    initKeySortSpecs(targetRelationSchema, keySortSpecs);
+  }
+
+  public boolean isUnique() {
+    return isUnique;
+  }
+
+  public void setUnique(boolean unique) {
+    this.isUnique = unique;
+  }
+
+  public boolean isClustered() {
+    return isClustered;
+  }
+
+  public void setClustered(boolean clustered) {
+    this.isClustered = clustered;
+  }
+
+  public Schema getTargetRelationSchema() {
+    return targetRelationSchema;
+  }
+
+  public KeyValueSet getOptions() {
+    return options;
+  }
+
+  public void setOptions(KeyValueSet options) {
+    this.options = options;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o instanceof IndexMeta) {
+      IndexMeta other = (IndexMeta) o;
+      return this.indexName.equals(other.indexName)
+          && this.indexPath.equals(other.indexPath)
+          && this.indexMethod.equals(other.indexMethod)
+          && TUtil.checkEquals(this.keySortSpecs, other.keySortSpecs)
+          && this.isUnique == other.isUnique
+          && this.isClustered == other.isClustered
+          && this.targetRelationSchema.equals(other.targetRelationSchema);
+    }
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(indexName, indexPath, indexMethod, 
Objects.hashCode(keySortSpecs),
+        isUnique, isClustered, targetRelationSchema);
+  }
+
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    IndexMeta clone = (IndexMeta) super.clone();
+    clone.indexName = indexName;
+    clone.indexPath = indexPath;
+    clone.indexMethod = indexMethod;
+    clone.keySortSpecs = new SortSpec[keySortSpecs.length];
+    for (int i = 0; i < keySortSpecs.length; i++) {
+      clone.keySortSpecs[i] = new SortSpec(this.keySortSpecs[i].getProto());
+    }
+    clone.isUnique = this.isUnique;
+    clone.isClustered = this.isClustered;
+    clone.targetRelationSchema = this.targetRelationSchema;
+    return clone;
+  }
+
+  @Override
+  public String toString() {
+    Gson gson = new GsonBuilder().setPrettyPrinting().create();
+    return gson.toJson(this);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/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 4700322..add77f2 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
@@ -22,9 +22,6 @@ import com.google.common.base.Objects;
 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.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableDescProto;
@@ -37,8 +34,6 @@ import org.apache.tajo.util.TUtil;
 import java.net.URI;
 
 public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, 
Cloneable {
-  private final Log LOG = LogFactory.getLog(TableDesc.class);
-
        @Expose protected String tableName;                        // required
   @Expose protected Schema schema;
   @Expose protected TableMeta meta;                          // required

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/UndefinedIndexException.java
----------------------------------------------------------------------
diff --git 
a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/UndefinedIndexException.java
 
b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/UndefinedIndexException.java
index d228a40..036a5cc 100644
--- 
a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/UndefinedIndexException.java
+++ 
b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/UndefinedIndexException.java
@@ -24,7 +24,7 @@ public class UndefinedIndexException extends CatalogException 
{
   private static final long serialVersionUID = 3705839985189534673L;
 
   public UndefinedIndexException(String tableName, String columnName) {
-    super(ResultCode.UNDEFINED_INDEX, tableName, columnName);
+    super(ResultCode.UNDEFINED_INDEX_FOR_COLUMNS, tableName, columnName);
   }
 
   public UndefinedIndexException(String indexName) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/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 f95df0a..86fee86 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
+++ b/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
@@ -119,11 +119,12 @@ message NamespaceProto {
 message IndexDescProto {
   required TableIdentifierProto tableIdentifier = 1;
   required string indexName = 2;
-  required ColumnProto column = 3;
-  required IndexMethod indexMethod = 4;
-  optional bool isUnique = 5 [default = false];
-  optional bool isClustered = 6 [default = false];
-  optional bool isAscending = 7 [default = false];
+  required IndexMethod indexMethod = 3;
+  required string indexPath = 4;
+  repeated SortSpecProto key_sort_specs = 5;
+  required SchemaProto targetRelationSchema = 6;
+  optional bool isUnique = 7 [default = false];
+  optional bool isClustered = 8 [default = false];
 }
 
 enum IndexMethod {
@@ -133,20 +134,10 @@ enum IndexMethod {
   BITMAP_IDX = 3;
 }
 
-message GetIndexesProto {
-  repeated IndexProto index = 1;
-}
-
-message IndexProto {
-  required int32 dbId = 1;
-  required int32 tId = 2;
+message IndexNameProto {
+  required string databaseName = 1;
+  optional string namespace = 2;
   required string indexName = 3;
-  required string columnName = 4;
-  required string dataType = 5;
-  required string indexType = 6;
-  optional bool isUnique = 7 [default = false];
-  optional bool isClustered = 8 [default = false];
-  optional bool isAscending = 9 [default = false];
 }
 
 message TableOptionProto {
@@ -161,17 +152,6 @@ message TablePartitionProto {
   optional string path = 4;
 }
 
-message GetIndexByColumnRequest {
-  required TableIdentifierProto tableIdentifier = 1;
-  required string columnName = 2;
-}
-
-message IndexNameProto {
-  required string databaseName = 1;
-  optional string namespace = 2;
-  required string indexName = 3;
-}
-
 message GetFunctionsResponse {
   repeated FunctionDescProto functionDesc = 1;
 }
@@ -407,3 +387,13 @@ message FunctionListResponse {
   required ReturnState state = 1;
   repeated FunctionDescProto function = 2;
 }
+
+message IndexListResponse {
+  required ReturnState state = 1;
+  repeated IndexDescProto indexDesc = 2;
+}
+
+message IndexResponse {
+  required ReturnState state = 1;
+  optional IndexDescProto indexDesc = 2;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestIndexDesc.java
----------------------------------------------------------------------
diff --git 
a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestIndexDesc.java
 
b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestIndexDesc.java
index 3fa8f53..247cd41 100644
--- 
a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestIndexDesc.java
+++ 
b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestIndexDesc.java
@@ -25,6 +25,9 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.net.URI;
+import java.net.URISyntaxException;
+
 import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotSame;
@@ -33,23 +36,29 @@ public class TestIndexDesc {
   static IndexDesc desc1;
   static IndexDesc desc2;
   static IndexDesc desc3;
-  
-  static {
-    desc1 = new IndexDesc(
-        "idx_test", DEFAULT_DATABASE_NAME, "indexed", new Column("id", 
Type.INT4),
-        IndexMethod.TWO_LEVEL_BIN_TREE, true, true, true);
-    
-    desc2 = new IndexDesc(
-        "idx_test2", DEFAULT_DATABASE_NAME, "indexed", new Column("score", 
Type.FLOAT8),
-        IndexMethod.TWO_LEVEL_BIN_TREE, false, false, false);
-    
-    desc3 = new IndexDesc(
-        "idx_test", DEFAULT_DATABASE_NAME, "indexed", new Column("id", 
Type.INT4),
-        IndexMethod.TWO_LEVEL_BIN_TREE, true, true, true);
-  }
+  static Schema relationSchema;
 
   @BeforeClass
   public static void setUp() throws Exception {
+    relationSchema = new Schema(new Column[]{new Column("id", Type.INT4),
+        new Column("score", Type.FLOAT8), new Column("name", Type.TEXT)});
+    SortSpec[] colSpecs1 = new SortSpec[1];
+    colSpecs1[0] = new SortSpec(new Column("id", Type.INT4), true, true);
+    desc1 = new IndexDesc(DEFAULT_DATABASE_NAME, "indexed",
+        "idx_test", new URI("idx_test"), colSpecs1,
+        IndexMethod.TWO_LEVEL_BIN_TREE, true, true, relationSchema);
+
+    SortSpec[] colSpecs2 = new SortSpec[1];
+    colSpecs2[0] = new SortSpec(new Column("score", Type.FLOAT8), false, 
false);
+    desc2 = new IndexDesc(DEFAULT_DATABASE_NAME, "indexed",
+        "idx_test2", new URI("idx_test2"), colSpecs2,
+        IndexMethod.TWO_LEVEL_BIN_TREE, false, false, relationSchema);
+
+    SortSpec[] colSpecs3 = new SortSpec[1];
+    colSpecs3[0] = new SortSpec(new Column("id", Type.INT4), true, true);
+    desc3 = new IndexDesc(DEFAULT_DATABASE_NAME, "indexed",
+        "idx_test", new URI("idx_test"), colSpecs3,
+        IndexMethod.TWO_LEVEL_BIN_TREE, true, true, relationSchema);
   }
 
   @AfterClass
@@ -64,22 +73,28 @@ public class TestIndexDesc {
   }
 
   @Test
-  public void testGetFields() {
-    assertEquals("idx_test", desc1.getIndexName());
+  public void testGetFields() throws URISyntaxException {
+    assertEquals("idx_test", desc1.getName());
     assertEquals("indexed", desc1.getTableName());
-    assertEquals(new Column("id", Type.INT4), desc1.getColumn());
+    assertEquals(1, desc1.getKeySortSpecs().length);
+    assertEquals(new Column("id", Type.INT4), 
desc1.getKeySortSpecs()[0].getSortKey());
+    assertEquals(true, desc1.getKeySortSpecs()[0].isAscending());
+    assertEquals(true, desc1.getKeySortSpecs()[0].isNullFirst());
     assertEquals(IndexMethod.TWO_LEVEL_BIN_TREE, desc1.getIndexMethod());
+    assertEquals(new URI("idx_test"), desc1.getIndexPath());
     assertEquals(true, desc1.isUnique());
     assertEquals(true, desc1.isClustered());
-    assertEquals(true, desc1.isAscending());
-    
-    assertEquals("idx_test2", desc2.getIndexName());
+
+    assertEquals("idx_test2", desc2.getName());
     assertEquals("indexed", desc2.getTableName());
-    assertEquals(new Column("score", Type.FLOAT8), desc2.getColumn());
+    assertEquals(1, desc2.getKeySortSpecs().length);
+    assertEquals(new Column("score", Type.FLOAT8), 
desc2.getKeySortSpecs()[0].getSortKey());
+    assertEquals(false, desc2.getKeySortSpecs()[0].isAscending());
+    assertEquals(false, desc2.getKeySortSpecs()[0].isNullFirst());
     assertEquals(IndexMethod.TWO_LEVEL_BIN_TREE, desc2.getIndexMethod());
+    assertEquals(new URI("idx_test2"), desc2.getIndexPath());
     assertEquals(false, desc2.isUnique());
     assertEquals(false, desc2.isClustered());
-    assertEquals(false, desc2.isAscending());
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/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 8a08b77..b49499f 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
@@ -41,7 +41,7 @@ import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.ColumnProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.DatabaseProto;
-import org.apache.tajo.catalog.proto.CatalogProtos.IndexProto;
+import org.apache.tajo.catalog.proto.CatalogProtos.IndexDescProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableDescriptorProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.TableOptionProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.TablePartitionProto;
@@ -762,22 +762,26 @@ public class HiveCatalogStore extends CatalogConstants 
implements CatalogStore {
   @Override
   public void addPartitionMethod(CatalogProtos.PartitionMethodProto 
partitionMethodProto) throws CatalogException {
     // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
   public CatalogProtos.PartitionMethodProto getPartitionMethod(String 
databaseName, String tableName)
       throws CatalogException {
-    return null;  // TODO - not implemented yet
+    // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
   public boolean existPartitionMethod(String databaseName, String tableName) 
throws CatalogException {
-    return false;  // TODO - not implemented yet
+    // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
   public void dropPartitionMethod(String databaseName, String tableName) 
throws CatalogException {
     // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
@@ -827,63 +831,75 @@ public class HiveCatalogStore extends CatalogConstants 
implements CatalogStore {
   @Override
   public final void addFunction(final FunctionDesc func) throws 
CatalogException {
     // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
   public final void deleteFunction(final FunctionDesc func) throws 
CatalogException {
     // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
   public final void existFunction(final FunctionDesc func) throws 
CatalogException {
     // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
   public final List<String> getAllFunctionNames() throws CatalogException {
     // TODO - not implemented yet
-    return null;
+    throw new UnsupportedOperationException();
   }
 
   @Override
-  public void dropIndex(String databaseName, String indexName) throws 
CatalogException {
+  public void createIndex(CatalogProtos.IndexDescProto proto) throws 
CatalogException {
     // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
-  public boolean existIndexByName(String databaseName, String indexName) 
throws CatalogException {
+  public void dropIndex(String databaseName, String indexName) throws 
CatalogException {
     // TODO - not implemented yet
-    return false;
+    throw new UnsupportedOperationException();
   }
 
   @Override
-  public CatalogProtos.IndexDescProto[] getIndexes(String databaseName, String 
tableName) throws CatalogException {
+  public CatalogProtos.IndexDescProto getIndexByName(String databaseName, 
String indexName) throws CatalogException {
     // TODO - not implemented yet
-    return null;
+    throw new UnsupportedOperationException();
   }
 
   @Override
-  public void createIndex(CatalogProtos.IndexDescProto proto) throws 
CatalogException {
+  public CatalogProtos.IndexDescProto getIndexByColumns(String databaseName, 
String tableName, String[] columnNames)
+      throws CatalogException {
     // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
-  public CatalogProtos.IndexDescProto getIndexByName(String databaseName, 
String indexName) throws CatalogException {
+  public boolean existIndexByName(String databaseName, String indexName) 
throws CatalogException {
     // TODO - not implemented yet
-    return null;
+    throw new UnsupportedOperationException();
   }
 
   @Override
-  public CatalogProtos.IndexDescProto getIndexByColumn(String databaseName, 
String tableName, String columnName)
+  public boolean existIndexByColumns(String databaseName, String tableName, 
String[] columnNames)
       throws CatalogException {
     // TODO - not implemented yet
-    return null;
+    throw new UnsupportedOperationException();
   }
 
   @Override
-  public boolean existIndexByColumn(String databaseName, String tableName, 
String columnName) throws CatalogException {
+  public List<String> getAllIndexNamesByTable(String databaseName, String 
tableName) throws CatalogException {
     // TODO - not implemented yet
-    return false;
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public boolean existIndexesByTable(String databaseName, String tableName) 
throws CatalogException {
+    // TODO - not implemented yet
+    throw new UnsupportedOperationException();
   }
 
   @Override
@@ -931,7 +947,7 @@ public class HiveCatalogStore extends CatalogConstants 
implements CatalogStore {
   }
 
   @Override
-  public List<IndexProto> getAllIndexes() throws CatalogException {
+  public List<IndexDescProto> getAllIndexes() throws CatalogException {
     throw new UnsupportedOperationException();
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/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 6a3fc16..0327367 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
@@ -31,7 +31,9 @@ import org.apache.tajo.TajoConstants;
 import org.apache.tajo.annotation.ThreadSafe;
 import org.apache.tajo.catalog.CatalogProtocol.*;
 import org.apache.tajo.catalog.dictionary.InfoSchemaMetadataDictionary;
-import org.apache.tajo.catalog.exception.*;
+import org.apache.tajo.catalog.exception.CatalogException;
+import org.apache.tajo.catalog.exception.DuplicateDatabaseException;
+import org.apache.tajo.catalog.exception.UndefinedTablespaceException;
 import org.apache.tajo.catalog.proto.CatalogProtos.*;
 import org.apache.tajo.catalog.store.CatalogStore;
 import org.apache.tajo.catalog.store.DerbyStore;
@@ -1094,7 +1096,12 @@ public class CatalogServer extends AbstractService {
 
       rlock.lock();
       try {
-        return store.existIndexByName(dbName, indexName) ? OK : 
errUndefinedIndexName(indexName);
+
+        if (store.existDatabase(dbName)) {
+          return store.existIndexByName(dbName, indexName) ? OK : 
errUndefinedIndexName(indexName);
+        } else {
+          return errUndefinedDatabase(dbName);
+        }
 
       } catch (Throwable t) {
         printStackTraceIfError(LOG, t);
@@ -1106,30 +1113,65 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public ReturnState existIndexByColumn(RpcController controller, 
GetIndexByColumnRequest request) {
+    public ReturnState existIndexByColumnNames(RpcController controller, 
GetIndexByColumnNamesRequest request)
+        throws ServiceException {
 
       TableIdentifierProto identifier = request.getTableIdentifier();
       String databaseName = identifier.getDatabaseName();
       String tableName = identifier.getTableName();
-      String columnName = request.getColumnName();
+      List<String> columnNames = request.getColumnNamesList();
 
       rlock.lock();
       try {
-        return store.existIndexByColumn(databaseName, tableName, columnName) ?
-            OK : errUndefinedIndex(tableName, columnName);
+
+        if (store.existDatabase(databaseName)) {
+          if (store.existTable(databaseName, tableName)) {
+            return store.existIndexByColumns(databaseName, tableName,
+                columnNames.toArray(new String[columnNames.size()])) ? OK : 
errUndefinedIndex(tableName, columnNames);
+          } else {
+            return errUndefinedTable(tableName);
+          }
+        } else {
+          return errUndefinedDatabase(databaseName);
+        }
 
       } catch (Throwable t) {
         printStackTraceIfError(LOG, t);
         return returnError(t);
-
       } finally {
         rlock.unlock();
       }
     }
 
     @Override
-    public GetIndexResponse getIndexByName(RpcController controller, 
IndexNameProto request)
+    public ReturnState existIndexesByTable(RpcController controller, 
TableIdentifierProto request)
         throws ServiceException {
+      String databaseName = request.getDatabaseName();
+      String tableName = request.getTableName();
+
+      rlock.lock();
+      try {
+
+        if (store.existDatabase(databaseName)) {
+          if (store.existTable(databaseName, tableName)) {
+            return store.existIndexesByTable(databaseName, tableName) ? OK : 
errUndefinedIndex(tableName);
+          } else {
+            return errUndefinedTable(tableName);
+          }
+        } else {
+          return errUndefinedDatabase(databaseName);
+        }
+
+      } catch (Throwable t) {
+        printStackTraceIfError(LOG, t);
+        return returnError(t);
+      } finally {
+        rlock.unlock();
+      }
+    }
+
+    @Override
+    public IndexResponse getIndexByName(RpcController controller, 
IndexNameProto request) throws ServiceException {
 
       String databaseName = request.getDatabaseName();
       String indexName = request.getIndexName();
@@ -1138,20 +1180,20 @@ public class CatalogServer extends AbstractService {
       try {
 
         if (!store.existIndexByName(databaseName, indexName)) {
-          return GetIndexResponse.newBuilder()
+          return IndexResponse.newBuilder()
               .setState(errUndefinedIndexName(indexName))
               .build();
         }
 
-        return GetIndexResponse.newBuilder()
+        return IndexResponse.newBuilder()
             .setState(OK)
-            .setIndex(store.getIndexByName(databaseName, indexName))
+            .setIndexDesc(store.getIndexByName(databaseName, indexName))
             .build();
 
       } catch (Throwable t) {
         printStackTraceIfError(LOG, t);
 
-        return GetIndexResponse.newBuilder()
+        return IndexResponse.newBuilder()
             .setState(returnError(t))
             .build();
 
@@ -1161,31 +1203,77 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public GetIndexResponse getIndexByColumn(RpcController controller, 
GetIndexByColumnRequest request)
+    public IndexResponse getIndexByColumnNames(RpcController controller, 
GetIndexByColumnNamesRequest request)
         throws ServiceException {
 
       TableIdentifierProto identifier = request.getTableIdentifier();
       String databaseName = identifier.getDatabaseName();
       String tableName = identifier.getTableName();
-      String columnName = request.getColumnName();
+      List<String> columnNamesList = request.getColumnNamesList();
+      String[] columnNames = new String[columnNamesList.size()];
+      columnNames = columnNamesList.toArray(columnNames);
 
       rlock.lock();
       try {
-        if (!store.existIndexByColumn(databaseName, tableName, columnName)) {
-          return GetIndexResponse.newBuilder()
-              .setState(errUndefinedIndex(tableName, columnName))
+        if (!store.existIndexByColumns(databaseName, tableName, columnNames)) {
+          return IndexResponse.newBuilder()
+              .setState(errUndefinedIndex(tableName, columnNamesList))
               .build();
         }
-
-        return GetIndexResponse.newBuilder()
+        return IndexResponse.newBuilder()
             .setState(OK)
-            .setIndex(store.getIndexByColumn(databaseName, tableName, 
columnName))
+            .setIndexDesc(store.getIndexByColumns(databaseName, tableName, 
columnNames))
             .build();
+      } catch (Throwable t) {
+        printStackTraceIfError(LOG, t);
 
+        return IndexResponse.newBuilder()
+            .setState(returnError(t))
+            .build();
+      } finally {
+        rlock.unlock();
+      }
+    }
+
+    @Override
+    public IndexListResponse getAllIndexesByTable(RpcController controller, 
TableIdentifierProto request)
+        throws ServiceException {
+      String databaseName = request.getDatabaseName();
+      String tableName = request.getTableName();
+
+      rlock.lock();
+      try {
+        if (!store.existIndexesByTable(databaseName, tableName)) {
+          return IndexListResponse.newBuilder()
+              .setState(errUndefinedIndex(tableName))
+              .build();
+        }
+        IndexListResponse.Builder builder = 
IndexListResponse.newBuilder().setState(OK);
+        for (String eachIndexName : 
store.getAllIndexNamesByTable(databaseName, tableName)) {
+          builder.addIndexDesc(store.getIndexByName(databaseName, 
eachIndexName));
+        }
+        return builder.build();
       } catch (Throwable t) {
         printStackTraceIfError(LOG, t);
 
-        return GetIndexResponse.newBuilder()
+        return IndexListResponse.newBuilder()
+            .setState(returnError(t))
+            .build();
+      } finally {
+        rlock.unlock();
+      }
+    }
+
+    @Override
+    public IndexListResponse getAllIndexes(RpcController controller, NullProto 
request) throws ServiceException {
+      rlock.lock();
+      try {
+        return 
IndexListResponse.newBuilder().addAllIndexDesc(store.getAllIndexes()).build();
+
+      } catch (Throwable t) {
+        printStackTraceIfError(LOG, t);
+
+        return IndexListResponse.newBuilder()
             .setState(returnError(t))
             .build();
 
@@ -1217,24 +1305,6 @@ public class CatalogServer extends AbstractService {
         wlock.unlock();
       }
     }
-    
-    @Override
-    public GetIndexesResponse getAllIndexes(RpcController controller, 
NullProto request) throws ServiceException {
-      rlock.lock();
-      try {
-        return 
GetIndexesResponse.newBuilder().addAllIndex(store.getAllIndexes()).build();
-
-      } catch (Throwable t) {
-        printStackTraceIfError(LOG, t);
-
-        return GetIndexesResponse.newBuilder()
-            .setState(returnError(t))
-            .build();
-
-      } finally {
-        rlock.unlock();
-      }
-    }
 
     private boolean containFunction(String signature) {
       List<FunctionDescProto> found = findFunction(signature);

http://git-wip-us.apache.org/repos/asf/tajo/blob/9840d378/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/IndexesTableDescriptor.java
----------------------------------------------------------------------
diff --git 
a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/IndexesTableDescriptor.java
 
b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/IndexesTableDescriptor.java
index a079a93..d527b19 100644
--- 
a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/IndexesTableDescriptor.java
+++ 
b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/dictionary/IndexesTableDescriptor.java
@@ -27,12 +27,8 @@ class IndexesTableDescriptor extends AbstractTableDescriptor 
{
       new ColumnDescriptor("db_id", Type.INT4, 0),
       new ColumnDescriptor("tid", Type.INT4, 0),
       new ColumnDescriptor("index_name", Type.TEXT, 0),
-      new ColumnDescriptor("column_name", Type.TEXT, 0),
-      new ColumnDescriptor("data_type", Type.TEXT, 0),
-      new ColumnDescriptor("index_type", Type.TEXT, 0),
-      new ColumnDescriptor("is_unique", Type.BOOLEAN, 0),
-      new ColumnDescriptor("is_clustered", Type.BOOLEAN, 0),
-      new ColumnDescriptor("is_ascending", Type.BOOLEAN, 0)
+      new ColumnDescriptor("index_method", Type.TEXT, 0),
+      new ColumnDescriptor("index_path", Type.TEXT, 0),
   };
 
   public IndexesTableDescriptor(InfoSchemaMetadataDictionary 
metadataDictionary) {

Reply via email to