You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2014/03/25 02:36:16 UTC

[01/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Repository: tajo
Updated Branches:
  refs/heads/master 7283c586a -> 3ba262412


http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/queries/TestCreateTable/create_table_various_types_for_hcatalog.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestCreateTable/create_table_various_types_for_hcatalog.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestCreateTable/create_table_various_types_for_hcatalog.sql
new file mode 100644
index 0000000..3eda994
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestCreateTable/create_table_various_types_for_hcatalog.sql
@@ -0,0 +1,50 @@
+-- Some types were commented out due to Hive meta test.
+
+create table various_types (
+--  col0 bit,
+--  col1 BIT(10),
+--  col2 bit varying,
+--  col3 bit VARYING(10),
+  col4 tinyint,
+  col5 smallInt,
+  col6 integer,
+  col7 biginT,
+  col8 real,
+  col9 float,
+  col10 float(53),
+  col11 double,
+  col12 doublE precision,
+--  col13 numeric,
+--  col14 numeric(10),
+--  col15 numeric(10,2),
+--  col16 decimal,
+--  col17 decimal(10),
+--  col18 decimal(10,2),
+--  col19 char,
+--  col20 character,
+--  col21 chaR(10),
+--  col22 character(10),
+--  col23 varchar,
+--  col24 character varying,
+--  col25 varchar(255),
+--  col26 character varying (255),
+--  col27 nchar,
+--  col28 nchar(255),
+--  col29 national character,
+--  col30 national character(255),
+--  col31 nvarchar,
+--  col32 nvarchar(255),
+--  col33 natIonal character varying,
+--  col34 national character varying (255),
+--  col35 date,
+--  col36 time,
+--  col37 timetz,
+--  col38 time With time zone,
+--  col39 timesTamptz,
+--  col40 timestamp with time zone,
+  col41 binary,
+--  col42 binary(10),
+--  col43 varbinary(10),
+--  col44 binary Varying(10),
+  col45 blOb
+);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk1.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk1.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk1.sql
index 910138f..5451b4a 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk1.sql
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk1.sql
@@ -1 +1 @@
-select region.*, customer.* from region, customer;
\ No newline at end of file
+select region.*, customer.* from region, customer order by r_regionkey,r_name;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk2.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk2.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk2.sql
index a68e40a..e9dac51 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk2.sql
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk2.sql
@@ -1 +1 @@
-select region.*, customer.* from customer, region;
\ No newline at end of file
+select region.*, customer.* from customer, region order by r_regionkey,r_name;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk3.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk3.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk3.sql
index f75c8dc..c98e19f 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk3.sql
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk3.sql
@@ -1 +1 @@
-select * from customer, region;
\ No newline at end of file
+select * from customer, region order by c_custkey,c_name;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk4.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk4.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk4.sql
index 100be80..7130def 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk4.sql
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testCrossJoinWithAsterisk4.sql
@@ -1 +1 @@
-select length(r_comment), *, c_custkey*10 from customer, region;
\ No newline at end of file
+select length(r_comment) as len, *, c_custkey*10 from customer, region order by len,r_regionkey,r_name;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testJoinOnMultipleDatabases.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testJoinOnMultipleDatabases.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testJoinOnMultipleDatabases.sql
new file mode 100644
index 0000000..4598dd8
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestJoinQuery/testJoinOnMultipleDatabases.sql
@@ -0,0 +1,25 @@
+select
+	s_acctbal,
+	s_name,
+	n_name,
+	p_partkey,
+	p_mfgr,
+	s_address,
+	s_phone,
+	s_comment
+from
+	JOINS.part_,
+	JOINS.supplier_,
+	partsupp,
+	nation,
+	region
+where
+	p_partkey = ps_partkey
+	and s_suppkey = ps_suppkey
+	and s_nationkey = n_nationkey
+	and n_regionkey = r_regionkey
+order by
+  s_acctbal,
+  s_name,
+  n_name,
+  p_partkey;

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table1_ddl.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table1_ddl.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table1_ddl.sql
index 45df638..c3ee88e 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table1_ddl.sql
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table1_ddl.sql
@@ -1,4 +1,4 @@
 -- It is used in TestNetTypes
 
-create external table table1 (id int, name text, score float, type text, addr inet4) using csv
+create external table IF NOT EXISTS table1 (id int, name text, score float, type text, addr inet4) using csv
 with ('csvfile.delimiter'='|', 'csvfile.null'='NULL') location ${table.path};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table2_ddl.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table2_ddl.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table2_ddl.sql
index 73fe19e..30bfafe 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table2_ddl.sql
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestNetTypes/table2_ddl.sql
@@ -1,4 +1,4 @@
 -- It is used in TestNetTypes
 
-create external table table2 (id int, name text, score float, type text, addr inet4) using csv
+create external table IF NOT EXISTS table2 (id int, name text, score float, type text, addr inet4) using csv
 with ('csvfile.delimiter'='|', 'csvfile.null'='NULL') location ${table.path};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk3.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk3.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk3.result
index f4e8c88..9db83f0 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk3.result
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk3.result
@@ -1,27 +1,27 @@
-r_regionkey,r_name,r_comment,c_custkey,c_name,c_address,c_nationkey,c_phone,c_acctbal,c_mktsegment,c_comment
+c_custkey,c_name,c_address,c_nationkey,c_phone,c_acctbal,c_mktsegment,c_comment,r_regionkey,r_name,r_comment
 -------------------------------
-0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e
-0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref
-0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov
-0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou
-0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor
-1,AMERICA,hs use ironic, even requests. s,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e
-1,AMERICA,hs use ironic, even requests. s,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref
-1,AMERICA,hs use ironic, even requests. s,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov
-1,AMERICA,hs use ironic, even requests. s,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou
-1,AMERICA,hs use ironic, even requests. s,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor
-2,ASIA,ges. thinly even pinto beans ca,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e
-2,ASIA,ges. thinly even pinto beans ca,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref
-2,ASIA,ges. thinly even pinto beans ca,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov
-2,ASIA,ges. thinly even pinto beans ca,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou
-2,ASIA,ges. thinly even pinto beans ca,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor
-3,EUROPE,ly final courts cajole furiously final excuse,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e
-3,EUROPE,ly final courts cajole furiously final excuse,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref
-3,EUROPE,ly final courts cajole furiously final excuse,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov
-3,EUROPE,ly final courts cajole furiously final excuse,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou
-3,EUROPE,ly final courts cajole furiously final excuse,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor
-4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e
-4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref
-4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov
-4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou
-4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor
\ No newline at end of file
+1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to 
+1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,1,AMERICA,hs use ironic, even requests. s
+1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,2,ASIA,ges. thinly even pinto beans ca
+1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,3,EUROPE,ly final courts cajole furiously final excuse
+1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl
+2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to 
+2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,1,AMERICA,hs use ironic, even requests. s
+2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,2,ASIA,ges. thinly even pinto beans ca
+2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,3,EUROPE,ly final courts cajole furiously final excuse
+2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl
+3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to 
+3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,1,AMERICA,hs use ironic, even requests. s
+3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,2,ASIA,ges. thinly even pinto beans ca
+3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,3,EUROPE,ly final courts cajole furiously final excuse
+3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl
+4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to 
+4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,1,AMERICA,hs use ironic, even requests. s
+4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,2,ASIA,ges. thinly even pinto beans ca
+4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,3,EUROPE,ly final courts cajole furiously final excuse
+4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl
+5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to 
+5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,1,AMERICA,hs use ironic, even requests. s
+5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,2,ASIA,ges. thinly even pinto beans ca
+5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,3,EUROPE,ly final courts cajole furiously final excuse
+5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk4.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk4.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk4.result
index 95b5bc3..23d985e 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk4.result
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testCrossJoinWithAsterisk4.result
@@ -1,27 +1,27 @@
-?length,r_regionkey,r_name,r_comment,c_custkey,c_name,c_address,c_nationkey,c_phone,c_acctbal,c_mktsegment,c_comment,?multiply_1
+len,c_custkey,c_name,c_address,c_nationkey,c_phone,c_acctbal,c_mktsegment,c_comment,r_regionkey,r_name,r_comment,?multiply
 -------------------------------
-115,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,10
-115,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,20
-115,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,30
-115,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,40
-115,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,50
-31,1,AMERICA,hs use ironic, even requests. s,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,10
-31,1,AMERICA,hs use ironic, even requests. s,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,20
-31,1,AMERICA,hs use ironic, even requests. s,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,30
-31,1,AMERICA,hs use ironic, even requests. s,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,40
-31,1,AMERICA,hs use ironic, even requests. s,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,50
-31,2,ASIA,ges. thinly even pinto beans ca,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,10
-31,2,ASIA,ges. thinly even pinto beans ca,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,20
-31,2,ASIA,ges. thinly even pinto beans ca,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,30
-31,2,ASIA,ges. thinly even pinto beans ca,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,40
-31,2,ASIA,ges. thinly even pinto beans ca,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,50
-45,3,EUROPE,ly final courts cajole furiously final excuse,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,10
-45,3,EUROPE,ly final courts cajole furiously final excuse,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,20
-45,3,EUROPE,ly final courts cajole furiously final excuse,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,30
-45,3,EUROPE,ly final courts cajole furiously final excuse,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,40
-45,3,EUROPE,ly final courts cajole furiously final excuse,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,50
-108,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,10
-108,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,20
-108,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,30
-108,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,40
-108,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,50
\ No newline at end of file
+31,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,1,AMERICA,hs use ironic, even requests. s,10
+31,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,1,AMERICA,hs use ironic, even requests. s,20
+31,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,1,AMERICA,hs use ironic, even requests. s,30
+31,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,1,AMERICA,hs use ironic, even requests. s,40
+31,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,1,AMERICA,hs use ironic, even requests. s,50
+31,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,2,ASIA,ges. thinly even pinto beans ca,10
+31,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,2,ASIA,ges. thinly even pinto beans ca,20
+31,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,2,ASIA,ges. thinly even pinto beans ca,30
+31,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,2,ASIA,ges. thinly even pinto beans ca,40
+31,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,2,ASIA,ges. thinly even pinto beans ca,50
+45,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,3,EUROPE,ly final courts cajole furiously final excuse,10
+45,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,3,EUROPE,ly final courts cajole furiously final excuse,20
+45,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,3,EUROPE,ly final courts cajole furiously final excuse,30
+45,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,3,EUROPE,ly final courts cajole furiously final excuse,40
+45,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,3,EUROPE,ly final courts cajole furiously final excuse,50
+108,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,10
+108,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,20
+108,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,30
+108,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,40
+108,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,4,MIDDLE EAST,uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl,50
+115,1,Customer#000000001,IVhzIApeRb ot,c,E,15,25-989-741-2988,711.56,BUILDING,to the even, regular platelets. regular, ironic epitaphs nag e,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,10
+115,2,Customer#000000002,XSTf4,NCwDVaWNe6tEgvwfmRchLXak,13,23-768-687-3665,121.65,AUTOMOBILE,l accounts. blithely ironic theodolites integrate boldly: caref,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,20
+115,3,Customer#000000003,MG9kdTD2WBHm,1,11-719-748-3364,7498.12,AUTOMOBILE, deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,30
+115,4,Customer#000000004,XxVSJsLAGtn,4,14-128-190-5944,2866.83,MACHINERY, requests. final, regular ideas sleep final accou,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,40
+115,5,Customer#000000005,KvpyuHCplrB84WgAiGV6sYpZq7Tj,3,13-750-942-6364,794.47,HOUSEHOLD,n accounts will have to unwind. foxes cajole accor,0,AFRICA,lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ,50
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testJoinOnMultipleDatabases.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testJoinOnMultipleDatabases.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testJoinOnMultipleDatabases.result
new file mode 100644
index 0000000..dc0968f
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestJoinQuery/testJoinOnMultipleDatabases.result
@@ -0,0 +1,5 @@
+s_acctbal,s_name,n_name,p_partkey,p_mfgr,s_address,s_phone,s_comment
+-------------------------------
+4032.68,Supplier#000000002,ETHIOPIA,1,Manufacturer#1,89eJ5ksX3ImxJQBvxObC,,15-679-861-2259, slyly bold instructions. idle dependen
+4192.4,Supplier#000000003,ARGENTINA,2,Manufacturer#1,q1,G3Pj6OjIuUYfUoH18BFTKP5aU9bEV3,11-383-516-1199,blithely silent requests after the express dependencies are sl
+4641.08,Supplier#000000004,MOROCCO,3,Manufacturer#4,Bk7ah4CK8SYQTepEmvMkkgMwg,25-843-787-7479,riously even requests above the exp
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables1.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables1.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables1.result
new file mode 100644
index 0000000..88df9a8
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables1.result
@@ -0,0 +1,4 @@
+table_cat,table_schem,table_name,table_type,remarks
+-------------------------------
+jdbc_test1,public,table1,TABLE,
+jdbc_test1,public,table2,TABLE,
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables2.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables2.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables2.result
new file mode 100644
index 0000000..06afed2
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables2.result
@@ -0,0 +1,4 @@
+table_cat,table_schem,table_name,table_type,remarks
+-------------------------------
+jdbc_test2,public,table3,TABLE,
+jdbc_test2,public,table4,TABLE,
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDL.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDL.result b/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDL.result
deleted file mode 100644
index a16119f..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDL.result
+++ /dev/null
@@ -1,5 +0,0 @@
---
--- Name: table1; Type: TABLE; Storage: CSV
--- Path: /table1
---
-CREATE EXTERNAL TABLE table1 (name BLOB, addr TEXT) USING CSV WITH ('compression.codec'='org.apache.hadoop.io.compress.GzipCodec', 'csvfile.delimiter'='|') PARTITION BY COLUMN(key INT4, key2 TEXT) LOCATION '/table1';
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDLForBaseTable.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDLForBaseTable.result b/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDLForBaseTable.result
new file mode 100644
index 0000000..bd59e2d
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDLForBaseTable.result
@@ -0,0 +1,5 @@
+--
+-- Name: db1.table2; Type: TABLE; Storage: CSV
+-- Path: /table1
+--
+CREATE TABLE db1.table2 (name BLOB, addr TEXT) USING CSV WITH ('compression.codec'='org.apache.hadoop.io.compress.GzipCodec', 'csvfile.delimiter'='|');
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDLForExternalTable.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDLForExternalTable.result b/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDLForExternalTable.result
new file mode 100644
index 0000000..78c64ff
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/testBuildDDLForExternalTable.result
@@ -0,0 +1,5 @@
+--
+-- Name: db1.table1; Type: TABLE; Storage: CSV
+-- Path: /table1
+--
+CREATE EXTERNAL TABLE db1.table1 (name BLOB, addr TEXT) USING CSV WITH ('compression.codec'='org.apache.hadoop.io.compress.GzipCodec', 'csvfile.delimiter'='|') PARTITION BY COLUMN(key INT4, key2 TEXT) LOCATION '/table1';
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-docs/src/main/sphinx/cli.rst
----------------------------------------------------------------------
diff --git a/tajo-docs/src/main/sphinx/cli.rst b/tajo-docs/src/main/sphinx/cli.rst
index 6c91d2f..fa3f4a7 100644
--- a/tajo-docs/src/main/sphinx/cli.rst
+++ b/tajo-docs/src/main/sphinx/cli.rst
@@ -8,8 +8,9 @@ Synopsis
 
 .. code-block:: bash
 
-  bin/tsql [options]
+  bin/tsql [options] [database name]
 
+If a *database_name* is given, tsql connects to the database at startup time. Otherwise, tsql connects to ``default`` database.
 
 Options
 
@@ -26,13 +27,15 @@ If the hostname and the port num are not given, tsql will try to connect the Taj
 
   bin/tsql
 
-  tajo>
+  default>
 
 If you want to connect a specified TajoMaster, you should use '-h' and (or) 'p' options as follows: ::
 
   bin/tsql -h localhost -p 9004
 
-  tajo> 
+  default> 
+
+The prompt indicates the current database.
 
 ===================
  Meta Commands
@@ -42,7 +45,7 @@ In tsql, anything command that begins with an unquoted backslash ('\') is a tsql
 
 In the current implementation, there are meta commands as follows: ::
 
-  tajo> \?
+  default> \?
 
   General
     \copyright  show Apache License 2.0
@@ -52,25 +55,44 @@ In the current implementation, there are meta commands as follows: ::
 
 
   Informational
-    \d         list tables
-    \d  NAME   describe table
+    \l           list databases
+    \c           show current database
+    \c [DBNAME]  connect to new database
+    \d           list tables
+    \d [TBNAME]  describe table
+    \df          list functions
+    \df NAME     describe function
+
+
+  Variables
+    \set [[NAME] [VALUE]  set session variable or list session variables
+    \unset NAME           unset session variable
 
 
   Documentations
-    tsql guide        http://wiki.apache.org/tajo/tsql
-    Query language    http://wiki.apache.org/tajo/QueryLanguage
-    Functions         http://wiki.apache.org/tajo/Functions
-    Backup & restore  http://wiki.apache.org/tajo/BackupAndRestore
-    Configuration     http://wiki.apache.org/tajo/Configuration
+    tsql guide        http://tajo.incubator.apache.org/docs/0.8.0/cli.html
+    Query language    http://tajo.incubator.apache.org/docs/0.8.0/sql_language.html
+    Functions         http://tajo.incubator.apache.org/docs/0.8.0/functions.html
+    Backup & restore  http://tajo.incubator.apache.org/docs/0.8.0/backup_and_restore.html
+    Configuration     http://tajo.incubator.apache.org/docs/0.8.0/configuration.html
+
+-----------------------------------------------
+Basic usages
+-----------------------------------------------
+
+``\l`` command shows a list of all databases.
 
+.. code-block:: sql
 
-================
-Examples
-================
+  default> \l
+  default
+  tpch
+  work1
+  default> 
 
-If you want to list all table names, use '\d' meta command as follows: ::
+``\d`` command shows a list of tables in the current database as follows: ..
 
-  tajo> \d
+  default> \d
   customer
   lineitem
   nation
@@ -80,9 +102,9 @@ If you want to list all table names, use '\d' meta command as follows: ::
   region
   supplier
 
-Now look at the table description: ::
+``\d [table name]`` command also shows a table description.
 
-  tajo> \d orders
+  default> \d orders
 
   table name: orders
   table path: hdfs:/xxx/xxx/tpch/orders
@@ -98,4 +120,40 @@ Now look at the table description: ::
   o_orderpriority TEXT
   o_clerk TEXT
   o_shippriority  INT4
-  o_comment       TEXT
\ No newline at end of file
+  o_comment       TEXT
+
+The prompt ``default>`` indicates the current database. Basically, all SQL statements and meta commands work in the current database. Also, you can change the current database with ``\c`` command.
+
+.. code-block:: sql
+
+  default> \c work1
+  You are now connected to database "test" as user "hyunsik".
+  work1>
+
+-----------------------------------------------
+Session Variables
+-----------------------------------------------
+
+Each client connection to TajoMaster creates a unique session, and the client and TajoMaster uses the session until disconnect. A session provides session variables which are used for various configs per session.
+
+``tsql`` provides the meta command ``\set`` to manipulate session variables. Just ``\set`` command shows all session variables. ::
+
+  default> \set
+  'name1'='val1'
+  'name2'='val2'
+  'name3'='val3'
+       ...
+
+``\set key val`` will set the session variable named *key* with the value *val*. ::
+
+  default> \set
+  'CURRENT_DATABASE'='default'
+  
+  default> \set key1 val1
+
+  default> \set
+  'CURRENT_DATABASE'='default'
+  'key1'='val1'
+
+
+Also, ``\unset key`` will unset the session variable named *key*.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-docs/src/main/sphinx/configuration/catalog_configuration.rst
----------------------------------------------------------------------
diff --git a/tajo-docs/src/main/sphinx/configuration/catalog_configuration.rst b/tajo-docs/src/main/sphinx/configuration/catalog_configuration.rst
index 86899ba..80abd57 100644
--- a/tajo-docs/src/main/sphinx/configuration/catalog_configuration.rst
+++ b/tajo-docs/src/main/sphinx/configuration/catalog_configuration.rst
@@ -25,9 +25,21 @@ If you want to customize the catalog service, copy ``$TAJO_HOME/conf/catalog-sit
 MySQLStore Configuration
 =========================
 
-If you want to use MySQLStore, you must create database and user on mysql for tajo. 
+In order to use MySQLStore, you need to create database and user on MySQL for Tajo.
 
-And then, you need to prepare mysql jdbc driver on host which can be ran TajoMaster. If you do, you should set ``TAJO_CLASSPATH`` variable in ``conf/tajo-env.sh`` with it as follows:
+.. code-block:: sh
+  
+  mysql> create user 'tajo'@'localhost' identified by 'xxxxxx';
+  Query OK, 0 rows affected (0.00 sec)
+
+  mysql> create database tajo;
+  Query OK, 1 row affected (0.00 sec)  
+
+  mysql> grant all on tajo.* to 'tajo'@'localhost';
+  Query OK, 0 rows affected (0.01 sec)
+
+
+And then, you need to prepare MySQL JDBC driver on the machine which can be ran TajoMaster. If you do, you should set ``TAJO_CLASSPATH`` variable in ``conf/tajo-env.sh`` with it as follows:
 
 .. code-block:: sh
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-docs/src/main/sphinx/configuration/cluster_setup.rst
----------------------------------------------------------------------
diff --git a/tajo-docs/src/main/sphinx/configuration/cluster_setup.rst b/tajo-docs/src/main/sphinx/configuration/cluster_setup.rst
index e9715f3..89db12c 100644
--- a/tajo-docs/src/main/sphinx/configuration/cluster_setup.rst
+++ b/tajo-docs/src/main/sphinx/configuration/cluster_setup.rst
@@ -1,5 +1,5 @@
 *******************************************
-Custer Setup
+Cluster Setup
 *******************************************
 
 Fully Distributed Mode

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-docs/src/main/sphinx/sql_language/ddl.rst
----------------------------------------------------------------------
diff --git a/tajo-docs/src/main/sphinx/sql_language/ddl.rst b/tajo-docs/src/main/sphinx/sql_language/ddl.rst
index 2f0e9d4..e2e64f6 100644
--- a/tajo-docs/src/main/sphinx/sql_language/ddl.rst
+++ b/tajo-docs/src/main/sphinx/sql_language/ddl.rst
@@ -2,6 +2,29 @@
 Data Definition Language
 ************************
 
+========================
+CREATE DATABASE
+========================
+
+*Synopsis*
+
+.. code-block:: sql
+
+  CREATE DATABASE [IF NOT EXISTS] <database_name> 
+
+``IF NOT EXISTS`` allows ``CREATE DATABASE`` statement to avoid an error which occurs when the database exists.
+
+========================
+DROP DATABASE
+========================
+
+*Synopsis*
+
+.. code-block:: sql
+
+  DROP DATABASE [IF EXISTS] <database_name>
+
+``IF EXISTS`` allows ``DROP DATABASE`` statement to avoid an error which occurs when the database does not exist.
 
 ========================
 CREATE TABLE
@@ -11,15 +34,13 @@ CREATE TABLE
 
 .. code-block:: sql
 
-  CREATE TABLE <table_name> [(<column_name> <data_type>, ... )]
+  CREATE TABLE [IF NOT EXISTS] <table_name> [(<column_name> <data_type>, ... )]
   [using <storage_type> [with (<key> = <value>, ...)]] [AS <select_statement>]
 
-  CREATE EXTERNAL TABLE
-
-  CREATE EXTERNAL TABLE <table_name> (<column_name> <data_type>, ... )
+  CREATE EXTERNAL TABLE [IF NOT EXISTS] <table_name> (<column_name> <data_type>, ... )
   using <storage_type> [with (<key> = <value>, ...)] LOCATION '<path>'
 
-
+``IF NOT EXISTS`` allows ``CREATE [EXTERNAL] TABLE`` statement to avoid an error which occurs when the table does not exist.
 
 ------------------------
  Compression
@@ -48,6 +69,10 @@ If you want to add an external table that contains compressed data, you should g
  DROP TABLE
 ========================
 
+*Synopsis*
+
 .. code-block:: sql
 
-  DROP TABLE <table_name>
\ No newline at end of file
+  DROP TABLE [IF EXISTS] <table_name> [PURGE]
+
+``IF EXISTS`` allows ``DROP DATABASE`` statement to avoid an error which occurs when the database does not exist. ``DROP TABLE`` statement removes a table from Tajo catalog, but it does not remove the contents. If ``PURGE`` option is given, ``DROP TABLE`` statement will eliminate the entry in the catalog as well as the contents.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoConnection.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoConnection.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoConnection.java
index b751d5d..5d967e8 100644
--- a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoConnection.java
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoConnection.java
@@ -1,4 +1,4 @@
-package org.apache.tajo.jdbc; /**
+/**
  * 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
@@ -16,71 +16,83 @@ package org.apache.tajo.jdbc; /**
  * limitations under the License.
  */
 
+package org.apache.tajo.jdbc;
+
+import com.google.protobuf.ServiceException;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.client.TajoClient;
 import org.apache.tajo.conf.TajoConf;
+import org.jboss.netty.handler.codec.http.QueryStringDecoder;
 
+import java.net.URI;
 import java.sql.*;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 public class TajoConnection implements Connection {
-  private TajoClient tajoClient;
-
-  private String databaseName;
-
-  private AtomicBoolean closed = new AtomicBoolean(true);
-
-  private String uri;
-
-  public TajoConnection(String uri, Properties properties) throws SQLException {
-    if (!uri.startsWith(TajoDriver.TAJO_JDBC_URL_PREFIX)) {
-      throw new SQLException("Invalid URL: " + uri, "TAJO-001");
-    }
-
-    this.uri = uri;
+  private final TajoClient tajoClient;
+  private final AtomicBoolean closed = new AtomicBoolean(true);
+  private final String rawURI;
+  private final Properties properties;
+
+  private final URI uri;
+  private final String hostName;
+  private final int port;
+  private final String databaseName;
+  @SuppressWarnings("unused")
+  /** it will be used soon. */
+  private final Map<String, List<String>> params;
+
+  public TajoConnection(String rawURI, Properties properties) throws SQLException {
+    this.rawURI = rawURI;
+    this.properties = properties;
 
-    // remove prefix
-    uri = uri.substring(TajoDriver.TAJO_JDBC_URL_PREFIX.length());
+    try {
+      if (!rawURI.startsWith(TajoDriver.TAJO_JDBC_URL_PREFIX)) {
+        throw new SQLException("Invalid URL: " + rawURI, "TAJO-001");
+      }
 
+      // URI form: jdbc:tajo://hostname:port/databasename
+      int startIdx = rawURI.indexOf(":");
+      if (startIdx < 0) {
+        throw new SQLException("Invalid URL: " + rawURI, "TAJO-001");
+      }
 
-    if (uri.isEmpty()) {
-      throw new SQLException("Invalid URL: " + uri, "TAJO-001");
-    }
+      String uri = rawURI.substring(startIdx+1, rawURI.length());
+      try {
+        this.uri = URI.create(uri);
+      } catch (IllegalArgumentException iae) {
+        throw new SQLException("Invalid URL: " + rawURI, "TAJO-001");
+      }
 
-    // parse uri
-    // form: hostname:port/databasename
-    String[] parts = uri.split("/");
-    if(parts.length == 0 || parts[0].trim().isEmpty()) {
-      throw new SQLException("Invalid URL(No tajo master's host:port): " + uri, "TAJO-001");
-    }
-    String[] hostAndPort = parts[0].trim().split(":");
-    String host = hostAndPort[0];
-    int port = 0;
-    try {
-      port = Integer.parseInt(hostAndPort[1]);
-    } catch (Exception e) {
-      throw new SQLException("Invalid URL(Wrong tajo master's host:port): " + uri, "TAJO-001");
-    }
+      hostName = this.uri.getHost();
+      if(hostName == null) {
+        throw new SQLException("Invalid JDBC URI: " + rawURI, "TAJO-001");
+      }
+      if (this.uri.getPort() < 1) {
+        port = 26002;
+      } else {
+        port = this.uri.getPort();
+      }
 
-    if(parts.length > 1) {
-      String[] tokens = parts[1].split("\\?");
-      databaseName = tokens[0].trim();
-      if(tokens.length > 1) {
-        String[] extraParamTokens = tokens[1].split("&");
-        for(String eachExtraParam: extraParamTokens) {
-          String[] paramTokens = eachExtraParam.split("=");
-          String extraParamKey = paramTokens[0];
-          String extraParamValue = paramTokens[1];
-        }
+      if (this.uri.getPath() == null) { // if no database is given, set default.
+        databaseName = TajoConstants.DEFAULT_DATABASE_NAME;
+      } else {
+        // getPath() will return '/database'.
+        databaseName = this.uri.getPath().split("/")[1];
       }
+
+      params = new QueryStringDecoder(rawURI).getParameters();
+    } catch (SQLException se) {
+      throw se;
+    } catch (Throwable t) { // for unexpected exceptions like ArrayIndexOutOfBoundsException.
+      throw new SQLException("Invalid JDBC URI: " + rawURI, "TAJO-001");
     }
 
     TajoConf tajoConf = new TajoConf();
-
-    tajoConf.setVar(TajoConf.ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS, host + ":" + port);
-
     if(properties != null) {
       for(Map.Entry<Object, Object> entry: properties.entrySet()) {
         tajoConf.set(entry.getKey().toString(), entry.getValue().toString());
@@ -88,15 +100,15 @@ public class TajoConnection implements Connection {
     }
 
     try {
-      tajoClient = new TajoClient(tajoConf);
+      tajoClient = new TajoClient(hostName, port, databaseName);
     } catch (Exception e) {
-      throw new SQLException("Can't create tajo client:" + e.getMessage(), "TAJO-002");
+      throw new SQLException("Cannot create TajoClient instance:" + e.getMessage(), "TAJO-002");
     }
     closed.set(false);
   }
 
   public String getUri() {
-    return uri;
+    return this.rawURI;
   }
 
   public TajoClient getTajoClient() {
@@ -181,7 +193,11 @@ public class TajoConnection implements Connection {
 
   @Override
   public String getCatalog() throws SQLException {
-    return "";
+    try {
+      return tajoClient.getCurrentDatabase();
+    } catch (ServiceException e) {
+      throw new SQLException(e);
+    }
   }
 
   @Override
@@ -231,7 +247,8 @@ public class TajoConnection implements Connection {
 
   @Override
   public boolean isValid(int timeout) throws SQLException {
-    throw new SQLFeatureNotSupportedException("isValid");
+    // TODO - It should be changed to submit a simple query.
+    return tajoClient.isConnected();
   }
 
   @Override
@@ -313,7 +330,11 @@ public class TajoConnection implements Connection {
 
   @Override
   public void setCatalog(String catalog) throws SQLException {
-    throw new SQLFeatureNotSupportedException("setCatalog");
+    try {
+      tajoClient.selectDatabase(catalog);
+    } catch (ServiceException e) {
+      throw new SQLException(e);
+    }
   }
 
   @Override
@@ -373,12 +394,12 @@ public class TajoConnection implements Connection {
 
   public void abort(Executor executor) throws SQLException {
     // JDK 1.7
-    throw new SQLFeatureNotSupportedException("abort not supported");
+    throw new SQLFeatureNotSupportedException("abort is not supported");
   }
 
   public int getNetworkTimeout() throws SQLException {
     // JDK 1.7
-    throw new SQLFeatureNotSupportedException("getNetworkTimeout not supported");
+    throw new SQLFeatureNotSupportedException("getNetworkTimeout is not supported");
   }
 
   public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
@@ -387,12 +408,10 @@ public class TajoConnection implements Connection {
   }
 
   public String getSchema() throws SQLException {
-    // JDK 1.7
-    throw new SQLFeatureNotSupportedException("getSchema not supported");
+    return TajoConstants.DEFAULT_SCHEMA_NAME;
   }
 
   public void setSchema(String schema) throws SQLException {
-    // JDK 1.7
-    throw new SQLFeatureNotSupportedException("setSchema not supported");
+    throw new SQLFeatureNotSupportedException("setSchema() is not supported yet");
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
index b3e67bc..f70b762 100644
--- a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
@@ -1,4 +1,4 @@
-package org.apache.tajo.jdbc; /**
+/**
  * 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
@@ -15,8 +15,11 @@ package org.apache.tajo.jdbc; /**
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.tajo.jdbc;
 
+import com.google.protobuf.ServiceException;
 import org.apache.tajo.TajoConstants;
+import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.client.ResultSetUtil;
@@ -28,6 +31,8 @@ import org.apache.tajo.datum.TextDatum;
 import java.sql.*;
 import java.util.*;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_SCHEMA_NAME;
+
 /**
  * TajoDatabaseMetaData.
  */
@@ -375,7 +380,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
+  public ResultSet getTables(@Nullable String catalog, String schemaPattern, String tableNamePattern, String [] types)
       throws SQLException {
     try {
       final List<MetaDataTuple> resultTables = new ArrayList<MetaDataTuple>();
@@ -389,17 +394,17 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
       String regtableNamePattern = convertPattern(tableNamePattern);
       try {
         TajoClient tajoClient = conn.getTajoClient();
-        List<String> tableNames = tajoClient.getTableList();
+        List<String> tableNames = tajoClient.getTableList(resultCatalog);
         for (String eachTableName: tableNames) {
           if (eachTableName.matches(regtableNamePattern)) {
             MetaDataTuple tuple = new MetaDataTuple(5);
 
             int index = 0;
-            tuple.put(index++, new TextDatum(resultCatalog));  //TABLE_CAT
-            tuple.put(index++, NullDatum.get());   //TABLE_SCHEM
-            tuple.put(index++, new TextDatum(eachTableName));
-            tuple.put(index++, new TextDatum("TABLE"));   //TABLE_TYPE
-            tuple.put(index++, NullDatum.get());   //REMARKS
+            tuple.put(index++, new TextDatum(resultCatalog));         // TABLE_CAT
+            tuple.put(index++, new TextDatum(DEFAULT_SCHEMA_NAME));   // TABLE_SCHEM
+            tuple.put(index++, new TextDatum(eachTableName));         // TABLE_NAME
+            tuple.put(index++, new TextDatum("TABLE"));               // TABLE_TYPE
+            tuple.put(index++, NullDatum.get());                      // REMARKS
 
             resultTables.add(tuple);
           }
@@ -427,25 +432,44 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public ResultSet getSchemas()
-      throws SQLException {
-    return getSchemas(null, null);
+  public ResultSet getSchemas() throws SQLException {
+    String databaseName;
+    try {
+      databaseName = conn.getTajoClient().getCurrentDatabase();
+    } catch (ServiceException e) {
+      throw new SQLException(e);
+    }
+
+    MetaDataTuple tuple = new MetaDataTuple(1);
+    tuple.put(0, new TextDatum(DEFAULT_SCHEMA_NAME));
+    tuple.put(1, new TextDatum(databaseName));
+
+    return new TajoMetaDataResultSet(
+        Arrays.asList("TABLE_SCHEM", "TABLE_CATALOG"),
+        Arrays.asList(Type.VARCHAR, Type.VARCHAR),
+        Arrays.asList(tuple));
   }
 
   @Override
-  public ResultSet getCatalogs()
-      throws SQLException {
-    List<MetaDataTuple> columns = new ArrayList<MetaDataTuple>();
-    MetaDataTuple tuple = new MetaDataTuple(1);
-    tuple.put(0, new TextDatum("default"));
-    columns.add(tuple);
+  public ResultSet getCatalogs() throws SQLException {
+    Collection<String> databaseNames;
+    try {
+      databaseNames = conn.getTajoClient().getAllDatabaseNames();
+    } catch (ServiceException e) {
+      throw new SQLException(e);
+    }
 
-    ResultSet result = new TajoMetaDataResultSet(
-        Arrays.asList("TABLE_CAT")
-        , Arrays.asList(Type.VARCHAR)
-        , columns);
+    List<MetaDataTuple> tuples = new ArrayList<MetaDataTuple>();
+    for (String databaseName : databaseNames) {
+      MetaDataTuple tuple = new MetaDataTuple(1);
+      tuple.put(0, new TextDatum(databaseName));
+      tuples.add(tuple);
+    }
 
-    return result;
+    return new TajoMetaDataResultSet(
+        Arrays.asList("TABLE_CAT"),
+        Arrays.asList(Type.VARCHAR) ,
+        tuples);
   }
 
   @Override
@@ -482,13 +506,13 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
     List<MetaDataTuple> columns = new ArrayList<MetaDataTuple>();
     try {
       if (catalog == null) {
-        catalog = "default";
+        catalog = TajoConstants.DEFAULT_DATABASE_NAME;
       }
 
       String regtableNamePattern = convertPattern(tableNamePattern);
       String regcolumnNamePattern = convertPattern(columnNamePattern);
 
-      List<String> tables = conn.getTajoClient().getTableList();
+      List<String> tables = conn.getTajoClient().getTableList(catalog);
       for (String table: tables) {
         if (table.matches(regtableNamePattern)) {
           TableDesc tableDesc = conn.getTajoClient().getTableDesc(table);
@@ -499,7 +523,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
               int index = 0;
               tuple.put(index++, new TextDatum(catalog));  //TABLE_CAT
-              tuple.put(index++, NullDatum.get());  //TABLE_SCHEM
+              tuple.put(index++, new TextDatum(catalog));  //TABLE_SCHEM
               tuple.put(index++, new TextDatum(table));  //TABLE_NAME
               tuple.put(index++, new TextDatum(column.getSimpleName()));  //COLUMN_NAME
               // TODO - DATA_TYPE
@@ -685,12 +709,22 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public ResultSet getSchemas(String catalog, String schemaPattern)
-      throws SQLException {
+  public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
+    String databaseName;
+    try {
+      databaseName = conn.getTajoClient().getCurrentDatabase();
+    } catch (ServiceException e) {
+      throw new SQLException(e);
+    }
+
+    MetaDataTuple tuple = new MetaDataTuple(1);
+    tuple.put(0, new TextDatum(DEFAULT_SCHEMA_NAME));
+    tuple.put(1, new TextDatum(databaseName));
+
     return new TajoMetaDataResultSet(
         Arrays.asList("TABLE_SCHEM", "TABLE_CATALOG"),
         Arrays.asList(Type.VARCHAR, Type.VARCHAR),
-        null);
+        Arrays.asList(tuple));
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-project/pom.xml
----------------------------------------------------------------------
diff --git a/tajo-project/pom.xml b/tajo-project/pom.xml
index 59628a9..cae8602 100644
--- a/tajo-project/pom.xml
+++ b/tajo-project/pom.xml
@@ -770,7 +770,7 @@
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
-        <version>4.10</version>
+        <version>4.11</version>
         <type>jar</type>
         <scope>compile</scope>
       </dependency>


[02/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCreateDatabase.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCreateDatabase.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCreateDatabase.java
new file mode 100644
index 0000000..c1c2591
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCreateDatabase.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.query;
+
+import org.apache.tajo.IntegrationTest;
+import org.apache.tajo.QueryTestCaseBase;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.sql.ResultSet;
+
+@Category(IntegrationTest.class)
+public class TestCreateDatabase extends QueryTestCaseBase {
+
+  @Test
+  public final void testCreateAndDropDatabase() throws Exception {
+    ResultSet res = null;
+    try {
+      res = executeString("CREATE DATABASE testCreateAndDropDatabase;");
+      assertDatabaseExists("testCreateAndDropDatabase");
+      executeString("DROP DATABASE testCreateAndDropDatabase;");
+      assertDatabaseNotExists("testCreateAndDropDatabase");
+    } finally {
+      cleanupQuery(res);
+    }
+  }
+
+  @Test
+  public final void testCreateIfNotExists() throws Exception {
+    String databaseName = "testCreateIfNotExists";
+
+    assertDatabaseNotExists(databaseName);
+    executeString("CREATE DATABASE " + databaseName + ";").close();
+    assertDatabaseExists(databaseName);
+
+    executeString("CREATE DATABASE IF NOT EXISTS " + databaseName + ";").close();
+    assertDatabaseExists(databaseName);
+
+    executeString("DROP DATABASE " + databaseName + ";").close();
+    assertDatabaseNotExists(databaseName);
+  }
+
+  @Test
+  public final void testDropIfExists() throws Exception {
+    String databaseName = "testDropIfExists";
+    assertDatabaseNotExists(databaseName);
+    executeString("CREATE DATABASE " + databaseName + ";").close();
+    assertDatabaseExists(databaseName);
+
+    executeString("DROP DATABASE " + databaseName + ";").close();
+    assertDatabaseNotExists(databaseName);
+
+    executeString("DROP DATABASE IF EXISTS " + databaseName + ";");
+    assertDatabaseNotExists(databaseName);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java
index f39ceb8..f2882dd 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCreateTable.java
@@ -23,140 +23,209 @@ import org.apache.tajo.QueryTestCaseBase;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import java.util.List;
+
 @Category(IntegrationTest.class)
 public class TestCreateTable extends QueryTestCaseBase {
 
   @Test
   public final void testVariousTypes() throws Exception {
-    String tableName = executeDDL("create_table_various_types.sql", null);
-    assertTableExists(tableName);
+    List<String> createdNames;
+    if (testingCluster.isHCatalogStoreRunning()) {
+      createdNames = executeDDL("create_table_various_types_for_hcatalog.sql", null);
+    } else {
+      createdNames = executeDDL("create_table_various_types.sql", null);
+    }
+    assertTableExists(createdNames.get(0));
   }
 
   @Test
   public final void testCreateTable1() throws Exception {
-    String tableName = executeDDL("table1_ddl.sql", "table1.tbl", "table1");
-    assertTableExists(tableName);
+    List<String> createdNames = executeDDL("table1_ddl.sql", "table1", "table1");
+    assertTableExists(createdNames.get(0));
+  }
+
+  @Test
+  public final void testCreateTable2() throws Exception {
+    executeString("CREATE DATABASE D1;").close();
+    executeString("CREATE DATABASE D2;").close();
+
+    executeString("CREATE TABLE D1.table1 (age int);").close();
+    executeString("CREATE TABLE D1.table2 (age int);").close();
+    executeString("CREATE TABLE D2.table3 (age int);").close();
+    executeString("CREATE TABLE D2.table4 (age int);").close();
+
+    assertTableExists("D1.table1");
+    assertTableExists("D1.table2");
+    assertTableNotExists("D2.table1");
+    assertTableNotExists("D2.table2");
+
+    assertTableExists("D2.table3");
+    assertTableExists("D2.table4");
+    assertTableNotExists("D1.table3");
+    assertTableNotExists("D1.table4");
+
+    executeString("DROP TABLE D1.table1");
+    executeString("DROP TABLE D1.table2");
+    executeString("DROP TABLE D2.table3");
+    executeString("DROP TABLE D2.table4");
+
+    assertDatabaseExists("D1");
+    assertDatabaseExists("D2");
+    executeString("DROP DATABASE D1").close();
+    executeString("DROP DATABASE D2").close();
+    assertDatabaseNotExists("D1");
+    assertDatabaseNotExists("D2");
+  }
+
+  @Test
+  public final void testCreateTableIfNotExists() throws Exception {
+    executeString("CREATE DATABASE D3;").close();
+
+    assertTableNotExists("D3.table1");
+    executeString("CREATE TABLE D3.table1 (age int);").close();
+    assertTableExists("D3.table1");
+
+    executeString("CREATE TABLE IF NOT EXISTS D3.table1 (age int);").close();
+    assertTableExists("D3.table1");
+
+    executeString("DROP TABLE D3.table1");
+  }
+
+  @Test
+  public final void testDropTableIfExists() throws Exception {
+    executeString("CREATE DATABASE D4;").close();
+
+    assertTableNotExists("D4.table1");
+    executeString("CREATE TABLE D4.table1 (age int);").close();
+    assertTableExists("D4.table1");
+
+    executeString("DROP TABLE D4.table1;").close();
+    assertTableNotExists("D4.table1");
+
+    executeString("DROP TABLE IF EXISTS D4.table1");
+    assertTableNotExists("D4.table1");
   }
 
   @Test
   public final void testNonreservedKeywordTableNames() throws Exception {
-    String tableName = null;
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "filter");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "first");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "format");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "grouping");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "hash");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "index");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "insert");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "last");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "location");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "max");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "min");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "national");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "nullif");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "overwrite");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "precision");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "range");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "regexp");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "rlike");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "set");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "unknown");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "var_pop");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "var_samp");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "varying");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "zone");
-    assertTableExists(tableName);
-
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "bigint");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "bit");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "blob");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "bool");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "boolean");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "bytea");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "char");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "date");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "decimal");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "double");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "float");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "float4");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "float8");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "inet4");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "int");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "int1");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "int2");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "int4");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "int8");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "integer");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "nchar");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "numeric");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "nvarchar");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "real");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "smallint");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "text");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "time");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "timestamp");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "timestamptz");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "timetz");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "tinyint");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "varbinary");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "varbit");
-    assertTableExists(tableName);
-    tableName = executeDDL("table1_ddl.sql", "table1.tbl", "varchar");
-    assertTableExists(tableName);
+    List<String> createdNames = null;
+    createdNames = executeDDL("table1_ddl.sql", "table1", "filter");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "first");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "format");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "grouping");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "hash");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "index");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "insert");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "last");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "location");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "max");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "min");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "national");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "nullif");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "overwrite");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "precision");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "range");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "regexp");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "rlike");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "set");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "unknown");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "var_pop");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "var_samp");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "varying");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "zone");
+    assertTableExists(createdNames.get(0));
+
+    createdNames = executeDDL("table1_ddl.sql", "table1", "bigint");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "bit");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "blob");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "bool");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "boolean");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "bytea");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "char");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "date");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "decimal");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "double");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "float");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "float4");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "float8");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "inet4");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "int");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "int1");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "int2");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "int4");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "int8");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "integer");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "nchar");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "numeric");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "nvarchar");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "real");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "smallint");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "text");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "time");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "timestamp");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "timestamptz");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "timetz");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "tinyint");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "varbinary");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "varbit");
+    assertTableExists(createdNames.get(0));
+    createdNames = executeDDL("table1_ddl.sql", "table1", "varchar");
+    assertTableExists(createdNames.get(0));
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
index 8ecf8ed..250d6f4 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.query;
 
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
@@ -27,6 +28,11 @@ import java.sql.ResultSet;
 
 @Category(IntegrationTest.class)
 public class TestGroupByQuery extends QueryTestCaseBase {
+
+  public TestGroupByQuery() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public final void testGroupBy() throws Exception {
     // select count(1) as unique_key from lineitem;

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java
index 8b2db9f..250be47 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestInsertQuery.java
@@ -36,6 +36,7 @@ import org.junit.experimental.categories.Category;
 import java.io.IOException;
 import java.sql.ResultSet;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
 import static org.junit.Assert.*;
 
 @Category(IntegrationTest.class)
@@ -57,14 +58,16 @@ public class TestInsertQuery {
     res.close();
     TajoTestingCluster cluster = tpch.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = tpch.execute("insert overwrite into " + tableName
         + " select l_orderkey, l_partkey, l_quantity from lineitem");
     res.close();
 
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
   }
 
   @Test
@@ -74,13 +77,15 @@ public class TestInsertQuery {
     res.close();
     TajoTestingCluster cluster = tpch.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    assertTrue(catalog.existsTable(tableName));
-    TableDesc originalDesc = catalog.getTableDesc(tableName);
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
+    TableDesc originalDesc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
 
     res = tpch.execute("insert overwrite into " + tableName + " select l_orderkey from lineitem");
     res.close();
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
     assertEquals(originalDesc.getSchema(), desc.getSchema());
   }
 
@@ -91,13 +96,15 @@ public class TestInsertQuery {
     res.close();
     TajoTestingCluster cluster = tpch.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    assertTrue(catalog.existsTable(tableName));
-    TableDesc originalDesc = catalog.getTableDesc(tableName);
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
+    TableDesc originalDesc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
 
     res = tpch.execute("insert overwrite into " + tableName + " (col1, col3) select l_orderkey, l_quantity from lineitem");
     res.close();
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
 
     res = tpch.execute("select * from " + tableName);
 
@@ -143,12 +150,14 @@ public class TestInsertQuery {
     res.close();
     TajoTestingCluster cluster = tpch.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = tpch.execute("insert overwrite into " + tableName + " select * from lineitem where l_orderkey = 3");
     res.close();
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(2, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(2, desc.getStats().getNumRows().intValue());
+    }
   }
 
   @Test
@@ -161,9 +170,11 @@ public class TestInsertQuery {
 
     TajoTestingCluster cluster = tpch.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    assertTrue(catalog.existsTable(tableName));
-    TableDesc orderKeys = catalog.getTableDesc(tableName);
-    assertEquals(5, orderKeys.getStats().getNumRows().intValue());
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
+    TableDesc orderKeys = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(5, orderKeys.getStats().getNumRows().intValue());
+    }
 
     // this query will result in the two rows.
     res = tpch.execute(
@@ -171,9 +182,11 @@ public class TestInsertQuery {
     assertFalse(res.next());
     res.close();
 
-    assertTrue(catalog.existsTable(tableName));
-    orderKeys = catalog.getTableDesc(tableName);
-    assertEquals(2, orderKeys.getStats().getNumRows().intValue());
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
+    orderKeys = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(2, orderKeys.getStats().getNumRows().intValue());
+    }
   }
 
   @Test
@@ -183,12 +196,14 @@ public class TestInsertQuery {
     res.close();
     TajoTestingCluster cluster = tpch.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = tpch.execute("insert overwrite into " + tableName + " select * from lineitem where l_orderkey = 3");
     res.close();
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(2, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(2, desc.getStats().getNumRows().intValue());
+    }
   }
 
   @Test
@@ -208,18 +223,20 @@ public class TestInsertQuery {
     res.close();
     TajoTestingCluster cluster = tpch.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = tpch.execute("insert overwrite into " + tableName + " select  l_orderkey, l_partkey, l_quantity from lineitem where l_orderkey = 3");
     res.close();
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(2, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(2, desc.getStats().getNumRows().intValue());
+    }
 
     FileSystem fs = FileSystem.get(tpch.getTestingCluster().getConfiguration());
     assertTrue(fs.exists(desc.getPath()));
     CompressionCodecFactory factory = new CompressionCodecFactory(tpch.getTestingCluster().getConfiguration());
 
-    for (FileStatus file : fs.listStatus(desc.getPath())){
+    for (FileStatus file : fs.listStatus(desc.getPath())) {
       CompressionCodec codec = factory.getCodec(file.getPath());
       assertTrue(codec instanceof DeflateCodec);
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java
index 4bda517..3e28f9e 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinOnPartitionedTables.java
@@ -19,14 +19,20 @@
 package org.apache.tajo.engine.query;
 
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.junit.Test;
 
 import java.sql.ResultSet;
 
 public class TestJoinOnPartitionedTables extends QueryTestCaseBase {
 
+  public TestJoinOnPartitionedTables() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public void testPartitionTableJoinSmallTable() throws Exception {
+
     executeDDL("customer_ddl.sql", null);
     ResultSet res = executeFile("insert_into_customer.sql");
     res.close();

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java
index 0c68fa6..19591ea 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.query;
 
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
@@ -27,6 +28,11 @@ import java.sql.ResultSet;
 
 @Category(IntegrationTest.class)
 public class TestJoinQuery extends QueryTestCaseBase {
+
+  public TestJoinQuery() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public final void testCrossJoin() throws Exception {
     ResultSet res = executeQuery();
@@ -169,8 +175,8 @@ public class TestJoinQuery extends QueryTestCaseBase {
 
   @Test
   public void testOuterJoinAndCaseWhen1() throws Exception {
-    executeDDL("oj_table1_ddl.sql", "table1.tbl");
-    executeDDL("oj_table2_ddl.sql", "table2.tbl");
+    executeDDL("oj_table1_ddl.sql", "table1");
+    executeDDL("oj_table2_ddl.sql", "table2");
     ResultSet res = executeQuery();
     assertResultSet(res);
     cleanupQuery(res);
@@ -264,4 +270,16 @@ public class TestJoinQuery extends QueryTestCaseBase {
     cleanupQuery(res);
   }
 
+  @Test
+  public final void testJoinOnMultipleDatabases() throws Exception {
+    executeString("CREATE DATABASE JOINS");
+    assertDatabaseExists("JOINS");
+    executeString("CREATE TABLE JOINS.part_ as SELECT * FROM part");
+    assertTableExists("JOINS.part_");
+    executeString("CREATE TABLE JOINS.supplier_ as SELECT * FROM supplier");
+    assertTableExists("JOINS.supplier_");
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNetTypes.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNetTypes.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNetTypes.java
index bba47cc..17235a6 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNetTypes.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNetTypes.java
@@ -27,48 +27,65 @@ import java.sql.ResultSet;
 public class TestNetTypes extends QueryTestCaseBase {
 
   @Before
-  public final void setup() throws Exception {
-    executeDDL("table1_ddl.sql", "table1.tbl");
-    executeDDL("table2_ddl.sql", "table2.tbl");
+  public final void setUp() throws Exception {
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      executeDDL("table1_ddl.sql", "table1");
+      executeDDL("table2_ddl.sql", "table2");
+    }
   }
 
   @Test
   public final void testSelect() throws Exception {
-    // select name, addr from table1;
-    ResultSet res = executeQuery();
-    assertResultSet(res);
-    cleanupQuery(res);
+    // Skip all tests when HCatalogStore is used.
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      // select name, addr from table1;
+      ResultSet res = executeQuery();
+      assertResultSet(res);
+      cleanupQuery(res);
+    }
   }
 
   @Test
   public final void testGroupby() throws Exception {
-    // select name, addr, count(1) from table1 group by name, addr;
-    ResultSet res = executeQuery();
-    assertResultSet(res);
-    cleanupQuery(res);
+    // Skip all tests when HCatalogStore is used.
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      // select name, addr, count(1) from table1 group by name, addr;
+      ResultSet res = executeQuery();
+      assertResultSet(res);
+      cleanupQuery(res);
+    }
   }
 
   @Test
   public final void testGroupby2() throws Exception {
-    // select addr, count(*) from table1 group by addr;
-    ResultSet res = executeQuery();
-    assertResultSet(res);
-    cleanupQuery(res);
+    // Skip all tests when HCatalogStore is used.
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      // select addr, count(*) from table1 group by addr;
+      ResultSet res = executeQuery();
+      assertResultSet(res);
+      cleanupQuery(res);
+    }
   }
 
   @Test
   public final void testSort() throws Exception {
-    // select * from table1 order by addr;
-    ResultSet res = executeQuery();
-    assertResultSet(res);
-    cleanupQuery(res);
+    // Skip all tests when HCatalogStore is used.
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      // select * from table1 order by addr;
+      ResultSet res = executeQuery();
+      assertResultSet(res);
+      cleanupQuery(res);
+    }
   }
 
   @Test
   public final void testJoin() throws Exception {
-    // select * from table1 as t1, table2 as t2 where t1.addr = t2.addr;
-    ResultSet res = executeQuery();
-    assertResultSet(res);
-    cleanupQuery(res);
+    // Skip all tests when HCatalogStore is used.
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      // select * from table1 as t1, table2 as t2 where t1.addr = t2.addr;
+      ResultSet res = executeQuery();
+      assertResultSet(res);
+      cleanupQuery(res);
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
index fece424..a75631a 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.query;
 
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.catalog.CatalogService;
 import org.apache.tajo.catalog.TableDesc;
@@ -28,12 +29,17 @@ import org.junit.experimental.categories.Category;
 
 import java.sql.ResultSet;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 @Category(IntegrationTest.class)
 public class TestSelectQuery extends QueryTestCaseBase {
 
+  public TestSelectQuery() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public final void testSelect() throws Exception {
     // select l_orderkey, l_partkey from lineitem;
@@ -227,9 +233,11 @@ public class TestSelectQuery extends QueryTestCaseBase {
     res.close();
     TajoTestingCluster cluster = testBase.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    assertTrue(catalog.existsTable("orderkeys"));
-    TableDesc orderKeys = catalog.getTableDesc("orderkeys");
-    assertEquals(5, orderKeys.getStats().getNumRows().intValue());
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, "orderkeys"));
+    TableDesc orderKeys = catalog.getTableDesc(DEFAULT_DATABASE_NAME, "orderkeys");
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(5, orderKeys.getStats().getNumRows().intValue());
+    }
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java
index 23d7bdb..61206cd 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.query;
 
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
@@ -28,6 +29,10 @@ import java.sql.ResultSet;
 @Category(IntegrationTest.class)
 public class TestSortQuery extends QueryTestCaseBase {
 
+  public TestSortQuery() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public final void testSort() throws Exception {
     ResultSet res = executeQuery();
@@ -96,12 +101,16 @@ public class TestSortQuery extends QueryTestCaseBase {
 
   @Test
   public final void testSortWithDate() throws Exception {
-    //select col1, col2, l_comment from table1 order by col1, col2;
-    executeDDL("create_table_with_date_ddl.sql", "table1.tbl");
-
-    ResultSet res = executeQuery();
-    assertResultSet(res);
-    cleanupQuery(res);
+    // skip this test if catalog uses HCatalogStore.
+    // It is because HCatalogStore does not support Time data type.
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      // create external table table1 (col1 timestamp, col2 date, col3 time) ...
+      executeDDL("create_table_with_date_ddl.sql", "table1");
+
+      ResultSet res = executeQuery();
+      assertResultSet(res);
+      cleanupQuery(res);
+    }
   }
 
   @Test
@@ -114,7 +123,7 @@ public class TestSortQuery extends QueryTestCaseBase {
 
   @Test
   public final void testSortWithAscDescKeys() throws Exception {
-    executeDDL("create_table_with_asc_desc_keys.sql", "table2.tbl");
+    executeDDL("create_table_with_asc_desc_keys.sql", "table2");
 
     ResultSet res = executeQuery();
     System.out.println(resultSetToString(res));

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java
index 60c8497..a53fff7 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTablePartitions.java
@@ -26,6 +26,7 @@ import org.apache.hadoop.io.compress.CompressionCodec;
 import org.apache.hadoop.io.compress.CompressionCodecFactory;
 import org.apache.hadoop.io.compress.DeflateCodec;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.catalog.CatalogService;
 import org.apache.tajo.catalog.TableDesc;
@@ -35,13 +36,14 @@ import java.io.IOException;
 import java.sql.ResultSet;
 import java.util.Map;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
 import static org.junit.Assert.*;
 
 public class TestTablePartitions extends QueryTestCaseBase {
 
 
   public TestTablePartitions() throws IOException {
-    super();
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
   }
 
   @Test
@@ -51,9 +53,9 @@ public class TestTablePartitions extends QueryTestCaseBase {
         "create table " + tableName + " (col1 int4, col2 int4) partition by column(key float8) ");
     res.close();
 
-    assertTrue(catalog.existsTable(tableName));
-    assertEquals(2, catalog.getTableDesc(tableName).getSchema().size());
-    assertEquals(3, catalog.getTableDesc(tableName).getLogicalSchema().size());
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
+    assertEquals(2, catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName).getSchema().size());
+    assertEquals(3, catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName).getLogicalSchema().size());
 
     res = testBase.execute(
         "insert overwrite into " + tableName + " select l_orderkey, l_partkey, l_quantity from lineitem");
@@ -67,9 +69,9 @@ public class TestTablePartitions extends QueryTestCaseBase {
         "create table " + tableName + " (col1 int4, col2 int4, null_col int4) partition by column(key float8) ");
     res.close();
 
-    assertTrue(catalog.existsTable(tableName));
-    assertEquals(3, catalog.getTableDesc(tableName).getSchema().size());
-    assertEquals(4, catalog.getTableDesc(tableName).getLogicalSchema().size());
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
+    assertEquals(3, catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName).getSchema().size());
+    assertEquals(4, catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName).getLogicalSchema().size());
 
     res = executeString("insert overwrite into " + tableName + " (col1, col2, key) select l_orderkey, " +
         "l_partkey, l_quantity from lineitem");
@@ -83,13 +85,13 @@ public class TestTablePartitions extends QueryTestCaseBase {
         "create table " + tableName + " (col1 int4, col2 int4, null_col int4) partition by column(key float8) ");
     res.close();
 
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = executeString("insert overwrite into " + tableName
         + " (col1, col2, key) select l_orderkey, l_partkey, l_quantity from lineitem");
     res.close();
 
-    TableDesc desc = catalog.getTableDesc(tableName);
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
     assertPartitionDirectories(desc);
 
     res = executeString(
@@ -116,7 +118,9 @@ public class TestTablePartitions extends QueryTestCaseBase {
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/key=38.0")));
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/key=45.0")));
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/key=49.0")));
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
   }
 
   @Test
@@ -126,14 +130,14 @@ public class TestTablePartitions extends QueryTestCaseBase {
         "create table " + tableName + " (col1 int4, col2 int4, null_col int4) partition by column(key float8) ");
     res.close();
 
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = executeString(
         "insert overwrite into " + tableName
             + " (col1, col2, key) select l_orderkey, l_partkey, l_quantity from lineitem");
     res.close();
 
-    TableDesc desc = catalog.getTableDesc(tableName);
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
     assertPartitionDirectories(desc);
 
     res = executeFile("case1.sql");
@@ -157,13 +161,13 @@ public class TestTablePartitions extends QueryTestCaseBase {
     res.close();
     TajoTestingCluster cluster = testBase.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = executeString("insert overwrite into " + tableName
         + " select l_returnflag, l_orderkey, l_partkey, l_quantity from lineitem");
     res.close();
 
-    TableDesc desc = catalog.getTableDesc(tableName);
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
     Path path = desc.getPath();
 
     FileSystem fs = FileSystem.get(conf);
@@ -179,7 +183,9 @@ public class TestTablePartitions extends QueryTestCaseBase {
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/col1=3/col2=3")));
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/col1=3/col2=2/col3=45.0")));
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/col1=3/col2=3/col3=49.0")));
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
 
     res = executeString("select * from " + tableName + " where col2 = 2");
 
@@ -219,13 +225,15 @@ public class TestTablePartitions extends QueryTestCaseBase {
             "WITH ('csvfile.delimiter'='|','compression.codec'='org.apache.hadoop.io.compress.DeflateCodec') " +
             "PARTITION BY column(col1 int4)");
     res.close();
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = executeString(
         "insert overwrite into " + tableName + " select l_partkey, l_quantity, l_orderkey from lineitem");
     res.close();
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
 
     FileSystem fs = FileSystem.get(conf);
     assertTrue(fs.exists(desc.getPath()));
@@ -253,14 +261,16 @@ public class TestTablePartitions extends QueryTestCaseBase {
         "PARTITION by column(col1 int4, col2 int4)");
     res.close();
 
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = executeString(
         "insert overwrite into " + tableName +
             " select  l_quantity, l_returnflag, l_orderkey, l_partkey from lineitem");
     res.close();
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
 
     FileSystem fs = FileSystem.get(conf);
     assertTrue(fs.exists(desc.getPath()));
@@ -296,14 +306,16 @@ public class TestTablePartitions extends QueryTestCaseBase {
             "partition by column(col1 int4, col2 int4, col3 float8)");
     res.close();
 
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = executeString(
         "insert overwrite into " + tableName +
             " select l_returnflag, l_orderkey, l_partkey, l_quantity from lineitem");
     res.close();
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
 
     FileSystem fs = FileSystem.get(conf);
     assertTrue(fs.exists(desc.getPath()));
@@ -377,14 +389,16 @@ public class TestTablePartitions extends QueryTestCaseBase {
             "partition by column(col1 int4, col2 int4, col3 float8)");
     res.close();
 
-    assertTrue(catalog.existsTable(tableName));
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
 
     res = executeString(
         "insert overwrite into " + tableName +
             " select l_returnflag , l_orderkey, l_partkey, l_quantity from lineitem");
     res.close();
-    TableDesc desc = catalog.getTableDesc(tableName);
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName);
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
 
     FileSystem fs = FileSystem.get(conf);
     assertTrue(fs.exists(desc.getPath()));

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTableSubQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTableSubQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTableSubQuery.java
index bbd533f..9be0302 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTableSubQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestTableSubQuery.java
@@ -19,12 +19,17 @@
 package org.apache.tajo.engine.query;
 
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.junit.Test;
 
 import java.sql.ResultSet;
 
 public class TestTableSubQuery extends QueryTestCaseBase {
 
+  public TestTableSubQuery() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public final void testTableSubquery1() throws Exception {
     ResultSet res = executeQuery();

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestUnionQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestUnionQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestUnionQuery.java
index 22830bf..a54f670 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestUnionQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestUnionQuery.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.query;
 
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
@@ -36,6 +37,10 @@ import java.sql.ResultSet;
 @Category(IntegrationTest.class)
 public class TestUnionQuery extends QueryTestCaseBase {
 
+  public TestUnionQuery() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   /**
    * S (SA U SA) O

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestResultSet.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestResultSet.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestResultSet.java
index 3610382..4477fa5 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestResultSet.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestResultSet.java
@@ -23,6 +23,7 @@ package org.apache.tajo.jdbc;
 
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.IntegrationTest;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.TpchTestBase;
 import org.apache.tajo.catalog.CatalogUtil;
@@ -90,7 +91,8 @@ public class TestResultSet {
     stats.setAvgRows(tupleNum);
     stats.setNumBlocks(1000);
     stats.setNumShuffleOutputs(100);
-    desc = new TableDesc("score", scoreSchema, scoreMeta, p);
+    desc = new TableDesc(CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "score"),
+        scoreSchema, scoreMeta, p);
     desc.setStats(stats);
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
index 445cd69..1279245 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
@@ -20,11 +20,12 @@ package org.apache.tajo.jdbc;
 
 import com.google.common.collect.Maps;
 import org.apache.tajo.IntegrationTest;
+import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TpchTestBase;
+import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.TableDesc;
-import org.apache.tajo.conf.TajoConf;
-import org.apache.tajo.util.NetUtils;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -32,42 +33,39 @@ import org.junit.experimental.categories.Category;
 
 import java.net.InetSocketAddress;
 import java.sql.*;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
 import static org.junit.Assert.*;
 
 @Category(IntegrationTest.class)
-public class TestTajoJdbc {
+public class TestTajoJdbc extends QueryTestCaseBase {
   private static TpchTestBase tpch;
-  private static Connection conn;
 
-  private static String connUri;
+  private static InetSocketAddress tajoMasterAddress;
   @BeforeClass
   public static void setUp() throws Exception {
-    tpch = TpchTestBase.getInstance();
-
-    TajoConf tajoConf = tpch.getTestingCluster().getMaster().getContext().getConf();
-    InetSocketAddress tajoMasterAddress =
-        NetUtils.createSocketAddr(tajoConf.getVar(TajoConf.ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS));
-
+    tajoMasterAddress = testingCluster.getMaster().getTajoMasterClientService().getBindAddress();
     Class.forName("org.apache.tajo.jdbc.TajoDriver").newInstance();
-
-    connUri = "jdbc:tajo://" + tajoMasterAddress.getHostName() + ":" + tajoMasterAddress.getPort();
-    conn = DriverManager.getConnection(connUri);
   }
 
   @AfterClass
   public static void tearDown() throws Exception {
-    if(conn != null) {
-      conn.close();
-    }
+  }
+
+  private static String buildConnectionUri(String hostName, int port, String databaseNme) {
+    return "jdbc:tajo://" + hostName + ":" + port + "/" + databaseNme;
   }
 
   @Test
   public void testStatement() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+
     Statement stmt = null;
     ResultSet res = null;
     try {
@@ -108,6 +106,10 @@ public class TestTajoJdbc {
 
   @Test
   public void testPreparedStatement() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        TajoConstants.DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+
     PreparedStatement stmt = null;
     ResultSet res = null;
     try {
@@ -184,6 +186,9 @@ public class TestTajoJdbc {
 
   @Test
   public void testDatabaseMetaDataGetTable() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        TajoConstants.DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
     DatabaseMetaData dbmd = conn.getMetaData();
 
     ResultSet rs = null;
@@ -193,21 +198,15 @@ public class TestTajoJdbc {
 
       ResultSetMetaData rsmd = rs.getMetaData();
       int numCols = rsmd.getColumnCount();
-
       assertEquals(5, numCols);
-      int numTables = 0;
 
-      List<String> tableNames = new ArrayList<String>(
-          tpch.getTestingCluster().getMaster().getCatalog().getAllTableNames());
-
-      Collections.sort(tableNames);
+      Set<String> retrivedViaJavaAPI = new HashSet<String>(client.getTableList(DEFAULT_DATABASE_NAME));
 
+      Set<String> retrievedViaJDBC = new HashSet<String>();
       while(rs.next()) {
-        assertEquals(tableNames.get(numTables), rs.getString("TABLE_NAME"));
-        numTables++;
+        retrievedViaJDBC.add(rs.getString("TABLE_NAME"));
       }
-
-      assertEquals(tableNames.size(), numTables);
+      assertEquals(retrievedViaJDBC, retrivedViaJavaAPI);
     } finally {
       if(rs != null) {
         rs.close();
@@ -217,6 +216,9 @@ public class TestTajoJdbc {
 
   @Test
   public void testDatabaseMetaDataGetColumns() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        TajoConstants.DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
     DatabaseMetaData dbmd = conn.getMetaData();
 
     ResultSet rs = null;
@@ -231,7 +233,7 @@ public class TestTajoJdbc {
       assertEquals(22, numCols);
       int numColumns = 0;
 
-      TableDesc tableDesc = tpch.getTestingCluster().getMaster().getCatalog().getTableDesc(tableName);
+      TableDesc tableDesc = client.getTableDesc(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName));
       assertNotNull(tableDesc);
 
       List<Column> columns = tableDesc.getSchema().getColumns();
@@ -253,6 +255,9 @@ public class TestTajoJdbc {
 
   @Test
   public void testMultipleConnections() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        TajoConstants.DEFAULT_DATABASE_NAME);
+
     Connection[] conns = new Connection[2];
     conns[0] = DriverManager.getConnection(connUri);
     conns[1] = DriverManager.getConnection(connUri);
@@ -304,6 +309,8 @@ public class TestTajoJdbc {
 
   @Test
   public void testMultipleConnectionsSequentialClose() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(), DEFAULT_DATABASE_NAME);
+
     Connection[] conns = new Connection[2];
     conns[0] = DriverManager.getConnection(connUri);
     conns[1] = DriverManager.getConnection(connUri);
@@ -357,4 +364,119 @@ public class TestTajoJdbc {
       }
     }
   }
+
+  @Test
+  public void testSetAndGetCatalog() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        TajoConstants.DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+
+    assertDatabaseNotExists("jdbc_test1");
+    PreparedStatement pstmt = conn.prepareStatement("CREATE DATABASE jdbc_test1");
+    pstmt.executeUpdate();
+    assertDatabaseExists("jdbc_test1");
+    pstmt.close();
+
+    pstmt = conn.prepareStatement("CREATE DATABASE jdbc_test2");
+    pstmt.executeUpdate();
+    assertDatabaseExists("jdbc_test2");
+    pstmt.close();
+
+    conn.setCatalog("jdbc_test1");
+    assertEquals("jdbc_test1", conn.getCatalog());
+    conn.setCatalog("jdbc_test2");
+    assertEquals("jdbc_test2", conn.getCatalog());
+    conn.setCatalog("jdbc_test1");
+    assertEquals("jdbc_test1", conn.getCatalog());
+
+    conn.setCatalog(TajoConstants.DEFAULT_DATABASE_NAME);
+    pstmt = conn.prepareStatement("DROP DATABASE jdbc_test1");
+    pstmt.executeUpdate();
+    pstmt.close();
+    pstmt = conn.prepareStatement("DROP DATABASE jdbc_test2");
+    pstmt.executeUpdate();
+    pstmt.close();
+
+    conn.close();
+  }
+
+  @Test
+  public void testGetCatalogsAndTables() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        TajoConstants.DEFAULT_DATABASE_NAME);
+    Connection defaultConnect = DriverManager.getConnection(connUri);
+
+    Set<String> existingDatabases = new HashSet<String>();
+    DatabaseMetaData dbmd = defaultConnect.getMetaData();
+    ResultSet res = dbmd.getCatalogs();
+    while(res.next()) {
+      existingDatabases.add(res.getString(1));
+    }
+    res.close();
+
+    // create database "jdbc_test1" and its tables
+    assertDatabaseNotExists("jdbc_test1");
+    PreparedStatement pstmt = defaultConnect.prepareStatement("CREATE DATABASE jdbc_test1");
+    pstmt.executeUpdate();
+    assertDatabaseExists("jdbc_test1");
+    pstmt.close();
+    pstmt = defaultConnect.prepareStatement("CREATE TABLE jdbc_test1.table1 (age int)");
+    pstmt.executeUpdate();
+    pstmt.close();
+    pstmt = defaultConnect.prepareStatement("CREATE TABLE jdbc_test1.table2 (age int)");
+    pstmt.executeUpdate();
+    pstmt.close();
+
+    // create database "jdbc_test2" and its tables
+    pstmt = defaultConnect.prepareStatement("CREATE DATABASE jdbc_test2");
+    pstmt.executeUpdate();
+    assertDatabaseExists("jdbc_test2");
+    pstmt.close();
+
+    pstmt = defaultConnect.prepareStatement("CREATE TABLE jdbc_test2.table3 (age int)");
+    pstmt.executeUpdate();
+    pstmt.close();
+    pstmt = defaultConnect.prepareStatement("CREATE TABLE jdbc_test2.table4 (age int)");
+    pstmt.executeUpdate();
+    pstmt.close();
+
+    // verify getCatalogs()
+    Set<String> newDatabases = new HashSet<String>();
+    dbmd = defaultConnect.getMetaData();
+    res = dbmd.getCatalogs();
+    while(res.next()) {
+      newDatabases.add(res.getString(1));
+    }
+    res.close();
+    newDatabases.removeAll(existingDatabases);
+    assertEquals(2, newDatabases.size());
+    assertTrue(newDatabases.contains("jdbc_test1"));
+    assertTrue(newDatabases.contains("jdbc_test2"));
+
+    // verify getTables()
+    res = defaultConnect.getMetaData().getTables("jdbc_test1", null, null, null);
+    assertResultSet(res, "getTables1.result");
+    res.close();
+    res = defaultConnect.getMetaData().getTables("jdbc_test2", null, null, null);
+    assertResultSet(res, "getTables2.result");
+    res.close();
+
+    defaultConnect.close();
+
+    // jdbc1_test database connection test
+    String jdbcTest1ConnUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        "jdbc_test1");
+    Connection jdbcTest1Conn = DriverManager.getConnection(jdbcTest1ConnUri);
+    assertEquals("jdbc_test1", jdbcTest1Conn.getCatalog());
+    jdbcTest1Conn.close();
+
+    String jdbcTest2ConnUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        "jdbc_test2");
+    Connection jdbcTest2Conn = DriverManager.getConnection(jdbcTest2ConnUri);
+    assertEquals("jdbc_test2", jdbcTest2Conn.getCatalog());
+    jdbcTest2Conn.close();
+
+    executeString("DROP DATABASE jdbc_test1");
+    executeString("DROP DATABASE jdbc_test2");
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java
index d862e87..869d199 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestExecutionBlockCursor.java
@@ -19,10 +19,7 @@ import org.apache.tajo.LocalTajoTestingUtility;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.benchmark.TPCH;
-import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.CatalogUtil;
-import org.apache.tajo.catalog.TableDesc;
-import org.apache.tajo.catalog.TableMeta;
+import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.statistics.TableStats;
 import org.apache.tajo.conf.TajoConf;
@@ -41,6 +38,8 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 
 public class TestExecutionBlockCursor {
@@ -60,16 +59,19 @@ public class TestExecutionBlockCursor {
 
     conf = util.getConfiguration();
     catalog = util.getMiniCatalogCluster().getCatalog();
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:!234/warehouse");
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     TPCH tpch = new TPCH();
     tpch.loadSchemas();
     tpch.loadOutSchema();
     for (String table : tpch.getTableNames()) {
       TableMeta m = CatalogUtil.newTableMeta(CatalogProtos.StoreType.CSV);
-      TableDesc d = CatalogUtil.newTableDesc(table, tpch.getSchema(table), m, CommonTestingUtil.getTestDir());
+      TableDesc d = CatalogUtil.newTableDesc(
+          CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, table), tpch.getSchema(table), m, CommonTestingUtil.getTestDir());
       TableStats stats = new TableStats();
       stats.setNumBytes(TPCH.tableVolumes.get(table));
       d.setStats(stats);
-      catalog.addTable(d);
+      catalog.createTable(d);
     }
 
     analyzer = new SQLAnalyzer();
@@ -98,7 +100,7 @@ public class TestExecutionBlockCursor {
             "join supplier on s_nationkey = n_nationkey " +
             "join partsupp on s_suppkey = ps_suppkey " +
             "join part on p_partkey = ps_partkey and p_type like '%BRASS' and p_size = 15");
-    LogicalPlan logicalPlan = logicalPlanner.createPlan(context);
+    LogicalPlan logicalPlan = logicalPlanner.createPlan(LocalTajoTestingUtility.createDummySession(), context);
     optimizer.optimize(logicalPlan);
     QueryContext queryContext = new QueryContext();
     MasterPlan plan = new MasterPlan(LocalTajoTestingUtility.newQueryId(), queryContext, logicalPlan);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java
index 4c7c9c5..4d3b096 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/TestGlobalPlanner.java
@@ -42,6 +42,9 @@ import org.junit.Test;
 import java.io.File;
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
+
 public class TestGlobalPlanner {
 
   private static TajoTestingCluster util;
@@ -60,6 +63,8 @@ public class TestGlobalPlanner {
     for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
       catalog.createFunction(funcDesc);
     }
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:1234/warehouse");
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
 
     // TPC-H Schema for Complex Queries
     String [] tables = {
@@ -75,9 +80,11 @@ public class TestGlobalPlanner {
       TableMeta m = CatalogUtil.newTableMeta(CatalogProtos.StoreType.CSV);
       TableStats stats = new TableStats();
       stats.setNumBytes(volumes[i]);
-      TableDesc d = CatalogUtil.newTableDesc(tables[i], tpch.getSchema(tables[i]), m, CommonTestingUtil.getTestDir());
+      TableDesc d = CatalogUtil.newTableDesc(
+          CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, tables[i]), tpch.getSchema(tables[i]), m,
+          CommonTestingUtil.getTestDir());
       d.setStats(stats);
-      catalog.addTable(d);
+      catalog.createTable(d);
     }
 
     sqlAnalyzer = new SQLAnalyzer();
@@ -93,7 +100,7 @@ public class TestGlobalPlanner {
 
   private MasterPlan buildPlan(String sql) throws PlanningException, IOException {
     Expr expr = sqlAnalyzer.parse(sql);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr);
     optimizer.optimize(plan);
     QueryContext context = new QueryContext();
     MasterPlan masterPlan = new MasterPlan(LocalTajoTestingUtility.newQueryId(), context, plan);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/querymaster/TestQueryUnitStatusUpdate.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/querymaster/TestQueryUnitStatusUpdate.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/querymaster/TestQueryUnitStatusUpdate.java
index 5d3f7bf..ddf8ecb 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/querymaster/TestQueryUnitStatusUpdate.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/master/querymaster/TestQueryUnitStatusUpdate.java
@@ -20,6 +20,7 @@ package org.apache.tajo.master.querymaster;
 
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.catalog.statistics.TableStats;
 import org.apache.tajo.worker.TajoWorker;
 import org.junit.Test;
@@ -28,12 +29,16 @@ import org.junit.experimental.categories.Category;
 import java.sql.ResultSet;
 import java.util.*;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.junit.Assert.*;
 
 @Category(IntegrationTest.class)
 public class TestQueryUnitStatusUpdate extends QueryTestCaseBase {
+
+  public TestQueryUnitStatusUpdate() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public final void case1() throws Exception {
     // select l_linenumber, count(1) as unique_key from lineitem group by l_linenumber;
@@ -96,9 +101,10 @@ public class TestQueryUnitStatusUpdate extends QueryTestCaseBase {
         "create table " + tableName + " (col1 int4, col2 int4) partition by column(key float8) ");
     res.close();
 
-    assertTrue(catalog.existsTable(tableName));
-    assertEquals(2, catalog.getTableDesc(tableName).getSchema().size());
-    assertEquals(3, catalog.getTableDesc(tableName).getLogicalSchema().size());
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, tableName));
+    assertEquals(2, catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName).getSchema().size());
+    assertEquals(3,
+        catalog.getTableDesc(DEFAULT_DATABASE_NAME, tableName).getLogicalSchema().size());
 
     res = testBase.execute(
         "insert overwrite into " + tableName + " select l_orderkey, l_partkey, l_quantity from lineitem");

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TestRangeRetrieverHandler.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TestRangeRetrieverHandler.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TestRangeRetrieverHandler.java
index 65b7d1e..0b3a22c 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TestRangeRetrieverHandler.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/worker/TestRangeRetrieverHandler.java
@@ -24,6 +24,7 @@ import org.apache.commons.codec.binary.Base64;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -55,6 +56,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -75,10 +77,12 @@ public class TestRangeRetrieverHandler {
   public void setUp() throws Exception {
     util = new TajoTestingCluster();
     conf = util.getConfiguration();
-    testDir = CommonTestingUtil.getTestDir("target/test-data/TestRangeRetrieverHandler");
+    testDir = CommonTestingUtil.getTestDir();
     fs = testDir.getFileSystem(conf);
     util.startCatalogCluster();
     catalog = util.getMiniCatalogCluster().getCatalog();
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(TajoConstants.DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
     analyzer = new SQLAnalyzer();
@@ -129,16 +133,18 @@ public class TestRangeRetrieverHandler {
     appender.flush();
     appender.close();
 
-    TableDesc employee = new TableDesc("employee", schema, employeeMeta, tableDir);
-    catalog.addTable(employee);
+    TableDesc employee = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, employeeMeta,
+        tableDir);
+    catalog.createTable(employee);
 
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employeeMeta, tableDir, Integer.MAX_VALUE);
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employeeMeta, tableDir, Integer.MAX_VALUE);
 
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(),
         new FileFragment[] {frags[0]}, testDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(SORT_QUERY[0]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf,sm);
@@ -250,17 +256,18 @@ public class TestRangeRetrieverHandler {
     appender.flush();
     appender.close();
 
-    TableDesc employee = new TableDesc("employee", schema, meta, tablePath);
-    catalog.addTable(employee);
+    TableDesc employee = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta, tablePath);
+    catalog.createTable(employee);
 
-    FileFragment[] frags = sm.splitNG(conf, "employee", meta, tablePath, Integer.MAX_VALUE);
+    FileFragment[] frags = sm.splitNG(conf, "default.employee", meta, tablePath, Integer.MAX_VALUE);
 
     TaskAttemptContext
         ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(),
         new FileFragment[] {frags[0]}, testDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(SORT_QUERY[1]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf,sm);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestCreateTable/table1.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestCreateTable/table1.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestCreateTable/table1.tbl
deleted file mode 100644
index 8095c0b..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestCreateTable/table1.tbl
+++ /dev/null
@@ -1,3 +0,0 @@
-1|abc|2
-2|def|5
-3|ghi|8
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestCreateTable/table1/table1.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestCreateTable/table1/table1.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestCreateTable/table1/table1.tbl
new file mode 100644
index 0000000..8095c0b
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestCreateTable/table1/table1.tbl
@@ -0,0 +1,3 @@
+1|abc|2
+2|def|5
+3|ghi|8
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table1.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table1.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table1.tbl
deleted file mode 100644
index 6405b31..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table1.tbl
+++ /dev/null
@@ -1,5 +0,0 @@
-1|ooo|1.1|a
-2|ppp|2.3|b
-3|qqq|3.4|c
-4|rrr|4.5|d
-5|xxx|5.6|e
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table1/table1.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table1/table1.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table1/table1.tbl
new file mode 100644
index 0000000..6405b31
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table1/table1.tbl
@@ -0,0 +1,5 @@
+1|ooo|1.1|a
+2|ppp|2.3|b
+3|qqq|3.4|c
+4|rrr|4.5|d
+5|xxx|5.6|e
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table2.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table2.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table2.tbl
deleted file mode 100644
index 68340bf..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table2.tbl
+++ /dev/null
@@ -1,4 +0,0 @@
-1|NULL|NULL|a
-2|NULL|NULL|b
-NULL|NULL|10.0|c
-NULL|NULL|20.0|d
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table2/table2.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table2/table2.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table2/table2.tbl
new file mode 100644
index 0000000..68340bf
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestJoinQuery/table2/table2.tbl
@@ -0,0 +1,4 @@
+1|NULL|NULL|a
+2|NULL|NULL|b
+NULL|NULL|10.0|c
+NULL|NULL|20.0|d
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table1.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table1.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table1.tbl
deleted file mode 100644
index 63db89d..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table1.tbl
+++ /dev/null
@@ -1,5 +0,0 @@
-1|ooo|1.1|a|127.0.0.1
-2|ppp|2.3|b|127.0.1.1
-3|qqq|3.4|c|127.0.0.8
-4|rrr|4.5|d|127.0.0.1
-5|xxx|5.6|e|127.0.1.1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table1/table1.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table1/table1.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table1/table1.tbl
new file mode 100644
index 0000000..63db89d
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table1/table1.tbl
@@ -0,0 +1,5 @@
+1|ooo|1.1|a|127.0.0.1
+2|ppp|2.3|b|127.0.1.1
+3|qqq|3.4|c|127.0.0.8
+4|rrr|4.5|d|127.0.0.1
+5|xxx|5.6|e|127.0.1.1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table2.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table2.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table2.tbl
deleted file mode 100644
index f33b22c..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table2.tbl
+++ /dev/null
@@ -1,4 +0,0 @@
-1|NULL|NULL|a|127.0.0.8
-2|NULL|NULL|b|127.0.0.8
-NULL|NULL|10.0|c|NULL
-NULL|NULL|20.0|d|127.0.0.1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table2/table2.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table2/table2.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table2/table2.tbl
new file mode 100644
index 0000000..f33b22c
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestNetTypes/table2/table2.tbl
@@ -0,0 +1,4 @@
+1|NULL|NULL|a|127.0.0.8
+2|NULL|NULL|b|127.0.0.8
+NULL|NULL|10.0|c|NULL
+NULL|NULL|20.0|d|127.0.0.1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table1.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table1.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table1.tbl
deleted file mode 100644
index a1ebde3..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table1.tbl
+++ /dev/null
@@ -1,5 +0,0 @@
-1997-11-09 20:34:56|1996-04-12|15:34:56
-1997-11-09 20:34:56|1996-03-13|19:34:56
-1993-11-09 20:34:56|1997-01-28|08:34:56
-1995-11-09 20:34:56|1994-02-02|17:34:56
-1995-11-09 20:34:56|1993-11-09|20:34:56
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table1/table1.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table1/table1.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table1/table1.tbl
new file mode 100644
index 0000000..a1ebde3
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table1/table1.tbl
@@ -0,0 +1,5 @@
+1997-11-09 20:34:56|1996-04-12|15:34:56
+1997-11-09 20:34:56|1996-03-13|19:34:56
+1993-11-09 20:34:56|1997-01-28|08:34:56
+1995-11-09 20:34:56|1994-02-02|17:34:56
+1995-11-09 20:34:56|1993-11-09|20:34:56
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table2.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table2.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table2.tbl
deleted file mode 100644
index bc237af..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table2.tbl
+++ /dev/null
@@ -1,24 +0,0 @@
-1,2132
-1,15635
-1,24027
-1,63700
-1,67310
-1,155190
-2,106170
-3,4297
-3,19036
-3,29380
-3,62143
-3,128449
-3,183095
-4,88035
-5,37531
-5,108570
-5,123927
-6,139636
-7,79251
-7,94780
-7,145243
-7,151894
-7,157238
-7,163073

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table2/table2.tbl
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table2/table2.tbl b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table2/table2.tbl
new file mode 100644
index 0000000..bc237af
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/dataset/TestSortQuery/table2/table2.tbl
@@ -0,0 +1,24 @@
+1,2132
+1,15635
+1,24027
+1,63700
+1,67310
+1,155190
+2,106170
+3,4297
+3,19036
+3,29380
+3,62143
+3,128449
+3,183095
+4,88035
+5,37531
+5,108570
+5,123927
+6,139636
+7,79251
+7,94780
+7,145243
+7,151894
+7,157238
+7,163073

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/resources/queries/TestCreateTable/create_table_various_types.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestCreateTable/create_table_various_types.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestCreateTable/create_table_various_types.sql
index 92a4990..891a139 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/queries/TestCreateTable/create_table_various_types.sql
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestCreateTable/create_table_various_types.sql
@@ -1,3 +1,5 @@
+-- Some types were commented out due to Hive meta test.
+
 create table various_types (
   col0 bit,
   col1 BIT(10),


[13/13] git commit: TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
TAJO-353: Add Database support to Tajo. (hyunsik)


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

Branch: refs/heads/master
Commit: 3ba262412cfef82943de7f2c831916b340c01925
Parents: 7283c58
Author: Hyunsik Choi <hy...@apache.org>
Authored: Thu Mar 20 21:18:18 2014 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Thu Mar 20 21:20:38 2014 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |    2 +
 .../tajo/algebra/ColumnReferenceExpr.java       |    5 +-
 .../org/apache/tajo/algebra/CreateDatabase.java |   65 +
 .../org/apache/tajo/algebra/CreateTable.java    |   19 +-
 .../org/apache/tajo/algebra/DropDatabase.java   |   52 +
 .../java/org/apache/tajo/algebra/DropTable.java |   14 +-
 .../java/org/apache/tajo/algebra/OpType.java    |    2 +
 .../tajo/catalog/AbstractCatalogClient.java     |  278 +++-
 .../org/apache/tajo/catalog/CatalogService.java |  100 +-
 .../src/main/proto/CatalogProtocol.proto        |   39 +-
 .../apache/tajo/catalog/CatalogConstants.java   |    7 +-
 .../org/apache/tajo/catalog/CatalogUtil.java    |   94 +-
 .../org/apache/tajo/catalog/DDLBuilder.java     |   23 +-
 .../org/apache/tajo/catalog/FunctionDesc.java   |    2 +-
 .../java/org/apache/tajo/catalog/IndexDesc.java |   57 +-
 .../java/org/apache/tajo/catalog/TableDesc.java |   45 +-
 .../AlreadyExistsDatabaseException.java         |   30 +
 .../exception/AlreadyExistsIndexException.java  |   24 +-
 .../exception/AlreadyExistsTableException.java  |    6 +-
 .../AlreadyExistsTablespaceException.java       |   30 +
 .../exception/InvalidTableException.java        |   36 -
 .../exception/NoPartitionedTableException.java  |   28 +
 .../exception/NoSuchDatabaseException.java      |   30 +
 .../exception/NoSuchFunctionException.java      |    4 +-
 .../catalog/exception/NoSuchIndexException.java |   25 +-
 .../catalog/exception/NoSuchTableException.java |    4 +
 .../exception/NoSuchTablespaceException.java    |   29 +
 .../tajo/catalog/partition/PartitionDesc.java   |   46 +-
 .../catalog/partition/PartitionMethodDesc.java  |   53 +-
 .../src/main/proto/CatalogProtos.proto          |   79 +-
 .../apache/tajo/catalog/TestCatalogUtil.java    |    3 +-
 .../org/apache/tajo/catalog/TestIndexDesc.java  |   21 +-
 .../org/apache/tajo/catalog/TestTableDesc.java  |    4 +-
 .../tajo/catalog/store/HCatalogStore.java       |  264 ++--
 .../catalog/store/HCatalogStoreClientPool.java  |    3 +-
 .../apache/tajo/catalog/store/HCatalogUtil.java |   46 +-
 .../tajo/catalog/store/TestHCatalogStore.java   |  119 +-
 .../org/apache/tajo/catalog/CatalogServer.java  |  448 ++++--
 .../tajo/catalog/store/AbstractDBStore.java     | 1390 +++++++++++-------
 .../apache/tajo/catalog/store/CatalogStore.java |   64 +-
 .../apache/tajo/catalog/store/DerbyStore.java   |  318 ++--
 .../org/apache/tajo/catalog/store/MemStore.java |  290 ++--
 .../apache/tajo/catalog/store/MySQLStore.java   |  151 +-
 .../src/main/resources/schemas/common/meta.sql  |    1 +
 .../main/resources/schemas/derby/columns.sql    |    8 +
 .../main/resources/schemas/derby/databases.sql  |    6 +
 .../resources/schemas/derby/databases_idx.sql   |    1 +
 .../main/resources/schemas/derby/indexes.sql    |   12 +
 .../schemas/derby/partition_methods.sql         |    6 +
 .../main/resources/schemas/derby/partitions.sql |   10 +
 .../src/main/resources/schemas/derby/stats.sql  |    6 +
 .../schemas/derby/table_properties.sql          |    6 +
 .../src/main/resources/schemas/derby/tables.sql |   10 +
 .../resources/schemas/derby/tablespaces.sql     |    7 +
 .../main/resources/schemas/mysql/columns.sql    |    9 +
 .../main/resources/schemas/mysql/databases.sql  |    7 +
 .../main/resources/schemas/mysql/indexes.sql    |   16 +
 .../schemas/mysql/partition_methods.sql         |    7 +
 .../main/resources/schemas/mysql/partitions.sql |   12 +
 .../src/main/resources/schemas/mysql/stats.sql  |    6 +
 .../schemas/mysql/table_properties.sql          |    7 +
 .../src/main/resources/schemas/mysql/tables.sql |   11 +
 .../resources/schemas/mysql/tablespaces.sql     |    7 +
 .../org/apache/tajo/catalog/TestCatalog.java    |  388 +++--
 .../tajo/catalog/TestCatalogConstants.java      |   46 -
 .../org/apache/tajo/catalog/TestDBStore.java    |  403 -----
 .../apache/tajo/cli/ConnectDatabaseCommand.java |   65 +
 .../org/apache/tajo/cli/CopyrightCommand.java   |   14 +-
 .../apache/tajo/cli/DescFunctionCommand.java    |   24 +-
 .../org/apache/tajo/cli/DescTableCommand.java   |   16 +-
 .../java/org/apache/tajo/cli/ExitCommand.java   |   10 +-
 .../java/org/apache/tajo/cli/HelpCommand.java   |   44 +-
 .../tajo/cli/InvalidClientSessionException.java |   27 +
 .../tajo/cli/InvalidStatementException.java     |   25 +
 .../apache/tajo/cli/ListDatabaseCommand.java    |   48 +
 .../java/org/apache/tajo/cli/ParsedResult.java  |   47 +
 .../java/org/apache/tajo/cli/SetCommand.java    |   61 +
 .../java/org/apache/tajo/cli/SimpleParser.java  |  262 ++++
 .../main/java/org/apache/tajo/cli/TajoCli.java  |  324 ++--
 .../org/apache/tajo/cli/TajoFileHistory.java    |   39 +
 .../org/apache/tajo/cli/TajoShellCommand.java   |   28 +-
 .../java/org/apache/tajo/cli/UnsetCommand.java  |   52 +
 .../org/apache/tajo/cli/VersionCommand.java     |    9 +-
 .../java/org/apache/tajo/client/TajoClient.java |  309 +++-
 .../java/org/apache/tajo/client/TajoDump.java   |   95 +-
 .../org/apache/tajo/jdbc/TajoResultSetBase.java |    4 +
 .../apache/tajo/jdbc/TajoResultSetMetaData.java |   10 +-
 tajo-client/src/main/proto/ClientProtos.proto   |   44 +-
 .../main/proto/TajoMasterClientProtocol.proto   |   49 +-
 .../java/org/apache/tajo/TajoConstants.java     |    5 +
 .../java/org/apache/tajo/conf/TajoConf.java     |    5 +
 .../org/apache/tajo/util/CommonTestingUtil.java |    3 +-
 .../java/org/apache/tajo/util/FileUtil.java     |   22 +-
 .../main/java/org/apache/tajo/util/Pair.java    |   37 +
 .../java/org/apache/tajo/util/ProtoBufUtil.java |   26 -
 .../java/org/apache/tajo/util/ProtoUtil.java    |   42 +
 .../java/org/apache/tajo/util/StringUtils.java  |    8 +
 .../main/java/org/apache/tajo/util/TUtil.java   |   12 +
 .../src/main/proto/PrimitiveProtos.proto        |    4 +
 tajo-common/src/main/proto/TajoIdProtos.proto   |    2 +-
 tajo-core/tajo-core-backend/pom.xml             |  210 ++-
 .../org/apache/tajo/engine/parser/SQLLexer.g4   |    2 +
 .../org/apache/tajo/engine/parser/SQLParser.g4  |   28 +-
 .../tajo/engine/parser/HiveQLAnalyzer.java      |    4 +-
 .../apache/tajo/engine/parser/SQLAnalyzer.java  |   14 +-
 .../tajo/engine/planner/AlgebraVisitor.java     |    2 +
 .../tajo/engine/planner/BaseAlgebraVisitor.java |   16 +
 .../engine/planner/BasicLogicalPlanVisitor.java |   17 +
 .../planner/ExplainLogicalPlanVisitor.java      |   14 +-
 .../tajo/engine/planner/ExprNormalizer.java     |    3 +-
 .../apache/tajo/engine/planner/LogicalPlan.java |   34 +-
 .../engine/planner/LogicalPlanPreprocessor.java |   53 +-
 .../engine/planner/LogicalPlanVerifier.java     |   96 +-
 .../tajo/engine/planner/LogicalPlanVisitor.java |    6 +
 .../tajo/engine/planner/LogicalPlanner.java     |   65 +-
 .../apache/tajo/engine/planner/PlannerUtil.java |   12 +-
 .../engine/planner/PreLogicalPlanVerifier.java  |  129 +-
 .../tajo/engine/planner/VerificationState.java  |    5 +
 .../engine/planner/global/GlobalPlanner.java    |    5 +-
 .../planner/logical/CreateDatabaseNode.java     |   85 ++
 .../engine/planner/logical/CreateTableNode.java |   37 +-
 .../planner/logical/DropDatabaseNode.java       |   85 ++
 .../engine/planner/logical/DropTableNode.java   |   25 +-
 .../tajo/engine/planner/logical/NodeType.java   |    3 +
 .../tajo/engine/planner/logical/ScanNode.java   |   21 +-
 .../apache/tajo/engine/query/QueryContext.java  |    1 -
 .../org/apache/tajo/engine/utils/ProtoUtil.java |   29 -
 .../org/apache/tajo/master/GlobalEngine.java    |  198 ++-
 .../java/org/apache/tajo/master/TajoMaster.java |   43 +-
 .../tajo/master/TajoMasterClientService.java    |  709 ++++++---
 .../tajo/master/YarnTaskRunnerLauncherImpl.java |    2 +-
 .../tajo/master/event/QueryStartEvent.java      |   18 +-
 .../master/metrics/CatalogMetricsGaugeSet.java  |    4 +-
 .../apache/tajo/master/querymaster/Query.java   |   38 +-
 .../master/querymaster/QueryInProgress.java     |    6 +
 .../master/querymaster/QueryJobManager.java     |    6 +-
 .../tajo/master/querymaster/QueryMaster.java    |    2 +-
 .../querymaster/QueryMasterManagerService.java  |    2 +
 .../master/querymaster/QueryMasterTask.java     |   16 +-
 .../tajo/master/rm/TajoResourceTracker.java     |    4 +-
 .../master/session/InvalidSessionException.java |   25 +
 .../session/NoSuchSessionVariableException.java |   25 +
 .../org/apache/tajo/master/session/Session.java |  124 ++
 .../tajo/master/session/SessionConstants.java   |   23 +
 .../tajo/master/session/SessionEvent.java       |   34 +
 .../tajo/master/session/SessionEventType.java   |   24 +
 .../session/SessionLivelinessMonitor.java       |   53 +
 .../tajo/master/session/SessionManager.java     |  139 ++
 .../src/main/proto/TajoWorkerProtocol.proto     |   15 +-
 .../resources/webapps/admin/catalogview.jsp     |   16 +-
 .../apache/tajo/LocalTajoTestingUtility.java    |   22 +-
 .../java/org/apache/tajo/QueryTestCaseBase.java |  160 +-
 .../org/apache/tajo/TajoTestingCluster.java     |   62 +-
 .../org/apache/tajo/benchmark/TestTPCH.java     |    6 +
 .../org/apache/tajo/cli/TestSimpleParser.java   |  164 +++
 .../org/apache/tajo/client/TestDDLBuilder.java  |   43 +-
 .../org/apache/tajo/client/TestTajoClient.java  |  141 +-
 .../apache/tajo/engine/eval/ExprTestBase.java   |   44 +-
 .../tajo/engine/eval/TestEvalTreeUtil.java      |   60 +-
 .../engine/function/TestBuiltinFunctions.java   |    6 +
 .../engine/planner/TestLogicalOptimizer.java    |   42 +-
 .../tajo/engine/planner/TestLogicalPlan.java    |    9 +-
 .../tajo/engine/planner/TestLogicalPlanner.java |  151 +-
 .../tajo/engine/planner/TestPlannerUtil.java    |   46 +-
 .../planner/physical/TestBNLJoinExec.java       |   25 +-
 .../planner/physical/TestBSTIndexExec.java      |   16 +-
 .../planner/physical/TestExternalSortExec.java  |   12 +-
 .../physical/TestFullOuterHashJoinExec.java     |   50 +-
 .../physical/TestFullOuterMergeJoinExec.java    |   83 +-
 .../planner/physical/TestHashAntiJoinExec.java  |   22 +-
 .../planner/physical/TestHashJoinExec.java      |   36 +-
 .../planner/physical/TestHashSemiJoinExec.java  |   22 +-
 .../physical/TestLeftOuterHashJoinExec.java     |   57 +-
 .../physical/TestLeftOuterNLJoinExec.java       |   57 +-
 .../planner/physical/TestMergeJoinExec.java     |   18 +-
 .../engine/planner/physical/TestNLJoinExec.java |   26 +-
 .../planner/physical/TestPhysicalPlanner.java   |  115 +-
 .../physical/TestProgressExternalSortExec.java  |   15 +-
 .../physical/TestRightOuterHashJoinExec.java    |   44 +-
 .../physical/TestRightOuterMergeJoinExec.java   |   78 +-
 .../engine/planner/physical/TestSortExec.java   |   11 +-
 .../apache/tajo/engine/query/TestCTASQuery.java |   28 +-
 .../tajo/engine/query/TestCaseByCases.java      |    6 +
 .../tajo/engine/query/TestCreateDatabase.java   |   72 +
 .../tajo/engine/query/TestCreateTable.java      |  313 ++--
 .../tajo/engine/query/TestGroupByQuery.java     |    6 +
 .../tajo/engine/query/TestInsertQuery.java      |   71 +-
 .../query/TestJoinOnPartitionedTables.java      |    6 +
 .../apache/tajo/engine/query/TestJoinQuery.java |   22 +-
 .../apache/tajo/engine/query/TestNetTypes.java  |   63 +-
 .../tajo/engine/query/TestSelectQuery.java      |   14 +-
 .../apache/tajo/engine/query/TestSortQuery.java |   23 +-
 .../tajo/engine/query/TestTablePartitions.java  |   68 +-
 .../tajo/engine/query/TestTableSubQuery.java    |    5 +
 .../tajo/engine/query/TestUnionQuery.java       |    5 +
 .../org/apache/tajo/jdbc/TestResultSet.java     |    4 +-
 .../java/org/apache/tajo/jdbc/TestTajoJdbc.java |  182 ++-
 .../tajo/master/TestExecutionBlockCursor.java   |   16 +-
 .../apache/tajo/master/TestGlobalPlanner.java   |   13 +-
 .../querymaster/TestQueryUnitStatusUpdate.java  |   18 +-
 .../tajo/worker/TestRangeRetrieverHandler.java  |   25 +-
 .../dataset/TestCreateTable/table1.tbl          |    3 -
 .../dataset/TestCreateTable/table1/table1.tbl   |    3 +
 .../resources/dataset/TestJoinQuery/table1.tbl  |    5 -
 .../dataset/TestJoinQuery/table1/table1.tbl     |    5 +
 .../resources/dataset/TestJoinQuery/table2.tbl  |    4 -
 .../dataset/TestJoinQuery/table2/table2.tbl     |    4 +
 .../resources/dataset/TestNetTypes/table1.tbl   |    5 -
 .../dataset/TestNetTypes/table1/table1.tbl      |    5 +
 .../resources/dataset/TestNetTypes/table2.tbl   |    4 -
 .../dataset/TestNetTypes/table2/table2.tbl      |    4 +
 .../resources/dataset/TestSortQuery/table1.tbl  |    5 -
 .../dataset/TestSortQuery/table1/table1.tbl     |    5 +
 .../resources/dataset/TestSortQuery/table2.tbl  |   24 -
 .../dataset/TestSortQuery/table2/table2.tbl     |   24 +
 .../create_table_various_types.sql              |    2 +
 .../create_table_various_types_for_hcatalog.sql |   50 +
 .../testCrossJoinWithAsterisk1.sql              |    2 +-
 .../testCrossJoinWithAsterisk2.sql              |    2 +-
 .../testCrossJoinWithAsterisk3.sql              |    2 +-
 .../testCrossJoinWithAsterisk4.sql              |    2 +-
 .../testJoinOnMultipleDatabases.sql             |   25 +
 .../queries/TestNetTypes/table1_ddl.sql         |    2 +-
 .../queries/TestNetTypes/table2_ddl.sql         |    2 +-
 .../testCrossJoinWithAsterisk3.result           |   52 +-
 .../testCrossJoinWithAsterisk4.result           |   52 +-
 .../testJoinOnMultipleDatabases.result          |    5 +
 .../results/TestTajoJdbc/getTables1.result      |    4 +
 .../results/TestTajoJdbc/getTables2.result      |    4 +
 .../test/resources/results/testBuildDDL.result  |    5 -
 .../results/testBuildDDLForBaseTable.result     |    5 +
 .../results/testBuildDDLForExternalTable.result |    5 +
 tajo-docs/src/main/sphinx/cli.rst               |   96 +-
 .../configuration/catalog_configuration.rst     |   16 +-
 .../main/sphinx/configuration/cluster_setup.rst |    2 +-
 tajo-docs/src/main/sphinx/sql_language/ddl.rst  |   37 +-
 .../org/apache/tajo/jdbc/TajoConnection.java    |  137 +-
 .../apache/tajo/jdbc/TajoDatabaseMetaData.java  |   90 +-
 tajo-project/pom.xml                            |    2 +-
 239 files changed, 9000 insertions(+), 3944 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 0304190..7b379b3 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,8 @@ Release 0.8.0 - unreleased
 
   NEW FEATURES
 
+    TAJO-353: Add Database support to Tajo. (hyunsik)
+
     TAJO-574: Add a sort-based physical executor for column partition store.
     (hyunsik)
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnReferenceExpr.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnReferenceExpr.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnReferenceExpr.java
index 97a6a3a..e1369df 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnReferenceExpr.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/ColumnReferenceExpr.java
@@ -55,12 +55,9 @@ public class ColumnReferenceExpr extends Expr {
   public void setName(String qualifiedName) {
     String [] parts = qualifiedName.toLowerCase().split("\\.");
 
-    if (parts.length == 3) {
+    if (parts.length > 1) {
       qualifier = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
       name = qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1, qualifiedName.length());
-    } else if (parts.length == 2) {
-      qualifier = parts[0];
-      name = parts[1];
     } else {
       name = parts[0];
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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
new file mode 100644
index 0000000..a4ebc84
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateDatabase.java
@@ -0,0 +1,65 @@
+/**
+ * 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 org.apache.tajo.util.TUtil;
+
+public class CreateDatabase extends Expr {
+  private String databaseName;
+  private String tablespaceName;
+  private boolean ifNotExists;
+
+  public CreateDatabase(final String databaseName, final String tablespaceName, final boolean ifNotExists) {
+    super(OpType.CreateDatabase);
+    this.databaseName = databaseName;
+    this.tablespaceName = tablespaceName;
+    this.ifNotExists = ifNotExists;
+  }
+
+  public String getDatabaseName() {
+    return this.databaseName;
+  }
+
+  public boolean hasTablespaceName() {
+    return tablespaceName != null;
+  }
+
+  public String getTablespaceName() {
+    return tablespaceName;
+  }
+
+  public boolean isIfNotExists() {
+    return ifNotExists;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(databaseName, tablespaceName, ifNotExists);
+  }
+
+  @Override
+  boolean equalsTo(Expr expr) {
+    CreateDatabase another = (CreateDatabase) expr;
+    return databaseName.equals(another.databaseName) &&
+        TUtil.checkEquals(tablespaceName, another.tablespaceName) &&
+        ifNotExists == another.ifNotExists;
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 7ad802c..42dcc68 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
@@ -33,14 +33,16 @@ public class CreateTable extends Expr {
   private Expr subquery;
   private Map<String, String> params;
   private PartitionMethodDescExpr partition;
+  private boolean ifNotExists;
 
-  public CreateTable(final String tableName) {
+  public CreateTable(final String tableName, boolean ifNotExists) {
     super(OpType.CreateTable);
     this.tableName = tableName;
+    this.ifNotExists = ifNotExists;
   }
 
-  public CreateTable(final String tableName, final Expr subQuery) {
-    this(tableName);
+  public CreateTable(final String tableName, final Expr subQuery, boolean ifNotExists) {
+    this(tableName, ifNotExists);
     this.subquery = subQuery;
   }
 
@@ -128,11 +130,15 @@ public class CreateTable extends Expr {
     return subquery;
   }
 
+  public boolean isIfNotExists() {
+    return ifNotExists;
+  }
+
   @Override
   public int hashCode() {
     return Objects.hashCode(
         external, tableName, Objects.hashCode(tableElements),
-        storageType, subquery, location, params, partition);
+        storageType, subquery, location, params, partition, ifNotExists);
   }
 
   @Override
@@ -145,7 +151,8 @@ public class CreateTable extends Expr {
         TUtil.checkEquals(location, another.location) &&
         TUtil.checkEquals(subquery, another.subquery) &&
         TUtil.checkEquals(params, another.params) &&
-        TUtil.checkEquals(partition, another.partition);
+        TUtil.checkEquals(partition, another.partition) &&
+        ifNotExists == another.ifNotExists;
   }
 
   public static class ColumnDefinition extends DataTypeExpr {
@@ -444,7 +451,7 @@ public class CreateTable extends Expr {
 
     public boolean equals(Object obj) {
       if (obj instanceof PartitionSpecifier ) {
-        return name == ((PartitionSpecifier)obj).name;
+        return name.equals(((PartitionSpecifier)obj).name);
       } else {
         return false;
       }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropDatabase.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropDatabase.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropDatabase.java
new file mode 100644
index 0000000..88e799c
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropDatabase.java
@@ -0,0 +1,52 @@
+/**
+ * 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;
+
+public class DropDatabase extends Expr {
+  @Expose private String databaseName;
+  @Expose private boolean ifExists;
+
+  public DropDatabase(final String databaseName, final boolean ifExists) {
+    super(OpType.DropDatabase);
+    this.databaseName = databaseName;
+    this.ifExists = ifExists;
+  }
+
+  public String getDatabaseName() {
+    return this.databaseName;
+  }
+
+  public boolean isIfExists() {
+    return ifExists;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(databaseName, ifExists);
+  }
+
+  @Override
+  boolean equalsTo(Expr expr) {
+    DropDatabase another = (DropDatabase) expr;
+    return databaseName.equals(another.databaseName) && ifExists == another.ifExists;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropTable.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropTable.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropTable.java
index 83e1707..cb0bbf4 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropTable.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DropTable.java
@@ -22,11 +22,13 @@ import com.google.common.base.Objects;
 
 public class DropTable extends Expr {
   private final String tableName;
+  private final boolean ifExists;
   private final boolean purge;
 
-  public DropTable(String tableName, boolean purge) {
+  public DropTable(String tableName, boolean ifExists, boolean purge) {
     super(OpType.DropTable);
     this.tableName = tableName;
+    this.ifExists = ifExists;
     this.purge = purge;
   }
 
@@ -34,20 +36,26 @@ public class DropTable extends Expr {
     return this.tableName;
   }
 
+  public boolean isIfExists() {
+    return ifExists;
+  }
+
   public boolean isPurge() {
     return purge;
   }
 
   @Override
   public int hashCode() {
-    return Objects.hashCode(tableName, purge);
+    return Objects.hashCode(tableName, ifExists, purge);
   }
 
   @Override
   boolean equalsTo(Expr expr) {
     if (expr instanceof DropTable) {
       DropTable another = (DropTable) expr;
-      return tableName.equals(another.tableName) && purge == another.purge;
+      return tableName.equals(another.tableName) &&
+          ifExists == another.ifExists &&
+          purge == another.purge;
     }
     return false;
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 7122af8..c4a007a 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
@@ -42,6 +42,8 @@ public enum OpType {
   ScalarSubQuery(ScalarSubQuery.class),
 
   // Data definition language
+  CreateDatabase(CreateDatabase.class),
+  DropDatabase(DropDatabase.class),
   CreateTable(CreateTable.class),
   DropTable(DropTable.class),
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 1932db5..6ee788c 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
@@ -21,6 +21,7 @@ package org.apache.tajo.catalog;
 import com.google.protobuf.ServiceException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.CatalogProtocol.CatalogProtocolService;
 import org.apache.tajo.catalog.exception.NoSuchFunctionException;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
@@ -30,8 +31,9 @@ import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.rpc.NettyClientBase;
 import org.apache.tajo.rpc.RpcConnectionPool;
 import org.apache.tajo.rpc.ServerCallable;
+import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.NullProto;
-import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringProto;
+import org.apache.tajo.util.ProtoUtil;
 
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
@@ -57,12 +59,148 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final TableDesc getTableDesc(final String name) {
+  public final Boolean createTablespace(final String tablespaceName, final String tablespaceUri) {
+    try {
+      return new ServerCallable<Boolean>(pool, catalogServerAddr, CatalogProtocol.class, false) {
+        public Boolean call(NettyClientBase client) throws ServiceException {
+          CatalogProtocolService.BlockingInterface stub = getStub(client);
+
+          CreateTablespaceRequest.Builder builder = CreateTablespaceRequest.newBuilder();
+          builder.setTablespaceName(tablespaceName);
+          builder.setTablespaceUri(tablespaceUri);
+          return stub.createTablespace(null, builder.build()).getValue();
+        }
+      }.withRetries();
+    } catch (ServiceException e) {
+      LOG.error(e.getMessage(), e);
+      return Boolean.FALSE;
+    }
+  }
+
+  @Override
+  public final Boolean dropTablespace(final String tablespaceName) {
+    try {
+      return new ServerCallable<Boolean>(pool, catalogServerAddr, CatalogProtocol.class, false) {
+        public Boolean call(NettyClientBase client) throws ServiceException {
+          CatalogProtocolService.BlockingInterface stub = getStub(client);
+          return stub.dropTablespace(null, ProtoUtil.convertString(tablespaceName)).getValue();
+        }
+      }.withRetries();
+    } catch (ServiceException e) {
+      LOG.error(e.getMessage(), e);
+      return Boolean.FALSE;
+    }
+  }
+
+  @Override
+  public final Boolean existTablespace(final String tablespaceName) {
+    try {
+      return new ServerCallable<Boolean>(pool, catalogServerAddr, CatalogProtocol.class, false) {
+        public Boolean call(NettyClientBase client) throws ServiceException {
+          CatalogProtocolService.BlockingInterface stub = getStub(client);
+          return stub.existTablespace(null, ProtoUtil.convertString(tablespaceName)).getValue();
+        }
+      }.withRetries();
+    } catch (ServiceException e) {
+      LOG.error(e.getMessage(), e);
+      return Boolean.FALSE;
+    }
+  }
+
+  @Override
+  public final Collection<String> getAllTablespaceNames() {
+    try {
+      return new ServerCallable<Collection<String>>(pool, catalogServerAddr, CatalogProtocol.class, false) {
+        public Collection<String> call(NettyClientBase client) throws ServiceException {
+          CatalogProtocolService.BlockingInterface stub = getStub(client);
+          PrimitiveProtos.StringListProto response = stub.getAllTablespaceNames(null, ProtoUtil.NULL_PROTO);
+          return ProtoUtil.convertStrings(response);
+        }
+      }.withRetries();
+    } catch (ServiceException e) {
+      LOG.error(e.getMessage(), e);
+      return null;
+    }
+  }
+
+  @Override
+  public final Boolean createDatabase(final String databaseName, @Nullable final String tablespaceName) {
+    try {
+      return new ServerCallable<Boolean>(pool, catalogServerAddr, CatalogProtocol.class, false) {
+        public Boolean call(NettyClientBase client) throws ServiceException {
+          CatalogProtocolService.BlockingInterface stub = getStub(client);
+
+          CreateDatabaseRequest.Builder builder = CreateDatabaseRequest.newBuilder();
+          builder.setDatabaseName(databaseName);
+          if (tablespaceName != null) {
+            builder.setTablespaceName(tablespaceName);
+          }
+          return stub.createDatabase(null, builder.build()).getValue();
+        }
+      }.withRetries();
+    } catch (ServiceException e) {
+      LOG.error(e.getMessage(), e);
+      return Boolean.FALSE;
+    }
+  }
+
+  @Override
+  public final Boolean dropDatabase(final String databaseName) {
+    try {
+      return new ServerCallable<Boolean>(pool, catalogServerAddr, CatalogProtocol.class, false) {
+        public Boolean call(NettyClientBase client) throws ServiceException {
+          CatalogProtocolService.BlockingInterface stub = getStub(client);
+          return stub.dropDatabase(null, ProtoUtil.convertString(databaseName)).getValue();
+        }
+      }.withRetries();
+    } catch (ServiceException e) {
+      LOG.error(e.getMessage(), e);
+      return Boolean.FALSE;
+    }
+  }
+
+  @Override
+  public final Boolean existDatabase(final String databaseName) {
+    try {
+      return new ServerCallable<Boolean>(pool, catalogServerAddr, CatalogProtocol.class, false) {
+        public Boolean call(NettyClientBase client) throws ServiceException {
+          CatalogProtocolService.BlockingInterface stub = getStub(client);
+          return stub.existDatabase(null, ProtoUtil.convertString(databaseName)).getValue();
+        }
+      }.withRetries();
+    } catch (ServiceException e) {
+      LOG.error(e.getMessage(), e);
+      return Boolean.FALSE;
+    }
+  }
+
+  @Override
+  public final Collection<String> getAllDatabaseNames() {
+    try {
+      return new ServerCallable<Collection<String>>(pool, catalogServerAddr, CatalogProtocol.class, false) {
+        public Collection<String> call(NettyClientBase client) throws ServiceException {
+          CatalogProtocolService.BlockingInterface stub = getStub(client);
+          PrimitiveProtos.StringListProto response = stub.getAllDatabaseNames(null, ProtoUtil.NULL_PROTO);
+          return ProtoUtil.convertStrings(response);
+        }
+      }.withRetries();
+    } catch (ServiceException e) {
+      LOG.error(e.getMessage(), e);
+      return null;
+    }
+  }
+
+  @Override
+  public final TableDesc getTableDesc(final String databaseName, final String tableName) {
     try {
       return new ServerCallable<TableDesc>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public TableDesc call(NettyClientBase client) throws ServiceException {
+          TableIdentifierProto.Builder builder = TableIdentifierProto.newBuilder();
+          builder.setDatabaseName(databaseName);
+          builder.setTableName(tableName);
+
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return CatalogUtil.newTableDesc(stub.getTableDesc(null, StringProto.newBuilder().setValue(name).build()));
+          return CatalogUtil.newTableDesc(stub.getTableDesc(null, builder.build()));
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -72,13 +210,23 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final PartitionMethodDesc getPartitionMethod(final String tableName) {
+  public TableDesc getTableDesc(String qualifiedName) {
+    String [] splitted = CatalogUtil.splitFQTableName(qualifiedName);
+    return getTableDesc(splitted[0], splitted[1]);
+  }
+
+  @Override
+  public final PartitionMethodDesc getPartitionMethod(final String databaseName, final String tableName) {
     try {
       return new ServerCallable<PartitionMethodDesc>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public PartitionMethodDesc call(NettyClientBase client) throws ServiceException {
+
+          TableIdentifierProto.Builder builder = TableIdentifierProto.newBuilder();
+          builder.setDatabaseName(databaseName);
+          builder.setTableName(tableName);
+
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return CatalogUtil.newPartitionMethodDesc(stub.getPartitionMethodByTableName(null,
-              StringProto.newBuilder().setValue(tableName).build()));
+          return CatalogUtil.newPartitionMethodDesc(stub.getPartitionMethodByTableName(null,  builder.build()));
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -88,13 +236,17 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final boolean existPartitionMethod(final String tableId) {
+  public final boolean existPartitionMethod(final String databaseName, final String tableName) {
     try {
       return new ServerCallable<Boolean>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public Boolean call(NettyClientBase client) throws ServiceException {
+
+          TableIdentifierProto.Builder builder = TableIdentifierProto.newBuilder();
+          builder.setDatabaseName(databaseName);
+          builder.setTableName(tableName);
+
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return stub.existPartitionMethod(null, StringProto.newBuilder().
-              setValue(tableId).build()).getValue();
+          return stub.existPartitionMethod(null, builder.build()).getValue();
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -104,19 +256,13 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final Collection<String> getAllTableNames() {
+  public final Collection<String> getAllTableNames(final String databaseName) {
     try {
       return new ServerCallable<Collection<String>>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public Collection<String> call(NettyClientBase client) throws ServiceException {
-          List<String> protos = new ArrayList<String>();
-          GetAllTableNamesResponse response;
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          response = stub.getAllTableNames(null, NullProto.newBuilder().build());
-          int size = response.getTableNameCount();
-          for (int i = 0; i < size; i++) {
-            protos.add(response.getTableName(i));
-          }
-          return protos;
+          PrimitiveProtos.StringListProto response = stub.getAllTableNames(null, ProtoUtil.convertString(databaseName));
+          return ProtoUtil.convertStrings(response);
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -153,12 +299,12 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final boolean addTable(final TableDesc desc) {
+  public final boolean createTable(final TableDesc desc) {
     try {
       return new ServerCallable<Boolean>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public Boolean call(NettyClientBase client) throws ServiceException {
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return stub.addTable(null, desc.getProto()).getValue();
+          return stub.createTable(null, desc.getProto()).getValue();
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -168,13 +314,21 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final boolean deleteTable(final String name) {
+  public boolean dropTable(String tableName) {
+    String [] splitted = CatalogUtil.splitFQTableName(tableName);
+    final String databaseName = splitted[0];
+    final String simpleName = splitted[1];
+
     try {
       return new ServerCallable<Boolean>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public Boolean call(NettyClientBase client) throws ServiceException {
+
+          TableIdentifierProto.Builder builder = TableIdentifierProto.newBuilder();
+          builder.setDatabaseName(databaseName);
+          builder.setTableName(simpleName);
+
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return stub.deleteTable(null,
-              StringProto.newBuilder().setValue(name).build()).getValue();
+          return stub.dropTable(null, builder.build()).getValue();
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -184,14 +338,21 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final boolean existsTable(final String tableId) {
+  public final boolean existsTable(final String databaseName, final String tableName) {
+    if (CatalogUtil.isFQTableName(tableName)) {
+      throw new IllegalArgumentException(
+          "tableName cannot be composed of multiple parts, but it is \"" + tableName + "\"");
+    }
     try {
       return new ServerCallable<Boolean>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public Boolean call(NettyClientBase client) throws ServiceException {
+
+          TableIdentifierProto.Builder builder = TableIdentifierProto.newBuilder();
+          builder.setDatabaseName(databaseName);
+          builder.setTableName(tableName);
+
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return stub
-              .existsTable(null, StringProto.newBuilder().setValue(tableId).build())
-              .getValue();
+          return stub.existsTable(null, builder.build()).getValue();
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -200,13 +361,18 @@ public abstract class AbstractCatalogClient implements CatalogService {
     }
   }
 
+  public final boolean existsTable(final String tableName) {
+    String [] splitted = CatalogUtil.splitFQTableName(tableName);
+    return existsTable(splitted[0], splitted[1]);
+  }
+
   @Override
-  public final boolean addIndex(final IndexDesc index) {
+  public final boolean createIndex(final IndexDesc index) {
     try {
       return new ServerCallable<Boolean>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public Boolean call(NettyClientBase client) throws ServiceException {
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return stub.addIndex(null, index.getProto()).getValue();
+          return stub.createIndex(null, index.getProto()).getValue();
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -216,13 +382,16 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final boolean existIndex(final String indexName) {
+  public final boolean existIndexByName(final String databaseName, final String indexName) {
     try {
       return new ServerCallable<Boolean>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public Boolean call(NettyClientBase client) throws ServiceException {
+          IndexNameProto.Builder builder = IndexNameProto.newBuilder();
+          builder.setDatabaseName(databaseName);
+          builder.setIndexName(indexName);
+
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return stub.existIndexByName(null, StringProto.newBuilder().
-              setValue(indexName).build()).getValue();
+          return stub.existIndexByName(null, builder.build()).getValue();
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -232,15 +401,17 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public boolean existIndex(final String tableName, final String columnName) {
+  public boolean existIndexByColumn(final String databaseName, final String tableName, final String columnName) {
     try {
       return new ServerCallable<Boolean>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public Boolean call(NettyClientBase client) throws ServiceException {
-          GetIndexRequest.Builder builder = GetIndexRequest.newBuilder();
-          builder.setTableName(tableName);
-          builder.setColumnName(columnName);
+
+          GetIndexByColumnRequest.Builder builder = GetIndexByColumnRequest.newBuilder();
+          builder.setTableIdentifier(CatalogUtil.buildTableIdentifier(databaseName, tableName));
+          builder.setColumnName(CatalogUtil.normalizeIdentifier(columnName));
+
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return stub.existIndex(null, builder.build()).getValue();
+          return stub.existIndexByColumn(null, builder.build()).getValue();
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -250,14 +421,17 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final IndexDesc getIndex(final String indexName) {
+  public final IndexDesc getIndexByName(final String databaseName, final String indexName) {
     try {
       return new ServerCallable<IndexDesc>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public IndexDesc call(NettyClientBase client) throws ServiceException {
+
+          IndexNameProto.Builder builder = IndexNameProto.newBuilder();
+          builder.setDatabaseName(databaseName);
+          builder.setIndexName(indexName);
+
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return new IndexDesc(
-              stub.getIndexByName(null,
-                  StringProto.newBuilder().setValue(indexName).build()));
+          return new IndexDesc(stub.getIndexByName(null, builder.build()));
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -267,16 +441,19 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public final IndexDesc getIndex(final String tableName, final String columnName) {
+  public final IndexDesc getIndexByColumn(final String databaseName,
+                                          final String tableName,
+                                          final String columnName) {
     try {
       return new ServerCallable<IndexDesc>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public IndexDesc call(NettyClientBase client) throws ServiceException {
-          GetIndexRequest.Builder builder = GetIndexRequest.newBuilder();
-          builder.setTableName(tableName);
+
+          GetIndexByColumnRequest.Builder builder = GetIndexByColumnRequest.newBuilder();
+          builder.setTableIdentifier(CatalogUtil.buildTableIdentifier(databaseName, tableName));
           builder.setColumnName(columnName);
 
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return new IndexDesc(stub.getIndex(null, builder.build()));
+          return new IndexDesc(stub.getIndexByColumn(null, builder.build()));
         }
       }.withRetries();
     } catch (ServiceException e) {
@@ -286,13 +463,18 @@ public abstract class AbstractCatalogClient implements CatalogService {
   }
 
   @Override
-  public boolean deleteIndex(final String indexName) {
+  public boolean dropIndex(final String databaseName,
+                           final String indexName) {
     try {
       return new ServerCallable<Boolean>(this.pool, catalogServerAddr, CatalogProtocol.class, false) {
         public Boolean call(NettyClientBase client) throws ServiceException {
+
+          IndexNameProto.Builder builder = IndexNameProto.newBuilder();
+          builder.setDatabaseName(databaseName);
+          builder.setIndexName(indexName);
+
           CatalogProtocolService.BlockingInterface stub = getStub(client);
-          return stub.delIndex(null,
-              StringProto.newBuilder().setValue(indexName).build()).getValue();
+          return stub.dropIndex(null, builder.build()).getValue();
         }
       }.withRetries();
     } catch (ServiceException e) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/CatalogService.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/CatalogService.java b/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/CatalogService.java
index 494ac0b..d69ed7e 100644
--- a/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/CatalogService.java
+++ b/tajo-catalog/tajo-catalog-client/src/main/java/org/apache/tajo/catalog/CatalogService.java
@@ -28,25 +28,85 @@ import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionType;
 public interface CatalogService {
 
   /**
+   *
+   * @param tableSpaceName Tablespace name to be created
+   * @return True if tablespace is created successfully. Otherwise, it will return FALSE.
+   */
+  Boolean createTablespace(String tableSpaceName, String uri);
+
+  /**
+   *
+   * @param tableSpaceName Tablespace name to be created
+   * @return True if tablespace is created successfully. Otherwise, it will return FALSE.
+   */
+  Boolean existTablespace(String tableSpaceName);
+
+  /**
+   *
+   * @param tableSpaceName Tablespace name to be created
+   * @return True if tablespace is created successfully. Otherwise, it will return FALSE.
+   */
+  Boolean dropTablespace(String tableSpaceName);
+
+  /**
+   *
+   * @return All tablespace names
+   */
+  Collection<String> getAllTablespaceNames();
+
+  /**
+   *
+   * @param databaseName Database name to be created
+   * @return True if database is created successfully. Otherwise, it will return FALSE.
+   */
+  Boolean createDatabase(String databaseName, String tablespaceName);
+
+  /**
+   *
+   * @param databaseName Database name to be dropped
+   * @return True if database is dropped sucessfully. Otherwise, it will return FALSE.
+   */
+  Boolean dropDatabase(String databaseName);
+
+  /**
+   *
+   * @param databaseName Database name to be checked
+   * @return True if database exists. Otherwise, it will return FALSE.
+   */
+  Boolean existDatabase(String databaseName);
+
+  /**
+   *
+   * @return All database names
+   */
+  Collection<String> getAllDatabaseNames();
+
+  /**
+   * Get a table description by name
+   * @param tableName table name
+   * @return a table description
+   * @see TableDesc
+   * @throws Throwable
+   */
+  TableDesc getTableDesc(String databaseName, String tableName);
+
+  /**
    * Get a table description by name
-   * @param name table name
    * @return a table description
    * @see TableDesc
    * @throws Throwable
    */
-  TableDesc getTableDesc(String name);
+  TableDesc getTableDesc(String qualifiedName);
 
   /**
    *
-   * @return
-   * @throws org.apache.tajo.catalog.exception.CatalogException
+   * @return All table names which belong to a given database.
    */
-  Collection<String> getAllTableNames();
+  Collection<String> getAllTableNames(String databaseName);
 
   /**
    *
-   * @return
-   * @throws org.apache.tajo.catalog.exception.CatalogException
+   * @return All FunctionDescs
    */
   Collection<FunctionDesc> getFunctions();
 
@@ -55,34 +115,36 @@ public interface CatalogService {
    * @see TableDesc
    * @throws Throwable
    */
-  boolean addTable(TableDesc desc);
+  boolean createTable(TableDesc desc);
 
 
   /**
    * Drop a table by name
    *
-   * @param name table name
+   * @param tableName table name
    * @throws Throwable
    */
-  boolean deleteTable(String name);
+  boolean dropTable(String tableName);
+
+  boolean existsTable(String databaseName, String tableName);
 
-  boolean existsTable(String tableId);
+  boolean existsTable(String tableName);
 
-  PartitionMethodDesc getPartitionMethod(String tableId);
+  PartitionMethodDesc getPartitionMethod(String databaseName, String tableName);
 
-  boolean existPartitionMethod(String tableId);
+  boolean existPartitionMethod(String databaseName, String tableName);
 
-  boolean addIndex(IndexDesc index);
+  boolean createIndex(IndexDesc index);
 
-  boolean existIndex(String indexName);
+  boolean existIndexByName(String databaseName, String indexName);
 
-  boolean existIndex(String tableName, String columnName);
+  boolean existIndexByColumn(String databaseName, String tableName, String columnName);
 
-  IndexDesc getIndex(String indexName);
+  IndexDesc getIndexByName(String databaseName, String indexName);
 
-  IndexDesc getIndex(String tableName, String columnName);
+  IndexDesc getIndexByColumn(String databaseName, String tableName, String columnName);
 
-  boolean deleteIndex(String indexName);
+  boolean dropIndex(String databaseName, String indexName);
 
   boolean createFunction(FunctionDesc funcDesc);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 6a96b4e..06b69c1 100644
--- a/tajo-catalog/tajo-catalog-client/src/main/proto/CatalogProtocol.proto
+++ b/tajo-catalog/tajo-catalog-client/src/main/proto/CatalogProtocol.proto
@@ -25,15 +25,26 @@ import "CatalogProtos.proto";
 import "PrimitiveProtos.proto";
 
 service CatalogProtocolService {
-  rpc getTableDesc(StringProto) returns (TableDescProto);
-  rpc getAllTableNames(NullProto) returns (GetAllTableNamesResponse);
-  rpc addTable(TableDescProto) returns (BoolProto);
-  rpc deleteTable(StringProto) returns (BoolProto);
-  rpc existsTable(StringProto) returns (BoolProto);
 
-  rpc getPartitionMethodByTableName(StringProto) returns (PartitionMethodProto);
-  rpc existPartitionMethod(StringProto) returns (BoolProto);
-  rpc delPartitionMethod(StringProto) returns (BoolProto);
+  rpc createTablespace(CreateTablespaceRequest) returns (BoolProto);
+  rpc dropTablespace(StringProto) returns (BoolProto);
+  rpc existTablespace(StringProto) returns (BoolProto);
+  rpc getAllTablespaceNames(NullProto) returns (StringListProto);
+
+  rpc createDatabase(CreateDatabaseRequest) returns (BoolProto);
+  rpc dropDatabase(StringProto) returns (BoolProto);
+  rpc existDatabase(StringProto) returns (BoolProto);
+  rpc getAllDatabaseNames(NullProto) returns (StringListProto);
+
+  rpc createTable(TableDescProto) returns (BoolProto);
+  rpc dropTable(TableIdentifierProto) returns (BoolProto);
+  rpc existsTable(TableIdentifierProto) returns (BoolProto);
+  rpc getTableDesc(TableIdentifierProto) returns (TableDescProto);
+  rpc getAllTableNames(StringProto) returns (StringListProto);
+
+  rpc getPartitionMethodByTableName(TableIdentifierProto) returns (PartitionMethodProto);
+  rpc existPartitionMethod(TableIdentifierProto) returns (BoolProto);
+  rpc dropPartitionMethod(TableIdentifierProto) returns (BoolProto);
 
   rpc addPartitions(PartitionsProto) returns (BoolProto);
   rpc addPartition(PartitionDescProto) returns (BoolProto);
@@ -41,12 +52,12 @@ service CatalogProtocolService {
   rpc getPartitionsByTableName(StringProto) returns (PartitionsProto);
   rpc delAllPartitions(StringProto) returns (PartitionsProto);
 
-  rpc addIndex(IndexDescProto) returns (BoolProto);
-  rpc existIndexByName(StringProto) returns (BoolProto);
-  rpc existIndex(GetIndexRequest) returns (BoolProto);
-  rpc getIndexByName(StringProto) returns (IndexDescProto);
-  rpc getIndex(GetIndexRequest) returns (IndexDescProto);
-  rpc delIndex(StringProto) returns (BoolProto);
+  rpc createIndex(IndexDescProto) returns (BoolProto);
+  rpc dropIndex(IndexNameProto) returns (BoolProto);
+  rpc existIndexByName(IndexNameProto) returns (BoolProto);
+  rpc existIndexByColumn(GetIndexByColumnRequest) returns (BoolProto);
+  rpc getIndexByName(IndexNameProto) returns (IndexDescProto);
+  rpc getIndexByColumn(GetIndexByColumnRequest) returns (IndexDescProto);
 
   rpc createFunction(FunctionDescProto) returns (BoolProto);
   rpc dropFunction(UnregisterFunctionRequest) returns (BoolProto);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 fa23da1..c7116f6 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
@@ -30,6 +30,8 @@ public class CatalogConstants {
   public static final String DEPRECATED_CATALOG_URI="tajo.catalog.jdbc.uri";
 
   public static final String TB_META = "META";
+  public static final String TB_SPACES = "TABLESPACES";
+  public static final String TB_DATABASES = "DATABASES_";
   public static final String TB_TABLES = "TABLES";
   public static final String TB_COLUMNS = "COLUMNS";
   public static final String TB_OPTIONS = "OPTIONS";
@@ -38,7 +40,10 @@ public class CatalogConstants {
   public static final String TB_PARTITION_METHODS = "PARTITION_METHODS";
   public static final String TB_PARTTIONS = "PARTITIONS";
 
-  public static final String C_TABLE_ID = "TABLE_ID";
+  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_TABLES_NAME = "TABLE_NAME";
 
   // table options
   public static final String COMPRESSION_CODEC = "compression.codec";

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 2a6727e..05a18bd 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
@@ -50,6 +50,52 @@ public class CatalogUtil {
     return identifier.toLowerCase();
   }
 
+  public static boolean isFQColumnName(String tableName) {
+    return tableName.split(IDENTIFIER_DELIMITER_REGEXP).length == 3;
+  }
+
+  public static boolean isFQTableName(String tableName) {
+    int lastDelimiterIdx = tableName.lastIndexOf(IDENTIFIER_DELIMITER);
+    return lastDelimiterIdx > -1;
+  }
+
+  public static String [] splitFQTableName(String qualifiedName) {
+    String [] splitted = CatalogUtil.splitTableName(CatalogUtil.normalizeIdentifier(qualifiedName));
+    if (splitted.length == 1) {
+      throw new IllegalArgumentException("createTable() requires a qualified table name, but it is \""
+          + qualifiedName + "\".");
+    }
+    return splitted;
+  }
+
+  public static String [] splitTableName(String tableName) {
+    int lastDelimiterIdx = tableName.lastIndexOf(IDENTIFIER_DELIMITER);
+    if (lastDelimiterIdx > -1) {
+      return new String [] {
+          tableName.substring(0, lastDelimiterIdx),
+          tableName.substring(lastDelimiterIdx + 1, tableName.length())
+      };
+    } else {
+      return new String [] {tableName};
+    }
+  }
+
+  public static String buildFQName(String... identifiers) {
+    boolean first = true;
+    StringBuilder sb = new StringBuilder();
+    for(String id : identifiers) {
+      if (first) {
+        first = false;
+      } else {
+        sb.append(IDENTIFIER_DELIMITER);
+      }
+
+      sb.append(id);
+    }
+
+    return sb.toString();
+  }
+
   /**
    * Extract a qualification name from an identifier.
    *
@@ -87,11 +133,18 @@ public class CatalogUtil {
     }
   }
 
-  public static String getCanonicalName(String signature, Collection<DataType> paramTypes) {
+  public static String getCanonicalTableName(String databaseName, String tableName) {
+    StringBuilder sb = new StringBuilder(databaseName);
+    sb.append(IDENTIFIER_DELIMITER);
+    sb.append(tableName);
+    return sb.toString();
+  }
+
+  public static String getCanonicalSignature(String functionName, Collection<DataType> paramTypes) {
     DataType [] types = paramTypes.toArray(new DataType[paramTypes.size()]);
-    return getCanonicalName(signature, types);
+    return getCanonicalSignature(functionName, types);
   }
-  public static String getCanonicalName(String signature, DataType...paramTypes) {
+  public static String getCanonicalSignature(String signature, DataType... paramTypes) {
     StringBuilder sb = new StringBuilder(signature);
     sb.append("(");
     int i = 0;
@@ -144,10 +197,6 @@ public class CatalogUtil {
     return new PartitionMethodDesc(proto);
   }
 
-  public static TableDesc newTableDesc(String tableName, Schema schema, StoreType type, Options options, Path path) {
-    return new TableDesc(tableName, schema, type, options, path);
-  }
-
   /**
   * This method transforms the unqualified names of a given schema into
   * the qualified names.
@@ -206,6 +255,13 @@ public class CatalogUtil {
     return sb.toString();
   }
 
+  public static CatalogProtos.TableIdentifierProto buildTableIdentifier(String databaseName, String tableName) {
+    CatalogProtos.TableIdentifierProto.Builder builder = CatalogProtos.TableIdentifierProto.newBuilder();
+    builder.setDatabaseName(databaseName);
+    builder.setTableName(tableName);
+    return builder.build();
+  }
+
   public static void closeQuietly(Connection conn) {
     try {
       if (conn != null)
@@ -230,31 +286,11 @@ public class CatalogUtil {
     }
   }
 
-  public static void closeQuietly(Connection conn, Statement stmt)  {
-    try {
-      closeQuietly(stmt);
-    } finally {
-      closeQuietly(conn);
-    }
-  }
-
-  public static void closeQuietly(Connection conn, ResultSet res) {
-    try {
-      closeQuietly(res);
-    } finally {
-      closeQuietly(conn);
-    }
-  }
-
-  public static void closeQuietly(Connection conn, Statement stmt, ResultSet res) {
+  public static void closeQuietly(Statement stmt, ResultSet res) {
     try {
       closeQuietly(res);
     } finally {
-      try {
-        closeQuietly(stmt);
-      } finally {
-        closeQuietly(conn);
-      }
+      closeQuietly(stmt);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 1e51cc2..fd2fe8f 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
@@ -25,7 +25,7 @@ import java.util.Map;
 
 public class DDLBuilder {
 
-  public static String buildDDL(TableDesc desc) {
+  public static String buildDDLForExternalTable(TableDesc desc) {
     StringBuilder sb = new StringBuilder();
 
     sb.append("--\n")
@@ -48,6 +48,27 @@ public class DDLBuilder {
     return sb.toString();
   }
 
+  public static String buildDDLForBaseTable(TableDesc desc) {
+    StringBuilder sb = new StringBuilder();
+
+    sb.append("--\n")
+        .append("-- Name: ").append(desc.getName()).append("; Type: TABLE;")
+        .append(" Storage: ").append(desc.getMeta().getStoreType().name());
+    sb.append("\n-- Path: ").append(desc.getPath());
+    sb.append("\n--\n");
+    sb.append("CREATE TABLE ").append(desc.getName());
+    buildSchema(sb, desc.getSchema());
+    buildUsingClause(sb, desc.getMeta());
+    buildWithClause(sb, desc.getMeta());
+
+    if (desc.hasPartition()) {
+      buildPartitionClause(sb, desc);
+    }
+
+    sb.append(";");
+    return sb.toString();
+  }
+
   private static void buildSchema(StringBuilder sb, Schema schema) {
     boolean first = true;
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
index 0ef8497..d6d9290 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/FunctionDesc.java
@@ -204,7 +204,7 @@ public class FunctionDesc implements ProtoObject<FunctionDescProto>, Cloneable,
   }
 
   public String getHelpSignature() {
-    return returnType.getType() + " " + CatalogUtil.getCanonicalName(signature, getParamTypes());
+    return returnType.getType() + " " + CatalogUtil.getCanonicalSignature(signature, getParamTypes());
   }
 
   public static String dataTypesToStr(List<DataType> parameterTypesList) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 6199259..ef65b36 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
@@ -21,6 +21,7 @@ package org.apache.tajo.catalog;
 import com.google.common.base.Objects;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.IndexDescProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.IndexMethod;
 import org.apache.tajo.common.ProtoObject;
@@ -28,11 +29,12 @@ import org.apache.tajo.common.ProtoObject;
 public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
   private IndexDescProto.Builder builder;
   
-  private String name; // required
-  private String tableId; // required
-  private Column column; // required
-  private IndexMethod indexMethod; // required
-  private boolean isUnique = false; // optional [default = false]
+  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]
   
@@ -40,11 +42,12 @@ public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
     this.builder = IndexDescProto.newBuilder();
   }
   
-  public IndexDesc(String name, String tableId, Column column, IndexMethod type,
-      boolean isUnique, boolean isClustered, boolean isAscending) {
+  public IndexDesc(String idxName, String databaseName, String tableName, Column column,
+                   IndexMethod type,  boolean isUnique, boolean isClustered, boolean isAscending) {
     this();
-    this.name = name.toLowerCase();
-    this.tableId = tableId.toLowerCase();
+    this.indexName = idxName.toLowerCase();
+    this.databaseName = databaseName;
+    this.tableName = tableName.toLowerCase();
     this.column = column;
     this.indexMethod = type;
     this.isUnique = isUnique;
@@ -53,16 +56,19 @@ public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
   }
   
   public IndexDesc(IndexDescProto proto) {
-    this(proto.getName(), proto.getTableId(), new Column(proto.getColumn()),
+    this(proto.getIndexName(),
+        proto.getTableIdentifier().getDatabaseName(),
+        proto.getTableIdentifier().getTableName(),
+        new Column(proto.getColumn()),
         proto.getIndexMethod(), proto.getIsUnique(), proto.getIsClustered(), proto.getIsAscending());
   }
   
-  public String getName() {
-    return name;
+  public String getIndexName() {
+    return indexName;
   }
   
-  public String getTableId() {
-    return tableId;
+  public String getTableName() {
+    return tableName;
   }
   
   public Column getColumn() {
@@ -90,8 +96,17 @@ public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
     if (builder == null) {
       builder = IndexDescProto.newBuilder();
     }
-    builder.setName(this.name);
-    builder.setTableId(this.tableId);
+
+    CatalogProtos.TableIdentifierProto.Builder tableIdentifierBuilder = CatalogProtos.TableIdentifierProto.newBuilder();
+    if (databaseName != null) {
+      tableIdentifierBuilder.setDatabaseName(databaseName);
+    }
+    if (tableName != null) {
+      tableIdentifierBuilder.setTableName(tableName);
+    }
+
+    builder.setTableIdentifier(tableIdentifierBuilder.build());
+    builder.setIndexName(this.indexName);
     builder.setColumn(this.column.getProto());
     builder.setIndexMethod(indexMethod);
     builder.setIsUnique(this.isUnique);
@@ -104,8 +119,8 @@ public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
   public boolean equals(Object obj) {
     if (obj instanceof IndexDesc) {
       IndexDesc other = (IndexDesc) obj;
-      return getName().equals(other.getName())
-          && getTableId().equals(other.getTableId())
+      return getIndexName().equals(other.getIndexName())
+          && getTableName().equals(other.getTableName())
           && getColumn().equals(other.getColumn())
           && getIndexMethod().equals(other.getIndexMethod())
           && isUnique() == other.isUnique()
@@ -117,14 +132,14 @@ public class IndexDesc implements ProtoObject<IndexDescProto>, Cloneable {
   }
   
   public int hashCode() {
-    return Objects.hashCode(getName(), getTableId(), getColumn(), 
+    return Objects.hashCode(getIndexName(), getTableName(), getColumn(),
         getIndexMethod(), isUnique(), isClustered(), isAscending());
   }
 
   public Object clone() throws CloneNotSupportedException {
     IndexDesc desc = (IndexDesc) super.clone();
-    desc.name = name;
-    desc.tableId = tableId;
+    desc.indexName = indexName;
+    desc.tableName = tableName;
     desc.column = (Column) column.clone();
     desc.indexMethod = indexMethod;
     desc.isUnique = isUnique;

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 153d5f0..30102eb 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
@@ -38,25 +38,33 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
   private final Log LOG = LogFactory.getLog(TableDesc.class);
 
   protected TableDescProto.Builder builder = null;
-  
 	@Expose protected String tableName;                        // required
   @Expose protected Schema schema;
   @Expose protected TableMeta meta;                          // required
-  @Expose protected Path uri;                                // required
+  /** uri is set if external flag is TRUE.*/
+  @Expose protected Path uri;                                // optional
   @Expose	protected TableStats stats;                        // optional
+  /** the description of table partition */
   @Expose protected PartitionMethodDesc partitionMethodDesc; // optional
+  /** True if it is an external table. False if it is a managed table. */
+  @Expose protected Boolean external;                        // optional
 
 	public TableDesc() {
 		builder = TableDescProto.newBuilder();
 	}
-	
-	public TableDesc(String tableName, Schema schema, TableMeta info, Path path) {
-		this();
-		// tajo deems all identifiers as lowcase characters
-	  this.tableName = tableName.toLowerCase();
+
+  public TableDesc(String tableName, Schema schema, TableMeta meta,
+                   Path path, boolean external) {
+    this();
+    this.tableName = tableName.toLowerCase();
     this.schema = schema;
-	  this.meta = info;
-	  this.uri = path;
+    this.meta = meta;
+    this.uri = path;
+    this.external = external;
+  }
+
+	public TableDesc(String tableName, Schema schema, TableMeta meta, Path path) {
+		this(CatalogUtil.normalizeIdentifier(tableName), schema, meta, path, true);
 	}
 	
 	public TableDesc(String tableName, Schema schema, StoreType type, Options options, Path path) {
@@ -64,7 +72,8 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
 	}
 	
 	public TableDesc(TableDescProto proto) {
-	  this(proto.getId(), new Schema(proto.getSchema()), new TableMeta(proto.getMeta()), new Path(proto.getPath()));
+	  this(proto.getTableName(), new Schema(proto.getSchema()),
+        new TableMeta(proto.getMeta()), new Path(proto.getPath()), proto.getIsExternal());
     if(proto.hasStats()) {
       this.stats = new TableStats(proto.getStats());
     }
@@ -141,6 +150,14 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
     this.partitionMethodDesc = partitionMethodDesc;
   }
 
+  public void setExternal(boolean external) {
+    this.external = external;
+  }
+
+  public boolean isExternal() {
+    return external;
+  }
+
   public int hashCode() {
     return Objects.hashCode(tableName, schema, meta, uri, stats, partitionMethodDesc);
   }
@@ -154,6 +171,7 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
       eq = eq && meta.equals(other.meta);
       eq = eq && uri.equals(other.uri);
       eq = eq && TUtil.checkEquals(partitionMethodDesc, other.partitionMethodDesc);
+      eq = eq && TUtil.checkEquals(external, other.external);
       return eq && TUtil.checkEquals(stats, other.stats);
     }
     
@@ -169,6 +187,7 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
     desc.uri = uri;
     desc.stats = stats != null ? (TableStats) stats.clone() : null;
     desc.partitionMethodDesc = partitionMethodDesc != null ? (PartitionMethodDesc) partitionMethodDesc.clone() : null;
+    desc.external = external != null ? external : null;
 	  return desc;
 	}
 
@@ -186,8 +205,9 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
     if (builder == null) {
       builder = TableDescProto.newBuilder();
     }
+
     if (this.tableName != null) {
-      builder.setId(this.tableName);
+      builder.setTableName(this.tableName);
     }
     if (this.schema != null) {
       builder.setSchema(schema.getProto());
@@ -204,6 +224,9 @@ public class TableDesc implements ProtoObject<TableDescProto>, GsonObject, Clone
     if (this.partitionMethodDesc != null) {
       builder.setPartition(this.partitionMethodDesc.getProto());
     }
+    if (this.external != null) {
+      builder.setIsExternal(external);
+    }
 
     return builder.build();
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsDatabaseException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsDatabaseException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsDatabaseException.java
new file mode 100644
index 0000000..f811689
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsDatabaseException.java
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.catalog.exception;
+
+
+public class AlreadyExistsDatabaseException extends CatalogException {
+
+  public AlreadyExistsDatabaseException() {
+	}
+
+	public AlreadyExistsDatabaseException(String dbName) {
+		super(String.format("Already exists database \"%s\"", dbName));
+	}
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsIndexException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsIndexException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsIndexException.java
index a254514..22c8172 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsIndexException.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsIndexException.java
@@ -18,6 +18,8 @@
 
 package org.apache.tajo.catalog.exception;
 
+import org.apache.tajo.annotation.Nullable;
+
 public class AlreadyExistsIndexException extends CatalogException {
   private static final long serialVersionUID = 3705839985189534673L;
 
@@ -27,25 +29,11 @@ public class AlreadyExistsIndexException extends CatalogException {
   public AlreadyExistsIndexException() {
   }
 
-  /**
-   * @param message
-   */
-  public AlreadyExistsIndexException(String message) {
-    super(message);
+  public AlreadyExistsIndexException(String databaseName, @Nullable String namespace, String indexName) {
+    super(String.format("index \" %s \" already exists in %s.%s", indexName, databaseName, namespace));
   }
 
-  /**
-   * @param cause
-   */
-  public AlreadyExistsIndexException(Throwable cause) {
-    super(cause);
-  }
-
-  /**
-   * @param message
-   * @param cause
-   */
-  public AlreadyExistsIndexException(String message, Throwable cause) {
-    super(message, cause);
+  public AlreadyExistsIndexException(String indexName) {
+    super("index \"" + indexName + "\" exists table");
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsTableException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsTableException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsTableException.java
index a2e3a6a..ec4cf67 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsTableException.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsTableException.java
@@ -25,7 +25,11 @@ public class AlreadyExistsTableException extends CatalogException {
 	public AlreadyExistsTableException() {		
 	}
 
+  public AlreadyExistsTableException(String databaseName, String relName) {
+    super(String.format("relation \" %s \" already exists in %s", relName, databaseName));
+  }
+
 	public AlreadyExistsTableException(String tableName) {
-		super("Already exists table: "+tableName);
+		super("relation \"" + tableName + "\" exists table");
 	}
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsTablespaceException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsTablespaceException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsTablespaceException.java
new file mode 100644
index 0000000..49c5bf9
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/AlreadyExistsTablespaceException.java
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.catalog.exception;
+
+
+public class AlreadyExistsTablespaceException extends CatalogException {
+
+  public AlreadyExistsTablespaceException() {
+	}
+
+	public AlreadyExistsTablespaceException(String dbName) {
+		super(String.format("Already exists tablespace \"%s\"", dbName));
+	}
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/InvalidTableException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/InvalidTableException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/InvalidTableException.java
deleted file mode 100644
index c19888f..0000000
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/InvalidTableException.java
+++ /dev/null
@@ -1,36 +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.exception;
-
-import org.apache.tajo.exception.InternalException;
-
-public class InvalidTableException extends InternalException {
-
-	private static final long serialVersionUID = -6326266814969872171L;
-
-	public InvalidTableException() {
-	}
-
-	/**
-	 * @param message
-	 */
-	public InvalidTableException(String message) {
-		super(message);
-	}
-}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoPartitionedTableException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoPartitionedTableException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoPartitionedTableException.java
new file mode 100644
index 0000000..faa8bc4
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoPartitionedTableException.java
@@ -0,0 +1,28 @@
+/**
+ * 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.exception;
+
+public class NoPartitionedTableException extends Exception {
+
+  public NoPartitionedTableException() {}
+
+  public NoPartitionedTableException(String databaseName, String relName) {
+    super(String.format("ERROR: \"%s.%s\" is not a partitioned table", databaseName, relName));
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchDatabaseException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchDatabaseException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchDatabaseException.java
new file mode 100644
index 0000000..757cad5
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchDatabaseException.java
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.catalog.exception;
+
+
+public class NoSuchDatabaseException extends CatalogException {
+	private static final long serialVersionUID = 277182608283894937L;
+
+	public NoSuchDatabaseException() {}
+
+	public NoSuchDatabaseException(String databaseName) {
+		super("ERROR: database \"" + databaseName + "\" does not exist");
+	}
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java
index 7765c31..78df08f 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchFunctionException.java
@@ -27,10 +27,10 @@ public class NoSuchFunctionException extends RuntimeException {
 	private static final long serialVersionUID = 5062193018697228028L;
 
   public NoSuchFunctionException(String funcName, TajoDataTypes.DataType [] parameters) {
-    super("function " + CatalogUtil.getCanonicalName(funcName, parameters) + " does not exist");
+    super("function " + CatalogUtil.getCanonicalSignature(funcName, parameters) + " does not exist");
   }
 
 	public NoSuchFunctionException(String funcName, Collection<TajoDataTypes.DataType> parameters) {
-		super("function " + CatalogUtil.getCanonicalName(funcName, parameters) + " does not exist");
+		super("function " + CatalogUtil.getCanonicalSignature(funcName, parameters) + " does not exist");
 	}
 }


[09/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogConstants.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogConstants.java b/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogConstants.java
deleted file mode 100644
index f7b5c19..0000000
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestCatalogConstants.java
+++ /dev/null
@@ -1,46 +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;
-
-import org.apache.hadoop.fs.Path;
-import org.apache.tajo.catalog.store.DerbyStore;
-import org.apache.tajo.conf.TajoConf;
-import org.apache.tajo.util.CommonTestingUtil;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-import java.io.File;
-
-public class TestCatalogConstants extends TestDBStore {
-
-  @BeforeClass
-  public static void setUp() throws Exception {
-    conf = new TajoConf();
-    Path testDir = CommonTestingUtil.getTestDir("target/test-data/TestDBSTore");
-    File absolutePath = new File(testDir.toUri());
-    conf.set(CatalogConstants.DEPRECATED_CATALOG_URI, "jdbc:derby:"+absolutePath.getAbsolutePath()+"/db;create=true");
-    LOG.info("derby repository is set to "+conf.get(CatalogConstants.DEPRECATED_CATALOG_URI));
-    store = new DerbyStore(conf);
-  }
-
-  @AfterClass
-  public static void tearDown() throws Exception {
-    store.close();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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
deleted file mode 100644
index a6b5b9a..0000000
--- a/tajo-catalog/tajo-catalog-server/src/test/java/org/apache/tajo/catalog/TestDBStore.java
+++ /dev/null
@@ -1,403 +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;
-
-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.PartitionMethodDesc;
-import org.apache.tajo.catalog.proto.CatalogProtos;
-import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
-import org.apache.tajo.catalog.statistics.TableStats;
-import org.apache.tajo.catalog.store.AbstractDBStore;
-import org.apache.tajo.catalog.store.DerbyStore;
-import org.apache.tajo.common.TajoDataTypes.Type;
-import org.apache.tajo.conf.TajoConf;
-import org.apache.tajo.util.CommonTestingUtil;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-
-import static org.junit.Assert.*;
-
-public class TestDBStore {
-  protected static final Log LOG = LogFactory.getLog(TestDBStore.class);
-  protected static Configuration conf;
-  protected static AbstractDBStore store;
-
-  @BeforeClass
-  public static void setUp() throws Exception {
-    conf = new TajoConf();
-    Path testDir = CommonTestingUtil.getTestDir("target/test-data/TestDBSTore");
-    File absolutePath = new File(testDir.toUri());
-    conf.set(CatalogConstants.CATALOG_URI, "jdbc:derby:"+absolutePath.getAbsolutePath()+"/db;create=true");
-    LOG.info("derby repository is set to "+conf.get(CatalogConstants.CATALOG_URI));
-    store = new DerbyStore(conf);
-  }
-
-  @AfterClass
-  public static void tearDown() throws Exception {
-    store.close();
-  }
-
-  @Test
-  public final void testAddAndDeleteTable() throws Exception {
-    Schema schema = new Schema();
-    schema.addColumn("id", Type.INT4)
-    .addColumn("name", Type.TEXT)
-    .addColumn("age", Type.INT4)
-    .addColumn("score", Type.FLOAT8);
-    
-    String tableName = "addedtable";
-    Options opts = new Options();
-    opts.put("file.delimiter", ",");
-    TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    assertFalse(store.existTable(tableName));
-    store.addTable(desc.getProto());
-    assertTrue(store.existTable(tableName));
-
-    TableDesc retrieved = new TableDesc(store.getTable(tableName));
-    // Schema order check
-    assertSchemaOrder(desc.getSchema(), retrieved.getSchema());
-    store.deleteTable(tableName);
-    assertFalse(store.existTable(tableName));
-  }
-  
-  @Test
-  public final void testGetTable() throws Exception {
-    Schema schema = new Schema();
-    schema.addColumn("gettable.id", Type.INT4)
-    .addColumn("gettable.name", Type.TEXT)
-    .addColumn("gettable.age", Type.INT4)
-    .addColumn("gettable.score", Type.FLOAT8);
-    
-    String tableName = "gettable";
-    Options opts = new Options();
-    opts.put("file.delimiter", ",");
-    TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
-
-    TableStats stat = new TableStats();
-    stat.setNumRows(957685);
-    stat.setNumBytes(1023234);
-
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "gettable"));
-    desc.setStats(stat);
-
-    store.addTable(desc.getProto());
-    TableDesc retrieved = new TableDesc(store.getTable(tableName));
-    assertEquals(",", retrieved.getMeta().getOption("file.delimiter"));
-    assertEquals(desc, retrieved);
-    assertTrue(957685 == desc.getStats().getNumRows());
-    assertTrue(1023234 == desc.getStats().getNumBytes());
-    // Schema order check
-    assertSchemaOrder(desc.getSchema(), retrieved.getSchema());
-    store.deleteTable(tableName);
-  }
-  
-  @Test
-  public final void testGetAllTableNames() throws Exception {
-    Schema schema = new Schema();
-    schema.addColumn("id", Type.INT4)
-    .addColumn("name", Type.TEXT)
-    .addColumn("age", Type.INT4)
-    .addColumn("score", Type.FLOAT8);
-    
-    int numTables = 5;
-    for (int i = 0; i < numTables; i++) {
-      String tableName = "tableA_" + i;
-      TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV);
-      TableDesc desc = new TableDesc(tableName, schema, meta,
-          new Path(CommonTestingUtil.getTestDir(), "tableA_" + i));
-      store.addTable(desc.getProto());
-    }
-    
-    assertEquals(numTables, store.getAllTableNames().size());
-  }  
-  
-  @Test
-  public final void testAddAndDeleteIndex() throws Exception {
-    TableDesc table = prepareTable();
-    store.addTable(table.getProto());
-    
-    store.addIndex(TestCatalog.desc1.getProto());
-    assertTrue(store.existIndex(TestCatalog.desc1.getName()));
-    store.delIndex(TestCatalog.desc1.getName());
-    assertFalse(store.existIndex(TestCatalog.desc1.getName()));
-    
-    store.deleteTable(table.getName());
-  }
-  
-  @Test
-  public final void testGetIndex() throws Exception {
-    
-    TableDesc table = prepareTable();
-    store.addTable(table.getProto());
-    
-    store.addIndex(TestCatalog.desc2.getProto());
-    assertEquals(
-        new IndexDesc(TestCatalog.desc2.getProto()),
-        new IndexDesc(store.getIndex(TestCatalog.desc2.getName())));
-    store.delIndex(TestCatalog.desc2.getName());
-    
-    store.deleteTable(table.getName());
-  }
-  
-  @Test
-  public final void testGetIndexByTableAndColumn() throws Exception {
-    
-    TableDesc table = prepareTable();
-    store.addTable(table.getProto());
-    
-    store.addIndex(TestCatalog.desc2.getProto());
-    
-    String tableId = TestCatalog.desc2.getTableId();
-    String columnName = "score";
-    assertEquals(
-        new IndexDesc(TestCatalog.desc2.getProto()),
-        new IndexDesc(store.getIndex(tableId, columnName)));
-    store.delIndex(TestCatalog.desc2.getName());
-    
-    store.deleteTable(table.getName());
-  }
-  
-  @Test
-  public final void testGetAllIndexes() throws Exception {
-    
-    TableDesc table = prepareTable();
-    store.addTable(table.getProto());
-    
-    store.addIndex(TestCatalog.desc1.getProto());
-    store.addIndex(TestCatalog.desc2.getProto());
-        
-    assertEquals(2, 
-        store.getIndexes(TestCatalog.desc2.getTableId()).length);
-    store.delIndex(TestCatalog.desc1.getName());
-    store.delIndex(TestCatalog.desc2.getName());
-    
-    store.deleteTable(table.getName());
-  }
-  
-  public static TableDesc prepareTable() throws IOException {
-    Schema schema = new Schema();
-    schema.addColumn("indexed.id", Type.INT4)
-    .addColumn("indexed.name", Type.TEXT)
-    .addColumn("indexed.age", Type.INT4)
-    .addColumn("indexed.score", Type.FLOAT8);
-    
-    String tableName = "indexed";
-    
-    TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV);
-    return new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "indexed"));
-  }
-
-  public static void assertSchemaOrder(Schema s1, Schema s2) {
-    // Schema order check
-    assertEquals(s1.size(),
-        s2.size());
-
-    for (int i = 0; i < s1.size(); i++) {
-      assertEquals(s1.getColumn(i).getSimpleName(),
-          s2.getColumn(i).getSimpleName());
-    }
-  }
-
-  @Test
-  public final void testAddAndDeleteTablePartitionByHash1() throws Exception {
-    Schema schema = new Schema();
-    schema.addColumn("id", Type.INT4)
-        .addColumn("name", Type.TEXT)
-        .addColumn("age", Type.INT4)
-        .addColumn("score", Type.FLOAT8);
-
-    String tableName = "addedtable";
-    Options opts = new Options();
-    opts.put("file.delimiter", ",");
-    TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
-
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
-    Schema partSchema = new Schema();
-    partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.HASH);
-
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitionMethod(partitionDesc);
-    assertFalse(store.existTable(tableName));
-    store.addTable(desc.getProto());
-    assertTrue(store.existTable(tableName));
-
-    TableDesc retrieved = new TableDesc(store.getTable(tableName));
-
-    // Schema order check
-    assertSchemaOrder(desc.getSchema(), retrieved.getSchema());
-    store.deleteTable(tableName);
-    assertFalse(store.existTable(tableName));
-  }
-
-  @Test
-  public final void testAddAndDeleteTablePartitionByHash2() throws Exception {
-    Schema schema = new Schema();
-    schema.addColumn("id", Type.INT4)
-        .addColumn("name", Type.TEXT)
-        .addColumn("age", Type.INT4)
-        .addColumn("score", Type.FLOAT8);
-
-    String tableName = "addedtable";
-    Options opts = new Options();
-    opts.put("file.delimiter", ",");
-    TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
-
-
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
-    Schema partSchema = new Schema();
-    partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.HASH);
-
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitionMethod(partitionDesc);
-    assertFalse(store.existTable(tableName));
-    store.addTable(desc.getProto());
-    assertTrue(store.existTable(tableName));
-
-    TableDesc retrieved = new TableDesc(store.getTable(tableName));
-
-    // Schema order check
-    assertSchemaOrder(desc.getSchema(), retrieved.getSchema());
-    store.deleteTable(tableName);
-    assertFalse(store.existTable(tableName));
-  }
-
-  @Test
-  public final void testAddAndDeleteTablePartitionByList() throws Exception {
-    Schema schema = new Schema();
-    schema.addColumn("id", Type.INT4)
-        .addColumn("name", Type.TEXT)
-        .addColumn("age", Type.INT4)
-        .addColumn("score", Type.FLOAT8);
-
-    String tableName = "addedtable";
-    Options opts = new Options();
-    opts.put("file.delimiter", ",");
-    TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
-
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
-    Schema partSchema = new Schema();
-    partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.LIST);
-
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitionMethod(partitionDesc);
-    assertFalse(store.existTable(tableName));
-    store.addTable(desc.getProto());
-    assertTrue(store.existTable(tableName));
-
-    TableDesc retrieved = new TableDesc(store.getTable(tableName));
-
-    // Schema order check
-    assertSchemaOrder(desc.getSchema(), retrieved.getSchema());
-    store.deleteTable(tableName);
-    assertFalse(store.existTable(tableName));
-  }
-
-  @Test
-  public final void testAddAndDeleteTablePartitionByRange() throws Exception {
-    Schema schema = new Schema();
-    schema.addColumn("id", Type.INT4)
-        .addColumn("name", Type.TEXT)
-        .addColumn("age", Type.INT4)
-        .addColumn("score", Type.FLOAT8);
-
-    String tableName = "addedtable";
-    Options opts = new Options();
-    opts.put("file.delimiter", ",");
-    TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
-
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
-    Schema partSchema = new Schema();
-    partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.RANGE);
-
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitionMethod(partitionDesc);
-    assertFalse(store.existTable(tableName));
-    store.addTable(desc.getProto());
-    assertTrue(store.existTable(tableName));
-
-    TableDesc retrieved = new TableDesc(store.getTable(tableName));
-
-    // Schema order check
-    assertSchemaOrder(desc.getSchema(), retrieved.getSchema());
-    store.deleteTable(tableName);
-    assertFalse(store.existTable(tableName));
-  }
-
-  @Test
-  public final void testAddAndDeleteTablePartitionByColumn() throws Exception {
-    Schema schema = new Schema();
-    schema.addColumn("id", Type.INT4)
-        .addColumn("name", Type.TEXT)
-        .addColumn("age", Type.INT4)
-        .addColumn("score", Type.FLOAT8);
-
-    String tableName = "addedtable";
-    Options opts = new Options();
-    opts.put("file.delimiter", ",");
-    TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
-
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
-    Schema partSchema = new Schema();
-    partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.COLUMN);
-
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
-    desc.setPartitionMethod(partitionDesc);
-    assertFalse(store.existTable(tableName));
-    store.addTable(desc.getProto());
-    assertTrue(store.existTable(tableName));
-
-    TableDesc retrieved = new TableDesc(store.getTable(tableName));
-
-    // Schema order check
-    assertSchemaOrder(desc.getSchema(), retrieved.getSchema());
-    store.deleteTable(tableName);
-    assertFalse(store.existTable(tableName));
-  }
-
-
-
-}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/ConnectDatabaseCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/ConnectDatabaseCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/ConnectDatabaseCommand.java
new file mode 100644
index 0000000..02f195a
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/ConnectDatabaseCommand.java
@@ -0,0 +1,65 @@
+/**
+ * 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.cli;
+
+import com.google.protobuf.ServiceException;
+
+public class ConnectDatabaseCommand extends TajoShellCommand {
+
+  public ConnectDatabaseCommand(TajoCli.TajoCliContext context) {
+    super(context);
+  }
+
+  @Override
+  public String getCommand() {
+    return "\\c";
+  }
+
+  @Override
+  public void invoke(String[] cmd) throws Exception {
+    if (cmd.length == 1) {
+      context.getOutput().write(String.format("You are now connected to database \"%s\" as user \"%s\".%n",
+          client.getCurrentDatabase(), client.getUserInfo().getUserName()));
+    } else if (cmd.length == 2) {
+      try {
+        if (client.selectDatabase(cmd[1])) {
+          context.setCurrentDatabase(client.getCurrentDatabase());
+          context.getOutput().write(String.format("You are now connected to database \"%s\" as user \"%s\".%n",
+              context.getCurrentDatabase(), client.getUserInfo().getUserName()));
+        }
+      } catch (ServiceException se) {
+        if (se.getMessage() != null) {
+          context.getOutput().write(se.getMessage());
+        } else {
+          context.getOutput().write(String.format("cannot connect the database \"%s\"", cmd[1]));
+        }
+      }
+    }
+  }
+
+  @Override
+  public String getUsage() {
+    return "";
+  }
+
+  @Override
+  public String getDescription() {
+    return "connect to new database";
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/CopyrightCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/CopyrightCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/CopyrightCommand.java
index 809cd37..07a3b51 100644
--- a/tajo-client/src/main/java/org/apache/tajo/cli/CopyrightCommand.java
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/CopyrightCommand.java
@@ -18,13 +18,9 @@
 
 package org.apache.tajo.cli;
 
-import org.apache.tajo.client.TajoClient;
-
-import java.io.PrintWriter;
-
 public class CopyrightCommand extends TajoShellCommand {
-  public CopyrightCommand(TajoClient client, PrintWriter sout) {
-    super(client, sout);
+  public CopyrightCommand(TajoCli.TajoCliContext context) {
+    super(context);
   }
 
   @Override
@@ -34,8 +30,8 @@ public class CopyrightCommand extends TajoShellCommand {
 
   @Override
   public void invoke(String[] cmd) throws Exception {
-    sout.println();
-    sout.println(
+    context.getOutput().println();
+    context.getOutput().println(
         "  Licensed to the Apache Software Foundation (ASF) under one\n" +
             "  or more contributor license agreements.  See the NOTICE file\n" +
             "  distributed with this work for additional information\n" +
@@ -51,7 +47,7 @@ public class CopyrightCommand extends TajoShellCommand {
             "   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +
             "   See the License for the specific language governing permissions and\n" +
             "   limitations under the License.");
-    sout.println();
+    context.getOutput().println();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/DescFunctionCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/DescFunctionCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/DescFunctionCommand.java
index e9f4964..c20840b 100644
--- a/tajo-client/src/main/java/org/apache/tajo/cli/DescFunctionCommand.java
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/DescFunctionCommand.java
@@ -21,14 +21,12 @@ package org.apache.tajo.cli;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
-import org.apache.tajo.client.TajoClient;
 
-import java.io.PrintWriter;
 import java.util.*;
 
 public class DescFunctionCommand extends TajoShellCommand {
-  public DescFunctionCommand(TajoClient client, PrintWriter sout) {
-    super(client, sout);
+  public DescFunctionCommand(TajoCli.TajoCliContext context) {
+    super(context);
   }
 
   @Override
@@ -77,20 +75,20 @@ public class DescFunctionCommand extends TajoShellCommand {
 
       int index = 0;
       printLeft(" " + name, columnWidths[index++]);
-      sout.print("|");
+      context.getOutput().print("|");
       printLeft(" " + resultDataType, columnWidths[index++]);
-      sout.print("|");
+      context.getOutput().print("|");
       printLeft(" " + arguments, columnWidths[index++]);
-      sout.print("|");
+      context.getOutput().print("|");
       printLeft(" " + description, columnWidths[index++]);
-      sout.print("|");
+      context.getOutput().print("|");
       printLeft(" " + functionType, columnWidths[index++]);
 
       println();
     }
 
     println();
-    sout.println("(" + functions.size() + ") rows");
+    context.getOutput().println("(" + functions.size() + ") rows");
     println();
 
     if (printDetail && !functions.isEmpty()) {
@@ -105,15 +103,15 @@ public class DescFunctionCommand extends TajoShellCommand {
 
       for (CatalogProtos.FunctionDescProto eachFunction: functionMap.values()) {
         String signature = eachFunction.getReturnType().getType() + " " +
-            CatalogUtil.getCanonicalName(eachFunction.getSignature(), eachFunction.getParameterTypesList());
+            CatalogUtil.getCanonicalSignature(eachFunction.getSignature(), eachFunction.getParameterTypesList());
         String fullDescription = eachFunction.getDescription();
         if(eachFunction.getDetail() != null && !eachFunction.getDetail().isEmpty()) {
           fullDescription += "\n" + eachFunction.getDetail();
         }
 
-        sout.println("Function:    " + signature);
-        sout.println("Description: " + fullDescription);
-        sout.println("Example:\n" + eachFunction.getExample());
+        context.getOutput().println("Function:    " + signature);
+        context.getOutput().println("Description: " + fullDescription);
+        context.getOutput().println("Example:\n" + eachFunction.getExample());
         println();
       }
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/DescTableCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/DescTableCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/DescTableCommand.java
index bdeb173..0907b56 100644
--- a/tajo-client/src/main/java/org/apache/tajo/cli/DescTableCommand.java
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/DescTableCommand.java
@@ -21,17 +21,15 @@ package org.apache.tajo.cli;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
-import org.apache.tajo.client.TajoClient;
 import org.apache.tajo.util.FileUtil;
 import org.apache.tajo.util.TUtil;
 
-import java.io.PrintWriter;
 import java.util.List;
 import java.util.Map;
 
 public class DescTableCommand extends TajoShellCommand {
-  public DescTableCommand(TajoClient client, PrintWriter sout) {
-    super(client, sout);
+  public DescTableCommand(TajoCli.TajoCliContext context) {
+    super(context);
   }
 
   @Override
@@ -44,17 +42,17 @@ public class DescTableCommand extends TajoShellCommand {
     if (cmd.length == 2) {
       TableDesc desc = client.getTableDesc(cmd[1]);
       if (desc == null) {
-        sout.println("Did not find any relation named \"" + cmd[1] + "\"");
+        context.getOutput().println("Did not find any relation named \"" + cmd[1] + "\"");
       } else {
-        sout.println(toFormattedString(desc));
+        context.getOutput().println(toFormattedString(desc));
       }
     } else if (cmd.length == 1) {
-      List<String> tableList = client.getTableList();
+      List<String> tableList = client.getTableList(null);
       if (tableList.size() == 0) {
-        sout.println("No Relation Found");
+        context.getOutput().println("No Relation Found");
       }
       for (String table : tableList) {
-        sout.println(table);
+        context.getOutput().println(table);
       }
     } else {
       throw new IllegalArgumentException();

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/ExitCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/ExitCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/ExitCommand.java
index dcf8893..1a18841 100644
--- a/tajo-client/src/main/java/org/apache/tajo/cli/ExitCommand.java
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/ExitCommand.java
@@ -18,14 +18,10 @@
 
 package org.apache.tajo.cli;
 
-import org.apache.tajo.client.TajoClient;
-
-import java.io.PrintWriter;
-
 public class ExitCommand extends TajoShellCommand {
 
-  public ExitCommand(TajoClient client, PrintWriter sout) {
-    super(client, sout);
+  public ExitCommand(TajoCli.TajoCliContext context) {
+    super(context);
   }
 
   @Override
@@ -35,7 +31,7 @@ public class ExitCommand extends TajoShellCommand {
 
   @Override
   public void invoke(String[] cmd) throws Exception {
-    sout.println("bye!");
+    context.getOutput().println("bye!");
     System.exit(0);
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/HelpCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/HelpCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/HelpCommand.java
index 85ba808..a808fc6 100644
--- a/tajo-client/src/main/java/org/apache/tajo/cli/HelpCommand.java
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/HelpCommand.java
@@ -18,13 +18,13 @@
 
 package org.apache.tajo.cli;
 
-import org.apache.tajo.client.TajoClient;
+import org.apache.tajo.TajoConstants;
 
 import java.io.PrintWriter;
 
 public class HelpCommand extends TajoShellCommand {
-  public HelpCommand(TajoClient client, PrintWriter sout) {
-    super(client, sout);
+  public HelpCommand(TajoCli.TajoCliContext context) {
+    super(context);
   }
 
   @Override
@@ -34,6 +34,8 @@ public class HelpCommand extends TajoShellCommand {
 
   @Override
   public void invoke(String[] cmd) throws Exception {
+    String docVersion = getDocumentationVersion();
+    PrintWriter sout = context.getOutput();
     sout.println();
 
     sout.println("General");
@@ -45,22 +47,40 @@ public class HelpCommand extends TajoShellCommand {
     sout.println();
 
     sout.println("Informational");
-    sout.println("  \\d         list tables");
-    sout.println("  \\d  NAME   describe table");
-    sout.println("  \\df        list functions");
-    sout.println("  \\df NAME   describe function");
+    sout.println("  \\l           list databases");
+    sout.println("  \\c           show current database");
+    sout.println("  \\c [DBNAME]  connect to new database");
+    sout.println("  \\d           list tables");
+    sout.println("  \\d [TBNAME]  describe table");
+    sout.println("  \\df          list functions");
+    sout.println("  \\df NAME     describe function");
+    sout.println();
+    sout.println();
+
+    sout.println("Variables");
+    sout.println("  \\set [[NAME] [VALUE]  set session variable or list session variables");
+    sout.println("  \\unset NAME           unset session variable");
     sout.println();
     sout.println();
 
     sout.println("Documentations");
-    sout.println("  tsql guide        http://wiki.apache.org/tajo/tsql");
-    sout.println("  Query language    http://wiki.apache.org/tajo/QueryLanguage");
-    sout.println("  Functions         http://wiki.apache.org/tajo/Functions");
-    sout.println("  Backup & restore  http://wiki.apache.org/tajo/BackupAndRestore");
-    sout.println("  Configuration     http://wiki.apache.org/tajo/Configuration");
+    sout.println("  tsql guide        http://tajo.incubator.apache.org/docs/"+ docVersion +"/cli.html");
+    sout.println("  Query language    http://tajo.incubator.apache.org/docs/"+ docVersion +"/sql_language.html");
+    sout.println("  Functions         http://tajo.incubator.apache.org/docs/"+ docVersion +"/functions.html");
+    sout.println("  Backup & restore  http://tajo.incubator.apache.org/docs/"+ docVersion +"/backup_and_restore.html");
+    sout.println("  Configuration     http://tajo.incubator.apache.org/docs/"+ docVersion +"/configuration.html");
     sout.println();
   }
 
+  private String getDocumentationVersion() {
+    int delimiterIdx = TajoConstants.TAJO_VERSION.indexOf("-");
+    if (delimiterIdx > -1) {
+      return TajoConstants.TAJO_VERSION.substring(0, delimiterIdx);
+    } else {
+      return TajoConstants.TAJO_VERSION;
+    }
+  }
+
   @Override
   public String getUsage() {
     return "";

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/InvalidClientSessionException.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/InvalidClientSessionException.java b/tajo-client/src/main/java/org/apache/tajo/cli/InvalidClientSessionException.java
new file mode 100644
index 0000000..5c6c96e
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/InvalidClientSessionException.java
@@ -0,0 +1,27 @@
+/**
+ * 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.cli;
+
+import com.google.protobuf.ServiceException;
+
+public class InvalidClientSessionException extends ServiceException {
+  public InvalidClientSessionException(String message) {
+    super(message);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/InvalidStatementException.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/InvalidStatementException.java b/tajo-client/src/main/java/org/apache/tajo/cli/InvalidStatementException.java
new file mode 100644
index 0000000..9782e84
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/InvalidStatementException.java
@@ -0,0 +1,25 @@
+/**
+ * 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.cli;
+
+public class InvalidStatementException extends Exception {
+  public InvalidStatementException(String message) {
+    super(message);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/ListDatabaseCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/ListDatabaseCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/ListDatabaseCommand.java
new file mode 100644
index 0000000..199fed2
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/ListDatabaseCommand.java
@@ -0,0 +1,48 @@
+/**
+ * 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.cli;
+
+public class ListDatabaseCommand extends TajoShellCommand {
+
+  public ListDatabaseCommand(TajoCli.TajoCliContext context) {
+    super(context);
+  }
+
+  @Override
+  public String getCommand() {
+    return "\\l";
+  }
+
+  @Override
+  public void invoke(String[] cmd) throws Exception {
+    for (String databaseName : client.getAllDatabaseNames()) {
+      context.getOutput().println(databaseName);
+    }
+  }
+
+  @Override
+  public String getUsage() {
+    return "";
+  }
+
+  @Override
+  public String getDescription() {
+    return "list all databases";
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/ParsedResult.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/ParsedResult.java b/tajo-client/src/main/java/org/apache/tajo/cli/ParsedResult.java
new file mode 100644
index 0000000..fb89678
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/ParsedResult.java
@@ -0,0 +1,47 @@
+/**
+ * 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.cli;
+
+
+public class ParsedResult {
+  public static enum StatementType {
+    META,
+    STATEMENT
+  }
+
+  private final StatementType type;
+  private final String statement;
+
+  public ParsedResult(StatementType type, String statement) {
+    this.type = type;
+    this.statement = statement;
+  }
+
+  public StatementType getType() {
+    return type;
+  }
+
+  public String getStatement() {
+    return statement.trim();
+  }
+
+  public String toString() {
+    return "(" + type.name() + ") " + statement;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/SetCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/SetCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/SetCommand.java
new file mode 100644
index 0000000..8b31d39
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/SetCommand.java
@@ -0,0 +1,61 @@
+/**
+ * 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.cli;
+
+import org.apache.tajo.util.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SetCommand extends TajoShellCommand {
+
+  public SetCommand(TajoCli.TajoCliContext context) {
+    super(context);
+  }
+
+  @Override
+  public String getCommand() {
+    return "\\set";
+  }
+
+  @Override
+  public void invoke(String[] cmd) throws Exception {
+    if (cmd.length == 1) {
+      for (Map.Entry<String, String> entry: client.getAllSessionVariables().entrySet()) {
+        context.getOutput().println(StringUtils.quote(entry.getKey()) + "=" + StringUtils.quote(entry.getValue()));
+      }
+    } else if (cmd.length == 3) {
+      Map<String, String> variables = new HashMap<String, String>();
+      variables.put(cmd[1], cmd[2]);
+      client.updateSessionVariables(variables);
+    } else {
+      context.getOutput().println("usage: \\set [[NAME] VALUE]");
+    }
+  }
+
+  @Override
+  public String getUsage() {
+    return "";
+  }
+
+  @Override
+  public String getDescription() {
+    return "set session variable or shows all session variables";
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/SimpleParser.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/SimpleParser.java b/tajo-client/src/main/java/org/apache/tajo/cli/SimpleParser.java
new file mode 100644
index 0000000..2146df7
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/SimpleParser.java
@@ -0,0 +1,262 @@
+/**
+ * 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.cli;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.tajo.cli.ParsedResult.StatementType.META;
+import static org.apache.tajo.cli.ParsedResult.StatementType.STATEMENT;
+
+/**
+ * This is a parser used in tsql to parse multiple SQL lines into SQL statements.
+ * It helps tsql recognizes the termination of each SQL statement and quotation mark (') while
+ * parses multiple separate lines.
+ */
+public class SimpleParser {
+
+  public static enum ParsingState {
+    TOK_START,     // Start State
+    META,          // Meta Command
+    STATEMENT,     // Statement
+    WITHIN_QUOTE,  // Within Quote
+    COMMENT,
+    INVALID,       // Invalid Statement
+    STATEMENT_EOS, // End State (End of Statement)
+    META_EOS       // End State (End of Statement)
+  }
+
+  ParsingState state = START_STATE;
+  int lineNum;
+  StringBuilder appender = new StringBuilder();
+
+  public static final ParsingState START_STATE = ParsingState.TOK_START;
+
+  /**
+   * <h2>State Machine</h2>
+   * All whitespace are ignored in all cases except for
+   *
+   * <pre>
+   * (start) TOK_START --> META ---------------------> META_EOS
+   *                    |
+   *                    |
+   *                    |
+   *                    |-----------> STATEMENT ----------> STMT_EOS
+   *                                  \       ^
+   *                                  \      /
+   *                                  \-> WITHIN_QUOTE
+   *                                        \    ^
+   *                                        \---/
+   * </pre>
+   */
+
+  public static List<ParsedResult> parseScript(String str) throws InvalidStatementException {
+    SimpleParser parser = new SimpleParser();
+    List<ParsedResult> parsedResults = new ArrayList<ParsedResult>();
+    parsedResults.addAll(parser.parseLines(str));
+    parsedResults.addAll(parser.EOF());
+    return parsedResults;
+  }
+
+  public List<ParsedResult> parseLines(String str) throws InvalidStatementException {
+    List<ParsedResult> statements = new ArrayList<ParsedResult>();
+    int lineStartIdx;
+    int idx = 0;
+    char [] chars = str.toCharArray();
+
+    while(idx < str.length()) {
+
+      // initialization for new statement
+      if (state == ParsingState.TOK_START) {
+        lineNum = 0;
+
+        // ignore all whitespace before start
+        if (Character.isWhitespace(chars[idx])) {
+          idx++;
+          continue;
+        }
+      }
+
+      ////////////////////////////
+      // TOK_START --> META
+      ////////////////////////////
+
+      lineStartIdx = idx;
+
+      if (state == ParsingState.TOK_START && chars[idx] == '\\') {
+        state = ParsingState.META;
+
+        ////////////////////////////
+        // META --> TOK_EOS
+        ////////////////////////////
+        while (state != ParsingState.META_EOS && idx < chars.length) {
+          char character = chars[idx++];
+          if (Character.isWhitespace(character)) {
+            // skip
+          } else if (isEndOfMeta(character)) {
+            state = ParsingState.META_EOS;
+          }
+        }
+
+        if (state == ParsingState.META_EOS) {
+          appender.append(str.subSequence(lineStartIdx, idx - 1).toString());
+        } else {
+          appender.append(str.subSequence(lineStartIdx, idx).toString());
+        }
+
+      } else if (isCommentStart(chars[idx])) {
+        idx++;
+        while (!isLineEnd(chars[idx]) && idx < chars.length) {
+          idx++;
+        }
+      /////////////////////////////////
+      //    TOK_START     -> STATEMENT
+      // or TOK_STATEMENT -> STATEMENT
+      ////////////////////////////////
+      } else if (isStatementContinue() || isStatementStart(chars[idx])) {
+        int endIdx = 0;
+        if (!isStatementContinue()) { // TOK_START -> STATEMENT
+          state = ParsingState.STATEMENT;
+        }
+
+        while (!isTerminateState(state) && idx < chars.length) {
+          char character = chars[idx++];
+
+          if (isEndOfStatement(character)) {
+            state = ParsingState.STATEMENT_EOS;
+            endIdx = idx - 1;
+          } else if (state == ParsingState.STATEMENT && character == '\'') { // TOK_STATEMENT -> WITHIN_QUOTE
+            state = ParsingState.WITHIN_QUOTE;
+
+            if (idx < chars.length) {
+              character = chars[idx++];
+            } else {
+              continue;
+            }
+          }
+
+          if (state == ParsingState.WITHIN_QUOTE) {
+            while(idx < chars.length) {
+              ///////////////////////////////
+              // WITHIN_QUOTE --> STATEMENT
+              ///////////////////////////////
+              if (character == '\'') {
+                state = ParsingState.STATEMENT;
+                break;
+              }
+              character = chars[idx++];
+            }
+            if (state == ParsingState.WITHIN_QUOTE && character == '\'') {
+              state = ParsingState.STATEMENT;
+            }
+          }
+        }
+
+        if (state == ParsingState.STATEMENT_EOS) {
+          appender.append(str.subSequence(lineStartIdx, endIdx).toString());
+        } else {
+          appender.append(str.subSequence(lineStartIdx, idx).toString());
+
+          // if it is not within quote and there is no space between lines, add a space.
+          if (state == ParsingState.STATEMENT && (appender.charAt(appender.length() - 1) != ' ')) {
+            appender.append(" ");
+          }
+        }
+      }
+
+      lineNum++;
+      statements.addAll(doProcessEndOfStatement(state == ParsingState.META));
+    }
+
+    return statements;
+  }
+
+  private static boolean isEndOfMeta(char character) {
+    return character == ';' || character == '\n';
+  }
+
+  private static boolean isEndOfStatement(char character) {
+    return character == ';';
+  }
+
+  private boolean isCommentStart(char character) {
+    return state == ParsingState.TOK_START && character == '-';
+  }
+
+  private boolean isLineEnd(char character) {
+    return character == '\n';
+  }
+
+  private boolean isStatementStart(char character) {
+    return state == ParsingState.TOK_START && (Character.isLetterOrDigit(character));
+  }
+
+  private boolean isStatementContinue() {
+    return state == ParsingState.WITHIN_QUOTE || state == ParsingState.STATEMENT;
+  }
+
+  private List<ParsedResult> doProcessEndOfStatement(boolean endOfFile) throws InvalidStatementException {
+    List<ParsedResult> parsedResults = new ArrayList<ParsedResult>();
+    String errorMessage = "";
+    if (endOfFile) {
+      if (state == ParsingState.META) {
+        state = ParsingState.META_EOS;
+      } else if (state == ParsingState.STATEMENT) {
+        state = ParsingState.STATEMENT_EOS;
+      } else if (state == ParsingState.WITHIN_QUOTE) {
+        state = ParsingState.INVALID;
+        errorMessage = "unterminated quoted string at LINE " + lineNum;
+      }
+    }
+
+    if (isTerminateState(state)) {
+      String statement = appender.toString();
+      if (state == ParsingState.META_EOS) {
+        parsedResults.add(new ParsedResult(META, statement));
+        state = ParsingState.TOK_START;
+      } else if (state == ParsingState.STATEMENT_EOS) {
+        parsedResults.add(new ParsedResult(STATEMENT, statement));
+      } else {
+        throw new InvalidStatementException("ERROR: " + errorMessage);
+      }
+
+      // reset all states
+      appender.delete(0, appender.length());
+      state = START_STATE;
+    }
+
+    return parsedResults;
+  }
+
+  public List<ParsedResult> EOF() throws InvalidStatementException {
+    return doProcessEndOfStatement(true);
+  }
+
+  private static boolean isTerminateState(ParsingState state) {
+    return (state == ParsingState.META_EOS || state == ParsingState.STATEMENT_EOS || state == ParsingState.INVALID);
+  }
+
+  public ParsingState getState() {
+    return state;
+  }
+
+  public String toString() {
+    return "[" + state.name() + "]: " + appender.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/TajoCli.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/TajoCli.java b/tajo-client/src/main/java/org/apache/tajo/cli/TajoCli.java
index 3026d9c..426c115 100644
--- a/tajo-client/src/main/java/org/apache/tajo/cli/TajoCli.java
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/TajoCli.java
@@ -18,11 +18,9 @@
 
 package org.apache.tajo.cli;
 
+import com.google.protobuf.ServiceException;
 import jline.console.ConsoleReader;
-import jline.console.history.FileHistory;
-import jline.console.history.PersistentHistory;
 import org.apache.commons.cli.*;
-import org.apache.commons.lang.StringUtils;
 import org.apache.tajo.QueryId;
 import org.apache.tajo.QueryIdFactory;
 import org.apache.tajo.TajoProtos.QueryState;
@@ -37,29 +35,33 @@ import org.apache.tajo.ipc.ClientProtos;
 import org.apache.tajo.jdbc.TajoResultSet;
 import org.apache.tajo.util.FileUtil;
 
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
+import java.io.*;
 import java.lang.reflect.Constructor;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
+import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
+import static org.apache.tajo.cli.ParsedResult.StatementType.META;
+import static org.apache.tajo.cli.ParsedResult.StatementType.STATEMENT;
+import static org.apache.tajo.cli.SimpleParser.ParsingState;
+
 public class TajoCli {
-  public static final int PRINT_LIMIT = 24;
 
   private final TajoConf conf;
-  private static final Options options;
-
   private TajoClient client;
+  private final TajoCliContext context;
 
+  // Jline and Console related things
   private final ConsoleReader reader;
   private final InputStream sin;
   private final PrintWriter sout;
+  private TajoFileHistory history;
 
-  private final Map<String, TajoShellCommand> commands = new TreeMap<String, TajoShellCommand>();
+  // Current States
+  private String currentDatabase;
 
   private static final Class [] registeredCommands = {
       DescTableCommand.class,
@@ -67,9 +69,16 @@ public class TajoCli {
       HelpCommand.class,
       ExitCommand.class,
       CopyrightCommand.class,
-      VersionCommand.class
+      VersionCommand.class,
+      ConnectDatabaseCommand.class,
+      ListDatabaseCommand.class,
+      SetCommand.class,
+      UnsetCommand.class
   };
+  private final Map<String, TajoShellCommand> commands = new TreeMap<String, TajoShellCommand>();
 
+  public static final int PRINT_LIMIT = 24;
+  private static final Options options;
   private static final String HOME_DIR = System.getProperty("user.home");
   private static final String HISTORY_FILE = ".tajo_history";
 
@@ -79,10 +88,29 @@ public class TajoCli {
     options.addOption("f", "file", true, "execute commands from file, then exit");
     options.addOption("h", "host", true, "Tajo server host");
     options.addOption("p", "port", true, "Tajo server port");
+    options.addOption("help", "help", false, "help");
   }
 
-  public TajoCli(TajoConf c, String [] args,
-                 InputStream in, OutputStream out) throws Exception {
+  public class TajoCliContext {
+
+    public TajoClient getTajoClient() {
+      return client;
+    }
+
+    public void setCurrentDatabase(String databasae) {
+      currentDatabase = databasae;
+    }
+
+    public String getCurrentDatabase() {
+      return currentDatabase;
+    }
+
+    public PrintWriter getOutput() {
+      return sout;
+    }
+  }
+
+  public TajoCli(TajoConf c, String [] args, InputStream in, OutputStream out) throws Exception {
     this.conf = new TajoConf(c);
     this.sin = in;
     this.reader = new ConsoleReader(sin, out);
@@ -91,6 +119,10 @@ public class TajoCli {
     CommandLineParser parser = new PosixParser();
     CommandLine cmd = parser.parse(options, args);
 
+    if (cmd.hasOption("help")) {
+      printUsage();
+    }
+
     String hostName = null;
     Integer port = null;
     if (cmd.hasOption("h")) {
@@ -100,6 +132,11 @@ public class TajoCli {
       port = Integer.parseInt(cmd.getOptionValue("p"));
     }
 
+    String baseDatabase = null;
+    if (cmd.getArgList().size() > 0) {
+      baseDatabase = (String) cmd.getArgList().get(0);
+    }
+
     // if there is no "-h" option,
     if(hostName == null) {
       if (conf.getVar(ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS) != null) {
@@ -121,24 +158,26 @@ public class TajoCli {
       System.exit(-1);
     } else if (hostName != null && port != null) {
       conf.setVar(ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS, hostName+":"+port);
-      client = new TajoClient(conf);
+      client = new TajoClient(conf, baseDatabase);
     } else if (hostName == null && port == null) {
-      client = new TajoClient(conf);
+      client = new TajoClient(conf, baseDatabase);
     }
 
+    context = new TajoCliContext();
+    context.setCurrentDatabase(client.getCurrentDatabase());
     initHistory();
     initCommands();
 
     if (cmd.hasOption("c")) {
-      executeStatements(cmd.getOptionValue("c"));
+      executeScript(cmd.getOptionValue("c"));
       sout.flush();
       System.exit(0);
     }
     if (cmd.hasOption("f")) {
       File sqlFile = new File(cmd.getOptionValue("f"));
       if (sqlFile.exists()) {
-        String contents = FileUtil.readTextFile(new File(cmd.getOptionValue("f")));
-        executeStatements(contents);
+        String script = FileUtil.readTextFile(new File(cmd.getOptionValue("f")));
+        executeScript(script);
         sout.flush();
         System.exit(0);
       } else {
@@ -146,13 +185,16 @@ public class TajoCli {
         System.exit(-1);
       }
     }
+
+    addShutdownHook();
   }
 
   private void initHistory() {
     try {
       String historyPath = HOME_DIR + File.separator + HISTORY_FILE;
       if ((new File(HOME_DIR)).exists()) {
-        reader.setHistory(new FileHistory(new File(historyPath)));
+        history = new TajoFileHistory(new File(historyPath));
+        reader.setHistory(history);
       } else {
         System.err.println("ERROR: home directory : '" + HOME_DIR +"' does not exist.");
       }
@@ -165,8 +207,8 @@ public class TajoCli {
     for (Class clazz : registeredCommands) {
       TajoShellCommand cmd = null;
       try {
-         Constructor cons = clazz.getConstructor(new Class[] {TajoClient.class, PrintWriter.class});
-         cmd = (TajoShellCommand) cons.newInstance(client, sout);
+         Constructor cons = clazz.getConstructor(new Class[] {TajoCliContext.class});
+         cmd = (TajoShellCommand) cons.newInstance(context);
       } catch (Exception e) {
         System.err.println(e.getMessage());
         System.exit(-1);
@@ -175,160 +217,114 @@ public class TajoCli {
     }
   }
 
-  public int runShell() throws Exception {
+  private void addShutdownHook() {
+    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          history.flush();
+        } catch (IOException e) {
+        }
+        client.close();
+      }
+    }));
+  }
+
+  private String updatePrompt(ParsingState state) throws ServiceException {
+    if (state == ParsingState.WITHIN_QUOTE) {
+      return "'";
+    } else if (state == ParsingState.TOK_START) {
+      return context.getCurrentDatabase();
+    } else {
+      return "";
+    }
+  }
 
-    String raw;
+  public int runShell() throws Exception {
     String line;
-    StringBuffer accumulatedLine = new StringBuffer();
-    String prompt = "tajo";
-    String curPrompt = prompt;
-    boolean newStatement = true;
+    String currentPrompt = context.getCurrentDatabase();
     int code = 0;
 
     sout.write("Try \\? for help.\n");
-    while((raw = reader.readLine(curPrompt + "> ")) != null) {
-      // each accumulated line has a space delimiter
-      if (accumulatedLine.length() > 0) {
-        accumulatedLine.append(' ');
-      }
-
-      line = raw.trim();
 
-      if (line.length() == 0) { // if empty line
-        continue;
+    SimpleParser parser = new SimpleParser();
+    while((line = reader.readLine(currentPrompt + "> ")) != null) {
 
-      } else if (line.charAt(0) == '/') { // warning for legacy usage
-        printInvalidCommand(line);
+      if (line.equals("")) {
         continue;
+      }
 
-      } else if (line.charAt(0) == '\\') { // command mode
-        ((PersistentHistory)reader.getHistory()).flush();
-        executeCommand(line);
-
-      } else if (line.endsWith(";") && !line.endsWith("\\;")) {
-
-        // remove a trailing newline
-        line = StringUtils.chomp(line).trim();
-
-        // get a punctuated statement
-        String punctuated = accumulatedLine + line;
-
-        if (!newStatement) {
-          // why do two lines are removed?
-          // First history line indicates an accumulated line.
-          // Second history line is a just typed line.
-          reader.getHistory().removeLast();
-          reader.getHistory().removeLast();
-          reader.getHistory().add(punctuated);
-          ((PersistentHistory)reader.getHistory()).flush();
-        }
-
-        code = executeStatements(punctuated);
-
-        // reset accumulated lines
-        newStatement = true;
-        accumulatedLine = new StringBuffer();
-        curPrompt = prompt;
-
-      } else {
-        line = StringUtils.chomp(raw).trim();
-
-        // accumulate a line
-        accumulatedLine.append(line);
+      List<ParsedResult> parsedResults = parser.parseLines(line);
 
-        // replace the latest line with a accumulated line
-        if (!newStatement) { // if this is not first line, remove one more line.
-          reader.getHistory().removeLast();
-        } else {
-          newStatement = false;
+      if (parsedResults.size() > 0) {
+        for (ParsedResult parsed : parsedResults) {
+          history.addStatement(parsed.getStatement() + (parsed.getType() == STATEMENT ? ";":""));
         }
-        reader.getHistory().removeLast();
-        reader.getHistory().add(accumulatedLine.toString());
-
-        // use an alternative prompt during accumulating lines
-        curPrompt = StringUtils.repeat(" ", prompt.length());
-        continue;
       }
+      executeParsedResults(parsedResults);
+      currentPrompt = updatePrompt(parser.getState());
     }
     return code;
   }
 
-  private void invokeCommand(String [] cmds) {
-    // this command should be moved to GlobalEngine
-    TajoShellCommand invoked;
-    try {
-      invoked = commands.get(cmds[0]);
-      invoked.invoke(cmds);
-    } catch (Throwable t) {
-      sout.println(t.getMessage());
+  private void executeParsedResults(Collection<ParsedResult> parsedResults) throws Exception {
+    for (ParsedResult parsedResult : parsedResults) {
+      if (parsedResult.getType() == META) {
+        executeMetaCommand(parsedResult.getStatement());
+      } else {
+        executeQuery(parsedResult.getStatement());
+      }
     }
   }
 
-  public int executeStatements(String line) throws Exception {
+  public int executeMetaCommand(String line) throws Exception {
+    String [] metaCommands = line.split(";");
+    for (String metaCommand : metaCommands) {
+      String arguments [];
+      arguments = metaCommand.split(" ");
 
-    // TODO - comment handling and multi line queries should be improved
-    // remove comments
-    String filtered = line.replaceAll("--[^\\r\\n]*", "").trim();
+      TajoShellCommand invoked = commands.get(arguments[0]);
+      if (invoked == null) {
+        printInvalidCommand(arguments[0]);
+        return -1;
+      }
 
-    String stripped;
-    for (String statement : filtered.split(";")) {
-      stripped = StringUtils.chomp(statement);
-      if (StringUtils.isBlank(stripped)) {
-        continue;
+      try {
+        invoked.invoke(arguments);
+      } catch (IllegalArgumentException ige) {
+        sout.println(ige.getMessage());
+      } catch (Exception e) {
+        sout.println(e.getMessage());
       }
+    }
 
-      String [] cmds = stripped.split(" ");
-      if (cmds[0].equalsIgnoreCase("exit") || cmds[0].equalsIgnoreCase("quit")) {
-        sout.println("\n\nbye!");
-        sout.flush();
-        ((PersistentHistory)this.reader.getHistory()).flush();
-        System.exit(0);
-      } else if (cmds[0].equalsIgnoreCase("detach") && cmds.length > 1 && cmds[1].equalsIgnoreCase("table")) {
-        // this command should be moved to GlobalEngine
-        invokeCommand(cmds);
-      } else if (cmds[0].equalsIgnoreCase("explain") && cmds.length > 1) {
-        String sql = stripped.substring(8);
-        ClientProtos.ExplainQueryResponse response = client.explainQuery(sql);
-        if (response == null) {
-          sout.println("response is null");
+    return 0;
+  }
+
+  private void executeQuery(String statement) throws ServiceException {
+    ClientProtos.GetQueryStatusResponse response = client.executeQuery(statement);
+    if (response == null) {
+      sout.println("response is null");
+    }
+    else if (response.getResultCode() == ClientProtos.ResultCode.OK) {
+      QueryId queryId = null;
+      try {
+        queryId = new QueryId(response.getQueryId());
+        if (queryId.equals(QueryIdFactory.NULL_QUERY_ID)) {
+          sout.println("OK");
         } else {
-          if (response.hasExplain()) {
-            sout.println(response.getExplain());
-          } else {
-            if (response.hasErrorMessage()) {
-              sout.println(response.getErrorMessage());
-            } else {
-              sout.println("No Explain");
-            }
-          }
+          waitForQueryCompleted(queryId);
         }
-      } else { // submit a query to TajoMaster
-        ClientProtos.GetQueryStatusResponse response = client.executeQuery(stripped);
-        if (response == null) {
-          sout.println("response is null");
-        }
-        else if (response.getResultCode() == ClientProtos.ResultCode.OK) {
-          QueryId queryId = null;
-          try {
-            queryId = new QueryId(response.getQueryId());
-            if (queryId.equals(QueryIdFactory.NULL_QUERY_ID)) {
-              sout.println("OK");
-            } else {
-              waitForQueryCompleted(queryId);
-            }
-          } finally {
-            if(queryId != null) {
-              client.closeQuery(queryId);
-            }
-          }
-        } else {
-          if (response.hasErrorMessage()) {
-            sout.println(response.getErrorMessage());
-          }
+      } finally {
+        if(queryId != null) {
+          client.closeQuery(queryId);
         }
       }
+    } else {
+      if (response.hasErrorMessage()) {
+        sout.println(response.getErrorMessage());
+      }
     }
-    return 0;
   }
 
   private void waitForQueryCompleted(QueryId queryId) {
@@ -453,33 +449,15 @@ public class TajoCli {
     }
   }
 
-  private void printUsage() {
-    HelpFormatter formatter = new HelpFormatter();
-    formatter.printHelp( "tajo cli [options]", options );
+  public int executeScript(String script) throws Exception {
+    List<ParsedResult> results = SimpleParser.parseScript(script);
+    executeParsedResults(results);
+    return 0;
   }
 
-  public int executeCommand(String line) throws Exception {
-    String [] metaCommands = line.split(";");
-    for (String metaCommand : metaCommands) {
-      String arguments [];
-      arguments = metaCommand.split(" ");
-
-      TajoShellCommand invoked = commands.get(arguments[0]);
-      if (invoked == null) {
-        printInvalidCommand(arguments[0]);
-        return -1;
-      }
-
-      try {
-        invoked.invoke(arguments);
-      } catch (IllegalArgumentException ige) {
-        sout.println(ige.getMessage());
-      } catch (Exception e) {
-        sout.println(e.getMessage());
-      }
-    }
-
-    return 0;
+  private void printUsage() {
+    HelpFormatter formatter = new HelpFormatter();
+    formatter.printHelp( "tsql [options] [database]", options );
   }
 
   private void printInvalidCommand(String command) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/TajoFileHistory.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/TajoFileHistory.java b/tajo-client/src/main/java/org/apache/tajo/cli/TajoFileHistory.java
new file mode 100644
index 0000000..3257f28
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/TajoFileHistory.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.cli;
+
+import jline.console.history.FileHistory;
+
+import java.io.File;
+import java.io.IOException;
+
+public class TajoFileHistory extends FileHistory {
+
+  public TajoFileHistory(File file) throws IOException {
+    super(file);
+  }
+
+  public void add(CharSequence item) {
+    // skip add
+  }
+
+  public void addStatement(String item) {
+    internalAdd(item);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/TajoShellCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/TajoShellCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/TajoShellCommand.java
index 2b61068..1ea2893 100644
--- a/tajo-client/src/main/java/org/apache/tajo/cli/TajoShellCommand.java
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/TajoShellCommand.java
@@ -21,37 +21,33 @@ package org.apache.tajo.cli;
 import org.apache.tajo.client.TajoClient;
 import org.apache.tajo.conf.TajoConf;
 
-import java.io.PrintWriter;
-
 public abstract class TajoShellCommand {
   public abstract String getCommand();
   public abstract void invoke(String [] command) throws Exception;
   public abstract String getUsage();
   public abstract String getDescription();
 
+  protected TajoCli.TajoCliContext context;
   protected TajoClient client;
-  protected PrintWriter sout;
-
   protected int maxColumn;
 
-  public TajoShellCommand(TajoClient client, PrintWriter sout) {
-    this.client = client;
-    this.sout = sout;
-
-    maxColumn = client.getConf().getIntVar(TajoConf.ConfVars.CLI_MAX_COLUMN);
+  public TajoShellCommand(TajoCli.TajoCliContext context) {
+    maxColumn = context.getTajoClient().getConf().getIntVar(TajoConf.ConfVars.CLI_MAX_COLUMN);
+    this.context = context;
+    client = context.getTajoClient();
   }
 
   protected void println() {
-    this.sout.println();
+    context.getOutput().println();
   }
 
   protected void printLeft(String message, int columnWidth) {
     int messageLength = message.length();
 
     if(messageLength >= columnWidth) {
-      sout.print(message.substring(0, columnWidth - 1));
+      context.getOutput().print(message.substring(0, columnWidth - 1));
     } else {
-      sout.print(message);
+      context.getOutput().print(message);
       print(' ', columnWidth - messageLength - 1);
     }
   }
@@ -60,12 +56,12 @@ public abstract class TajoShellCommand {
     int messageLength = message.length();
 
     if(messageLength > columnWidth) {
-      sout.print(message.substring(0, columnWidth - 1));
+      context.getOutput().print(message.substring(0, columnWidth - 1));
     } else {
       int numPadding = (columnWidth - messageLength)/2;
 
       print(' ', numPadding);
-      sout.print(message);
+      context.getOutput().print(message);
       print(' ', numPadding);
     }
     if(warp) {
@@ -79,7 +75,7 @@ public abstract class TajoShellCommand {
 
   protected void print(char c, int count) {
     for(int i = 0; i < count; i++) {
-      sout.print(c);
+      context.getOutput().print(c);
     }
   }
 
@@ -98,7 +94,7 @@ public abstract class TajoShellCommand {
 
     String prefix = "";
     for(int i = 0; i < headers.length; i++) {
-      sout.print(prefix);
+      context.getOutput().print(prefix);
       printLeft(" " + headers[i], columnWidths[i]);
       prefix = "|";
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/UnsetCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/UnsetCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/UnsetCommand.java
new file mode 100644
index 0000000..7b7685f
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/UnsetCommand.java
@@ -0,0 +1,52 @@
+/**
+ * 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.cli;
+
+import com.google.common.collect.Lists;
+
+public class UnsetCommand extends TajoShellCommand {
+
+  public UnsetCommand(TajoCli.TajoCliContext context) {
+    super(context);
+  }
+
+  @Override
+  public String getCommand() {
+    return "\\unset";
+  }
+
+  @Override
+  public void invoke(String[] cmd) throws Exception {
+    if (cmd.length == 2) {
+      client.unsetSessionVariables(Lists.newArrayList(cmd[1]));
+    } else {
+      context.getOutput().println("usage: \\unset NAME");
+    }
+  }
+
+  @Override
+  public String getUsage() {
+    return "";
+  }
+
+  @Override
+  public String getDescription() {
+    return "unset a session variable";
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/cli/VersionCommand.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/cli/VersionCommand.java b/tajo-client/src/main/java/org/apache/tajo/cli/VersionCommand.java
index 744c786..b62c425 100644
--- a/tajo-client/src/main/java/org/apache/tajo/cli/VersionCommand.java
+++ b/tajo-client/src/main/java/org/apache/tajo/cli/VersionCommand.java
@@ -19,14 +19,11 @@
 package org.apache.tajo.cli;
 
 import org.apache.tajo.TajoConstants;
-import org.apache.tajo.client.TajoClient;
-
-import java.io.PrintWriter;
 
 public class VersionCommand extends TajoShellCommand {
 
-  public VersionCommand(TajoClient client, PrintWriter sout) {
-    super(client, sout);
+  public VersionCommand(TajoCli.TajoCliContext context) {
+    super(context);
   }
 
   @Override
@@ -36,7 +33,7 @@ public class VersionCommand extends TajoShellCommand {
 
   @Override
   public void invoke(String[] cmd) throws Exception {
-    sout.println(TajoConstants.TAJO_VERSION);
+    context.getOutput().println(TajoConstants.TAJO_VERSION);
   }
 
   @Override


[05/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/QueryTestCaseBase.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/QueryTestCaseBase.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/QueryTestCaseBase.java
index ddb9952..a5c5d78 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/QueryTestCaseBase.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/QueryTestCaseBase.java
@@ -19,6 +19,8 @@
 package org.apache.tajo;
 
 import com.google.protobuf.ServiceException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.algebra.CreateTable;
@@ -27,15 +29,16 @@ import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.algebra.OpType;
 import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.CatalogService;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.cli.ParsedResult;
+import org.apache.tajo.cli.SimpleParser;
 import org.apache.tajo.client.TajoClient;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.engine.parser.SQLAnalyzer;
 import org.apache.tajo.storage.StorageUtil;
 import org.apache.tajo.util.FileUtil;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
+import org.junit.*;
 import org.junit.rules.TestName;
 
 import java.io.File;
@@ -44,8 +47,7 @@ import java.net.URL;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
 
 import static org.junit.Assert.*;
 
@@ -118,13 +120,13 @@ import static org.junit.Assert.*;
  * </ul>
  */
 public class QueryTestCaseBase {
-
+  private static final Log LOG = LogFactory.getLog(QueryTestCaseBase.class);
   protected static final TpchTestBase testBase;
   protected static final TajoTestingCluster testingCluster;
   protected static TajoConf conf;
   protected static TajoClient client;
-  protected static CatalogService catalog;
-  protected static SQLAnalyzer sqlParser = new SQLAnalyzer();
+  protected static final CatalogService catalog;
+  protected static final SQLAnalyzer sqlParser = new SQLAnalyzer();
 
   /** the base path of dataset directories */
   protected static final Path datasetBasePath;
@@ -147,14 +149,15 @@ public class QueryTestCaseBase {
   }
 
   /** It transiently contains created tables for the running test class. */
-  private static Set<String> createdTableSet = new HashSet<String>();
+  private static String currentDatabase;
+  private static Set<String> createdTableGlobalSet = new HashSet<String>();
   // queries and results directory corresponding to subclass class.
   private Path currentQueryPath;
   private Path currentResultPath;
   private Path currentDatasetPath;
 
   // for getting a method name
-  @Rule public TestName name= new TestName();
+  @Rule public TestName name = new TestName();
 
   @BeforeClass
   public static void setUpClass() throws IOException {
@@ -164,19 +167,56 @@ public class QueryTestCaseBase {
 
   @AfterClass
   public static void tearDownClass() throws ServiceException {
-    for (String tableName : createdTableSet) {
-      client.dropTable(tableName, false);
+    for (String tableName : createdTableGlobalSet) {
+      client.updateQuery("DROP TABLE IF EXISTS " +tableName + " PURGE");
+    }
+    createdTableGlobalSet.clear();
+
+    // if the current database is "default", shouldn't drop it.
+    if (!currentDatabase.equals(TajoConstants.DEFAULT_DATABASE_NAME)) {
+      for (String tableName : catalog.getAllTableNames(currentDatabase)) {
+        client.updateQuery("DROP TABLE IF EXISTS " +tableName + " PURGE");
+      }
+
+      client.selectDatabase(TajoConstants.DEFAULT_DATABASE_NAME);
+      client.dropDatabase(currentDatabase);
     }
-    createdTableSet.clear();
     client.close();
   }
 
-  @Before
-  public void setUp() {
+  public QueryTestCaseBase() {
+    this.currentDatabase = getClass().getSimpleName();
+    init();
+  }
+
+  public QueryTestCaseBase(String currentDatabase) {
+    this.currentDatabase = currentDatabase;
+    init();
+  }
+
+  private void init() {
     String className = getClass().getSimpleName();
     currentQueryPath = new Path(queryBasePath, className);
     currentResultPath = new Path(resultBasePath, className);
     currentDatasetPath = new Path(datasetBasePath, className);
+
+    try {
+      // if the current database is "default", we don't need create it because it is already prepated at startup time.
+      if (!currentDatabase.equals(TajoConstants.DEFAULT_DATABASE_NAME)) {
+        client.updateQuery("CREATE DATABASE IF NOT EXISTS " + currentDatabase);
+      }
+      client.selectDatabase(currentDatabase);
+    } catch (ServiceException e) {
+      e.printStackTrace();
+    }
+  }
+
+  protected TajoClient getClient() {
+    return client;
+  }
+
+  public String getCurrentDatabase() {
+    return currentDatabase;
   }
 
   protected ResultSet executeString(String sql) throws Exception {
@@ -204,7 +244,12 @@ public class QueryTestCaseBase {
     Path queryFilePath = getQueryFilePath(queryFileName);
     FileSystem fs = currentQueryPath.getFileSystem(testBase.getTestingCluster().getConfiguration());
     assertTrue(queryFilePath.toString() + " existence check", fs.exists(queryFilePath));
-    ResultSet result = testBase.execute(FileUtil.readTextFile(new File(queryFilePath.toUri())));
+
+    List<ParsedResult> parsedResults = SimpleParser.parseScript(FileUtil.readTextFile(new File(queryFilePath.toUri())));
+    if (parsedResults.size() > 1) {
+      assertNotNull("This script \"" + queryFileName + "\" includes two or more queries");
+    }
+    ResultSet result = client.executeQueryAndGetResult(parsedResults.get(0).getStatement());
     assertNotNull("Query succeeded test", result);
     return result;
   }
@@ -264,10 +309,22 @@ public class QueryTestCaseBase {
     }
   }
 
+  public void assertDatabaseExists(String databaseName) throws ServiceException {
+    assertTrue(client.existDatabase(databaseName));
+  }
+
+  public void assertDatabaseNotExists(String databaseName) throws ServiceException {
+    assertTrue(!client.existDatabase(databaseName));
+  }
+
   public void assertTableExists(String tableName) throws ServiceException {
     assertTrue(client.existTable(tableName));
   }
 
+  public void assertTableNotExists(String tableName) throws ServiceException {
+    assertTrue(!client.existTable(tableName));
+  }
+
   /**
    * It transforms a ResultSet instance to rows represented as strings.
    *
@@ -316,7 +373,7 @@ public class QueryTestCaseBase {
     return StorageUtil.concatPath(currentDatasetPath, fileName);
   }
 
-  public String executeDDL(String ddlFileName, @Nullable String [] args) throws Exception {
+  public List<String> executeDDL(String ddlFileName, @Nullable String [] args) throws Exception {
     return executeDDL(ddlFileName, null, true, args);
   }
 
@@ -337,17 +394,16 @@ public class QueryTestCaseBase {
    * @param dataFileName A file name, containing data rows, which columns have to be separated by vertical bar '|'.
    *                     This file name is used for replacing some format string indicating an external table location.
    * @param args A list of arguments, each of which is used to replace corresponding variable which has a form of ${i}.
-   * @return The table name created
+   * @return The table names created
    */
-  public String executeDDL(String ddlFileName, @Nullable String dataFileName, @Nullable String ... args)
+  public List<String> executeDDL(String ddlFileName, @Nullable String dataFileName, @Nullable String ... args)
       throws Exception {
 
     return executeDDL(ddlFileName, dataFileName, true, args);
   }
 
-  private String executeDDL(String ddlFileName, @Nullable String dataFileName, boolean isLocalTable,
-                            @Nullable String [] args)
-      throws Exception {
+  private List<String> executeDDL(String ddlFileName, @Nullable String dataFileName, boolean isLocalTable,
+                            @Nullable String [] args) throws Exception {
 
     Path ddlFilePath = new Path(currentQueryPath, ddlFileName);
     FileSystem fs = ddlFilePath.getFileSystem(conf);
@@ -360,33 +416,43 @@ public class QueryTestCaseBase {
     }
     String compiled = compileTemplate(template, dataFilePath, args);
 
-    // parse a statement
-    Expr expr = sqlParser.parse(compiled);
-    assertNotNull(ddlFilePath + " cannot be parsed", expr);
-
-    String tableName = null;
-    if (expr.getType() == OpType.CreateTable) {
-      CreateTable createTable = (CreateTable) expr;
-      tableName = createTable.getTableName();
-      client.updateQuery(compiled);
-      assertTrue("table '" + tableName  + "' creation check", client.existTable(tableName));
-      if (isLocalTable) {
-        createdTableSet.add(tableName);
-      }
-    } else if (expr.getType() == OpType.DropTable) {
-      DropTable dropTable = (DropTable) expr;
-      tableName = dropTable.getTableName();
-      assertTrue("table '" + tableName + "' existence check", client.existTable(tableName));
-      client.updateQuery(compiled);
-      assertFalse("table '" + tableName + "' dropped check", client.existTable(tableName));
-      if (isLocalTable) {
-        createdTableSet.remove(tableName);
+    List<ParsedResult> parsedResults = SimpleParser.parseScript(compiled);
+    List<String> createdTableNames = new ArrayList<String>();
+
+    for (ParsedResult parsedResult : parsedResults) {
+      // parse a statement
+      Expr expr = sqlParser.parse(parsedResult.getStatement());
+      assertNotNull(ddlFilePath + " cannot be parsed", expr);
+
+      if (expr.getType() == OpType.CreateTable) {
+        CreateTable createTable = (CreateTable) expr;
+        String tableName = createTable.getTableName();
+        assertTrue("Table creation is failed.", client.updateQuery(parsedResult.getStatement()));
+        TableDesc createdTable = client.getTableDesc(tableName);
+        String createdTableName = createdTable.getName();
+
+        assertTrue("table '" + createdTableName  + "' creation check", client.existTable(createdTableName));
+        if (isLocalTable) {
+          createdTableGlobalSet.add(createdTableName);
+          createdTableNames.add(tableName);
+        }
+      } else if (expr.getType() == OpType.DropTable) {
+        DropTable dropTable = (DropTable) expr;
+        String tableName = dropTable.getTableName();
+        assertTrue("table '" + tableName + "' existence check",
+            client.existTable(CatalogUtil.buildFQName(currentDatabase, tableName)));
+        assertTrue("table drop is failed.", client.updateQuery(parsedResult.getStatement()));
+        assertFalse("table '" + tableName + "' dropped check",
+            client.existTable(CatalogUtil.buildFQName(currentDatabase, tableName)));
+        if (isLocalTable) {
+          createdTableGlobalSet.remove(tableName);
+        }
+      } else {
+        assertTrue(ddlFilePath + " is not a Create or Drop Table statement", false);
       }
-    } else {
-      assertTrue(ddlFilePath + " is not a Create or Drop Table statement", false);
     }
 
-    return tableName;
+    return createdTableNames;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TajoTestingCluster.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TajoTestingCluster.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TajoTestingCluster.java
index 323a7cf..e24106a 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TajoTestingCluster.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/TajoTestingCluster.java
@@ -80,6 +80,11 @@ public class TajoTestingCluster {
 	 */
 	public static final String DEFAULT_TEST_DIRECTORY = "target/test-data";
 
+  /**
+   * True If HCatalogStore is used. Otherwise, it is FALSE.
+   */
+  public Boolean isHCatalogStoreUse = false;
+
   public TajoTestingCluster() {
     this.conf = new TajoConf();
     initPropertiesAndConfigs();
@@ -260,6 +265,10 @@ public class TajoTestingCluster {
     return this.catalogServer;
   }
 
+  public boolean isHCatalogStoreRunning() {
+    return isHCatalogStoreUse;
+  }
+
   ////////////////////////////////////////////////////////
   // Tajo Cluster Section
   ////////////////////////////////////////////////////////
@@ -271,9 +280,6 @@ public class TajoTestingCluster {
     c.setVar(ConfVars.TAJO_MASTER_UMBILICAL_RPC_ADDRESS, "localhost:0");
     c.setVar(ConfVars.RESOURCE_TRACKER_RPC_ADDRESS, "localhost:0");
     c.setVar(ConfVars.WORKER_PEER_RPC_ADDRESS, "localhost:0");
-    c.setVar(ConfVars.CATALOG_ADDRESS, "localhost:0");
-    c.set(CatalogConstants.STORE_CLASS, "org.apache.tajo.catalog.store.MemStore");
-    c.set(CatalogConstants.CATALOG_URI, "jdbc:derby:" + testBuildDir.getAbsolutePath() + "/db");
     c.setVar(ConfVars.WORKER_TEMPORAL_DIR, "file://" + testBuildDir.getAbsolutePath() + "/tajo-localdir");
 
     LOG.info("derby repository is set to "+conf.get(CatalogConstants.CATALOG_URI));
@@ -282,10 +288,11 @@ public class TajoTestingCluster {
       c.setVar(ConfVars.ROOT_DIR,
           getMiniDFSCluster().getFileSystem().getUri() + "/tajo");
     } else {
-      c.setVar(ConfVars.ROOT_DIR,
-          clusterTestBuildDir.getAbsolutePath() + "/tajo");
+      c.setVar(ConfVars.ROOT_DIR, clusterTestBuildDir.getAbsolutePath() + "/tajo");
     }
 
+    setupCatalogForTesting(c, clusterTestBuildDir);
+
     tajoMaster = new TajoMaster();
     tajoMaster.init(c);
     tajoMaster.start();
@@ -304,6 +311,51 @@ public class TajoTestingCluster {
       startTajoWorkers(numSlaves);
     }
     LOG.info("Mini Tajo cluster is up");
+    LOG.info("====================================================================================");
+    LOG.info("=                           MiniTajoCluster starts up                              =");
+    LOG.info("====================================================================================");
+    LOG.info("= * Master Address: " + tajoMaster.getMasterName());
+    LOG.info("= * CatalogStore: " + tajoMaster.getCatalogServer().getStoreClassName());
+    LOG.info("------------------------------------------------------------------------------------");
+    LOG.info("= * Warehouse Dir: " + TajoConf.getWarehouseDir(c));
+    LOG.info("= * Worker Tmp Dir: " + c.getVar(ConfVars.WORKER_TEMPORAL_DIR));
+    LOG.info("====================================================================================");
+  }
+
+  private void setupCatalogForTesting(TajoConf c, File testBuildDir) throws IOException {
+    final String HCATALOG_CLASS_NAME = "org.apache.tajo.catalog.store.HCatalogStore";
+    boolean hcatalogClassExists = false;
+    try {
+      getClass().getClassLoader().loadClass(HCATALOG_CLASS_NAME);
+      hcatalogClassExists = true;
+    } catch (ClassNotFoundException e) {
+      LOG.info("HCatalogStore is not available.");
+    }
+    String driverClass = System.getProperty(CatalogConstants.STORE_CLASS);
+
+    if (hcatalogClassExists &&
+        driverClass != null && driverClass.equals(HCATALOG_CLASS_NAME)) {
+      try {
+        getClass().getClassLoader().loadClass(HCATALOG_CLASS_NAME);
+        String jdbcUri = "jdbc:derby:;databaseName="+ testBuildDir.toURI().getPath()  + "/metastore_db;create=true";
+        c.set("hive.metastore.warehouse.dir", TajoConf.getWarehouseDir(c).toString() + "/default");
+        c.set("javax.jdo.option.ConnectionURL", jdbcUri);
+        c.set(TajoConf.ConfVars.WAREHOUSE_DIR.varname, conf.getVar(ConfVars.WAREHOUSE_DIR));
+        c.set(CatalogConstants.STORE_CLASS, HCATALOG_CLASS_NAME);
+        Path defaultDatabasePath = new Path(TajoConf.getWarehouseDir(c).toString() + "/default");
+        FileSystem fs = defaultDatabasePath.getFileSystem(c);
+        if (!fs.exists(defaultDatabasePath)) {
+          fs.mkdirs(defaultDatabasePath);
+        }
+        isHCatalogStoreUse = true;
+      } catch (ClassNotFoundException cnfe) {
+        throw new IOException(cnfe);
+      }
+    } else { // for derby
+      c.set(CatalogConstants.STORE_CLASS, "org.apache.tajo.catalog.store.MemStore");
+      c.set(CatalogConstants.CATALOG_URI, "jdbc:derby:" + testBuildDir.getAbsolutePath() + "/db");
+    }
+    c.setVar(ConfVars.CATALOG_ADDRESS, "localhost:0");
   }
 
   private void startTajoWorkers(int numSlaves) throws Exception {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/benchmark/TestTPCH.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/benchmark/TestTPCH.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/benchmark/TestTPCH.java
index f0a0812..4ca9b3e 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/benchmark/TestTPCH.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/benchmark/TestTPCH.java
@@ -20,6 +20,7 @@ package org.apache.tajo.benchmark;
 
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
@@ -27,6 +28,11 @@ import java.sql.ResultSet;
 
 @Category(IntegrationTest.class)
 public class TestTPCH extends QueryTestCaseBase {
+
+  public TestTPCH() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public void testQ1OrderBy() throws Exception {
     ResultSet res = executeQuery();

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/cli/TestSimpleParser.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/cli/TestSimpleParser.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/cli/TestSimpleParser.java
new file mode 100644
index 0000000..e524652
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/cli/TestSimpleParser.java
@@ -0,0 +1,164 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.cli;
+
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class TestSimpleParser {
+
+  @Test
+  public final void testMetaCommands() throws InvalidStatementException {
+    List<ParsedResult> res1 = SimpleParser.parseScript("\\d");
+    assertEquals(1, res1.size());
+    assertEquals(ParsedResult.StatementType.META, res1.get(0).getType());
+    assertEquals("\\d", res1.get(0).getStatement());
+
+    List<ParsedResult> res2 = SimpleParser.parseScript("\\d;\\c;\\f;");
+    assertEquals(3, res2.size());
+    assertEquals(ParsedResult.StatementType.META, res2.get(0).getType());
+    assertEquals("\\d", res2.get(0).getStatement());
+    assertEquals(ParsedResult.StatementType.META, res2.get(1).getType());
+    assertEquals("\\c", res2.get(1).getStatement());
+    assertEquals(ParsedResult.StatementType.META, res2.get(2).getType());
+    assertEquals("\\f", res2.get(2).getStatement());
+
+    List<ParsedResult> res3 = SimpleParser.parseScript("\n\t\t  \\d;\n\\c;\t\t\\f  ;");
+    assertEquals(3, res3.size());
+    assertEquals(ParsedResult.StatementType.META, res3.get(0).getType());
+    assertEquals("\\d", res3.get(0).getStatement());
+    assertEquals(ParsedResult.StatementType.META, res3.get(1).getType());
+    assertEquals("\\c", res3.get(1).getStatement());
+    assertEquals(ParsedResult.StatementType.META, res3.get(2).getType());
+    assertEquals("\\f", res3.get(2).getStatement());
+
+    List<ParsedResult> res4 = SimpleParser.parseScript("\\\td;");
+    assertEquals(1, res4.size());
+    assertEquals("\\\td", res4.get(0).getStatement());
+  }
+
+  @Test
+  public final void testStatements() throws InvalidStatementException {
+    List<ParsedResult> res1 = SimpleParser.parseScript("select * from test;");
+    assertEquals(1, res1.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res1.get(0).getType());
+    assertEquals("select * from test", res1.get(0).getStatement());
+
+    List<ParsedResult> res2 = SimpleParser.parseScript("select * from test;");
+    assertEquals(1, res2.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res2.get(0).getType());
+    assertEquals("select * from test", res2.get(0).getStatement());
+
+    List<ParsedResult> res3 = SimpleParser.parseScript("select * from test1;select * from test2;");
+    assertEquals(2, res3.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res3.get(0).getType());
+    assertEquals("select * from test1", res3.get(0).getStatement());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res3.get(1).getType());
+    assertEquals("select * from test2", res3.get(1).getStatement());
+
+    List<ParsedResult> res4 = SimpleParser.parseScript("\t\t\n\rselect * from \ntest1;select * from test2\n;");
+    assertEquals(2, res4.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res4.get(0).getType());
+    assertEquals("select * from \ntest1", res4.get(0).getStatement());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res4.get(1).getType());
+    assertEquals("select * from test2", res4.get(1).getStatement());
+
+    List<ParsedResult> res5 =
+        SimpleParser.parseScript("\t\t\n\rselect * from \ntest1;\\d test;select * from test2;\n\nselect 1;");
+    assertEquals(4, res5.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res5.get(0).getType());
+    assertEquals("select * from \ntest1", res5.get(0).getStatement());
+    assertEquals(ParsedResult.StatementType.META, res5.get(1).getType());
+    assertEquals("\\d test", res5.get(1).getStatement());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res5.get(2).getType());
+    assertEquals("select * from test2", res5.get(2).getStatement());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res5.get(3).getType());
+    assertEquals("select 1", res5.get(3).getStatement());
+  }
+
+  @Test
+  public final void testQuoted() throws InvalidStatementException {
+    List<ParsedResult> res1 = SimpleParser.parseScript("select '\n;' from test;");
+    assertEquals(1, res1.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res1.get(0).getType());
+    assertEquals("select '\n;' from test", res1.get(0).getStatement());
+
+    List<ParsedResult> res2 = SimpleParser.parseScript("select 'abc\nbbc\nddf' from test;");
+    assertEquals(1, res2.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res2.get(0).getType());
+    assertEquals("select 'abc\nbbc\nddf' from test", res2.get(0).getStatement());
+
+    try {
+      SimpleParser.parseScript("select 'abc");
+      assertTrue(false);
+    } catch (InvalidStatementException is) {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public final void testParseLines1() throws InvalidStatementException {
+    String [] lines = {
+      "select abc, ",
+      "bbc from test"
+    };
+    SimpleParser parser = new SimpleParser();
+    List<ParsedResult> result1 = parser.parseLines(lines[0]);
+    assertEquals(0, result1.size());
+    List<ParsedResult> result2 = parser.parseLines(lines[1]);
+    assertEquals(0, result2.size());
+    List<ParsedResult> result3 = parser.EOF();
+    assertEquals(1, result3.size());
+    assertEquals(lines[0] + lines[1], result3.get(0).getStatement());
+  }
+
+  @Test
+  public final void testParseLines2() throws InvalidStatementException {
+    String [] lines = {
+        "select abc, '",
+        "bbc' from test; select * from test3;"
+    };
+    SimpleParser parser = new SimpleParser();
+    List<ParsedResult> result1 = parser.parseLines(lines[0]);
+    assertEquals(0, result1.size());
+    List<ParsedResult> result2 = parser.parseLines(lines[1]);
+    assertEquals(2, result2.size());
+    assertEquals("select abc, 'bbc' from test", result2.get(0).getStatement());
+    assertEquals("select * from test3", result2.get(1).getStatement());
+  }
+
+  @Test
+  public final void testParseLines3() throws InvalidStatementException {
+    String [] lines = {
+        "select abc, 'bbc",
+        "' from test; select * from test3;"
+    };
+    SimpleParser parser = new SimpleParser();
+    List<ParsedResult> result1 = parser.parseLines(lines[0]);
+    assertEquals(0, result1.size());
+    List<ParsedResult> result2 = parser.parseLines(lines[1]);
+    assertEquals(2, result2.size());
+    assertEquals("select abc, 'bbc' from test", result2.get(0).getStatement());
+    assertEquals("select * from test3", result2.get(1).getStatement());
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestDDLBuilder.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestDDLBuilder.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestDDLBuilder.java
index 23b0877..1ae4753 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestDDLBuilder.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestDDLBuilder.java
@@ -27,34 +27,47 @@ import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.util.FileUtil;
 import org.junit.Test;
 
-import java.io.File;
-
 import static org.junit.Assert.assertEquals;
 
 
 public class TestDDLBuilder {
-  @Test
-  public void testBuildDDL() throws Exception {
-    Schema schema = new Schema();
-    schema.addColumn("name", TajoDataTypes.Type.BLOB);
-    schema.addColumn("addr", TajoDataTypes.Type.TEXT);
-    TableMeta meta = CatalogUtil.newTableMeta(CatalogProtos.StoreType.CSV);
-    meta.putOption(CatalogConstants.CSVFILE_DELIMITER, CatalogConstants.CSVFILE_DELIMITER_DEFAULT);
-    meta.putOption(CatalogConstants.COMPRESSION_CODEC, GzipCodec.class.getName());
+  private static final Schema schema1;
+  private static final TableMeta meta1;
+  private static final PartitionMethodDesc partitionMethod1;
 
-    TableDesc desc = new TableDesc("table1", schema, meta, new Path("/table1"));
+  static {
+    schema1 = new Schema();
+    schema1.addColumn("name", TajoDataTypes.Type.BLOB);
+    schema1.addColumn("addr", TajoDataTypes.Type.TEXT);
+
+    meta1 = CatalogUtil.newTableMeta(CatalogProtos.StoreType.CSV);
+    meta1.putOption(CatalogConstants.CSVFILE_DELIMITER, CatalogConstants.CSVFILE_DELIMITER_DEFAULT);
+    meta1.putOption(CatalogConstants.COMPRESSION_CODEC, GzipCodec.class.getName());
 
     Schema expressionSchema = new Schema();
     expressionSchema.addColumn("key", TajoDataTypes.Type.INT4);
     expressionSchema.addColumn("key2", TajoDataTypes.Type.TEXT);
-    PartitionMethodDesc partitionMethod = new PartitionMethodDesc(
+    partitionMethod1 = new PartitionMethodDesc(
+        "db1",
         "table1",
         CatalogProtos.PartitionType.COLUMN,
         "key,key2",
         expressionSchema);
-    desc.setPartitionMethod(partitionMethod);
+  }
 
-    assertEquals(FileUtil.readTextFile(new File("src/test/resources/results/testBuildDDL.result")),
-        DDLBuilder.buildDDL(desc));
+  @Test
+  public void testBuildDDLForExternalTable() throws Exception {
+    TableDesc desc = new TableDesc("db1.table1", schema1, meta1, new Path("/table1"));
+    desc.setPartitionMethod(partitionMethod1);
+    desc.setExternal(true);
+    assertEquals(FileUtil.readTextFileFromResource("results/testBuildDDLForExternalTable.result"),
+        DDLBuilder.buildDDLForExternalTable(desc));
+  }
+
+  @Test
+  public void testBuildDDLForBaseTable() throws Exception {
+    TableDesc desc = new TableDesc("db1.table2", schema1, meta1, new Path("/table1"));
+    assertEquals(FileUtil.readTextFileFromResource("results/testBuildDDLForBaseTable.result"),
+        DDLBuilder.buildDDLForBaseTable(desc));
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java
index 3dac2f1..5949d1b 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/client/TestTajoClient.java
@@ -18,6 +18,8 @@
 
 package org.apache.tajo.client;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import com.google.protobuf.ServiceException;
 import com.sun.org.apache.commons.logging.Log;
@@ -25,6 +27,7 @@ import com.sun.org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.*;
+import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
@@ -32,6 +35,7 @@ import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.ipc.ClientProtos;
 import org.apache.tajo.storage.StorageUtil;
 import org.apache.tajo.util.CommonTestingUtil;
+import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
@@ -39,11 +43,10 @@ import org.junit.experimental.categories.Category;
 import java.io.IOException;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 @Category(IntegrationTest.class)
 public class TestTajoClient {
@@ -60,6 +63,11 @@ public class TestTajoClient {
     testDir = CommonTestingUtil.getTestDir();
   }
 
+  @AfterClass
+  public static void tearDown() throws Exception {
+    client.close();
+  }
+
   private static Path writeTmpTable(String tableName) throws IOException {
     Path tablePath = StorageUtil.concatPath(testDir, tableName);
     BackendTestingUtil.writeTmpTable(conf, tablePath);
@@ -67,6 +75,125 @@ public class TestTajoClient {
   }
 
   @Test
+  public final void testCreateAndDropDatabases() throws ServiceException {
+    int currentNum = client.getAllDatabaseNames().size();
+
+    String prefix = CatalogUtil.normalizeIdentifier("testCreateDatabase_");
+    for (int i = 0; i < 10; i++) {
+      // test allDatabaseNames
+      assertEquals(currentNum + i, client.getAllDatabaseNames().size());
+
+      // test existence
+      assertFalse(client.existDatabase(prefix + i));
+      assertTrue(client.createDatabase(prefix + i));
+      assertTrue(client.existDatabase(prefix + i));
+
+      // test allDatabaseNames
+      assertEquals(currentNum + i + 1, client.getAllDatabaseNames().size());
+      assertTrue(client.getAllDatabaseNames().contains(prefix + i));
+    }
+
+    // test dropDatabase, existDatabase and getAllDatabaseNames()
+    for (int i = 0; i < 10; i++) {
+      assertTrue(client.existDatabase(prefix + i));
+      assertTrue(client.getAllDatabaseNames().contains(prefix + i));
+      assertTrue(client.dropDatabase(prefix + i));
+      assertFalse(client.existDatabase(prefix + i));
+      assertFalse(client.getAllDatabaseNames().contains(prefix + i));
+    }
+
+    assertEquals(currentNum, client.getAllDatabaseNames().size());
+  }
+
+  @Test
+  public final void testCurrentDatabase() throws IOException, ServiceException, InterruptedException {
+    int currentNum = client.getAllDatabaseNames().size();
+    assertEquals(TajoConstants.DEFAULT_DATABASE_NAME, client.getCurrentDatabase());
+
+    assertTrue(client.createDatabase("testcurrentdatabase"));
+    assertEquals(currentNum + 1, client.getAllDatabaseNames().size());
+    assertEquals(TajoConstants.DEFAULT_DATABASE_NAME, client.getCurrentDatabase());
+    assertTrue(client.selectDatabase("testcurrentdatabase"));
+    assertEquals("testcurrentdatabase", client.getCurrentDatabase());
+    assertTrue(client.selectDatabase("default"));
+    assertTrue(client.dropDatabase("testcurrentdatabase"));
+
+    assertEquals(currentNum, client.getAllDatabaseNames().size());
+  }
+
+  @Test
+  public final void testSelectDatabaseToInvalidOne() throws IOException, ServiceException, InterruptedException {
+    int currentNum = client.getAllDatabaseNames().size();
+    assertFalse(client.existDatabase("invaliddatabase"));
+
+    try {
+      assertTrue(client.selectDatabase("invaliddatabase"));
+      assertFalse(true);
+    } catch (Throwable t) {
+      assertFalse(false);
+    }
+
+    assertEquals(currentNum, client.getAllDatabaseNames().size());
+  }
+
+  @Test
+  public final void testDropCurrentDatabase() throws IOException, ServiceException, InterruptedException {
+    int currentNum = client.getAllDatabaseNames().size();
+    assertTrue(client.createDatabase("testdropcurrentdatabase"));
+    assertTrue(client.selectDatabase("testdropcurrentdatabase"));
+    assertEquals("testdropcurrentdatabase", client.getCurrentDatabase());
+
+    try {
+      client.dropDatabase("testdropcurrentdatabase");
+      assertFalse(true);
+    } catch (Throwable t) {
+      assertFalse(false);
+    }
+
+    assertTrue(client.selectDatabase("default"));
+    assertTrue(client.dropDatabase("testdropcurrentdatabase"));
+    assertEquals(currentNum, client.getAllDatabaseNames().size());
+  }
+
+  @Test
+  public final void testSessionVariables() throws IOException, ServiceException, InterruptedException {
+    String prefixName = "key_";
+    String prefixValue = "val_";
+    for (int i = 0; i < 10; i++) {
+      String key = prefixName + i;
+      String val = prefixValue + i;
+
+      assertEquals(i, client.getAllSessionVariables().size());
+      assertFalse(client.getAllSessionVariables().containsKey(key));
+      assertFalse(client.existSessionVariable(key));
+
+      Map<String, String> map = Maps.newHashMap();
+      map.put(key, val);
+      client.updateSessionVariables(map);
+
+      assertEquals(i + 1, client.getAllSessionVariables().size());
+      assertTrue(client.getAllSessionVariables().containsKey(key));
+      assertTrue(client.existSessionVariable(key));
+    }
+
+    int totalSessionVarNum = client.getAllSessionVariables().size();
+
+    for (int i = 0; i < 10; i++) {
+      String key = prefixName + i;
+
+      assertTrue(client.getAllSessionVariables().containsKey(key));
+      assertTrue(client.existSessionVariable(key));
+
+      client.unsetSessionVariables(Lists.newArrayList(key));
+
+      assertFalse(client.getAllSessionVariables().containsKey(key));
+      assertFalse(client.existSessionVariable(key));
+    }
+
+    assertEquals(totalSessionVarNum - 10, client.getAllSessionVariables().size());
+  }
+
+  @Test
   public final void testKillQuery() throws IOException, ServiceException, InterruptedException {
     ClientProtos.GetQueryStatusResponse res = client.executeQuery("select sleep(1) from lineitem");
     Thread.sleep(1000);
@@ -142,7 +269,7 @@ public class TestTajoClient {
     assertTrue(client.existTable(tableName));
 
     client.updateQuery("drop table " + tableName);
-    assertFalse(client.existTable(tableName));
+    assertFalse(client.existTable("tableName"));
     FileSystem localFS = FileSystem.getLocal(conf);
     assertTrue(localFS.exists(tablePath));
   }
@@ -235,7 +362,7 @@ public class TestTajoClient {
     assertTrue(client.existTable(tableName1));
     assertTrue(client.existTable(tableName2));
 
-    Set<String> tables = Sets.newHashSet(client.getTableList());
+    Set<String> tables = Sets.newHashSet(client.getTableList(null));
     assertTrue(tables.contains(tableName1));
     assertTrue(tables.contains(tableName2));
   }
@@ -258,7 +385,7 @@ public class TestTajoClient {
 
     TableDesc desc = client.getTableDesc(tableName1);
     assertNotNull(desc);
-    assertEquals(tableName1, desc.getName());
+    assertEquals(CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, tableName1), desc.getName());
     assertTrue(desc.getStats().getNumBytes() > 0);
   }
 
@@ -424,7 +551,7 @@ public class TestTajoClient {
     assertFalse(client.existTable(tableName));
 
     String sql = "create table " + tableName + " (deptname text, score int4)";
-    sql += "PARTITION BY COLUMN (deptname text)";
+    sql += "PARTITION BY COLUMN (key1 text)";
 
     client.updateQuery(sql);
     assertTrue(client.existTable(tableName));

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
index 2982f83..a89f2bb 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
@@ -18,18 +18,22 @@
 
 package org.apache.tajo.engine.eval;
 
+import org.apache.tajo.LocalTajoTestingUtility;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.cli.InvalidStatementException;
+import org.apache.tajo.cli.ParsedResult;
+import org.apache.tajo.cli.SimpleParser;
 import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.datum.TextDatum;
 import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.engine.parser.SQLAnalyzer;
 import org.apache.tajo.engine.planner.*;
-import org.apache.tajo.engine.planner.logical.LogicalNode;
 import org.apache.tajo.engine.utils.SchemaUtil;
 import org.apache.tajo.master.TajoMaster;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.LazyTuple;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.VTuple;
@@ -39,8 +43,10 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 
 import java.io.IOException;
-import java.util.Stack;
+import java.util.List;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
@@ -58,6 +64,8 @@ public class ExprTestBase {
     util = new TajoTestingCluster();
     util.startCatalogCluster();
     cat = util.getMiniCatalogCluster().getCatalog();
+    cat.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:1234/warehouse");
+    cat.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
       cat.createFunction(funcDesc);
     }
@@ -88,27 +96,34 @@ public class ExprTestBase {
    * @return
    * @throws PlanningException
    */
-  private static Target[] getRawTargets(String query, boolean condition) throws PlanningException {
-    Expr expr = analyzer.parse(query);
+  private static Target[] getRawTargets(String query, boolean condition) throws PlanningException,
+      InvalidStatementException {
+
+    Session session = LocalTajoTestingUtility.createDummySession();
+    List<ParsedResult> parsedResults = SimpleParser.parseScript(query);
+    if (parsedResults.size() > 1) {
+      throw new RuntimeException("this query includes two or more statements.");
+    }
+    Expr expr = analyzer.parse(parsedResults.get(0).getStatement());
     VerificationState state = new VerificationState();
-    preLogicalPlanVerifier.visit(state, new Stack<Expr>(), expr);
+    preLogicalPlanVerifier.verify(session, state, expr);
     if (state.getErrorMessages().size() > 0) {
       if (!condition && state.getErrorMessages().size() > 0) {
         throw new PlanningException(state.getErrorMessages().get(0));
       }
       assertFalse(state.getErrorMessages().get(0), true);
     }
-    LogicalPlan plan = planner.createPlan(expr, true);
+    LogicalPlan plan = planner.createPlan(session, expr, true);
     optimizer.optimize(plan);
-    annotatedPlanVerifier.visit(state, plan, plan.getRootBlock(), plan.getRootBlock().getRoot(),
-        new Stack<LogicalNode>());
+    annotatedPlanVerifier.verify(session, state, plan);
+
     if (state.getErrorMessages().size() > 0) {
       assertFalse(state.getErrorMessages().get(0), true);
     }
 
     Target [] targets = plan.getRootBlock().getRawTargets();
     if (targets == null) {
-      throw new PlanningException("Wrong query statement or query plan: " + query);
+      throw new PlanningException("Wrong query statement or query plan: " + parsedResults.get(0).getStatement());
     }
     for (Target t : targets) {
       assertJsonSerDer(t.getEvalTree());
@@ -133,10 +148,11 @@ public class ExprTestBase {
                        char delimiter, boolean condition) throws IOException {
     LazyTuple lazyTuple;
     VTuple vtuple  = null;
+    String qualifiedTableName = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, tableName);
     Schema inputSchema = null;
     if (schema != null) {
       inputSchema = SchemaUtil.clone(schema);
-      inputSchema.setQualifier(tableName);
+      inputSchema.setQualifier(qualifiedTableName);
 
       int targetIdx [] = new int[inputSchema.size()];
       for (int i = 0; i < targetIdx.length; i++) {
@@ -154,8 +170,8 @@ public class ExprTestBase {
           vtuple.put(i, lazyTuple.get(i));
         }
       }
-      cat.addTable(new TableDesc(tableName, inputSchema, CatalogProtos.StoreType.CSV, new Options(),
-          CommonTestingUtil.getTestDir()));
+      cat.createTable(new TableDesc(qualifiedTableName, inputSchema,
+          CatalogProtos.StoreType.CSV, new Options(), CommonTestingUtil.getTestDir()));
     }
 
     Target [] targets;
@@ -172,6 +188,8 @@ public class ExprTestBase {
       for (int i = 0; i < expected.length; i++) {
         assertEquals(query, expected[i], outTuple.get(i).asChars());
       }
+    } catch (InvalidStatementException e) {
+      assertFalse(e.getMessage(), true);
     } catch (PlanningException e) {
       // In failure test case, an exception must occur while executing query.
       // So, we should check an error message, and return it.
@@ -182,7 +200,7 @@ public class ExprTestBase {
       }
     } finally {
       if (schema != null) {
-        cat.deleteTable(tableName);
+        cat.dropTable(qualifiedTableName);
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
index f9c50ac..d916bbc 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
@@ -19,6 +19,8 @@
 package org.apache.tajo.engine.eval;
 
 import com.google.common.collect.Sets;
+import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.algebra.OpType;
@@ -39,6 +41,7 @@ import org.apache.tajo.engine.planner.logical.GroupbyNode;
 import org.apache.tajo.engine.planner.logical.NodeType;
 import org.apache.tajo.exception.InternalException;
 import org.apache.tajo.master.TajoMaster;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.junit.AfterClass;
@@ -50,6 +53,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.common.TajoDataTypes.Type.INT4;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -62,6 +66,8 @@ public class TestEvalTreeUtil {
   static EvalNode expr3;
   static SQLAnalyzer analyzer;
   static LogicalPlanner planner;
+  static Session session = LocalTajoTestingUtility.createDummySession();
+
   public static class TestSum extends GeneralFunction {
     private Integer x;
     private Integer y;
@@ -87,6 +93,8 @@ public class TestEvalTreeUtil {
     for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
       catalog.createFunction(funcDesc);
     }
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:1234/warehouse");
+    catalog.createDatabase(TajoConstants.DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
 
     Schema schema = new Schema();
     schema.addColumn("name", TajoDataTypes.Type.TEXT);
@@ -94,8 +102,10 @@ public class TestEvalTreeUtil {
     schema.addColumn("age", TajoDataTypes.Type.INT4);
 
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV);
-    TableDesc desc = new TableDesc("people", schema, meta, CommonTestingUtil.getTestDir());
-    catalog.addTable(desc);
+    TableDesc desc = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "people"), schema, meta,
+        CommonTestingUtil.getTestDir());
+    catalog.createTable(desc);
 
     FunctionDesc funcMeta = new FunctionDesc("test_sum", TestSum.class,
         FunctionType.GENERAL,
@@ -126,7 +136,7 @@ public class TestEvalTreeUtil {
     Expr expr = analyzer.parse(query);
     LogicalPlan plan = null;
     try {
-      plan = planner.createPlan(expr);
+      plan = planner.createPlan(session, expr);
     } catch (PlanningException e) {
       e.printStackTrace();
     }
@@ -138,7 +148,7 @@ public class TestEvalTreeUtil {
     Expr block = analyzer.parse(query);
     LogicalPlan plan = null;
     try {
-      plan = planner.createPlan(block);
+      plan = planner.createPlan(session, block);
     } catch (PlanningException e) {
       e.printStackTrace();
     }
@@ -150,23 +160,23 @@ public class TestEvalTreeUtil {
   @Test
   public final void testChangeColumnRef() throws CloneNotSupportedException {
     EvalNode copy = (EvalNode)expr1.clone();
-    EvalTreeUtil.changeColumnRef(copy, "people.score", "newscore");
+    EvalTreeUtil.changeColumnRef(copy, "default.people.score", "newscore");
     Set<Column> set = EvalTreeUtil.findUniqueColumns(copy);
     assertEquals(1, set.size());
     assertTrue(set.contains(new Column("newscore", TajoDataTypes.Type.INT4)));
 
     copy = (EvalNode)expr2.clone();
-    EvalTreeUtil.changeColumnRef(copy, "people.age", "sum_age");
+    EvalTreeUtil.changeColumnRef(copy, "default.people.age", "sum_age");
     set = EvalTreeUtil.findUniqueColumns(copy);
     assertEquals(2, set.size());
-    assertTrue(set.contains(new Column("people.score", TajoDataTypes.Type.INT4)));
+    assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4)));
     assertTrue(set.contains(new Column("sum_age", TajoDataTypes.Type.INT4)));
 
     copy = (EvalNode)expr3.clone();
-    EvalTreeUtil.changeColumnRef(copy, "people.age", "sum_age");
+    EvalTreeUtil.changeColumnRef(copy, "default.people.age", "sum_age");
     set = EvalTreeUtil.findUniqueColumns(copy);
     assertEquals(2, set.size());
-    assertTrue(set.contains(new Column("people.score", TajoDataTypes.Type.INT4)));
+    assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4)));
     assertTrue(set.contains(new Column("sum_age", TajoDataTypes.Type.INT4)));
   }
 
@@ -174,17 +184,17 @@ public class TestEvalTreeUtil {
   public final void testFindAllRefColumns() {    
     Set<Column> set = EvalTreeUtil.findUniqueColumns(expr1);
     assertEquals(1, set.size());
-    assertTrue(set.contains(new Column("people.score", TajoDataTypes.Type.INT4)));
+    assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4)));
     
     set = EvalTreeUtil.findUniqueColumns(expr2);
     assertEquals(2, set.size());
-    assertTrue(set.contains(new Column("people.score", TajoDataTypes.Type.INT4)));
-    assertTrue(set.contains(new Column("people.age", TajoDataTypes.Type.INT4)));
+    assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4)));
+    assertTrue(set.contains(new Column("default.people.age", TajoDataTypes.Type.INT4)));
     
     set = EvalTreeUtil.findUniqueColumns(expr3);
     assertEquals(2, set.size());
-    assertTrue(set.contains(new Column("people.score", TajoDataTypes.Type.INT4)));
-    assertTrue(set.contains(new Column("people.age", TajoDataTypes.Type.INT4)));
+    assertTrue(set.contains(new Column("default.people.score", TajoDataTypes.Type.INT4)));
+    assertTrue(set.contains(new Column("default.people.age", TajoDataTypes.Type.INT4)));
   }
   
   public static final String [] QUERIES = {
@@ -213,9 +223,9 @@ public class TestEvalTreeUtil {
   @Test
   public final void testGetContainExprs() throws CloneNotSupportedException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[1]);
-    LogicalPlan plan = planner.createPlan(expr, true);
+    LogicalPlan plan = planner.createPlan(session, expr, true);
     Target [] targets = plan.getRootBlock().getRawTargets();
-    Column col1 = new Column("people.score", TajoDataTypes.Type.INT4);
+    Column col1 = new Column("default.people.score", TajoDataTypes.Type.INT4);
     Collection<EvalNode> exprs =
         EvalTreeUtil.getContainExpr(targets[0].getEvalTree(), col1);
     EvalNode node = exprs.iterator().next();
@@ -223,11 +233,11 @@ public class TestEvalTreeUtil {
     assertEquals(EvalType.PLUS, node.getLeftExpr().getType());
     assertEquals(new ConstEval(DatumFactory.createInt4(4)), node.getRightExpr());
 
-    Column col2 = new Column("people.age", TajoDataTypes.Type.INT4);
+    Column col2 = new Column("default.people.age", TajoDataTypes.Type.INT4);
     exprs = EvalTreeUtil.getContainExpr(targets[1].getEvalTree(), col2);
     node = exprs.iterator().next();
     assertEquals(EvalType.GTH, node.getType());
-    assertEquals("people.age", node.getLeftExpr().getName());
+    assertEquals("default.people.age", node.getLeftExpr().getName());
     assertEquals(new ConstEval(DatumFactory.createInt4(5)), node.getRightExpr());
   }
   
@@ -237,7 +247,7 @@ public class TestEvalTreeUtil {
     EvalNode node = getRootSelection(QUERIES[5]);
     EvalNode [] cnf = AlgebraicUtil.toConjunctiveNormalFormArray(node);
     
-    Column col1 = new Column("people.score", TajoDataTypes.Type.INT4);
+    Column col1 = new Column("default.people.score", TajoDataTypes.Type.INT4);
     
     assertEquals(2, cnf.length);
     EvalNode first = cnf[0];
@@ -276,8 +286,8 @@ public class TestEvalTreeUtil {
     EvalNode [] cnf = AlgebraicUtil.toDisjunctiveNormalFormArray(node);
     assertEquals(2, cnf.length);
 
-    assertEquals("people.score (INT4) > 1 AND people.score (INT4) < 3", cnf[0].toString());
-    assertEquals("7 < people.score (INT4) AND people.score (INT4) < 10", cnf[1].toString());
+    assertEquals("default.people.score (INT4) > 1 AND default.people.score (INT4) < 3", cnf[0].toString());
+    assertEquals("7 < default.people.score (INT4) AND default.people.score (INT4) < 10", cnf[1].toString());
   }
   
   @Test
@@ -291,9 +301,9 @@ public class TestEvalTreeUtil {
     assertTrue(7.0d == node.eval(null, null).asFloat8());
 
     Expr expr = analyzer.parse(QUERIES[1]);
-    LogicalPlan plan = planner.createPlan(expr, true);
+    LogicalPlan plan = planner.createPlan(session, expr, true);
     targets = plan.getRootBlock().getRawTargets();
-    Column col1 = new Column("people.score", TajoDataTypes.Type.INT4);
+    Column col1 = new Column("default.people.score", TajoDataTypes.Type.INT4);
     Collection<EvalNode> exprs =
         EvalTreeUtil.getContainExpr(targets[0].getEvalTree(), col1);
     node = exprs.iterator().next();
@@ -309,7 +319,7 @@ public class TestEvalTreeUtil {
   
   @Test
   public final void testTranspose() throws PlanningException {
-    Column col1 = new Column("people.score", TajoDataTypes.Type.INT4);
+    Column col1 = new Column("default.people.score", TajoDataTypes.Type.INT4);
     EvalNode node = getRootSelection(QUERIES[3]);
     // we expect that score < 3
     EvalNode transposed = AlgebraicUtil.transpose(node, col1);
@@ -331,7 +341,7 @@ public class TestEvalTreeUtil {
   public final void testFindDistinctAggFunctions() throws PlanningException {
     String query = "select sum(score) + max(age) from people";
     Expr expr = analyzer.parse(query);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     GroupbyNode groupByNode = plan.getRootBlock().getNode(NodeType.GROUP_BY);
     EvalNode [] aggEvals = groupByNode.getAggFunctions();
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestBuiltinFunctions.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestBuiltinFunctions.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestBuiltinFunctions.java
index 3e64016..65612f7 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestBuiltinFunctions.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestBuiltinFunctions.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.function;
 
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
@@ -29,6 +30,11 @@ import static org.junit.Assert.assertTrue;
 
 @Category(IntegrationTest.class)
 public class TestBuiltinFunctions extends QueryTestCaseBase {
+
+  public TestBuiltinFunctions() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public void testMaxLong() throws Exception {
     ResultSet res = executeQuery();

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java
index 6107ca7..c4ef32b 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalOptimizer.java
@@ -18,6 +18,8 @@
 
 package org.apache.tajo.engine.planner;
 
+import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -28,11 +30,14 @@ import org.apache.tajo.engine.function.builtin.SumInt;
 import org.apache.tajo.engine.parser.SQLAnalyzer;
 import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.master.TajoMaster;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.*;
 
 public class TestLogicalOptimizer {
@@ -42,12 +47,15 @@ public class TestLogicalOptimizer {
   private static SQLAnalyzer sqlAnalyzer;
   private static LogicalPlanner planner;
   private static LogicalOptimizer optimizer;
+  private static Session session = LocalTajoTestingUtility.createDummySession();
 
   @BeforeClass
   public static void setUp() throws Exception {
     util = new TajoTestingCluster();
     util.startCatalogCluster();
     catalog = util.getMiniCatalogCluster().getCatalog();
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:1234/warehouse");
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
       catalog.createFunction(funcDesc);
     }
@@ -67,14 +75,22 @@ public class TestLogicalOptimizer {
     schema3.addColumn("phone", Type.INT4);
 
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV);
-    TableDesc people = new TableDesc("employee", schema, meta, CommonTestingUtil.getTestDir());
-    catalog.addTable(people);
+    TableDesc people = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
+        CommonTestingUtil.getTestDir());
+    catalog.createTable(people);
 
-    TableDesc student = new TableDesc("dept", schema2, StoreType.CSV, new Options(), CommonTestingUtil.getTestDir());
-    catalog.addTable(student);
+    TableDesc student =
+        new TableDesc(
+            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, StoreType.CSV, new Options(),
+            CommonTestingUtil.getTestDir());
+    catalog.createTable(student);
 
-    TableDesc score = new TableDesc("score", schema3, StoreType.CSV, new Options(), CommonTestingUtil.getTestDir());
-    catalog.addTable(score);
+    TableDesc score =
+        new TableDesc(
+            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, StoreType.CSV, new Options(),
+            CommonTestingUtil.getTestDir());
+    catalog.createTable(score);
 
     FunctionDesc funcDesc = new FunctionDesc("sumtest", SumInt.class, FunctionType.GENERAL,
         CatalogUtil.newSimpleDataType(Type.INT4),
@@ -104,7 +120,7 @@ public class TestLogicalOptimizer {
   public final void testProjectionPushWithNaturalJoin() throws PlanningException, CloneNotSupportedException {
     // two relations
     Expr expr = sqlAnalyzer.parse(QUERIES[4]);
-    LogicalPlan newPlan = planner.createPlan(expr);
+    LogicalPlan newPlan = planner.createPlan(session, expr);
     LogicalNode plan = newPlan.getRootBlock().getRoot();
     assertEquals(NodeType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
@@ -131,7 +147,7 @@ public class TestLogicalOptimizer {
   public final void testProjectionPushWithInnerJoin() throws PlanningException {
     // two relations
     Expr expr = sqlAnalyzer.parse(QUERIES[5]);
-    LogicalPlan newPlan = planner.createPlan(expr);
+    LogicalPlan newPlan = planner.createPlan(session, expr);
     optimizer.optimize(newPlan);
   }
   
@@ -139,7 +155,7 @@ public class TestLogicalOptimizer {
   public final void testProjectionPush() throws CloneNotSupportedException, PlanningException {
     // two relations
     Expr expr = sqlAnalyzer.parse(QUERIES[2]);
-    LogicalPlan newPlan = planner.createPlan(expr);
+    LogicalPlan newPlan = planner.createPlan(session, expr);
     LogicalNode plan = newPlan.getRootBlock().getRoot();
     
     assertEquals(NodeType.ROOT, plan.getType());
@@ -161,7 +177,7 @@ public class TestLogicalOptimizer {
   @Test
   public final void testOptimizeWithGroupBy() throws CloneNotSupportedException, PlanningException {
     Expr expr = sqlAnalyzer.parse(QUERIES[3]);
-    LogicalPlan newPlan = planner.createPlan(expr);
+    LogicalPlan newPlan = planner.createPlan(session, expr);
     LogicalNode plan = newPlan.getRootBlock().getRoot();
         
     assertEquals(NodeType.ROOT, plan.getType());
@@ -188,7 +204,7 @@ public class TestLogicalOptimizer {
   public final void testPushable() throws CloneNotSupportedException, PlanningException {
     // two relations
     Expr expr = sqlAnalyzer.parse(QUERIES[0]);
-    LogicalPlan newPlan = planner.createPlan(expr);
+    LogicalPlan newPlan = planner.createPlan(session, expr);
     LogicalNode plan = newPlan.getRootBlock().getRoot();
     
     assertEquals(NodeType.ROOT, plan.getType());
@@ -219,7 +235,7 @@ public class TestLogicalOptimizer {
     
     // Scan Pushable Test
     expr = sqlAnalyzer.parse(QUERIES[1]);
-    newPlan = planner.createPlan(expr);
+    newPlan = planner.createPlan(session, expr);
     plan = newPlan.getRootBlock().getRoot();
     
     assertEquals(NodeType.ROOT, plan.getType());
@@ -241,7 +257,7 @@ public class TestLogicalOptimizer {
   @Test
   public final void testInsertInto() throws CloneNotSupportedException, PlanningException {
     Expr expr = sqlAnalyzer.parse(TestLogicalPlanner.insertStatements[0]);
-    LogicalPlan newPlan = planner.createPlan(expr);
+    LogicalPlan newPlan = planner.createPlan(session, expr);
     optimizer.optimize(newPlan);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java
index bfd1f81..2f1e0f9 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java
@@ -18,6 +18,7 @@
 
 package org.apache.tajo.engine.planner;
 
+import org.apache.tajo.LocalTajoTestingUtility;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.benchmark.TPCH;
 import org.apache.tajo.catalog.*;
@@ -33,6 +34,8 @@ import org.junit.Test;
 import java.util.HashSet;
 import java.util.Set;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.engine.planner.LogicalPlan.BlockType;
 import static org.junit.Assert.*;
 
@@ -49,6 +52,8 @@ public class TestLogicalPlan {
     util = new TajoTestingCluster();
     util.startCatalogCluster();
     catalog = util.getMiniCatalogCluster().getCatalog();
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, CommonTestingUtil.getTestDir().toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
       catalog.createFunction(funcDesc);
     }
@@ -71,7 +76,7 @@ public class TestLogicalPlan {
       TableDesc d = CatalogUtil.newTableDesc(tpchTables[i], tpch.getSchema(tpchTables[i]), m,
           CommonTestingUtil.getTestDir());
       d.setStats(stats);
-      catalog.addTable(d);
+      catalog.createTable(d);
     }
     planner = new LogicalPlanner(catalog);
     optimizer = new LogicalOptimizer(util.getConfiguration());
@@ -83,7 +88,7 @@ public class TestLogicalPlan {
 
   @Test
   public final void testQueryBlockGraph() {
-    LogicalPlan plan = new LogicalPlan(planner);
+    LogicalPlan plan = new LogicalPlan(LocalTajoTestingUtility.createDummySession().getCurrentDatabase(), planner);
     LogicalPlan.QueryBlock root = plan.newAndGetBlock(LogicalPlan.ROOT_BLOCK);
     LogicalPlan.QueryBlock new1 = plan.newQueryBlock();
     LogicalPlan.QueryBlock new2 = plan.newQueryBlock();


[11/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 ef485ef..98c289e 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
@@ -25,38 +25,40 @@ import com.google.protobuf.InvalidProtocolBufferException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.CatalogConstants;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.FunctionDesc;
 import org.apache.tajo.catalog.exception.CatalogException;
+import org.apache.tajo.catalog.exception.NoSuchDatabaseException;
+import org.apache.tajo.catalog.exception.NoSuchTableException;
+import org.apache.tajo.catalog.exception.NoSuchTablespaceException;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.*;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.exception.InternalException;
+import org.apache.tajo.exception.UnimplementedException;
+import org.apache.tajo.util.FileUtil;
+import org.apache.tajo.util.Pair;
 
+import java.io.IOException;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 public abstract class AbstractDBStore extends CatalogConstants implements CatalogStore {
   protected final Log LOG = LogFactory.getLog(getClass());
-
-  protected Configuration conf;
-  protected String connectionId;
-  protected String connectionPassword;
-  protected String catalogUri;
+  protected final Configuration conf;
+  protected final String connectionId;
+  protected final String connectionPassword;
+  protected final String catalogUri;
 
   private Connection conn;
 
   protected Map<String, Boolean> baseTableMaps = new HashMap<String, Boolean>();
 
-  protected static final int VERSION = 1;
-
   protected abstract String getCatalogDriverName();
 
   protected abstract Connection createConnection(final Configuration conf) throws SQLException;
@@ -67,8 +69,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
 
   protected abstract void dropBaseTable() throws CatalogException;
 
-  public AbstractDBStore(Configuration conf)
-      throws InternalException {
+  public AbstractDBStore(Configuration conf) throws InternalException {
 
     this.conf = conf;
 
@@ -114,40 +115,35 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     }
 
     try {
-      if (!isInitialized()) {
+      if (isInitialized()) {
+        LOG.info("The base tables of CatalogServer already is initialized.");
+        verifySchemaVersion();
+      } else {
         try {
           createBaseTable();
           LOG.info("The base tables of CatalogServer are created.");
         } catch (CatalogException ce) {
-          dropBaseTable();
+          try {
+            dropBaseTable();
+          } catch (Throwable t) {
+            LOG.error(t);
+          }
           throw ce;
         }
-      } else {
-        LOG.info("The base tables of CatalogServer already is initialized.");
       }
     } catch (Exception se) {
-      throw new CatalogException(
-          "Cannot initialize the persistent storage of Catalog", se);
+      throw new CatalogException("Cannot initialize the persistent storage of Catalog", se);
     }
+  }
+
+  public abstract int getDriverVersion();
 
-//    int dbVersion = 0;
+  public String readSchemaFile(String path) throws CatalogException {
     try {
-//      dbVersion = needUpgrade();
-      needUpgrade();
-    } catch (Exception e) {
-      throw new CatalogException(
-          "Cannot check if the DB need to be upgraded.", e);
+      return FileUtil.readTextFileFromResource("schemas/" + path);
+    } catch (IOException e) {
+      throw new CatalogException(e);
     }
-
-//    if (dbVersion < VERSION) {
-//      LOG.info("DB Upgrade is needed");
-//      try {
-//        upgrade(dbVersion, VERSION);
-//      } catch (SQLException e) {
-//        LOG.error(e.getMessage());
-//        throw new InternalException("DB upgrade is failed.", e);
-//      }
-//    }
   }
 
   protected String getCatalogUri(){
@@ -167,109 +163,407 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     return conn;
   }
 
-  private int needUpgrade() throws CatalogException {
+  private void verifySchemaVersion() throws CatalogException {
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    ResultSet result = null;
+
+    try {
+      String sql = "SELECT version FROM META";
+      if (LOG.isDebugEnabled()) {
+        LOG.debug(sql.toString());
+      }
+
+      conn = getConnection();
+      pstmt = conn.prepareStatement(sql);
+      result = pstmt.executeQuery();
+
+      boolean noVersion = !result.next();
+
+      int schemaVersion =  result.getInt(1);
+      if (noVersion || schemaVersion != getDriverVersion()) {
+        LOG.error(String.format("Catalog version (%d) and current driver version (%d) are mismatch to each other",
+            schemaVersion, getDriverVersion()));
+        LOG.error("=========================================================================");
+        LOG.error("|                Catalog Store Migration Is Needed                      |");
+        LOG.error("=========================================================================");
+        LOG.error("| You might downgrade or upgrade Apache Tajo. Downgrading or upgrading  |");
+        LOG.error("| Tajo without migration process is only available in some versions.    |");
+        LOG.error("| In order to learn how to migration Apache Tajo instance,              |");
+        LOG.error("| please refer http://s.apache.org/0_8_migration.                       |");
+        LOG.error("=========================================================================");
+        throw new CatalogException("Migration Needed. Please refer http://s.apache.org/0_8_migration.");
+      }
+    } catch (SQLException e) {
+      throw new CatalogException(e);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, result);
+    }
+
+    LOG.info(String.format("The compatibility of the catalog schema (version: %d) has been verified.",
+        getDriverVersion()));
+  }
+
+  /**
+   * Insert the version of the current catalog schema
+   */
+  protected void insertSchemaVersion() throws CatalogException {
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    try {
+      conn = getConnection();
+      pstmt = conn.prepareStatement("INSERT INTO META VALUES (?)");
+      pstmt.setInt(1, getDriverVersion());
+      pstmt.executeUpdate();
+    } catch (SQLException se) {
+      throw new CatalogException("cannot insert catalog schema version", se);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt);
+    }
+  }
+
+  @Override
+  public void createTablespace(String spaceName, String spaceUri) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
     ResultSet res = null;
-    int retValue = -1;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.delete(0, sql.length());
-      sql.append("SELECT VERSION FROM ");
-      sql.append(TB_META);
+      conn = getConnection();
+      conn.setAutoCommit(false);
+      String sql = String.format("INSERT INTO %s (SPACE_NAME, SPACE_URI) VALUES (?, ?)", TB_SPACES);
 
       if (LOG.isDebugEnabled()) {
+        LOG.debug(sql);
+      }
+
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setString(1, spaceName);
+      pstmt.setString(2, spaceUri);
+      pstmt.executeUpdate();
+      pstmt.close();
+      conn.commit();
+    } catch (SQLException se) {
+      if (conn != null) {
+        try {
+          conn.rollback();
+        } catch (SQLException e) {
+          LOG.error(e);
+        }
+      }
+      throw new CatalogException(se);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, res);
+    }
+  }
+
+  @Override
+  public boolean existTablespace(String tableSpaceName) throws CatalogException {
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    ResultSet res = null;
+    boolean exist = false;
+
+    try {
+      StringBuilder sql = new StringBuilder();
+      sql.append("SELECT SPACE_NAME FROM " + TB_SPACES +" WHERE SPACE_NAME = ?");
+      if (LOG.isDebugEnabled()) {
         LOG.debug(sql.toString());
       }
 
       conn = getConnection();
       pstmt = conn.prepareStatement(sql.toString());
+      pstmt.setString(1, tableSpaceName);
       res = pstmt.executeQuery();
+      exist = res.next();
+    } catch (SQLException se) {
+      throw new CatalogException(se);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, res);
+    }
 
-      if (!res.next()) { // if this db version is 0
-        insertVersion();
-        retValue = 0;
-      } else {
-        retValue =  res.getInt(1);
+    return exist;
+  }
+
+  @Override
+  public void dropTablespace(String tableSpaceName) throws CatalogException {
+
+
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    try {
+      TableSpaceInternal tableSpace = getTableSpaceInfo(tableSpaceName);
+      Collection<String> databaseNames = getAllDatabaseNamesInternal(COL_TABLESPACE_PK + " = " + tableSpace.spaceId);
+
+      conn = getConnection();
+      conn.setAutoCommit(false);
+
+      for (String databaseName : databaseNames) {
+        dropDatabase(databaseName);
       }
-    } catch (SQLException e) {
-      throw new CatalogException(e);
+
+      String sql = "DELETE FROM " + TB_SPACES + " WHERE " + COL_TABLESPACE_PK +"= ?";
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableSpace.getSpaceId());
+      pstmt.executeUpdate();
+      conn.commit();
+    } catch (SQLException se) {
+      if (conn != null) {
+        try {
+          conn.rollback();
+        } catch (SQLException e) {
+          LOG.error(e);
+        }
+      }
+      throw new CatalogException(String.format("Failed to drop tablespace \"%s\"", tableSpaceName), se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt);
     }
-    return retValue;
   }
 
-  private void insertVersion() throws CatalogException {
+  @Override
+  public Collection<String> getAllTablespaceNames() throws CatalogException {
+    return getAllTablespaceNamesInternal(null);
+  }
+
+
+  private Collection<String> getAllTablespaceNamesInternal(@Nullable String whereCondition) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
+    ResultSet resultSet = null;
+
+    List<String> tablespaceNames = new ArrayList<String>();
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("INSERT INTO ");
-      sql.append(TB_META);
-      sql.append(" values (0)");
+      String sql = "SELECT SPACE_NAME FROM " + TB_SPACES;
+
+      if (whereCondition != null) {
+        sql += " WHERE " + whereCondition;
+      }
+
+      conn = getConnection();
+      pstmt = conn.prepareStatement(sql);
+      resultSet = pstmt.executeQuery();
+      while(resultSet.next()) {
+        tablespaceNames.add(resultSet.getString(1));
+      }
+    } catch (SQLException se) {
+      throw new CatalogException(se);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, resultSet);
+    }
+
+    return tablespaceNames;
+  }
+
+  @Override
+  public void createDatabase(String databaseName, String tablespaceName) throws CatalogException {
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    ResultSet res = null;
+
+    try {
+      TableSpaceInternal spaceInfo = getTableSpaceInfo(tablespaceName);
+
+      String sql = "INSERT INTO " + TB_DATABASES + " (DB_NAME, SPACE_ID) VALUES (?, ?)";
+
+      if (LOG.isDebugEnabled()) {
+        LOG.debug(sql);
+      }
 
+      conn = getConnection();
+      conn.setAutoCommit(false);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setString(1, databaseName);
+      pstmt.setInt(2, spaceInfo.getSpaceId());
+      pstmt.executeUpdate();
+      pstmt.close();
+      conn.commit();
+    } catch (SQLException se) {
+      if (conn != null) {
+        try {
+          conn.rollback();
+        } catch (SQLException e) {
+          LOG.error(e);
+        }
+      }
+      throw new CatalogException(se);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, res);
+    }
+  }
+
+  @Override
+  public boolean existDatabase(String databaseName) throws CatalogException {
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    ResultSet res = null;
+    boolean exist = false;
+
+    try {
+      StringBuilder sql = new StringBuilder();
+      sql.append("SELECT DB_NAME FROM " + TB_DATABASES + " WHERE DB_NAME = ?");
       if (LOG.isDebugEnabled()) {
         LOG.debug(sql.toString());
       }
 
       conn = getConnection();
       pstmt = conn.prepareStatement(sql.toString());
+      pstmt.setString(1, databaseName);
+      res = pstmt.executeQuery();
+      exist = res.next();
+    } catch (SQLException se) {
+      throw new CatalogException(se);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, res);
+    }
+
+    return exist;
+  }
+
+  @Override
+  public void dropDatabase(String databaseName) throws CatalogException {
+    Collection<String> tableNames = getAllTableNames(databaseName);
+
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    try {
+      conn = getConnection();
+      conn.setAutoCommit(false);
+
+      for (String tableName : tableNames) {
+        dropTableInternal(conn, databaseName, tableName);
+      }
+
+      String sql = "DELETE FROM " + TB_DATABASES + " WHERE DB_NAME = ?";
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setString(1, databaseName);
       pstmt.executeUpdate();
-    } catch (SQLException e) {
-      throw new CatalogException(e);
+      conn.commit();
+    } catch (SQLException se) {
+      if (conn != null) {
+        try {
+          conn.rollback();
+        } catch (SQLException e) {
+          LOG.error(e);
+        }
+      }
+      throw new CatalogException(String.format("Failed to drop database \"%s\"", databaseName), se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt);
     }
   }
 
-  private void upgrade(int from, int to) throws CatalogException {
+  @Override
+  public Collection<String> getAllDatabaseNames() throws CatalogException {
+    return getAllDatabaseNamesInternal(null);
+  }
+
+  private Collection<String> getAllDatabaseNamesInternal(@Nullable String whereCondition) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
+    ResultSet resultSet = null;
+
+    List<String> databaseNames = new ArrayList<String>();
 
     try {
-      if (from == 0) {
-        if (to == 1) {
-          StringBuilder sql = new StringBuilder();
-          sql.append(" DROP INDEX idx_options_key");
+      String sql = "SELECT DB_NAME FROM " + TB_DATABASES;
 
-          if (LOG.isDebugEnabled()) {
-            LOG.debug(sql.toString());
-          }
+      if (whereCondition != null) {
+        sql += " WHERE " + whereCondition;
+      }
 
-          conn = getConnection();
-          pstmt = conn.prepareStatement(sql.toString());
-          pstmt.executeUpdate();
-          pstmt.close();
+      conn = getConnection();
+      pstmt = conn.prepareStatement(sql);
+      resultSet = pstmt.executeQuery();
+      while(resultSet.next()) {
+        databaseNames.add(resultSet.getString(1));
+      }
+    } catch (SQLException se) {
+      throw new CatalogException(se);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, resultSet);
+    }
 
-          sql.delete(0, sql.length());
-          sql.append(" CREATE INDEX idx_options_key on ").append(TB_OPTIONS);
-          sql.append(" (").append(C_TABLE_ID).append(")");
+    return databaseNames;
+  }
 
-          if (LOG.isDebugEnabled()) {
-            LOG.debug(sql.toString());
-          }
+  private static class TableSpaceInternal {
+    private final int spaceId;
+    private final String spaceURI;
+    private final String handler;
 
-          pstmt = conn.prepareStatement(sql.toString());
-          pstmt.executeUpdate();
+    TableSpaceInternal(int spaceId, String spaceURI, String handler) {
+      this.spaceId = spaceId;
+      this.spaceURI = spaceURI;
+      this.handler = handler;
+    }
 
-          LOG.info("DB Upgraded from " + from + " to " + to);
-        } else {
-          LOG.info("DB Upgraded from " + from + " to " + to);
-        }
+    public int getSpaceId() {
+      return spaceId;
+    }
+
+    public String getSpaceURI() {
+      return spaceURI;
+    }
+
+    public String getHandler() {
+      return handler;
+    }
+  }
+
+  private TableSpaceInternal getTableSpaceInfo(String spaceName) {
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    ResultSet res = null;
+
+    try {
+      String sql = "SELECT SPACE_ID, SPACE_URI, SPACE_HANDLER from " + TB_SPACES + " WHERE SPACE_NAME = ?";
+      conn = getConnection();
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setString(1, spaceName);
+      res = pstmt.executeQuery();
+      if (!res.next()) {
+        throw new CatalogException("ERROR: there is no SPACE_ID matched to the space name \"" + spaceName + "\"");
       }
-    } catch (SQLException e) {
-      throw new CatalogException(e);
+      return new TableSpaceInternal(res.getInt(1), res.getString(2), res.getString(3));
+    } catch (SQLException se) {
+      throw new NoSuchTablespaceException(spaceName);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, res);
+    }
+  }
+
+  private int getTableId(int databaseId, String databaseName, String tableName) {
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    ResultSet res = null;
+
+    try {
+      String tidSql = "SELECT TID from TABLES WHERE db_id = ? AND " + COL_TABLES_NAME + "=?";
+      conn = getConnection();
+      pstmt = conn.prepareStatement(tidSql);
+      pstmt.setInt(1, databaseId);
+      pstmt.setString(2, tableName);
+      res = pstmt.executeQuery();
+      if (!res.next()) {
+        throw new CatalogException("ERROR: there is no tid matched to " + tableName);
+      }
+      return res.getInt(1);
+    } catch (SQLException se) {
+      throw new NoSuchTableException(databaseName, tableName);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
   }
 
+  enum TableType {
+    BASE_TABLE,
+    EXTERNAL_TABLE
+  }
 
   @Override
-  public void addTable(final CatalogProtos.TableDescProto table) throws CatalogException {
+  public void createTable(final CatalogProtos.TableDescProto table) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
     ResultSet res = null;
@@ -277,50 +571,78 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     try {
       conn = getConnection();
       conn.setAutoCommit(false);
-      String tableName = table.getId().toLowerCase();
 
-      String sql = String.format("INSERT INTO %s (%s, path, store_type) VALUES(?, ?, ?) ", TB_TABLES, C_TABLE_ID);
-
-      if (LOG.isDebugEnabled()) {
-        LOG.debug(sql);
+      String [] splitted = CatalogUtil.splitTableName(CatalogUtil.normalizeIdentifier(table.getTableName()));
+      if (splitted.length == 1) {
+        throw new IllegalArgumentException("createTable() requires a qualified table name, but it is \""
+            + table.getTableName() + "\".");
       }
+      String databaseName = splitted[0];
+      String tableName = splitted[1];
 
-      pstmt = conn.prepareStatement(sql);
-      pstmt.setString(1, tableName);
-      pstmt.setString(2, table.getPath());
-      pstmt.setString(3, table.getMeta().getStoreType().name());
-      pstmt.executeUpdate();
-      pstmt.close();
+      int dbid = getDatabaseId(databaseName);
+
+      if (table.getIsExternal()) {
+        String sql = "INSERT INTO TABLES (DB_ID, " + COL_TABLES_NAME + ", TABLE_TYPE, PATH, STORE_TYPE) VALUES(?, ?, ?, ?, ?) ";
+
+        if (LOG.isDebugEnabled()) {
+          LOG.debug(sql);
+        }
+
+        pstmt = conn.prepareStatement(sql);
+        pstmt.setInt(1, dbid);
+        pstmt.setString(2, tableName);
+        pstmt.setString(3, TableType.EXTERNAL_TABLE.name());
+        pstmt.setString(4, table.getPath());
+        pstmt.setString(5, table.getMeta().getStoreType().name());
+        pstmt.executeUpdate();
+        pstmt.close();
+      } else {
+        String sql = "INSERT INTO TABLES (DB_ID, " + COL_TABLES_NAME + ", TABLE_TYPE, STORE_TYPE) VALUES(?, ?, ?, ?) ";
 
-      String tidSql = String.format("SELECT TID from %s WHERE %s = ?", TB_TABLES, C_TABLE_ID);
+        if (LOG.isDebugEnabled()) {
+          LOG.debug(sql);
+        }
+
+        pstmt = conn.prepareStatement(sql);
+        pstmt.setInt(1, dbid);
+        pstmt.setString(2, tableName);
+        pstmt.setString(3, TableType.BASE_TABLE.name());
+        pstmt.setString(4, table.getMeta().getStoreType().name());
+        pstmt.executeUpdate();
+        pstmt.close();
+      }
+
+      String tidSql =
+          "SELECT TID from " + TB_TABLES + " WHERE " + COL_DATABASES_PK + "=? AND " + COL_TABLES_NAME + "=?";
       pstmt = conn.prepareStatement(tidSql);
-      pstmt.setString(1, tableName);
+      pstmt.setInt(1, dbid);
+      pstmt.setString(2, tableName);
       res = pstmt.executeQuery();
 
       if (!res.next()) {
-        throw new CatalogException("ERROR: there is no tid matched to " + table.getId());
+        throw new CatalogException("ERROR: there is no TID matched to " + table.getTableName());
       }
 
-      int tid = res.getInt("TID");
+      int tableId = res.getInt("TID");
       res.close();
       pstmt.close();
 
-      String colSql = String.format("INSERT INTO %s (TID, %s, column_id, column_name, data_type, type_length)"
-          + " VALUES(?, ?, ?, ?, ?, ?) ", TB_COLUMNS, C_TABLE_ID);
+      String colSql =
+          "INSERT INTO " + TB_COLUMNS + " (TID, COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE, TYPE_LENGTH) VALUES(?, ?, ?, ?, ?) ";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql);
+        LOG.debug(colSql);
       }
 
       pstmt = conn.prepareStatement(colSql);
       for(int i = 0; i < table.getSchema().getFieldsCount(); i++) {
         ColumnProto col = table.getSchema().getFields(i);
-        pstmt.setInt(1, tid);
-        pstmt.setString(2, tableName);
+        pstmt.setInt(1, tableId);
+        pstmt.setString(2, CatalogUtil.extractSimpleName(col.getName()));
         pstmt.setInt(3, i);
-        pstmt.setString(4, CatalogUtil.extractSimpleName(col.getName()));
-        pstmt.setString(5, col.getDataType().getType().name());
-        pstmt.setInt(6, (col.getDataType().hasLength() ? col.getDataType().getLength() : 0));
+        pstmt.setString(4, col.getDataType().getType().name());
+        pstmt.setInt(5, (col.getDataType().hasLength() ? col.getDataType().getLength() : 0));
         pstmt.addBatch();
         pstmt.clearParameters();
       }
@@ -328,15 +650,15 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       pstmt.close();
 
       if(table.getMeta().hasParams()) {
-        String optSql = String.format("INSERT INTO %s (%s, key_, value_) VALUES(?, ?, ?)", TB_OPTIONS, C_TABLE_ID);
+        String propSQL = "INSERT INTO " + TB_OPTIONS + "(TID, KEY_, VALUE_) VALUES(?, ?, ?)";
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(optSql);
+          LOG.debug(propSQL);
         }
 
-        pstmt = conn.prepareStatement(optSql);
+        pstmt = conn.prepareStatement(propSQL);
         for (CatalogProtos.KeyValueProto entry : table.getMeta().getParams().getKeyvalList()) {
-          pstmt.setString(1, tableName);
+          pstmt.setInt(1, tableId);
           pstmt.setString(2, entry.getKey());
           pstmt.setString(3, entry.getValue());
           pstmt.addBatch();
@@ -348,15 +670,14 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
 
       if (table.hasStats()) {
 
-        String statSql =
-            String.format("INSERT INTO %s (%s, num_rows, num_bytes) VALUES(?, ?, ?)", TB_STATISTICS, C_TABLE_ID);
+        String statSql = "INSERT INTO " + TB_STATISTICS + " (TID, NUM_ROWS, NUM_BYTES) VALUES(?, ?, ?)";
 
         if (LOG.isDebugEnabled()) {
           LOG.debug(statSql);
         }
 
         pstmt = conn.prepareStatement(statSql);
-        pstmt.setString(1, tableName);
+        pstmt.setInt(1, tableId);
         pstmt.setLong(2, table.getStats().getNumRows());
         pstmt.setLong(3, table.getStats().getNumBytes());
         pstmt.executeUpdate();
@@ -365,15 +686,14 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
 
       if(table.hasPartition()) {
         String partSql =
-            String.format("INSERT INTO %s (%s, partition_type, expression, expression_schema) VALUES(?, ?, ?, ?)",
-                TB_PARTITION_METHODS, C_TABLE_ID);
+            "INSERT INTO PARTITION_METHODS (TID, PARTITION_TYPE, EXPRESSION, EXPRESSION_SCHEMA) VALUES(?, ?, ?, ?)";
 
         if (LOG.isDebugEnabled()) {
           LOG.debug(partSql);
         }
 
         pstmt = conn.prepareStatement(partSql);
-        pstmt.setString(1, tableName);
+        pstmt.setInt(1, tableId);
         pstmt.setString(2, table.getPartition().getPartitionType().name());
         pstmt.setString(3, table.getPartition().getExpression());
         pstmt.setBytes(4, table.getPartition().getExpressionSchema().toByteArray());
@@ -383,29 +703,56 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       // If there is no error, commit the changes.
       conn.commit();
     } catch (SQLException se) {
-      try {
-        // If there is any error, rollback the changes.
-        conn.rollback();
-      } catch (SQLException se2) {
+      if (conn != null) {
+        try {
+          conn.rollback();
+        } catch (SQLException e) {
+          LOG.error(e);
+        }
       }
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
+    }
+  }
+
+  private int getDatabaseId(String databaseName) throws SQLException {
+    String sql = String.format("SELECT DB_ID from %s WHERE DB_NAME = ?", TB_DATABASES);
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug(sql);
+    }
+
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    ResultSet res = null;
+
+    try {
+      conn = getConnection();
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setString(1, databaseName);
+      res = pstmt.executeQuery();
+      if (!res.next()) {
+        throw new NoSuchDatabaseException(databaseName);
+      }
+
+      return res.getInt("DB_ID");
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, res);
     }
   }
 
   @Override
-  public boolean existTable(final String name) throws CatalogException {
+  public boolean existTable(String databaseName, final String tableName) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
     ResultSet res = null;
     boolean exist = false;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append(" SELECT ").append(C_TABLE_ID);
-      sql.append(" FROM ").append(TB_TABLES);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      int dbid = getDatabaseId(databaseName);
+
+      String sql = "SELECT TID FROM TABLES WHERE DB_ID = ? AND " + COL_TABLES_NAME + "=?";
 
       if (LOG.isDebugEnabled()) {
         LOG.debug(sql.toString());
@@ -414,198 +761,255 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
       conn = getConnection();
       pstmt = conn.prepareStatement(sql.toString());
 
-      pstmt.setString(1, name);
+      pstmt.setInt(1, dbid);
+      pstmt.setString(2, tableName);
       res = pstmt.executeQuery();
       exist = res.next();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
 
     return exist;
   }
 
-  @Override
-  public void deleteTable(final String name) throws CatalogException {
-    Connection conn = null;
+  public void dropTableInternal(Connection conn, String databaseName, final String tableName)
+      throws SQLException {
+
     PreparedStatement pstmt = null;
 
     try {
-      conn = getConnection();
-      conn.setAutoCommit(false);
+      int databaseId = getDatabaseId(databaseName);
+      int tableId = getTableId(databaseId, databaseName, tableName);
 
-      StringBuilder sql = new StringBuilder();
-      sql.append("DELETE FROM ").append(TB_COLUMNS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      String sql = "DELETE FROM " + TB_COLUMNS + " WHERE " + COL_TABLES_PK + " = ?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
       pstmt.executeUpdate();
       pstmt.close();
 
-      sql.delete(0, sql.length());
-      sql.append("DELETE FROM ").append(TB_OPTIONS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+
+      sql = "DELETE FROM " + TB_OPTIONS + " WHERE " + COL_TABLES_PK + " = ? ";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
       pstmt.executeUpdate();
       pstmt.close();
 
-      sql.delete(0, sql.length());
-      sql.append("DELETE FROM ").append(TB_STATISTICS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+
+      sql = "DELETE FROM " + TB_STATISTICS + " WHERE " + COL_TABLES_PK + " = ? ";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
       pstmt.executeUpdate();
       pstmt.close();
 
-      sql.delete(0, sql.length());
-      sql.append("DELETE FROM ").append(TB_PARTTIONS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      sql = "DELETE FROM " + TB_PARTTIONS + " WHERE " + COL_TABLES_PK + " = ? ";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
       pstmt.executeUpdate();
       pstmt.close();
 
-      sql.delete(0, sql.length());
-      sql.append("DELETE FROM ").append(TB_TABLES);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      sql = "DELETE FROM " + TB_PARTITION_METHODS + " WHERE " + COL_TABLES_PK + " = ? ";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
+      pstmt.executeUpdate();
+      pstmt.close();
+
+      sql = "DELETE FROM TABLES WHERE DB_ID = ? AND " + COL_TABLES_PK + " = ?";
+
+      if (LOG.isDebugEnabled()) {
+        LOG.debug(sql);
+      }
+
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, databaseId);
+      pstmt.setInt(2, tableId);
       pstmt.executeUpdate();
 
-      // If there is no error, commit the changes.
+    } finally {
+      CatalogUtil.closeQuietly(pstmt);
+    }
+  }
+
+  @Override
+  public void dropTable(String databaseName, final String tableName) throws CatalogException {
+    Connection conn = null;
+    try {
+      conn = getConnection();
+      conn.setAutoCommit(false);
+      dropTableInternal(conn, databaseName, tableName);
       conn.commit();
     } catch (SQLException se) {
       try {
-        // If there is any error, rollback the changes.
         conn.rollback();
-      } catch (SQLException se2) {
+      } catch (SQLException e) {
+        LOG.error(e);
+      }
+    } finally {
+      CatalogUtil.closeQuietly(conn);
+    }
+  }
+
+  public Pair<Integer, String> getDatabaseIdAndUri(String databaseName) throws SQLException {
+    String sql =
+        "SELECT DB_ID, SPACE_URI from " + TB_DATABASES + " natural join " + TB_SPACES + " WHERE db_name = ?";
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug(sql);
+    }
+
+    Connection conn = null;
+    PreparedStatement pstmt = null;
+    ResultSet res = null;
+
+    try {
+      conn = getConnection();
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setString(1, databaseName);
+      res = pstmt.executeQuery();
+      if (!res.next()) {
+        throw new NoSuchDatabaseException(databaseName);
       }
-      throw new CatalogException(se);
+
+      return new Pair<Integer, String>(res.getInt(1), res.getString(2) + "/" + databaseName);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
   }
 
   @Override
-  public CatalogProtos.TableDescProto getTable(final String name) throws CatalogException {
+  public CatalogProtos.TableDescProto getTable(String databaseName, String tableName)
+      throws CatalogException {
     Connection conn = null;
     ResultSet res = null;
     PreparedStatement pstmt = null;
 
     CatalogProtos.TableDescProto.Builder tableBuilder = null;
-    StoreType storeType = null;
+    StoreType storeType;
 
     try {
       tableBuilder = CatalogProtos.TableDescProto.newBuilder();
 
-      StringBuilder sql = new StringBuilder();
-      sql.append(" SELECT ").append(C_TABLE_ID).append(", path, store_type");
-      sql.append(" from ").append(TB_TABLES);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      Pair<Integer, String> databaseIdAndUri = getDatabaseIdAndUri(databaseName);
+
+      //////////////////////////////////////////
+      // Geting Table Description
+      //////////////////////////////////////////
+      String sql =
+          "SELECT TID, " + COL_TABLES_NAME + ", TABLE_TYPE, PATH, STORE_TYPE FROM TABLES " +
+              "WHERE DB_ID = ? AND " + COL_TABLES_NAME + "=?";
+
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, databaseIdAndUri.getFirst());
+      pstmt.setString(2, tableName);
       res = pstmt.executeQuery();
 
       if (!res.next()) { // there is no table of the given name.
         return null;
       }
 
-      tableBuilder.setId(res.getString(C_TABLE_ID).trim());
-      tableBuilder.setPath(res.getString("path").trim());
-      storeType = CatalogUtil.getStoreType(res.getString("store_type").trim());
+      int tableId = res.getInt(1);
+      tableBuilder.setTableName(CatalogUtil.buildFQName(databaseName, res.getString(2).trim()));
+      TableType tableType = TableType.valueOf(res.getString(3));
+      if (tableType == TableType.EXTERNAL_TABLE) {
+        tableBuilder.setIsExternal(true);
+      }
+
+      if (tableType == TableType.BASE_TABLE) {
+        tableBuilder.setPath(databaseIdAndUri.getSecond() + "/" + tableName);
+      } else {
+        tableBuilder.setPath(res.getString(4).trim());
+      }
+      storeType = CatalogUtil.getStoreType(res.getString(5).trim());
 
       res.close();
       pstmt.close();
 
+      //////////////////////////////////////////
+      // Geting Column Descriptions
+      //////////////////////////////////////////
       CatalogProtos.SchemaProto.Builder schemaBuilder = CatalogProtos.SchemaProto.newBuilder();
-      sql.delete(0, sql.length());
-      sql.append(" SELECT column_name, data_type, type_length ");
-      sql.append(" from ").append(TB_COLUMNS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
-      sql.append("ORDER by column_id asc");
+      sql = "SELECT COLUMN_NAME, DATA_TYPE, TYPE_LENGTH from " + TB_COLUMNS +
+          " WHERE " + COL_TABLES_PK + " = ? ORDER BY ORDINAL_POSITION ASC";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
       res = pstmt.executeQuery();
 
       while (res.next()) {
         schemaBuilder.addFields(resultToColumnProto(res));
       }
 
-      tableBuilder.setSchema(CatalogUtil.getQualfiedSchema(name, schemaBuilder.build()));
+      tableBuilder.setSchema(
+          CatalogUtil.getQualfiedSchema(databaseName + "." + tableName, schemaBuilder.build()));
 
       res.close();
       pstmt.close();
 
+      //////////////////////////////////////////
+      // Geting Table Properties
+      //////////////////////////////////////////
       CatalogProtos.TableProto.Builder metaBuilder = CatalogProtos.TableProto.newBuilder();
       metaBuilder.setStoreType(storeType);
-      sql.delete(0, sql.length());
-      sql.append(" SELECT key_, value_ ");
-      sql.append(" from ").append(TB_OPTIONS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      sql = "SELECT key_, value_ FROM " + TB_OPTIONS +" WHERE " + COL_TABLES_PK + " = ?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
       res = pstmt.executeQuery();
       metaBuilder.setParams(resultToKeyValueSetProto(res));
-
       tableBuilder.setMeta(metaBuilder);
 
       res.close();
       pstmt.close();
 
-      sql.delete(0, sql.length());
-      sql.append(" SELECT num_rows, num_bytes ");
-      sql.append(" from ").append(TB_STATISTICS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
-
+      //////////////////////////////////////////
+      // Geting Table Stats
+      //////////////////////////////////////////
+      sql = "SELECT num_rows, num_bytes FROM " + TB_STATISTICS + " WHERE " + COL_TABLES_PK + " = ?";
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
-
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
       res = pstmt.executeQuery();
 
       if (res.next()) {
@@ -614,70 +1018,38 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
         statBuilder.setNumBytes(res.getLong("num_bytes"));
         tableBuilder.setStats(statBuilder);
       }
-
       res.close();
       pstmt.close();
 
-      sql.delete(0, sql.length());
-      sql.append(" SELECT partition_type, expression, expression_schema ");
-      sql.append(" from ").append(TB_PARTITION_METHODS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+
+      //////////////////////////////////////////
+      // Getting Table Partition Method
+      //////////////////////////////////////////
+      sql = " SELECT partition_type, expression, expression_schema FROM " + TB_PARTITION_METHODS +
+          " WHERE " + COL_TABLES_PK + " = ?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, name);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
       res = pstmt.executeQuery();
 
       if (res.next()) {
-        tableBuilder.setPartition(resultToPartitionMethodProto(name, res));
+        tableBuilder.setPartition(resultToPartitionMethodProto(databaseName, tableName, res));
       }
     } catch (InvalidProtocolBufferException e) {
       throw new CatalogException(e);
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
 
     return tableBuilder.build();
   }
 
-  private ColumnProto getColumn(String tableName, int tid, String columnId) throws CatalogException {
-    Connection conn = null;
-    ResultSet res = null;
-    PreparedStatement pstmt = null;
-
-    try {
-      StringBuilder sql = new StringBuilder();
-      sql.append(" SELECT column_name, data_type, type_length");
-      sql.append(" FROM ").append(TB_COLUMNS);
-      sql.append(" WHERE TID = ? ");
-      sql.append(" AND column_id = ? ");
-
-      if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
-      }
-
-      conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setInt(1, tid);
-      pstmt.setInt(2, Integer.parseInt(columnId));
-      res = pstmt.executeQuery();
-
-      if (res.next()) {
-        return resultToColumnProto(res);
-      }
-    } catch (SQLException se) {
-      throw new CatalogException(se);
-    } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
-    }
-    return null;
-  }
-
   private Type getDataType(final String typeStr) {
     try {
       return Enum.valueOf(Type.class, typeStr);
@@ -688,7 +1060,7 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
   }
 
   @Override
-  public List<String> getAllTableNames() throws CatalogException {
+  public List<String> getAllTableNames(String databaseName) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
     ResultSet res = null;
@@ -696,89 +1068,104 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     List<String> tables = new ArrayList<String>();
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("SELECT ");
-      sql.append(C_TABLE_ID);
-      sql.append(" from ");
-      sql.append(TB_TABLES);
+
+      int dbid = getDatabaseId(databaseName);
+
+      String sql = "SELECT " + COL_TABLES_NAME + " FROM TABLES WHERE DB_ID = ?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, dbid);
       res = pstmt.executeQuery();
       while (res.next()) {
-        tables.add(res.getString(C_TABLE_ID).trim());
+        tables.add(res.getString(COL_TABLES_NAME).trim());
       }
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
     return tables;
   }
 
+  private static final String ADD_PARTITION_SQL =
+      "INSERT INTO " + TB_PARTTIONS + " (TID, PARTITION_NAME, ORDINAL_POSITION, PATH) VALUES (?,?,?,?)";
+
+
   @Override
   public void addPartitions(CatalogProtos.PartitionsProto partitionsProto) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("INSERT INTO ");
-      sql.append(TB_PARTTIONS);
-      sql.append(" (");
-      sql.append(C_TABLE_ID);
-      sql.append(",  partition_name, ordinal_position, path, cache_nodes) ");
-      sql.append("VALUES (?, ?, ?, ?, ?, ?) ");
-
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(ADD_PARTITION_SQL);
       }
 
+      String databaseName = CatalogUtil.normalizeIdentifier(partitionsProto.getTableIdentifier().getDatabaseName());
+      String tableName = CatalogUtil.normalizeIdentifier(partitionsProto.getTableIdentifier().getTableName());
+
+      int databaseId = getDatabaseId(databaseName);
+      int tableId = getTableId(databaseId, databaseName, tableName);
+
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
+      pstmt = conn.prepareStatement(ADD_PARTITION_SQL);
 
-      for (CatalogProtos.PartitionDescProto proto : partitionsProto.getPartitionList()) {
-        pstmt.setString(1, proto.getTableId());
-        pstmt.setString(2, proto.getPartitionName());
-        pstmt.setInt(3, proto.getOrdinalPosition());
-        pstmt.setString(4, proto.getPartitionValue());
-        pstmt.setString(5, proto.getPath());
-        pstmt.addBatch();
-        pstmt.clearParameters();
+      for (CatalogProtos.PartitionDescProto partition : partitionsProto.getPartitionList()) {
+        addPartitionInternal(pstmt, tableId, partition);
       }
       pstmt.executeBatch();
+      conn.commit();
     } catch (SQLException se) {
+      if (conn != null) {
+        try {
+          conn.rollback();
+        } catch (SQLException e) {
+          LOG.error(e);
+        }
+      }
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt);
     }
   }
 
+  private static void addPartitionInternal(PreparedStatement pstmt, int tableId, PartitionDescProto partition) throws
+      SQLException {
+      pstmt.setInt(1, tableId);
+      pstmt.setString(2, partition.getPartitionName());
+      pstmt.setInt(3, partition.getOrdinalPosition());
+      pstmt.setString(4, partition.getPath());
+      pstmt.addBatch();
+      pstmt.clearParameters();
+  }
+
   @Override
   public void addPartitionMethod(CatalogProtos.PartitionMethodProto proto) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("INSERT INTO ");
-      sql.append(TB_PARTITION_METHODS);
-      sql.append( " (");
-      sql.append(C_TABLE_ID);
-      sql.append(", partition_type,  expression, expression_schema) ");
-      sql.append("VALUES (?, ?, ?, ?) ");
+      String sql = "INSERT INTO " + TB_PARTITION_METHODS + " (TID, PARTITION_TYPE,  EXPRESSION, EXPRESSION_SCHEMA) " +
+              "VALUES (?,?,?,?)";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
+      String databaseName = CatalogUtil.normalizeIdentifier(proto.getTableIdentifier().getDatabaseName());
+      String tableName = CatalogUtil.normalizeIdentifier(proto.getTableIdentifier().getTableName());
+
+      int databaseId = getDatabaseId(databaseName);
+      int tableId = getTableId(databaseId, databaseName, tableName);
+
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, proto.getTableId().toLowerCase());
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, tableId);
       pstmt.setString(2, proto.getPartitionType().name());
       pstmt.setString(3, proto.getExpression());
       pstmt.setBytes(4, proto.getExpressionSchema().toByteArray());
@@ -786,88 +1173,83 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt);
     }
   }
 
   @Override
-  public void delPartitionMethod(String tableName) throws CatalogException {
+  public void dropPartitionMethod(String databaseName, String tableName) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append(" DELETE FROM ").append(TB_PARTITION_METHODS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      String sql = "DELETE FROM " + TB_PARTITION_METHODS + " WHERE " + COL_TABLES_NAME + " = ? ";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
+      pstmt = conn.prepareStatement(sql);
       pstmt.setString(1, tableName);
       pstmt.executeUpdate();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt);
     }
   }
 
   @Override
-  public CatalogProtos.PartitionMethodProto getPartitionMethod(String tableName) throws CatalogException {
+  public CatalogProtos.PartitionMethodProto getPartitionMethod(String databaseName, String tableName)
+      throws CatalogException {
     Connection conn = null;
     ResultSet res = null;
     PreparedStatement pstmt = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append(" SELECT partition_type, expression, expression_schema");
-      sql.append(" FROM ").append(TB_PARTITION_METHODS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      String sql = "SELECT partition_type, expression, expression_schema FROM " + TB_PARTITION_METHODS +
+      " WHERE " + COL_TABLES_NAME + " = ? ";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
+      pstmt = conn.prepareStatement(sql);
       pstmt.setString(1, tableName);
       res = pstmt.executeQuery();
 
       if (res.next()) {
-        return resultToPartitionMethodProto(tableName, res);
+        return resultToPartitionMethodProto(databaseName, tableName, res);
       }
     } catch (InvalidProtocolBufferException e) {
       throw new CatalogException(e);
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
     return null;
   }
 
   @Override
-  public boolean existPartitionMethod(String tableName) throws CatalogException {
+  public boolean existPartitionMethod(String databaseName, String tableName) throws CatalogException {
     Connection conn = null;
     ResultSet res = null;
     PreparedStatement pstmt = null;
     boolean exist = false;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append(" SELECT partition_type, expression, expression_schema");
-      sql.append(" FROM ").append(TB_PARTITION_METHODS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      String sql = "SELECT partition_type, expression, expression_schema FROM " + TB_PARTITION_METHODS +
+      " WHERE " + COL_TABLES_NAME + "= ?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
+      pstmt = conn.prepareStatement(sql);
       pstmt.setString(1, tableName);
       res = pstmt.executeQuery();
 
@@ -875,121 +1257,47 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {                           
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
     return exist;
   }
 
   @Override
-  public void addPartition(CatalogProtos.PartitionDescProto proto) throws CatalogException {
+  public void addPartition(String databaseName, String tableName,
+                           CatalogProtos.PartitionDescProto partition) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("INSERT INTO ");
-      sql.append(TB_PARTTIONS);
-      sql.append(" (");
-      sql.append(C_TABLE_ID);
-      sql.append(", partition_method_id,  partition_name, ordinal_position, path, cache_nodes) ");
-      sql.append("VALUES (?, ?, ?, ?, ?, ?, ?) ");
-
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(ADD_PARTITION_SQL);
       }
 
+      int databaseId = getDatabaseId(databaseName);
+      int tableId = getTableId(databaseId, databaseName, tableName);
+
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, proto.getTableId().toLowerCase());
-      pstmt.setString(2, proto.getPartitionName().toLowerCase());
-      pstmt.setInt(3, proto.getOrdinalPosition());
-      pstmt.setString(4, proto.getPartitionValue());
-      pstmt.setString(5, proto.getPath());
+      pstmt = conn.prepareStatement(ADD_PARTITION_SQL);
+      addPartitionInternal(pstmt, tableId, partition);
       pstmt.executeUpdate();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt);
     }
   }
 
   @Override
   public CatalogProtos.PartitionDescProto getPartition(String partitionName) throws CatalogException {
-    Connection conn = null;
-    ResultSet res = null;
-    PreparedStatement pstmt = null;
-    CatalogProtos.PartitionDescProto proto = null;
-
-    try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("SELECT ");
-      sql.append(C_TABLE_ID);
-      sql.append(", partition_name, ordinal_position, partition_value, path, cache_nodes FROM ");
-      sql.append(TB_PARTTIONS);
-      sql.append("where partition_name = ?");
-
-
-      if (LOG.isDebugEnabled()) {
-        LOG.debug(sql);
-      }
-
-      conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, partitionName);
-      res = pstmt.executeQuery();
-      if (!res.next()) {
-        throw new CatalogException("ERROR: there is no index matched to " + partitionName);
-      }
-
-      proto = resultToPartitionDescProto(res);
-    } catch (SQLException se) {
-      throw new CatalogException(se);
-    } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
-    }
-
-    return proto;
+    // TODO
+    throw new UnimplementedException("getPartition is not implemented");
   }
 
 
   @Override
   public CatalogProtos.PartitionsProto getPartitions(String tableName) throws CatalogException {
-    Connection conn = null;
-    ResultSet res = null;
-    PreparedStatement pstmt = null;
-    CatalogProtos.PartitionsProto proto = null;
-
-    try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("SELECT ");
-      sql.append(C_TABLE_ID);
-      sql.append(", partition_name, ordinal_position, partition_value, path, cache_nodes FROM ");
-      sql.append(TB_PARTTIONS);
-      sql.append("where ");
-      sql.append(C_TABLE_ID);
-      sql.append(" = ?");
-
-      if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
-      }
-
-      // PARTITIONS
-      conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, tableName);
-      res = pstmt.executeQuery();
-      CatalogProtos.PartitionsProto.Builder builder = CatalogProtos.PartitionsProto.newBuilder();
-      while(res.next()) {
-        builder.addPartition(resultToPartitionDescProto(res));
-      }
-      proto = builder.build();
-    } catch (SQLException se) {
-      throw new CatalogException(se);
-    } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
-    }
-
-    return proto;
+    // TODO
+    throw new UnimplementedException("getPartitions is not implemented");
   }
 
 
@@ -999,313 +1307,331 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     PreparedStatement pstmt = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append(" DELETE FROM ").append(TB_PARTTIONS);
-      sql.append(" WHERE partition_name = ? ");
+      String sql = "DELETE FROM " + TB_PARTTIONS + " WHERE PARTITION_NAME = ? ";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
+      pstmt = conn.prepareStatement(sql);
       pstmt.setString(1, partitionName);
       pstmt.executeUpdate();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt);
     }
   }
 
   @Override
-  public void delPartitions(String tableName) throws CatalogException {
+  public void dropPartitions(String tableName) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append(" DELETE FROM ").append(TB_PARTTIONS);
-      sql.append(" WHERE ").append(C_TABLE_ID).append(" = ? ");
+      String sql = "DELETE FROM " + TB_PARTTIONS + " WHERE " + COL_TABLES_NAME + "= ? ";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
+      pstmt = conn.prepareStatement(sql);
       pstmt.setString(1, tableName);
       pstmt.executeUpdate();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt);
     }
   }
 
 
   @Override
-  public void addIndex(final IndexDescProto proto) throws CatalogException {
+  public void createIndex(final IndexDescProto proto) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
 
+    String databaseName = CatalogUtil.normalizeIdentifier(proto.getTableIdentifier().getDatabaseName());
+    String tableName = CatalogUtil.normalizeIdentifier(proto.getTableIdentifier().getTableName());
+    String columnName = CatalogUtil.extractSimpleName(CatalogUtil.normalizeIdentifier(proto.getColumn().getName()));
+
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("INSERT INTO indexes (index_name, ");
-      sql.append(C_TABLE_ID);
-      sql.append(", column_name, ");
-      sql.append("data_type, index_type, is_unique, is_clustered, is_ascending) VALUES ");
-      sql.append("(?,?,?,?,?,?,?,?)");
+      int databaseId = getDatabaseId(databaseName);
+      int tableId = getTableId(databaseId, databaseName, tableName);
+
+      String sql = "INSERT INTO " + TB_INDEXES +
+        " (" + COL_DATABASES_PK + ", " + COL_TABLES_PK + ", INDEX_NAME, " +
+          "COLUMN_NAME, DATA_TYPE, INDEX_TYPE, IS_UNIQUE, IS_CLUSTERED, IS_ASCENDING) VALUES (?,?,?,?,?,?,?,?,?)";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
+      conn.setAutoCommit(false);
 
-      pstmt.setString(1, proto.getName());
-      pstmt.setString(2, proto.getTableId());
-      pstmt.setString(3, CatalogUtil.extractSimpleName(proto.getColumn().getName()));
-      pstmt.setString(4, proto.getColumn().getDataType().getType().name());
-      pstmt.setString(5, proto.getIndexMethod().toString());
-      pstmt.setBoolean(6, proto.hasIsUnique() && proto.getIsUnique());
-      pstmt.setBoolean(7, proto.hasIsClustered() && proto.getIsClustered());
-      pstmt.setBoolean(8, proto.hasIsAscending() && proto.getIsAscending());
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, databaseId);
+      pstmt.setInt(2, tableId);
+      pstmt.setString(3, proto.getIndexName());
+      pstmt.setString(4, columnName);
+      pstmt.setString(5, proto.getColumn().getDataType().getType().name());
+      pstmt.setString(6, proto.getIndexMethod().toString());
+      pstmt.setBoolean(7, proto.hasIsUnique() && proto.getIsUnique());
+      pstmt.setBoolean(8, proto.hasIsClustered() && proto.getIsClustered());
+      pstmt.setBoolean(9, proto.hasIsAscending() && proto.getIsAscending());
       pstmt.executeUpdate();
-
+      conn.commit();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt);
     }
   }
 
   @Override
-  public void delIndex(final String indexName) throws CatalogException {
+  public void dropIndex(String databaseName, final String indexName) throws CatalogException {
     Connection conn = null;
     PreparedStatement pstmt = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append(" DELETE FROM ").append(TB_INDEXES);
-      sql.append(" WHERE index_name ").append(" = ? ");
+      int databaseId = getDatabaseId(databaseName);
+      String sql = "DELETE FROM " + TB_INDEXES + " WHERE " + COL_DATABASES_PK + "=? AND INDEX_NAME=?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, indexName);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, databaseId);
+      pstmt.setString(2, indexName);
       pstmt.executeUpdate();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt);
+      CatalogUtil.closeQuietly(pstmt);
+    }
+  }
+
+  public static String getTableName(Connection conn, int tableId) throws SQLException {
+    ResultSet res = null;
+    PreparedStatement pstmt = null;
+
+    try {
+      pstmt =
+          conn.prepareStatement("SELECT " + COL_TABLES_NAME + " FROM " + TB_TABLES + " WHERE " + COL_TABLES_PK +"=?");
+      pstmt.setInt(1, tableId);
+      res = pstmt.executeQuery();
+      if (!res.next()) {
+        throw new CatalogException("Cannot get any table name from TID");
+      }
+      return res.getString(1);
+    } finally {
+      CatalogUtil.closeQuietly(pstmt, res);
     }
   }
 
+  final static String GET_INDEXES_SQL =
+      "SELECT " + COL_TABLES_PK + ", INDEX_NAME, COLUMN_NAME, DATA_TYPE, INDEX_TYPE, IS_UNIQUE, "+
+          "IS_CLUSTERED, IS_ASCENDING FROM " + TB_INDEXES;
+
   @Override
-  public IndexDescProto getIndex(final String indexName) throws CatalogException {
+  public IndexDescProto getIndexByName(String databaseName, final String indexName)
+      throws CatalogException {
     Connection conn = null;
     ResultSet res = null;
     PreparedStatement pstmt = null;
     IndexDescProto proto = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append( "SELECT index_name, ");
-      sql.append(C_TABLE_ID);
-      sql.append(", column_name, data_type, ");
-      sql.append("index_type, is_unique, is_clustered, is_ascending FROM indexes ");
-      sql.append("where index_name = ?");
+      int databaseId = getDatabaseId(databaseName);
+
+      String sql = GET_INDEXES_SQL + " WHERE " + COL_DATABASES_PK + "=? AND INDEX_NAME=?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, indexName);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, databaseId);
+      pstmt.setString(2, indexName);
       res = pstmt.executeQuery();
       if (!res.next()) {
         throw new CatalogException("ERROR: there is no index matched to " + indexName);
       }
-      proto = resultToIndexDescProto(res);
+      IndexDescProto.Builder builder = IndexDescProto.newBuilder();
+      resultToIndexDescProtoBuilder(builder, res);
+      String tableName = getTableName(conn, res.getInt(COL_TABLES_PK));
+      builder.setTableIdentifier(CatalogUtil.buildTableIdentifier(databaseName, tableName));
+      proto = builder.build();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
 
     return proto;
   }
 
   @Override
-  public IndexDescProto getIndex(final String tableName,
-                                 final String columnName) throws CatalogException {
+  public IndexDescProto getIndexByColumn(final String databaseName,
+                                         final String tableName,
+                                         final String columnName) throws CatalogException {
     Connection conn = null;
     ResultSet res = null;
     PreparedStatement pstmt = null;
     IndexDescProto proto = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("SELECT index_name, ");
-      sql.append(C_TABLE_ID);
-      sql.append(", column_name, data_type, ");
-      sql.append("index_type, is_unique, is_clustered, is_ascending FROM indexes ");
-      sql.append("where ");
-      sql.append(C_TABLE_ID);
-      sql.append(" = ? AND column_name = ?");
+      int databaseId = getDatabaseId(databaseName);
+
+      String sql = GET_INDEXES_SQL + " WHERE " + COL_DATABASES_PK + "=? AND COLUMN_NAME=?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, tableName);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, databaseId);;
       pstmt.setString(2, columnName);
-
       res = pstmt.executeQuery();
       if (!res.next()) {
-        throw new CatalogException("ERROR: there is no index matched to "
-            + tableName + "." + columnName);
+        throw new CatalogException("ERROR: there is no index matched to " + columnName);
       }
-      proto = resultToIndexDescProto(res);
+      IndexDescProto.Builder builder = IndexDescProto.newBuilder();
+      resultToIndexDescProtoBuilder(builder, res);
+      builder.setTableIdentifier(CatalogUtil.buildTableIdentifier(databaseName, tableName));
+      proto = builder.build();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
 
     return proto;
   }
 
   @Override
-  public boolean existIndex(final String indexName) throws CatalogException {
+  public boolean existIndexByName(String databaseName, final String indexName) throws CatalogException {
     Connection conn = null;
-    PreparedStatement pstmt = null;
     ResultSet res = null;
+    PreparedStatement pstmt = null;
+
     boolean exist = false;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("SELECT index_name from ");
-      sql.append(TB_INDEXES);
-      sql.append(" WHERE index_name = ?");
+      int databaseId = getDatabaseId(databaseName);
+
+      String sql =
+          "SELECT INDEX_NAME FROM " + TB_INDEXES + " WHERE " + COL_DATABASES_PK + "=? AND INDEX_NAME=?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, indexName);
-      if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
-      }
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, databaseId);
+      pstmt.setString(2, indexName);
       res = pstmt.executeQuery();
       exist = res.next();
     } catch (SQLException se) {
-
+      throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
 
     return exist;
   }
 
   @Override
-  public boolean existIndex(String tableName, String columnName)
+  public boolean existIndexByColumn(String databaseName, String tableName, String columnName)
       throws CatalogException {
     Connection conn = null;
+    ResultSet res = null;
     PreparedStatement pstmt = null;
+
     boolean exist = false;
-    ResultSet res = null;
 
     try {
-      StringBuilder sql = new StringBuilder();
-      sql.append("SELECT index_name from ");
-      sql.append(TB_INDEXES);
-      sql.append(" WHERE ");
-      sql.append(C_TABLE_ID);
-      sql.append(" = ? AND COLUMN_NAME = ?");
+      int databaseId = getDatabaseId(databaseName);
+
+      String sql =
+          "SELECT INDEX_NAME FROM " + TB_INDEXES + " WHERE " + COL_DATABASES_PK + "=? AND COLUMN_NAME=?";
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, tableName);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, databaseId);
       pstmt.setString(2, columnName);
-      if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
-      }
       res = pstmt.executeQuery();
       exist = res.next();
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
-
     return exist;
   }
 
   @Override
-  public IndexDescProto[] getIndexes(final String tableName)
+  public IndexDescProto[] getIndexes(String databaseName, final String tableName)
       throws CatalogException {
     Connection conn = null;
     ResultSet res = null;
     PreparedStatement pstmt = null;
-    List<IndexDescProto> protos = null;
+    final List<IndexDescProto> protos = new ArrayList<IndexDescProto>();
 
     try {
-      protos = new ArrayList<IndexDescProto>();
+      final int databaseId = getDatabaseId(databaseName);
+      final int tableId = getTableId(databaseId, databaseName, tableName);
+      final TableIdentifierProto tableIdentifier = CatalogUtil.buildTableIdentifier(databaseName, tableName);
+
+
+      String sql = GET_INDEXES_SQL + " WHERE " + COL_DATABASES_PK + "=? AND " + COL_TABLES_PK + "=?";
 
-      StringBuilder sql = new StringBuilder();
-      sql.append("SELECT index_name, ");
-      sql.append(C_TABLE_ID);
-      sql.append(", column_name, data_type, ");
-      sql.append("index_type, is_unique, is_clustered, is_ascending FROM indexes ");
-      sql.append("where ");
-      sql.append(C_TABLE_ID);
-      sql.append("= ?");
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug(sql.toString());
+        LOG.debug(sql);
       }
 
       conn = getConnection();
-      pstmt = conn.prepareStatement(sql.toString());
-      pstmt.setString(1, tableName);
+      pstmt = conn.prepareStatement(sql);
+      pstmt.setInt(1, databaseId);
+      pstmt.setInt(2, tableId);
       res = pstmt.executeQuery();
+
       while (res.next()) {
-        protos.add(resultToIndexDescProto(res));
+        IndexDescProto.Builder builder = IndexDescProto.newBuilder();
+        resultToIndexDescProtoBuilder(builder, res);
+        builder.setTableIdentifier(tableIdentifier);
+        protos.add(builder.build());
       }
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, pstmt, res);
+      CatalogUtil.closeQuietly(pstmt, res);
     }
 
     return protos.toArray(new IndexDescProto[protos.size()]);
   }
 
-  private IndexDescProto resultToIndexDescProto(final ResultSet res) throws SQLException {
-    IndexDescProto.Builder builder = IndexDescProto.newBuilder();
-    builder.setName(res.getString("index_name"));
-    builder.setTableId(res.getString(C_TABLE_ID));
+  private void resultToIndexDescProtoBuilder(IndexDescProto.Builder builder,
+                                                final ResultSet res) throws SQLException {
+    builder.setIndexName(res.getString("index_name"));
     builder.setColumn(indexResultToColumnProto(res));
     builder.setIndexMethod(getIndexMethod(res.getString("index_type").trim()));
     builder.setIsUnique(res.getBoolean("is_unique"));
     builder.setIsClustered(res.getBoolean("is_clustered"));
     builder.setIsAscending(res.getBoolean("is_ascending"));
-    return builder.build();
   }
 
   /**
@@ -1358,26 +1684,18 @@ public abstract class AbstractDBStore extends CatalogConstants implements Catalo
     }
   }
 
-  private CatalogProtos.PartitionMethodProto resultToPartitionMethodProto(final String tableName, final ResultSet res)
+  private CatalogProtos.PartitionMethodProto resultToPartitionMethodProto(final String databaseName,
+                                                                          final String tableName,
+                                                                          final ResultSet res)
       throws SQLException, InvalidProtocolBufferException {
     CatalogProtos.PartitionMethodProto.Builder partBuilder = CatalogProtos.PartitionMethodProto.newBuilder();
-    partBuilder.setTableId(tableName);
+    partBuilder.setTableIdentifier(CatalogUtil.buildTableIdentifier(databaseName, tableName));
     partBuilder.setPartitionType(CatalogProtos.PartitionType.valueOf(res.getString("partition_type")));
     partBuilder.setExpression(res.getString("expression"));
     partBuilder.setExpressionSchema(SchemaProto.parseFrom(res.getBytes("expression_schema")));
     return partBuilder.build();
   }
 
-  private CatalogProtos.PartitionDescProto resultToPartitionDescProto(ResultSet res) throws SQLException {
-    CatalogProtos.PartitionDescProto.Builder builder = CatalogProtos.PartitionDescProto.newBuilder();
-    builder.setTableId(res.getString(1));
-    builder.setPartitionName(res.getString(2));
-    builder.setOrdinalPosition(res.getInt(3));
-    builder.setPartitionValue(res.getString(4));
-    builder.setPath(res.getString(5));
-    return builder.build();
-  }
-
   @Override
   public void close() {
     CatalogUtil.closeQuietly(conn);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/CatalogStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/CatalogStore.java b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/CatalogStore.java
index db15c02..3f8686d 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/CatalogStore.java
+++ b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/CatalogStore.java
@@ -24,35 +24,59 @@ import org.apache.tajo.catalog.proto.CatalogProtos.IndexDescProto;
 
 import java.io.Closeable;
 import org.apache.tajo.catalog.exception.CatalogException;
+
+import java.util.Collection;
 import java.util.List;
 
+import static org.apache.tajo.catalog.proto.CatalogProtos.PartitionMethodProto;
+
 public interface CatalogStore extends Closeable {
+  /*************************** Tablespace ******************************/
+  void createTablespace(String spaceName, String spaceUri) throws CatalogException;
+
+  boolean existTablespace(String spaceName) throws CatalogException;
+
+  void dropTablespace(String spaceName) throws CatalogException;
+
+  Collection<String> getAllTablespaceNames() throws CatalogException;
+
+  /*************************** Database ******************************/
+  void createDatabase(String databaseName, String tablespaceName) throws CatalogException;
+
+  boolean existDatabase(String databaseName) throws CatalogException;
+
+  void dropDatabase(String databaseName) throws CatalogException;
+
+  Collection<String> getAllDatabaseNames() throws CatalogException;
+
   /*************************** TABLE ******************************/
-  void addTable(CatalogProtos.TableDescProto desc) throws CatalogException;
+  void createTable(CatalogProtos.TableDescProto desc) throws CatalogException;
   
-  boolean existTable(String name) throws CatalogException;
+  boolean existTable(String databaseName, String tableName) throws CatalogException;
   
-  void deleteTable(String name) throws CatalogException;
+  void dropTable(String databaseName, String tableName) throws CatalogException;
   
-  CatalogProtos.TableDescProto getTable(String name) throws CatalogException;
+  CatalogProtos.TableDescProto getTable(String databaseName, String tableName) throws CatalogException;
   
-  List<String> getAllTableNames() throws CatalogException;
+  List<String> getAllTableNames(String databaseName) throws CatalogException;
 
 
   /************************ PARTITION METHOD **************************/
-  void addPartitionMethod(CatalogProtos.PartitionMethodProto partitionMethodProto) throws CatalogException;
+  void addPartitionMethod(PartitionMethodProto partitionMethodProto) throws CatalogException;
 
-  CatalogProtos.PartitionMethodProto getPartitionMethod(String tableName) throws CatalogException;
+  PartitionMethodProto getPartitionMethod(String databaseName, String tableName)
+      throws CatalogException;
 
-  boolean existPartitionMethod(String tableName) throws CatalogException;
+  boolean existPartitionMethod(String databaseName, String tableName) throws CatalogException;
 
-  void delPartitionMethod(String tableName) throws CatalogException;
+  void dropPartitionMethod(String dbName, String tableName) throws CatalogException;
 
 
   /************************** PARTITIONS *****************************/
   void addPartitions(CatalogProtos.PartitionsProto partitionsProto) throws CatalogException;
 
-  void addPartition(CatalogProtos.PartitionDescProto partitionDescProto) throws CatalogException;
+  void addPartition(String databaseName, String tableName,
+                    CatalogProtos.PartitionDescProto partitionDescProto) throws CatalogException;
 
   /**
    * Get all partitions of a table
@@ -66,23 +90,27 @@ public interface CatalogStore extends Closeable {
 
   void delPartition(String partitionName) throws CatalogException;
 
-  void delPartitions(String tableName) throws CatalogException;
+  void dropPartitions(String tableName) throws CatalogException;
 
   /**************************** INDEX *******************************/
-  void addIndex(IndexDescProto proto) throws CatalogException;
+  void createIndex(IndexDescProto proto) throws CatalogException;
   
-  void delIndex(String indexName) throws CatalogException;
+  void dropIndex(String databaseName, String indexName) throws CatalogException;
   
-  IndexDescProto getIndex(String indexName) throws CatalogException;
+  IndexDescProto getIndexByName(String databaseName, String indexName) throws CatalogException;
   
-  IndexDescProto getIndex(String tableName, String columnName) throws CatalogException;
+  IndexDescProto getIndexByColumn(String databaseName, String tableName, String columnName)
+      throws CatalogException;
   
-  boolean existIndex(String indexName) throws CatalogException;
+  boolean existIndexByName(String databaseName, String indexName) throws CatalogException;
   
-  boolean existIndex(String tableName, String columnName) throws CatalogException;
+  boolean existIndexByColumn(String databaseName, String tableName, String columnName)
+      throws CatalogException;
+
+  IndexDescProto [] getIndexes(String databaseName, String tableName) throws CatalogException;
 
   /************************** FUNCTION *****************************/
-  IndexDescProto [] getIndexes(String tableName) throws CatalogException;
+
   
   void addFunction(FunctionDesc func) throws CatalogException;
   


[08/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/client/TajoClient.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/client/TajoClient.java b/tajo-client/src/main/java/org/apache/tajo/client/TajoClient.java
index 7fc6780..bf77f03 100644
--- a/tajo-client/src/main/java/org/apache/tajo/client/TajoClient.java
+++ b/tajo-client/src/main/java/org/apache/tajo/client/TajoClient.java
@@ -22,15 +22,16 @@ import com.google.protobuf.ServiceException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.tajo.QueryId;
 import org.apache.tajo.QueryIdFactory;
+import org.apache.tajo.TajoIdProtos;
 import org.apache.tajo.TajoProtos.QueryState;
+import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.annotation.ThreadSafe;
-import org.apache.tajo.catalog.CatalogUtil;
-import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.catalog.TableDesc;
-import org.apache.tajo.catalog.TableMeta;
+import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.cli.InvalidClientSessionException;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.conf.TajoConf.ConfVars;
 import org.apache.tajo.ipc.ClientProtos.*;
@@ -40,11 +41,12 @@ import org.apache.tajo.ipc.TajoMasterClientProtocol;
 import org.apache.tajo.ipc.TajoMasterClientProtocol.TajoMasterClientProtocolService;
 import org.apache.tajo.jdbc.SQLStates;
 import org.apache.tajo.jdbc.TajoResultSet;
-import org.apache.tajo.rpc.*;
-import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringProto;
-import org.apache.tajo.util.NetUtils;
+import org.apache.tajo.rpc.NettyClientBase;
+import org.apache.tajo.rpc.RpcConnectionPool;
 import org.apache.tajo.rpc.ServerCallable;
+import org.apache.tajo.util.NetUtils;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.sql.ResultSet;
@@ -54,39 +56,69 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 @ThreadSafe
-public class TajoClient {
+public class TajoClient implements Closeable {
   private final Log LOG = LogFactory.getLog(TajoClient.class);
 
   private final TajoConf conf;
 
-  private Map<QueryId, InetSocketAddress> queryMasterMap = new ConcurrentHashMap<QueryId, InetSocketAddress>();
+  private final Map<QueryId, InetSocketAddress> queryMasterMap = new ConcurrentHashMap<QueryId, InetSocketAddress>();
+
+  private final InetSocketAddress tajoMasterAddr;
+
+  private final RpcConnectionPool connPool;
 
-  private InetSocketAddress tajoMasterAddr;
+  private final String baseDatabase;
 
-  private RpcConnectionPool connPool;
+  private final UserGroupInformation userInfo;
+
+  private volatile TajoIdProtos.SessionIdProto sessionId;
 
   public TajoClient(TajoConf conf) throws IOException {
-    this(conf, NetUtils.createSocketAddr(conf.getVar(ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS)));
+    this(conf, NetUtils.createSocketAddr(conf.getVar(ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS)), null);
+  }
+
+  public TajoClient(TajoConf conf, String baseDatabase) throws IOException {
+    this(conf, NetUtils.createSocketAddr(conf.getVar(ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS)), baseDatabase);
   }
 
-  public TajoClient(TajoConf conf, InetSocketAddress addr) throws IOException {
+  public TajoClient(TajoConf conf, InetSocketAddress addr, @Nullable String baseDatabase) throws IOException {
     this.conf = conf;
     this.conf.set("tajo.disk.scheduler.report.interval", "0");
     this.tajoMasterAddr = addr;
     int workerNum = conf.getIntVar(TajoConf.ConfVars.RPC_CLIENT_WORKER_THREAD_NUM);
     //Don't share connection pool per client
     connPool = RpcConnectionPool.newPool(conf, getClass().getSimpleName(), workerNum);
+    userInfo = UserGroupInformation.getCurrentUser();
+    this.baseDatabase = baseDatabase;
+  }
+
+  public boolean isConnected() {
+    try {
+      return connPool.getConnection(tajoMasterAddr, TajoMasterClientProtocol.class, false).isConnected();
+    } catch (Exception e) {
+      return false;
+    }
   }
 
   public TajoClient(InetSocketAddress addr) throws IOException {
-    this(new TajoConf(), addr);
+    this(new TajoConf(), addr, null);
   }
 
-  public TajoClient(String hostname, int port) throws IOException {
-    this(new TajoConf(), NetUtils.createSocketAddr(hostname, port));
+  public TajoClient(String hostname, int port, String baseDatabase) throws IOException {
+    this(new TajoConf(), NetUtils.createSocketAddr(hostname, port), baseDatabase);
   }
 
+  @Override
   public void close() {
+    // remove session
+    try {
+      NettyClientBase client = connPool.getConnection(tajoMasterAddr, TajoMasterClientProtocol.class, false);
+      TajoMasterClientProtocolService.BlockingInterface tajoMaster = client.getStub();
+      tajoMaster.removeSession(null, sessionId);
+    } catch (Exception e) {
+      LOG.error(e);
+    }
+
     if(connPool != null) {
       connPool.shutdown();
     }
@@ -97,6 +129,10 @@ public class TajoClient {
     return conf;
   }
 
+  public UserGroupInformation getUserInfo() {
+    return userInfo;
+  }
+
   /**
    * Call to QueryMaster closing query resources
    * @param queryId
@@ -117,15 +153,134 @@ public class TajoClient {
     }
   }
 
+  private void checkSessionAndGet(NettyClientBase client) throws ServiceException {
+    if (sessionId == null) {
+      TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+      CreateSessionRequest.Builder builder = CreateSessionRequest.newBuilder();
+      builder.setUsername(userInfo.getUserName()).build();
+      if (baseDatabase != null) {
+        builder.setBaseDatabaseName(baseDatabase);
+      }
+      CreateSessionResponse response = tajoMasterService.createSession(null, builder.build());
+      if (response.getState() == CreateSessionResponse.ResultState.SUCCESS) {
+        sessionId = response.getSessionId();
+        LOG.info(String.format("Got session %s as a user '%s'.", sessionId.getId(), userInfo.getUserName()));
+      } else {
+        throw new InvalidClientSessionException(response.getMessage());
+      }
+    }
+  }
+
+  private SessionedStringProto convertSessionedString(String str) {
+    SessionedStringProto.Builder builder = SessionedStringProto.newBuilder();
+    builder.setSessionId(sessionId);
+    builder.setValue(str);
+    return builder.build();
+  }
+
+  public String getCurrentDatabase() throws ServiceException {
+    return new ServerCallable<String>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+
+      public String call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        return tajoMasterService.getCurrentDatabase(null, sessionId).getValue();
+      }
+    }.withRetries();
+  }
+
+  public Boolean selectDatabase(final String databaseName) throws ServiceException {
+    return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+
+      public Boolean call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        return tajoMasterService.selectDatabase(null, convertSessionedString(databaseName)).getValue();
+      }
+    }.withRetries();
+  }
+
+  public Boolean updateSessionVariables(final Map<String, String> variables) throws ServiceException {
+    return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+
+      public Boolean call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        Options options = new Options();
+        options.putAll(variables);
+        UpdateSessionVariableRequest request = UpdateSessionVariableRequest.newBuilder()
+            .setSessionId(sessionId)
+            .setSetVariables(options.getProto()).build();
+
+        return tajoMasterService.updateSessionVariables(null, request).getValue();
+      }
+    }.withRetries();
+  }
+
+  public Boolean unsetSessionVariables(final List<String> variables)  throws ServiceException {
+    return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+
+      public Boolean call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        UpdateSessionVariableRequest request = UpdateSessionVariableRequest.newBuilder()
+            .setSessionId(sessionId)
+            .addAllUnsetVariables(variables).build();
+        return tajoMasterService.updateSessionVariables(null, request).getValue();
+      }
+    }.withRetries();
+  }
+
+  public String getSessionVariable(final String varname) throws ServiceException {
+    return new ServerCallable<String>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+
+      public String call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        return tajoMasterService.getSessionVariable(null, convertSessionedString(varname)).getValue();
+      }
+    }.withRetries();
+  }
+
+  public Boolean existSessionVariable(final String varname) throws ServiceException {
+    return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+
+      public Boolean call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        return tajoMasterService.existSessionVariable(null, convertSessionedString(varname)).getValue();
+      }
+    }.withRetries();
+  }
+
+  public Map<String, String> getAllSessionVariables() throws ServiceException {
+    return new ServerCallable<Map<String, String>>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class,
+        false, true) {
+
+      public Map<String, String> call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        Options options = new Options(tajoMasterService.getAllSessionVariables(null, sessionId));
+        return options.getAllKeyValus();
+      }
+    }.withRetries();
+  }
+
   public ExplainQueryResponse explainQuery(final String sql) throws ServiceException {
     return new ServerCallable<ExplainQueryResponse>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public ExplainQueryResponse call(NettyClientBase client) throws ServiceException {
-        final ExplainQueryRequest.Builder builder = ExplainQueryRequest.newBuilder();
-        builder.setQuery(sql);
+        checkSessionAndGet(client);
 
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
-        return tajoMasterService.explainQuery(null, builder.build());
+        return tajoMasterService.explainQuery(null, convertSessionedString(sql));
       }
     }.withRetries();
   }
@@ -140,9 +295,11 @@ public class TajoClient {
     return new ServerCallable<GetQueryStatusResponse>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public GetQueryStatusResponse call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
         final QueryRequest.Builder builder = QueryRequest.newBuilder();
+        builder.setSessionId(sessionId);
         builder.setQuery(sql);
-
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
         return tajoMasterService.submitQuery(null, builder.build());
       }
@@ -162,7 +319,10 @@ public class TajoClient {
     GetQueryStatusResponse response = new ServerCallable<GetQueryStatusResponse>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public GetQueryStatusResponse call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
         final QueryRequest.Builder builder = QueryRequest.newBuilder();
+        builder.setSessionId(sessionId);
         builder.setQuery(sql);
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
         return tajoMasterService.submitQuery(null, builder.build());
@@ -178,8 +338,7 @@ public class TajoClient {
   }
 
   public QueryStatus getQueryStatus(QueryId queryId) throws ServiceException {
-    GetQueryStatusRequest.Builder builder
-        = GetQueryStatusRequest.newBuilder();
+    GetQueryStatusRequest.Builder builder = GetQueryStatusRequest.newBuilder();
     builder.setQueryId(queryId.getProto());
 
     GetQueryStatusResponse res = null;
@@ -198,8 +357,11 @@ public class TajoClient {
     } else {
       NettyClientBase tmClient = null;
       try {
-        tmClient = connPool.getConnection(tajoMasterAddr,
-            TajoMasterClientProtocol.class, false);
+        tmClient = connPool.getConnection(tajoMasterAddr, TajoMasterClientProtocol.class, false);
+
+        checkSessionAndGet(tmClient);
+        builder.setSessionId(sessionId);
+
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = tmClient.getStub();
         res = tajoMasterService.getQueryStatus(null, builder.build());
 
@@ -315,9 +477,11 @@ public class TajoClient {
     return new ServerCallable<Boolean>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public Boolean call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
         QueryRequest.Builder builder = QueryRequest.newBuilder();
+        builder.setSessionId(sessionId);
         builder.setQuery(sql);
-
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
         UpdateQueryResponse response = tajoMasterService.updateQuery(null, builder.build());
         if (response.getResultCode() == ResultCode.OK) {
@@ -332,6 +496,46 @@ public class TajoClient {
     }.withRetries();
   }
 
+  public boolean createDatabase(final String databaseName) throws ServiceException {
+    return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+      public Boolean call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        return tajoMasterService.createDatabase(null, convertSessionedString(databaseName)).getValue();
+      }
+    }.withRetries();
+  }
+
+  public boolean existDatabase(final String databaseName) throws ServiceException {
+    return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+      public Boolean call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        return tajoMasterService.existDatabase(null, convertSessionedString(databaseName)).getValue();
+      }
+    }.withRetries();
+  }
+
+  public boolean dropDatabase(final String databaseName) throws ServiceException {
+    return new ServerCallable<Boolean>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+      public Boolean call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        return tajoMasterService.dropDatabase(null, convertSessionedString(databaseName)).getValue();
+      }
+    }.withRetries();
+  }
+
+  public List<String> getAllDatabaseNames() throws ServiceException {
+    return new ServerCallable<List<String>>(connPool, tajoMasterAddr, TajoMasterClientProtocol.class, false, true) {
+      public List<String> call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        return tajoMasterService.getAllDatabases(null, sessionId).getValuesList();
+      }
+    }.withRetries();
+  }
+
   /**
    * Test for the existence of table in catalog data.
    * <p/>
@@ -344,11 +548,9 @@ public class TajoClient {
     return new ServerCallable<Boolean>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public Boolean call(NettyClientBase client) throws ServiceException {
-        StringProto.Builder builder = StringProto.newBuilder();
-        builder.setValue(name);
-
+        checkSessionAndGet(client);
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
-        return tajoMasterService.existTable(null, builder.build()).getValue();
+        return tajoMasterService.existTable(null, convertSessionedString(name)).getValue();
       }
     }.withRetries();
   }
@@ -358,9 +560,12 @@ public class TajoClient {
     return new ServerCallable<TableDesc>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public TableDesc call(NettyClientBase client) throws ServiceException, SQLException {
+        checkSessionAndGet(client);
+
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
 
         CreateTableRequest.Builder builder = CreateTableRequest.newBuilder();
+        builder.setSessionId(sessionId);
         builder.setName(name);
         builder.setSchema(schema.getProto());
         builder.setMeta(meta.getProto());
@@ -389,9 +594,12 @@ public class TajoClient {
     return new ServerCallable<Boolean>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public Boolean call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
 
         DropTableRequest.Builder builder = DropTableRequest.newBuilder();
+        builder.setSessionId(sessionId);
         builder.setName(tableName);
         builder.setPurge(purge);
         return tajoMasterService.dropTable(null, builder.build()).getValue();
@@ -404,9 +612,11 @@ public class TajoClient {
     return new ServerCallable<List<BriefQueryInfo>>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public List<BriefQueryInfo> call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
 
         GetQueryListRequest.Builder builder = GetQueryListRequest.newBuilder();
+        builder.setSessionId(sessionId);
         GetQueryListResponse res = tajoMasterService.getRunningQueryList(null, builder.build());
         return res.getQueryListList();
       }
@@ -420,6 +630,7 @@ public class TajoClient {
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
 
         GetQueryListRequest.Builder builder = GetQueryListRequest.newBuilder();
+        builder.setSessionId(sessionId);
         GetQueryListResponse res = tajoMasterService.getFinishedQueryList(null, builder.build());
         return res.getQueryListList();
       }
@@ -430,9 +641,12 @@ public class TajoClient {
     return new ServerCallable<List<WorkerResourceInfo>>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public List<WorkerResourceInfo> call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
 
         GetClusterInfoRequest.Builder builder = GetClusterInfoRequest.newBuilder();
+        builder.setSessionId(sessionId);
         GetClusterInfoResponse res = tajoMasterService.getClusterInfo(null, builder.build());
         return res.getWorkerListList();
       }
@@ -442,29 +656,41 @@ public class TajoClient {
   /**
    * Get a list of table names. All table and column names are
    * represented as lower-case letters.
+   *
+   * @param databaseName The database name to show all tables. If it is null, this method will show all tables
+   *                     in the current database of this session.
    */
-  public List<String> getTableList() throws ServiceException {
+  public List<String> getTableList(@Nullable final String databaseName) throws ServiceException {
     return new ServerCallable<List<String>>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public List<String> call(NettyClientBase client) throws ServiceException {
+        checkSessionAndGet(client);
+
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
 
         GetTableListRequest.Builder builder = GetTableListRequest.newBuilder();
+        builder.setSessionId(sessionId);
+        if (databaseName != null) {
+          builder.setDatabaseName(databaseName);
+        }
         GetTableListResponse res = tajoMasterService.getTableList(null, builder.build());
         return res.getTablesList();
       }
     }.withRetries();
   }
 
-  public TableDesc getTableDesc(final String tableName) throws SQLException, ServiceException {
+  public TableDesc getTableDesc(final String tableName) throws ServiceException {
     return new ServerCallable<TableDesc>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public TableDesc call(NettyClientBase client) throws ServiceException, SQLException {
+        checkSessionAndGet(client);
+
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
 
-        GetTableDescRequest.Builder build = GetTableDescRequest.newBuilder();
-        build.setTableName(tableName);
-        TableResponse res = tajoMasterService.getTableDesc(null, build.build());
+        GetTableDescRequest.Builder builder = GetTableDescRequest.newBuilder();
+        builder.setSessionId(sessionId);
+        builder.setTableName(tableName);
+        TableResponse res = tajoMasterService.getTableDesc(null, builder.build());
         if (res.getResultCode() == ResultCode.OK) {
           return CatalogUtil.newTableDesc(res.getTableDesc());
         } else {
@@ -484,7 +710,13 @@ public class TajoClient {
       /* send a kill to the TM */
       tmClient = connPool.getConnection(tajoMasterAddr, TajoMasterClientProtocol.class, false);
       TajoMasterClientProtocolService.BlockingInterface tajoMasterService = tmClient.getStub();
-      tajoMasterService.killQuery(null, queryId.getProto());
+
+      checkSessionAndGet(tmClient);
+
+      KillQueryRequest.Builder builder = KillQueryRequest.newBuilder();
+      builder.setSessionId(sessionId);
+      builder.setQueryId(queryId.getProto());
+      tajoMasterService.killQuery(null, builder.build());
 
       long currentTimeMillis = System.currentTimeMillis();
       long timeKillIssued = currentTimeMillis;
@@ -510,12 +742,11 @@ public class TajoClient {
     return new ServerCallable<List<CatalogProtos.FunctionDescProto>>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
       public List<CatalogProtos.FunctionDescProto> call(NettyClientBase client) throws ServiceException, SQLException {
-        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
+        checkSessionAndGet(client);
 
+        TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
         String paramFunctionName = functionName == null ? "" : functionName;
-
-        FunctionResponse res = tajoMasterService.getFunctionList(null,
-            StringProto.newBuilder().setValue(paramFunctionName).build());
+        FunctionResponse res = tajoMasterService.getFunctionList(null,convertSessionedString(paramFunctionName));
         if (res.getResultCode() == ResultCode.OK) {
           return res.getFunctionsList();
         } else {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/client/TajoDump.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/client/TajoDump.java b/tajo-client/src/main/java/org/apache/tajo/client/TajoDump.java
index 486ff9f..9aaef8e 100644
--- a/tajo-client/src/main/java/org/apache/tajo/client/TajoDump.java
+++ b/tajo-client/src/main/java/org/apache/tajo/client/TajoDump.java
@@ -18,21 +18,21 @@
 
 package org.apache.tajo.client;
 
-import com.google.common.collect.Lists;
 import com.google.protobuf.ServiceException;
 import org.apache.commons.cli.*;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.DDLBuilder;
 import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.util.Pair;
 
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.io.Writer;
 import java.sql.SQLException;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
-import java.util.List;
 
 public class TajoDump {
   private static final org.apache.commons.cli.Options options;
@@ -46,15 +46,10 @@ public class TajoDump {
 
   private static void printUsage() {
     HelpFormatter formatter = new HelpFormatter();
-    formatter.printHelp( "tajo_dump [options] [table_name]", options );
+    formatter.printHelp( "tajo_dump [options] [database name]", options);
   }
 
-  public static void main(String [] args) throws ParseException, IOException, ServiceException, SQLException {
-    TajoConf conf = new TajoConf();
-
-    CommandLineParser parser = new PosixParser();
-    CommandLine cmd = parser.parse(options, args);
-
+  private static Pair<String, Integer> getConnectionAddr(TajoConf conf, CommandLine cmd) {
     String hostName = null;
     Integer port = null;
     if (cmd.hasOption("h")) {
@@ -64,25 +59,44 @@ public class TajoDump {
       port = Integer.parseInt(cmd.getOptionValue("p"));
     }
 
-    // if there is no "-h" option,
     if(hostName == null) {
       if (conf.getVar(TajoConf.ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS) != null) {
-        // it checks if the client service address is given in configuration and distributed mode.
-        // if so, it sets entryAddr.
         hostName = conf.getVar(TajoConf.ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS).split(":")[0];
       }
     }
     if (port == null) {
       if (conf.getVar(TajoConf.ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS) != null) {
-        // it checks if the client service address is given in configuration and distributed mode.
-        // if so, it sets entryAddr.
         port = Integer.parseInt(conf.getVar(TajoConf.ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS).split(":")[1]);
       }
     }
+    return new Pair<String, Integer>(hostName, port);
+  }
+
+  public static void main(String [] args) throws ParseException, IOException, ServiceException, SQLException {
+    final TajoConf conf = new TajoConf();
+    final CommandLineParser parser = new PosixParser();
+    final CommandLine cmd = parser.parse(options, args);
+    final Pair<String, Integer> hostAndPort = getConnectionAddr(conf, cmd);
+    final String hostName = hostAndPort.getFirst();
+    final Integer port = hostAndPort.getSecond();
+    final UserGroupInformation userInfo = UserGroupInformation.getCurrentUser();
+
+    String baseDatabaseName = null;
+    if (cmd.getArgList().size() > 0) {
+      baseDatabaseName = (String) cmd.getArgList().get(0);
+    }
+
+    boolean isDumpingAllDatabases = cmd.hasOption('a');
+
+    // Neither two choices
+    if (!isDumpingAllDatabases && baseDatabaseName == null) {
+      printUsage();
+      System.exit(-1);
+    }
 
     TajoClient client = null;
     if ((hostName == null) ^ (port == null)) {
-      System.err.println("ERROR: cannot find valid Tajo server address");
+      System.err.println("ERROR: cannot find any TajoMaster rpc address in arguments and tajo-site.xml.");
       System.exit(-1);
     } else if (hostName != null && port != null) {
       conf.setVar(TajoConf.ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS, hostName+":"+port);
@@ -91,34 +105,53 @@ public class TajoDump {
       client = new TajoClient(conf);
     }
 
-    List<TableDesc> tableDescList = Lists.newArrayList();
+    PrintWriter writer = new PrintWriter(System.out);
 
-    if (cmd.hasOption("a")) {
-      for (String tableName : client.getTableList()) {
-        tableDescList.add(client.getTableDesc(tableName));
-      }
-    } else if (cmd.getArgs().length > 0) {
-      for (String tableName : cmd.getArgs()) {
-        tableDescList.add(client.getTableDesc(tableName));
+    printHeader(writer, userInfo);
+
+    if (isDumpingAllDatabases) {
+      for (String databaseName : client.getAllDatabaseNames()) {
+        dumpDatabase(client, databaseName, writer);
       }
     } else {
-      printUsage();
+      dumpDatabase(client, baseDatabaseName, writer);
     }
+    client.close();
 
+    writer.flush();
+    writer.close();
+    System.exit(0);
+  }
 
-    Writer writer = new PrintWriter(System.out);
+  private static void printHeader(PrintWriter writer, UserGroupInformation userInfo) {
     writer.write("--\n");
     writer.write("-- Tajo database dump\n");
+    writer.write("--\n");
+    writer.write("-- Dump user: " + userInfo.getUserName() + "\n");
     writer.write("-- Dump date: " + toDateString() + "\n");
     writer.write("--\n");
     writer.write("\n");
-    for (TableDesc tableDesc : tableDescList) {
-      writer.write(DDLBuilder.buildDDL(tableDesc));
+  }
+
+  private static void dumpDatabase(TajoClient client, String databaseName, PrintWriter writer)
+      throws SQLException, ServiceException {
+    writer.write("\n");
+    writer.write("--\n");
+    writer.write(String.format("-- Database name: %s%n", databaseName));
+    writer.write("--\n");
+    writer.write("\n");
+    writer.write(String.format("CREATE DATABASE IF NOT EXISTS %s;", databaseName));
+    writer.write("\n");
+
+    for (String tableName : client.getTableList(databaseName)) {
+      TableDesc table = client.getTableDesc(CatalogUtil.buildFQName(databaseName, tableName));
+      if (table.isExternal()) {
+        writer.write(DDLBuilder.buildDDLForExternalTable(table));
+      } else {
+        writer.write(DDLBuilder.buildDDLForBaseTable(table));
+      }
       writer.write("\n\n");
     }
-    writer.flush();
-    writer.close();
-    System.exit(0);
   }
 
   private static String toDateString() {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetBase.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetBase.java b/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetBase.java
index f4d685f..577fe0e 100644
--- a/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetBase.java
+++ b/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetBase.java
@@ -51,6 +51,10 @@ public abstract class TajoResultSetBase implements ResultSet {
     wasNull = (d instanceof NullDatum);
   }
 
+  public Tuple getCurrentTuple() {
+    return cur;
+  }
+
   @Override
   public void beforeFirst() throws SQLException {
     init();

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java b/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java
index 4f2e586..5b7f822 100644
--- a/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java
+++ b/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoResultSetMetaData.java
@@ -21,6 +21,8 @@
  */
 package org.apache.tajo.jdbc;
 
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.client.ResultSetUtil;
 import org.apache.tajo.common.TajoDataTypes.DataType;
@@ -32,7 +34,7 @@ import java.sql.SQLFeatureNotSupportedException;
 public class TajoResultSetMetaData implements ResultSetMetaData {
   Schema schema;
 
-  
+
   public TajoResultSetMetaData(Schema schema) {
     this.schema = schema;
   }
@@ -49,7 +51,11 @@ public class TajoResultSetMetaData implements ResultSetMetaData {
 
   @Override
   public String getCatalogName(int column) throws SQLException {
-    throw new SQLFeatureNotSupportedException("getCatalogName not supported");
+    Column c = schema.getColumn(column - 1);
+    if (CatalogUtil.isFQColumnName(c.getQualifiedName())) {
+      return CatalogUtil.splitFQTableName(c.getQualifier())[0];
+    }
+    return "";
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/proto/ClientProtos.proto
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/proto/ClientProtos.proto b/tajo-client/src/main/proto/ClientProtos.proto
index c0c9462..6e69a66 100644
--- a/tajo-client/src/main/proto/ClientProtos.proto
+++ b/tajo-client/src/main/proto/ClientProtos.proto
@@ -31,14 +31,30 @@ enum ResultCode {
   ERROR = 1;
 }
 
+message CreateSessionRequest {
+  required string username = 1;
+  optional string baseDatabaseName = 2;
+}
+
+message CreateSessionResponse {
+  enum ResultState {
+      SUCCESS = 0;
+      FAILED = 1;
+  }
+  required ResultState state = 1;
+  optional SessionIdProto sessionId = 2;
+  optional string message = 3;
+}
+
 message UpdateSessionVariableRequest {
   optional SessionIdProto sessionId = 1;
-  repeated KeyValueProto setVariables = 2;
+  optional KeyValueSetProto setVariables = 2;
   repeated string unsetVariables = 3;
 }
 
-message ExplainQueryRequest {
-  required string query = 1;
+message SessionedStringProto {
+  optional SessionIdProto sessionId = 1;
+  required string value = 2;
 }
 
 message ExplainQueryResponse {
@@ -75,6 +91,11 @@ message GetQueryResultResponse {
   required string tajoUserName = 3;
 }
 
+message KillQueryRequest {
+  optional SessionIdProto sessionId = 1;
+  required QueryIdProto queryId = 2;
+}
+
 message GetQueryListRequest {
   optional SessionIdProto sessionId = 1;
 }
@@ -146,6 +167,7 @@ message GetClusterInfoResponse {
 
 message GetTableListRequest {
   optional SessionIdProto sessionId = 1;
+  optional string databaseName = 2;
 }
 
 message GetTableListResponse {
@@ -158,16 +180,18 @@ message GetTableDescRequest {
 }
 
 message CreateTableRequest {
-  required string name = 1;
-  required SchemaProto schema = 2;
-  required TableProto meta = 3;
-  required string path = 4;
-  optional PartitionMethodProto partition = 5;
+  optional SessionIdProto sessionId = 1;
+  required string name = 2;
+  required SchemaProto schema = 3;
+  required TableProto meta = 4;
+  required string path = 5;
+  optional PartitionMethodProto partition = 6;
 }
 
 message DropTableRequest {
-  required string name = 1;
-  optional bool purge = 2 [default = false];
+  optional SessionIdProto sessionId = 1;
+  required string name = 2;
+  optional bool purge = 3 [default = false];
 }
 
 message TableResponse {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-client/src/main/proto/TajoMasterClientProtocol.proto
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/proto/TajoMasterClientProtocol.proto b/tajo-client/src/main/proto/TajoMasterClientProtocol.proto
index 93e5af9..3bfd9df 100644
--- a/tajo-client/src/main/proto/TajoMasterClientProtocol.proto
+++ b/tajo-client/src/main/proto/TajoMasterClientProtocol.proto
@@ -29,34 +29,41 @@ import "PrimitiveProtos.proto";
 import "ClientProtos.proto";
 
 service TajoMasterClientProtocolService {
+
+  // Session APIs
+  rpc createSession(CreateSessionRequest) returns (CreateSessionResponse);
+  rpc removeSession(SessionIdProto) returns (BoolProto);
   rpc updateSessionVariables(UpdateSessionVariableRequest) returns (BoolProto);
+  rpc existSessionVariable(SessionedStringProto) returns (BoolProto);
+  rpc getSessionVariable(SessionedStringProto) returns (StringProto);
+  rpc getAllSessionVariables(SessionIdProto) returns (KeyValueSetProto);
+
+  // Query Submission and Result APIs
+  rpc explainQuery(SessionedStringProto) returns (ExplainQueryResponse);
   rpc submitQuery(QueryRequest) returns (GetQueryStatusResponse);
   rpc updateQuery(QueryRequest) returns (UpdateQueryResponse);
-  rpc explainQuery(ExplainQueryRequest) returns (ExplainQueryResponse);
   rpc getQueryResult(GetQueryResultRequest) returns (GetQueryResultResponse);
+
+  // Query And Resource Management APIs
+  rpc getQueryStatus(GetQueryStatusRequest) returns (GetQueryStatusResponse);
   rpc getRunningQueryList(GetQueryListRequest) returns (GetQueryListResponse);
   rpc getFinishedQueryList(GetQueryListRequest) returns (GetQueryListResponse);
-  rpc getQueryStatus(GetQueryStatusRequest) returns (GetQueryStatusResponse);
-  rpc killQuery(QueryIdProto) returns (BoolProto);
+  rpc killQuery(KillQueryRequest) returns (BoolProto);
   rpc getClusterInfo(GetClusterInfoRequest) returns (GetClusterInfoResponse);
-  rpc existTable(StringProto) returns (BoolProto);
-  rpc getTableList(GetTableListRequest) returns (GetTableListResponse);
-  rpc getTableDesc(GetTableDescRequest) returns (TableResponse);
+
+  // Database Management APIs
+  rpc createDatabase(SessionedStringProto) returns (BoolProto);
+  rpc existDatabase(SessionedStringProto) returns (BoolProto);
+  rpc dropDatabase(SessionedStringProto) returns (BoolProto);
+  rpc getAllDatabases(SessionIdProto) returns (StringListProto);
+  rpc getCurrentDatabase(SessionIdProto) returns (StringProto);
+  rpc selectDatabase(SessionedStringProto) returns (BoolProto);
+
+  // Table Management APIs
   rpc createExternalTable(CreateTableRequest) returns (TableResponse);
+  rpc existTable(SessionedStringProto) returns (BoolProto);
   rpc dropTable(DropTableRequest) returns (BoolProto);
-  rpc getFunctionList(StringProto) returns (FunctionResponse);
-
-  // TODO - to be implemented
-  //
-  // authenticate
-  //
-  // getSessionVariableList
-  // detachTable
-  // createIndex
-  // dropIndex
-  // registerUDF
-  // dropUDF
-  // getUDFDesc
-  // registerJars
-  // getListRegisteredJars
+  rpc getTableList(GetTableListRequest) returns (GetTableListResponse);
+  rpc getTableDesc(GetTableDescRequest) returns (TableResponse);
+  rpc getFunctionList(SessionedStringProto) returns (FunctionResponse);
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/java/org/apache/tajo/TajoConstants.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/TajoConstants.java b/tajo-common/src/main/java/org/apache/tajo/TajoConstants.java
index d4ce48f..61eecd1 100644
--- a/tajo-common/src/main/java/org/apache/tajo/TajoConstants.java
+++ b/tajo-common/src/main/java/org/apache/tajo/TajoConstants.java
@@ -27,6 +27,11 @@ public class TajoConstants {
   public static final String SYSTEM_RESOURCE_DIR_NAME = "resource";
   public static final String RESULT_DIR_NAME="RESULT";
 
+  public static final String DEFAULT_TABLESPACE_NAME = "default";
+  public static final String DEFAULT_DATABASE_NAME = "default";
+  public static final String DEFAULT_SCHEMA_NAME = "public";
+
+
   public static final String EMPTY_STRING = "";
 
   private TajoConstants() {}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/java/org/apache/tajo/conf/TajoConf.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/conf/TajoConf.java b/tajo-common/src/main/java/org/apache/tajo/conf/TajoConf.java
index 3ca17a0..befaa98 100644
--- a/tajo-common/src/main/java/org/apache/tajo/conf/TajoConf.java
+++ b/tajo-common/src/main/java/org/apache/tajo/conf/TajoConf.java
@@ -234,6 +234,11 @@ public class TajoConf extends Configuration {
     TASK_DEFAULT_SIZE("tajo.task.size-mb", 128),
     //////////////////////////////////
 
+    //////////////////////////////////
+    // User Session Configuration
+    //////////////////////////////////
+    CLIENT_SESSION_EXPIRY_TIME("tajo.client.session.expiry-time-sec", 3600), // default time is one hour.
+
     // Metrics
     METRICS_PROPERTY_FILENAME("tajo.metrics.property.file", "tajo-metrics.properties"),
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/java/org/apache/tajo/util/CommonTestingUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/CommonTestingUtil.java b/tajo-common/src/main/java/org/apache/tajo/util/CommonTestingUtil.java
index cae7129..8dd8bfe 100644
--- a/tajo-common/src/main/java/org/apache/tajo/util/CommonTestingUtil.java
+++ b/tajo-common/src/main/java/org/apache/tajo/util/CommonTestingUtil.java
@@ -55,8 +55,9 @@ public class CommonTestingUtil {
     String randomStr = UUID.randomUUID().toString();
     Path path = new Path("target/test-data", randomStr);
     FileSystem fs = FileSystem.getLocal(new Configuration());
-    if(fs.exists(path))
+    if(fs.exists(path)) {
       fs.delete(path, true);
+    }
 
     fs.mkdirs(path);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/java/org/apache/tajo/util/FileUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/FileUtil.java b/tajo-common/src/main/java/org/apache/tajo/util/FileUtil.java
index 778bcbb..6bbce04 100644
--- a/tajo-common/src/main/java/org/apache/tajo/util/FileUtil.java
+++ b/tajo-common/src/main/java/org/apache/tajo/util/FileUtil.java
@@ -19,13 +19,11 @@
 package org.apache.tajo.util;
 
 import com.google.protobuf.Message;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.*;
 import org.apache.hadoop.io.IOUtils;
 
 import java.io.*;
+import java.nio.charset.Charset;
 
 public class FileUtil {
   public static void writeProto(File file, Message proto) throws IOException {
@@ -83,6 +81,22 @@ public class FileUtil {
     return new File(path);
   }
 
+  public static String readTextFileFromResource(String resource) throws IOException {
+    StringBuilder fileData = new StringBuilder(1000);
+    InputStream inputStream = ClassLoader.getSystemResourceAsStream(resource);
+    byte[] buf = new byte[1024];
+    int numRead;
+    try {
+      while ((numRead = inputStream.read(buf)) != -1) {
+        String readData = new String(buf, 0, numRead, Charset.defaultCharset());
+        fileData.append(readData);
+      }
+    } finally {
+      IOUtils.cleanup(null, inputStream);
+    }
+    return fileData.toString();
+  }
+
   public static String readTextFile(File file) throws IOException {
     StringBuilder fileData = new StringBuilder(1000);
     BufferedReader reader = new BufferedReader(new FileReader(file));

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/java/org/apache/tajo/util/Pair.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/Pair.java b/tajo-common/src/main/java/org/apache/tajo/util/Pair.java
new file mode 100644
index 0000000..72cfc5c
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/util/Pair.java
@@ -0,0 +1,37 @@
+/**
+ * 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.util;
+
+public class Pair<T1, T2> {
+  private final T1 value1;
+  private final T2 value2;
+
+  public Pair(T1 value1, T2 value2) {
+    this.value1 = value1;
+    this.value2 = value2;
+  }
+
+  public T1 getFirst() {
+    return value1;
+  }
+
+  public T2 getSecond() {
+    return value2;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/java/org/apache/tajo/util/ProtoBufUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/ProtoBufUtil.java b/tajo-common/src/main/java/org/apache/tajo/util/ProtoBufUtil.java
deleted file mode 100644
index 0dc7f24..0000000
--- a/tajo-common/src/main/java/org/apache/tajo/util/ProtoBufUtil.java
+++ /dev/null
@@ -1,26 +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.util;
-
-import static org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.BoolProto;
-
-public class ProtoBufUtil {
-  public static final BoolProto TRUE = BoolProto.newBuilder().setValue(true).build();
-  public static final BoolProto FALSE = BoolProto.newBuilder().setValue(true).build();
-}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/java/org/apache/tajo/util/ProtoUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/ProtoUtil.java b/tajo-common/src/main/java/org/apache/tajo/util/ProtoUtil.java
new file mode 100644
index 0000000..90ffb64
--- /dev/null
+++ b/tajo-common/src/main/java/org/apache/tajo/util/ProtoUtil.java
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.util;
+
+import java.util.Collection;
+
+import static org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.*;
+
+public class ProtoUtil {
+  public static final BoolProto TRUE = BoolProto.newBuilder().setValue(true).build();
+  public static final BoolProto FALSE = BoolProto.newBuilder().setValue(false).build();
+
+  public static final NullProto NULL_PROTO = NullProto.newBuilder().build();
+
+  public static StringProto convertString(String value) {
+    return StringProto.newBuilder().setValue(value).build();
+  }
+
+  public static StringListProto convertStrings(Collection<String> strings) {
+    return StringListProto.newBuilder().addAllValues(strings).build();
+  }
+
+  public static Collection<String> convertStrings(StringListProto strings) {
+    return strings.getValuesList();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java b/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java
index b5aa61c..ad60a50 100644
--- a/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java
+++ b/tajo-common/src/main/java/org/apache/tajo/util/StringUtils.java
@@ -54,4 +54,12 @@ public class StringUtils {
     }
     return buf.toString();
   }
+
+  public static String quote(String str) {
+    return "'" + str + "'";
+  }
+
+  public static String doubleQuote(String str) {
+    return "\"" + str + "\"";
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 1eb55bc..e116000 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
@@ -213,4 +213,16 @@ public class TUtil {
     T array = (T) Array.newInstance(type, collection.size());
     return collection.toArray((T[]) array);
   }
+
+  /**
+   * It returns the exact code point at which this running thread is executed.
+   *
+   * @param depth in the call stack (0 means current method, 1 means call method, ...)
+   * @return A string including class name, method, and line.
+   */
+  public static String getCurrentCodePoint(final int depth) {
+    final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
+    StackTraceElement element = ste[2 + depth];
+    return element.getClassName() + ":" + element.getMethodName() + "(" + element.getLineNumber() +")";
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/proto/PrimitiveProtos.proto
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/proto/PrimitiveProtos.proto b/tajo-common/src/main/proto/PrimitiveProtos.proto
index e722190..820f96c 100644
--- a/tajo-common/src/main/proto/PrimitiveProtos.proto
+++ b/tajo-common/src/main/proto/PrimitiveProtos.proto
@@ -39,3 +39,7 @@ message BoolProto {
 
 message NullProto {
 }
+
+message StringListProto {
+  repeated string values = 1;
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-common/src/main/proto/TajoIdProtos.proto
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/proto/TajoIdProtos.proto b/tajo-common/src/main/proto/TajoIdProtos.proto
index a87c825..1fb8bbd 100644
--- a/tajo-common/src/main/proto/TajoIdProtos.proto
+++ b/tajo-common/src/main/proto/TajoIdProtos.proto
@@ -42,5 +42,5 @@ message QueryUnitAttemptIdProto {
 }
 
 message SessionIdProto {
-  required string sid = 1;
+  required string id = 1;
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/pom.xml
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/pom.xml b/tajo-core/tajo-core-backend/pom.xml
index d073736..1a67fa7 100644
--- a/tajo-core/tajo-core-backend/pom.xml
+++ b/tajo-core/tajo-core-backend/pom.xml
@@ -68,7 +68,7 @@
           <systemProperties>
             <tajo.test>TRUE</tajo.test>
           </systemProperties>
-          <argLine>-Xms512m -Xmx1024m -Dfile.encoding=UTF-8</argLine>
+          <argLine>-Xms512m -Xmx1024m -XX:MaxPermSize=128m -Dfile.encoding=UTF-8</argLine>
         </configuration>
       </plugin>
       <plugin>
@@ -501,6 +501,214 @@
         </plugins>
       </build>
     </profile>
+    <profile>
+      <id>hcatalog-0.12.0</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.thrift</groupId>
+          <artifactId>libfb303</artifactId>
+          <version>0.9.0</version>
+          <scope>test</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.thrift</groupId>
+          <artifactId>libthrift</artifactId>
+          <version>0.9.0</version>
+          <scope>test</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.tajo</groupId>
+          <artifactId>tajo-hcatalog</artifactId>
+          <scope>test</scope>
+          <version>${tajo.version}</version>
+          <exclusions>
+            <exclusion>
+              <groupId>com.google.protobuf</groupId>
+              <artifactId>protobuf-java</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.hive</groupId>
+          <artifactId>hive-exec</artifactId>
+          <version>0.12.0</version>
+          <scope>provided</scope>
+          <exclusions>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-common</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-contrib</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-hbase-handler</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-metastore</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-serde</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-shims</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-testutils</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.thrift</groupId>
+              <artifactId>libfb303</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.thrift</groupId>
+              <artifactId>libthrift</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>com.jolbox</groupId>
+              <artifactId>bonecp</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hbase</groupId>
+              <artifactId>hbase</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>com.google.protobuf</groupId>
+              <artifactId>protobuf-java</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.hive</groupId>
+          <artifactId>hive-metastore</artifactId>
+          <version>0.12.0</version>
+          <scope>provided</scope>
+          <exclusions>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-common</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-serde</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-shimss</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.thrift</groupId>
+              <artifactId>libfb303</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.thrift</groupId>
+              <artifactId>libthrift</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>com.jolbox</groupId>
+              <artifactId>bonecp</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>com.google.protobuf</groupId>
+              <artifactId>protobuf-java</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.hive</groupId>
+          <artifactId>hive-cli</artifactId>
+          <version>0.12.0</version>
+          <scope>provided</scope>
+          <exclusions>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-common</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-exec</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-metastore</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-serde</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-service</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-shims</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>com.jolbox</groupId>
+              <artifactId>bonecp</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>com.google.protobuf</groupId>
+              <artifactId>protobuf-java</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.hive.hcatalog</groupId>
+          <artifactId>hcatalog-core</artifactId>
+          <version>0.12.0</version>
+          <scope>provided</scope>
+          <exclusions>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-cli</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-common</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-exec</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-metastore</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-serde</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-service</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>org.apache.hive</groupId>
+              <artifactId>hive-shims</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>com.jolbox</groupId>
+              <artifactId>bonecp</artifactId>
+            </exclusion>
+            <exclusion>
+              <groupId>com.google.protobuf</groupId>
+              <artifactId>protobuf-java</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+      </dependencies>
+    </profile>
   </profiles>
 
   <reporting>

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 1ceaca8..8966fd3 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
@@ -202,6 +202,7 @@ COUNT : C O U N T;
 CUBE : C U B E;
 
 DAY : D A Y;
+DATABASE : D A T A B A S E;
 DEC : D E C;
 DECADE : D E C A D E;
 DOW : D O W;
@@ -225,6 +226,7 @@ GROUPING : G R O U P I N G;
 HASH : H A S H;
 HOUR : H O U R;
 
+IF : I F;
 INDEX : I N D E X;
 INSERT : I N S E R T;
 INTERSECTION : I N T E R S E C T I O N;

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 71c16f2..4dada45 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
@@ -54,7 +54,9 @@ data_change_statement
   ;
 
 schema_statement
-  : create_table_statement
+  : database_definition
+  | drop_database_statement
+  | create_table_statement
   | drop_table_statement
   ;
 
@@ -63,12 +65,28 @@ index_statement
     LEFT_PAREN s=sort_specifier_list RIGHT_PAREN p=param_clause?
   ;
 
+database_definition
+  : CREATE DATABASE (if_not_exists)? dbname = identifier
+  ;
+
+if_not_exists
+  : IF NOT EXISTS
+  ;
+
+drop_database_statement
+  : DROP DATABASE (if_exists)? dbname = identifier
+  ;
+
+if_exists
+  : IF EXISTS
+  ;
+
 create_table_statement
-  : CREATE EXTERNAL TABLE table_name table_elements USING file_type=identifier
+  : CREATE EXTERNAL TABLE (if_not_exists)? table_name table_elements USING file_type=identifier
     (param_clause)? (table_partitioning_clauses)? (LOCATION path=Character_String_Literal)
-  | CREATE TABLE table_name table_elements (USING file_type=identifier)?
+  | CREATE TABLE (if_not_exists)? table_name table_elements (USING file_type=identifier)?
     (param_clause)? (table_partitioning_clauses)? (AS query_expression)?
-  | CREATE TABLE table_name (USING file_type=identifier)?
+  | CREATE TABLE (if_not_exists)? table_name (USING file_type=identifier)?
     (param_clause)? (table_partitioning_clauses)? AS query_expression
   ;
 
@@ -168,7 +186,7 @@ partition_name
 */
 
 drop_table_statement
-  : DROP TABLE table_name (PURGE)?
+  : DROP TABLE (if_exists)? table_name (PURGE)?
   ;
 
 /*

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java
index 6d95fe1..afd0ce9 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java
@@ -1419,7 +1419,7 @@ public class HiveQLAnalyzer extends HiveQLParserBaseVisitor<Expr> {
     Map<String, String> params = new HashMap<String, String>();
 
     if (ctx.name != null) {
-      createTable = new CreateTable(ctx.name.getText());
+      createTable = new CreateTable(ctx.name.getText(), ctx.ifNotExists() != null);
       if (ctx.KW_EXTERNAL() != null) {
         createTable.setExternal();
       }
@@ -1511,7 +1511,7 @@ public class HiveQLAnalyzer extends HiveQLParserBaseVisitor<Expr> {
 
   @Override
   public Expr visitDropTableStatement(HiveQLParser.DropTableStatementContext ctx) {
-    DropTable dropTable = new DropTable(ctx.tableName().getText(), false);
+    DropTable dropTable = new DropTable(ctx.tableName().getText(), false, ctx.ifExists() != null);
     return dropTable;
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
index a8407fd..784e737 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
@@ -962,9 +962,19 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
   }
 
   @Override
+  public Expr visitDatabase_definition(@NotNull SQLParser.Database_definitionContext ctx) {
+    return new CreateDatabase(ctx.identifier().getText(), null, checkIfExist(ctx.if_not_exists()));
+  }
+
+  @Override
+  public Expr visitDrop_database_statement(@NotNull SQLParser.Drop_database_statementContext ctx) {
+    return new DropDatabase(ctx.identifier().getText(), checkIfExist(ctx.if_exists()));
+  }
+
+  @Override
   public Expr visitCreate_table_statement(SQLParser.Create_table_statementContext ctx) {
     String tableName = ctx.table_name().getText();
-    CreateTable createTable = new CreateTable(tableName);
+    CreateTable createTable = new CreateTable(tableName, checkIfExist(ctx.if_not_exists()));
 
     if (checkIfExist(ctx.EXTERNAL())) {
       createTable.setExternal();
@@ -1265,7 +1275,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
 
   @Override
   public Expr visitDrop_table_statement(SQLParser.Drop_table_statementContext ctx) {
-    return new DropTable(ctx.table_name().getText(), checkIfExist(ctx.PURGE()));
+    return new DropTable(ctx.table_name().getText(), checkIfExist(ctx.if_exists()), checkIfExist(ctx.PURGE()));
   }
 
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
index acb9008..84cdc08 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
@@ -41,6 +41,8 @@ public interface AlgebraVisitor<CONTEXT, RESULT> {
   RESULT visitScalarSubQuery(CONTEXT ctx, Stack<Expr> stack, ScalarSubQuery expr) throws PlanningException;
 
   // Data definition language
+  RESULT visitCreateDatabase(CONTEXT ctx, Stack<Expr> stack, CreateDatabase expr) throws PlanningException;
+  RESULT visitDropDatabase(CONTEXT ctx, Stack<Expr> stack, DropDatabase expr) throws PlanningException;
   RESULT visitCreateTable(CONTEXT ctx, Stack<Expr> stack, CreateTable expr) throws PlanningException;
   RESULT visitDropTable(CONTEXT ctx, Stack<Expr> stack, DropTable expr) throws PlanningException;
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
index cf36539..62cee57 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
@@ -97,6 +97,12 @@ public class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisitor<CONTE
       current = visitScalarSubQuery(ctx, stack, (ScalarSubQuery) expr);
       break;
 
+    case CreateDatabase:
+      current = visitCreateDatabase(ctx, stack, (CreateDatabase) expr);
+      break;
+    case DropDatabase:
+      current = visitDropDatabase(ctx, stack, (DropDatabase) expr);
+      break;
     case CreateTable:
       current = visitCreateTable(ctx, stack, (CreateTable) expr);
       break;
@@ -403,6 +409,16 @@ public class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisitor<CONTE
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   @Override
+  public RESULT visitCreateDatabase(CONTEXT ctx, Stack<Expr> stack, CreateDatabase expr) throws PlanningException {
+    return null;
+  }
+
+  @Override
+  public RESULT visitDropDatabase(CONTEXT ctx, Stack<Expr> stack, DropDatabase expr) throws PlanningException {
+    return null;
+  }
+
+  @Override
   public RESULT visitCreateTable(CONTEXT ctx, Stack<Expr> stack, CreateTable expr) throws PlanningException {
     stack.push(expr);
     RESULT child = null;

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java
index 94e2482..772e5fb 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BasicLogicalPlanVisitor.java
@@ -104,6 +104,12 @@ public class BasicLogicalPlanVisitor<CONTEXT, RESULT> implements LogicalPlanVisi
       case INSERT:
         current = visitInsert(context, plan, block, (InsertNode) node, stack);
         break;
+      case CREATE_DATABASE:
+        current = visitCreateDatabase(context, plan, block, (CreateDatabaseNode) node, stack);
+        break;
+      case DROP_DATABASE:
+        current = visitDropDatabase(context, plan, block, (DropDatabaseNode) node, stack);
+        break;
       case CREATE_TABLE:
         current = visitCreateTable(context, plan, block, (CreateTableNode) node, stack);
         break;
@@ -265,6 +271,17 @@ public class BasicLogicalPlanVisitor<CONTEXT, RESULT> implements LogicalPlanVisi
   }
 
   @Override
+  public RESULT visitCreateDatabase(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                    CreateDatabaseNode node, Stack<LogicalNode> stack) throws PlanningException {
+    return null;
+  }
+
+  @Override
+  public RESULT visitDropDatabase(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, DropDatabaseNode node, Stack<LogicalNode> stack) throws PlanningException {
+    return null;
+  }
+
+  @Override
   public RESULT visitCreateTable(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, CreateTableNode node,
                                  Stack<LogicalNode> stack) throws PlanningException {
     RESULT result = null;

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java
index e2f65ad..9dd8700 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExplainLogicalPlanVisitor.java
@@ -166,7 +166,7 @@ public class ExplainLogicalPlanVisitor extends BasicLogicalPlanVisitor<ExplainLo
                                         TableSubQueryNode node, Stack<LogicalNode> stack) throws PlanningException {
     context.depth++;
     stack.push(node);
-    super.visitTableSubQuery(context, plan, block, node, stack);
+    visit(context, plan, block, node.getSubQuery(), new Stack<LogicalNode>());
     stack.pop();
     context.depth--;
     context.add(context.depth, node.getPlanString());
@@ -195,6 +195,18 @@ public class ExplainLogicalPlanVisitor extends BasicLogicalPlanVisitor<ExplainLo
     return visitUnaryNode(context, plan, block, node, stack);
   }
 
+  public LogicalNode visitCreateDatabase(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                         CreateDatabaseNode node, Stack<LogicalNode> stack) throws PlanningException {
+    context.add(context.depth, node.getPlanString());
+    return node;
+  }
+
+  public LogicalNode visitDropDatabase(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                         DropDatabaseNode node, Stack<LogicalNode> stack) throws PlanningException {
+    context.add(context.depth, node.getPlanString());
+    return node;
+  }
+
   @Override
   public LogicalNode visitInsert(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, InsertNode node,
                                  Stack<LogicalNode> stack) throws PlanningException {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java
index 0dc8f82..5c24192 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java
@@ -19,6 +19,7 @@
 package org.apache.tajo.engine.planner;
 
 import org.apache.tajo.algebra.*;
+import org.apache.tajo.catalog.CatalogUtil;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -245,7 +246,7 @@ class ExprNormalizer extends SimpleAlgebraVisitor<ExprNormalizer.ExprNormalizedR
   public Expr visitColumnReference(ExprNormalizedResult ctx, Stack<Expr> stack, ColumnReferenceExpr expr)
       throws PlanningException {
     // normalize column references.
-    if (!expr.hasQualifier()) {
+    if (!(expr.hasQualifier() && CatalogUtil.isFQTableName(expr.getQualifier()))) {
       if (ctx.block.namedExprsMgr.contains(expr.getCanonicalName())) {
         NamedExpr namedExpr = ctx.block.namedExprsMgr.getNamedExpr(expr.getCanonicalName());
         return new ColumnReferenceExpr(namedExpr.getAlias());

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
index 8280d3e..c3bca66 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
@@ -66,7 +66,10 @@ public class LogicalPlan {
   private List<String> planingHistory = Lists.newArrayList();
   LogicalPlanner planner;
 
-  public LogicalPlan(LogicalPlanner planner) {
+  private final String currentDatabase;
+
+  public LogicalPlan(String currentDatabase, LogicalPlanner planner) {
+    this.currentDatabase = currentDatabase;
     this.planner = planner;
   }
 
@@ -257,27 +260,40 @@ public class LogicalPlan {
 
     if (columnRef.hasQualifier()) { // if a column reference is qualified
 
-      RelationNode relationOp = block.getRelation(columnRef.getQualifier());
+      String qualifier;
+      String canonicalName;
+      String qualifiedName;
+
+      if (CatalogUtil.isFQTableName(columnRef.getQualifier())) {
+        qualifier = columnRef.getQualifier();
+        canonicalName = columnRef.getCanonicalName();
+      } else {
+        qualifier = CatalogUtil.buildFQName(currentDatabase, columnRef.getQualifier());
+        canonicalName = CatalogUtil.buildFQName(currentDatabase, columnRef.getCanonicalName());
+      }
+      qualifiedName = CatalogUtil.buildFQName(qualifier, columnRef.getName());
+
+      RelationNode relationOp = block.getRelation(qualifier);
 
       // if a column name is outside of this query block
       if (relationOp == null) {
         // TODO - nested query can only refer outer query block? or not?
         for (QueryBlock eachBlock : queryBlocks.values()) {
-          if (eachBlock.existsRelation(columnRef.getQualifier())) {
-            relationOp = eachBlock.getRelation(columnRef.getQualifier());
+          if (eachBlock.existsRelation(qualifier)) {
+            relationOp = eachBlock.getRelation(qualifier);
           }
         }
       }
 
       // If we cannot find any relation against a qualified column name
       if (relationOp == null) {
-        throw new NoSuchColumnException(columnRef.getCanonicalName());
+        throw new NoSuchColumnException(canonicalName);
       }
 
       Schema schema = relationOp.getTableSchema();
-      Column column = schema.getColumn(columnRef.getCanonicalName());
+      Column column = schema.getColumn(canonicalName);
       if (column == null) {
-        throw new NoSuchColumnException(columnRef.getCanonicalName());
+        throw new NoSuchColumnException(canonicalName);
       }
 
       // If code reach here, a column is found.
@@ -292,8 +308,8 @@ public class LogicalPlan {
       // the column can be used at the current node. So, we don't need to find aliase name.
       if (currentNode != null && !currentNode.getInSchema().contains(column)) {
         List<Column> candidates = TUtil.newList();
-        if (block.namedExprsMgr.isAliased(column.getQualifiedName())) {
-          String alias = block.namedExprsMgr.getAlias(columnRef.getCanonicalName());
+        if (block.namedExprsMgr.isAliased(qualifiedName)) {
+          String alias = block.namedExprsMgr.getAlias(canonicalName);
           Column found = resolveColumn(block, new ColumnReferenceExpr(alias));
           if (found != null) {
             candidates.add(found);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java
index b08109d..1ac416f 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java
@@ -19,10 +19,7 @@
 package org.apache.tajo.engine.planner;
 
 import org.apache.tajo.algebra.*;
-import org.apache.tajo.catalog.CatalogService;
-import org.apache.tajo.catalog.Column;
-import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.catalog.*;
 import org.apache.tajo.engine.eval.EvalNode;
 import org.apache.tajo.engine.eval.EvalType;
 import org.apache.tajo.engine.eval.FieldEval;
@@ -30,6 +27,7 @@ import org.apache.tajo.engine.exception.NoSuchColumnException;
 import org.apache.tajo.engine.planner.LogicalPlan.QueryBlock;
 import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.engine.utils.SchemaUtil;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.util.TUtil;
 
 import java.util.*;
@@ -41,15 +39,18 @@ class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPreprocessor
   private ExprAnnotator annotator;
 
   static class PreprocessContext {
+    Session session;
     LogicalPlan plan;
     LogicalPlan.QueryBlock currentBlock;
 
-    public PreprocessContext(LogicalPlan plan, LogicalPlan.QueryBlock currentBlock) {
+    public PreprocessContext(Session session, LogicalPlan plan, LogicalPlan.QueryBlock currentBlock) {
+      this.session = session;
       this.plan = plan;
       this.currentBlock = currentBlock;
     }
 
     public PreprocessContext(PreprocessContext context, LogicalPlan.QueryBlock currentBlock) {
+      this.session = context.session;
       this.plan = context.plan;
       this.currentBlock = currentBlock;
     }
@@ -94,21 +95,29 @@ class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPreprocessor
     QueryBlock block = ctx.currentBlock;
     Collection<QueryBlock> queryBlocks = ctx.plan.getQueryBlocks();
     if (asteriskExpr.hasQualifier()) {
-      relationOp = block.getRelation(asteriskExpr.getQualifier());
+      String qualifier;
+
+      if (CatalogUtil.isFQTableName(asteriskExpr.getQualifier())) {
+        qualifier = asteriskExpr.getQualifier();
+      } else {
+        qualifier = CatalogUtil.buildFQName(ctx.session.getCurrentDatabase(), asteriskExpr.getQualifier());
+      }
+
+      relationOp = block.getRelation(qualifier);
 
       // if a column name is outside of this query block
       if (relationOp == null) {
         // TODO - nested query can only refer outer query block? or not?
         for (QueryBlock eachBlock : queryBlocks) {
-          if (eachBlock.existsRelation(asteriskExpr.getQualifier())) {
-            relationOp = eachBlock.getRelation(asteriskExpr.getQualifier());
+          if (eachBlock.existsRelation(qualifier)) {
+            relationOp = eachBlock.getRelation(qualifier);
           }
         }
       }
 
       // If we cannot find any relation against a qualified column name
       if (relationOp == null) {
-        throw new NoSuchColumnException(asteriskExpr.toString());
+        throw new NoSuchColumnException(CatalogUtil.buildFQName(qualifier, "*"));
       }
 
       Schema schema = relationOp.getTableSchema();
@@ -326,10 +335,16 @@ class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPreprocessor
   @Override
   public LogicalNode visitRelation(PreprocessContext ctx, Stack<Expr> stack, Relation expr)
       throws PlanningException {
-
     Relation relation = expr;
-    TableDesc desc = catalog.getTableDesc(relation.getName());
 
+    String actualRelationName;
+    if (CatalogUtil.isFQTableName(expr.getName())) {
+      actualRelationName = relation.getName();
+    } else {
+      actualRelationName = CatalogUtil.buildFQName(ctx.session.getCurrentDatabase(), relation.getName());
+    }
+
+    TableDesc desc = catalog.getTableDesc(actualRelationName);
     ScanNode scanNode = ctx.plan.createNode(ScanNode.class);
     if (relation.hasAlias()) {
       scanNode.init(desc, relation.getAlias());
@@ -353,7 +368,7 @@ class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPreprocessor
 
     // a table subquery should be dealt as a relation.
     TableSubQueryNode node = ctx.plan.createNode(TableSubQueryNode.class);
-    node.init(expr.getName(), child);
+    node.init(CatalogUtil.buildFQName(ctx.session.getCurrentDatabase(), expr.getName()), child);
     ctx.currentBlock.addRelation(node);
     return node;
   }
@@ -363,6 +378,20 @@ class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPreprocessor
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   @Override
+  public LogicalNode visitCreateDatabase(PreprocessContext ctx, Stack<Expr> stack, CreateDatabase expr)
+      throws PlanningException {
+    CreateDatabaseNode createDatabaseNode = ctx.plan.createNode(CreateDatabaseNode.class);
+    return createDatabaseNode;
+  }
+
+  @Override
+  public LogicalNode visitDropDatabase(PreprocessContext ctx, Stack<Expr> stack, DropDatabase expr)
+      throws PlanningException {
+    DropDatabaseNode dropDatabaseNode = ctx.plan.createNode(DropDatabaseNode.class);
+    return dropDatabaseNode;
+  }
+
+  @Override
   public LogicalNode visitCreateTable(PreprocessContext ctx, Stack<Expr> stack, CreateTable expr)
       throws PlanningException {
 


[04/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
index 228d42d..65ade68 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlanner.java
@@ -20,6 +20,8 @@ package org.apache.tajo.engine.planner;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
+import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.algebra.JoinType;
@@ -34,6 +36,7 @@ import org.apache.tajo.engine.json.CoreGsonHelper;
 import org.apache.tajo.engine.parser.SQLAnalyzer;
 import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.master.TajoMaster;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.apache.tajo.util.FileUtil;
 import org.junit.AfterClass;
@@ -44,6 +47,8 @@ import java.io.File;
 import java.io.IOException;
 import java.util.*;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.*;
 
 public class TestLogicalPlanner {
@@ -52,12 +57,16 @@ public class TestLogicalPlanner {
   private static SQLAnalyzer sqlAnalyzer;
   private static LogicalPlanner planner;
   private static TPCH tpch;
+  private static Session session = LocalTajoTestingUtility.createDummySession();
 
   @BeforeClass
   public static void setUp() throws Exception {
     util = new TajoTestingCluster();
     util.startCatalogCluster();
     catalog = util.getMiniCatalogCluster().getCatalog();
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:1234");
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
+
     for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
       catalog.createFunction(funcDesc);
     }
@@ -76,14 +85,20 @@ public class TestLogicalPlanner {
     schema3.addColumn("score", Type.INT4);
 
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV);
-    TableDesc people = new TableDesc("employee", schema, meta, CommonTestingUtil.getTestDir());
-    catalog.addTable(people);
+    TableDesc people = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
+        CommonTestingUtil.getTestDir());
+    catalog.createTable(people);
 
-    TableDesc student = new TableDesc("dept", schema2, StoreType.CSV, new Options(), CommonTestingUtil.getTestDir());
-    catalog.addTable(student);
+    TableDesc student = new TableDesc(
+        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, StoreType.CSV, new Options(),
+        CommonTestingUtil.getTestDir());
+    catalog.createTable(student);
 
-    TableDesc score = new TableDesc("score", schema3, StoreType.CSV, new Options(), CommonTestingUtil.getTestDir());
-    catalog.addTable(score);
+    TableDesc score = new TableDesc(
+        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, StoreType.CSV, new Options(),
+        CommonTestingUtil.getTestDir());
+    catalog.createTable(score);
 
     FunctionDesc funcDesc = new FunctionDesc("sumtest", SumInt.class, FunctionType.AGGREGATION,
         CatalogUtil.newSimpleDataType(Type.INT4),
@@ -99,8 +114,10 @@ public class TestLogicalPlanner {
     tpch.loadOutSchema();
     for (String table : tpchTables) {
       TableMeta m = CatalogUtil.newTableMeta(StoreType.CSV);
-      TableDesc d = CatalogUtil.newTableDesc(table, tpch.getSchema(table), m, CommonTestingUtil.getTestDir());
-      catalog.addTable(d);
+      TableDesc d = CatalogUtil.newTableDesc(
+          CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, table), tpch.getSchema(table), m,
+          CommonTestingUtil.getTestDir());
+      catalog.createTable(d);
     }
 
     catalog.createFunction(funcDesc);
@@ -133,7 +150,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testSingleRelation() throws CloneNotSupportedException, PlanningException {
     Expr expr = sqlAnalyzer.parse(QUERIES[0]);
-    LogicalPlan planNode = planner.createPlan(expr);
+    LogicalPlan planNode = planner.createPlan(session, expr);
     LogicalNode plan = planNode.getRootBlock().getRoot();
     assertEquals(NodeType.ROOT, plan.getType());
     TestLogicalNode.testCloneLogicalNode(plan);
@@ -148,7 +165,7 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, selNode.getChild().getType());
     ScanNode scanNode = selNode.getChild();
-    assertEquals("employee", scanNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
   }
 
   public static void assertSchema(Schema expected, Schema schema) {
@@ -166,7 +183,7 @@ public class TestLogicalPlanner {
   public final void testImplicityJoinPlan() throws CloneNotSupportedException, PlanningException {
     // two relations
     Expr expr = sqlAnalyzer.parse(QUERIES[1]);
-    LogicalPlan planNode = planner.createPlan(expr);
+    LogicalPlan planNode = planner.createPlan(session, expr);
     LogicalNode plan = planNode.getRootBlock().getRoot();
 
     assertEquals(NodeType.ROOT, plan.getType());
@@ -192,14 +209,14 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, joinNode.getLeftChild().getType());
     ScanNode leftNode = joinNode.getLeftChild();
-    assertEquals("employee", leftNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), leftNode.getTableName());
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
     ScanNode rightNode = joinNode.getRightChild();
-    assertEquals("dept", rightNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), rightNode.getTableName());
 
     // three relations
     expr = sqlAnalyzer.parse(QUERIES[2]);
-    plan = planner.createPlan(expr).getRootBlock().getRoot();
+    plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
 
@@ -219,18 +236,18 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
     ScanNode scan1 = joinNode.getRightChild();
-    assertEquals("score", scan1.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), scan1.getTableName());
 
     JoinNode leftNode2 = joinNode.getLeftChild();
     assertEquals(NodeType.JOIN, leftNode2.getType());
 
     assertEquals(NodeType.SCAN, leftNode2.getLeftChild().getType());
     ScanNode leftScan = leftNode2.getLeftChild();
-    assertEquals("employee", leftScan.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), leftScan.getTableName());
 
     assertEquals(NodeType.SCAN, leftNode2.getRightChild().getType());
     ScanNode rightScan = leftNode2.getRightChild();
-    assertEquals("dept", rightScan.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), rightScan.getTableName());
   }
 
 
@@ -253,7 +270,7 @@ public class TestLogicalPlanner {
   public final void testNaturalJoinPlan() throws PlanningException {
     // two relations
     Expr context = sqlAnalyzer.parse(JOINS[0]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, context).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     assertSchema(expectedJoinSchema, plan.getOutSchema());
 
@@ -267,24 +284,24 @@ public class TestLogicalPlanner {
     assertEquals(NodeType.SCAN, join.getRightChild().getType());
     assertTrue(join.hasJoinQual());
     ScanNode scan = join.getRightChild();
-    assertEquals("score", scan.getTableName());
+    assertEquals("default.score", scan.getTableName());
 
     assertEquals(NodeType.JOIN, join.getLeftChild().getType());
     join = join.getLeftChild();
     assertEquals(JoinType.INNER, join.getJoinType());
     assertEquals(NodeType.SCAN, join.getLeftChild().getType());
     ScanNode outer = join.getLeftChild();
-    assertEquals("employee", outer.getTableName());
+    assertEquals("default.employee", outer.getTableName());
     assertEquals(NodeType.SCAN, join.getRightChild().getType());
     ScanNode inner = join.getRightChild();
-    assertEquals("dept", inner.getTableName());
+    assertEquals("default.dept", inner.getTableName());
   }
 
   @Test
   public final void testInnerJoinPlan() throws PlanningException {
     // two relations
     Expr expr = sqlAnalyzer.parse(JOINS[1]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     LogicalNode root = plan.getRootBlock().getRoot();
     testJsonSerDerObject(root);
     assertSchema(expectedJoinSchema, root.getOutSchema());
@@ -297,17 +314,17 @@ public class TestLogicalPlanner {
     assertEquals(JoinType.INNER, join.getJoinType());
     assertEquals(NodeType.SCAN, join.getRightChild().getType());
     ScanNode scan = join.getRightChild();
-    assertEquals("score", scan.getTableName());
+    assertEquals("default.score", scan.getTableName());
 
     assertEquals(NodeType.JOIN, join.getLeftChild().getType());
     join = join.getLeftChild();
     assertEquals(JoinType.INNER, join.getJoinType());
     assertEquals(NodeType.SCAN, join.getLeftChild().getType());
     ScanNode outer = join.getLeftChild();
-    assertEquals("employee", outer.getTableName());
+    assertEquals("default.employee", outer.getTableName());
     assertEquals(NodeType.SCAN, join.getRightChild().getType());
     ScanNode inner = join.getRightChild();
-    assertEquals("dept", inner.getTableName());
+    assertEquals("default.dept", inner.getTableName());
     assertTrue(join.hasJoinQual());
     assertEquals(EvalType.EQUAL, join.getJoinQual().getType());
   }
@@ -316,7 +333,7 @@ public class TestLogicalPlanner {
   public final void testOuterJoinPlan() throws PlanningException {
     // two relations
     Expr expr = sqlAnalyzer.parse(JOINS[2]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     assertSchema(expectedJoinSchema, plan.getOutSchema());
 
@@ -329,17 +346,17 @@ public class TestLogicalPlanner {
     assertEquals(JoinType.RIGHT_OUTER, join.getJoinType());
     assertEquals(NodeType.SCAN, join.getRightChild().getType());
     ScanNode scan = join.getRightChild();
-    assertEquals("score", scan.getTableName());
+    assertEquals("default.score", scan.getTableName());
 
     assertEquals(NodeType.JOIN, join.getLeftChild().getType());
     join = join.getLeftChild();
     assertEquals(JoinType.LEFT_OUTER, join.getJoinType());
     assertEquals(NodeType.SCAN, join.getLeftChild().getType());
     ScanNode outer = join.getLeftChild();
-    assertEquals("employee", outer.getTableName());
+    assertEquals("default.employee", outer.getTableName());
     assertEquals(NodeType.SCAN, join.getRightChild().getType());
     ScanNode inner = join.getRightChild();
-    assertEquals("dept", inner.getTableName());
+    assertEquals("default.dept", inner.getTableName());
     assertTrue(join.hasJoinQual());
     assertEquals(EvalType.EQUAL, join.getJoinQual().getType());
   }
@@ -349,7 +366,7 @@ public class TestLogicalPlanner {
   public final void testGroupby() throws CloneNotSupportedException, PlanningException {
     // without 'having clause'
     Expr context = sqlAnalyzer.parse(QUERIES[7]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, context).getRootBlock().getRoot();
 
     assertEquals(NodeType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
@@ -358,7 +375,7 @@ public class TestLogicalPlanner {
 
     // with having clause
     context = sqlAnalyzer.parse(QUERIES[3]);
-    plan = planner.createPlan(context).getRootBlock().getRoot();
+    plan = planner.createPlan(session, context).getRootBlock().getRoot();
     TestLogicalNode.testCloneLogicalNode(plan);
 
     assertEquals(NodeType.ROOT, plan.getType());
@@ -376,10 +393,10 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, joinNode.getLeftChild().getType());
     ScanNode leftNode = joinNode.getLeftChild();
-    assertEquals("dept", leftNode.getTableName());
+    assertEquals("default.dept", leftNode.getTableName());
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
     ScanNode rightNode = joinNode.getRightChild();
-    assertEquals("score", rightNode.getTableName());
+    assertEquals("default.score", rightNode.getTableName());
 
     //LogicalOptimizer.optimize(context, plan);
   }
@@ -389,7 +406,7 @@ public class TestLogicalPlanner {
   public final void testMultipleJoin() throws IOException, PlanningException {
     Expr expr = sqlAnalyzer.parse(
         FileUtil.readTextFile(new File("src/test/resources/queries/TestJoinQuery/testTPCHQ2Join.sql")));
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     Schema expected = tpch.getOutSchema("q2");
     assertSchema(expected, plan.getOutSchema());
@@ -407,17 +424,17 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, joinNode.getLeftChild().getType());
     ScanNode leftNode = joinNode.getLeftChild();
-    assertEquals("dept", leftNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), leftNode.getTableName());
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
     ScanNode rightNode = joinNode.getRightChild();
-    assertEquals("score", rightNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), rightNode.getTableName());
   }
 
 
   @Test
   public final void testStoreTable() throws CloneNotSupportedException, PlanningException {
     Expr context = sqlAnalyzer.parse(QUERIES[8]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, context).getRootBlock().getRoot();
     TestLogicalNode.testCloneLogicalNode(plan);
     testJsonSerDerObject(plan);
 
@@ -432,7 +449,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testOrderBy() throws CloneNotSupportedException, PlanningException {
     Expr expr = sqlAnalyzer.parse(QUERIES[4]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
 
@@ -450,16 +467,16 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, joinNode.getLeftChild().getType());
     ScanNode leftNode = joinNode.getLeftChild();
-    assertEquals("dept", leftNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), leftNode.getTableName());
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
     ScanNode rightNode = joinNode.getRightChild();
-    assertEquals("score", rightNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), rightNode.getTableName());
   }
 
   @Test
   public final void testLimit() throws CloneNotSupportedException, PlanningException {
     Expr expr = sqlAnalyzer.parse(QUERIES[12]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
 
@@ -478,7 +495,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testSPJPush() throws CloneNotSupportedException, PlanningException {
     Expr expr = sqlAnalyzer.parse(QUERIES[5]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
 
@@ -490,7 +507,7 @@ public class TestLogicalPlanner {
     SelectionNode selNode = projNode.getChild();
     assertEquals(NodeType.SCAN, selNode.getChild().getType());
     ScanNode scanNode = selNode.getChild();
-    assertEquals(scanNode.getTableName(), "employee");
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
   }
 
 
@@ -498,7 +515,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testSPJ() throws CloneNotSupportedException, PlanningException {
     Expr expr = sqlAnalyzer.parse(QUERIES[6]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     TestLogicalNode.testCloneLogicalNode(plan);
   }
@@ -506,7 +523,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testJson() throws PlanningException {
 	  Expr expr = sqlAnalyzer.parse(QUERIES[9]);
-	  LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+	  LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
 
 	  String json = plan.toJson();
@@ -527,7 +544,7 @@ public class TestLogicalPlanner {
   public final void testVisitor() throws PlanningException {
     // two relations
     Expr expr = sqlAnalyzer.parse(QUERIES[1]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     TestVisitor vis = new TestVisitor();
     plan.postOrder(vis);
@@ -551,7 +568,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testExprNode() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(QUERIES[10]);
-    LogicalPlan rootNode = planner.createPlan(expr);
+    LogicalPlan rootNode = planner.createPlan(session, expr);
     LogicalNode plan = rootNode.getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     assertEquals(NodeType.ROOT, plan.getType());
@@ -571,7 +588,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testAsterisk() throws CloneNotSupportedException, PlanningException {
     Expr expr = sqlAnalyzer.parse(QUERIES[13]);
-    LogicalPlan planNode = planner.createPlan(expr);
+    LogicalPlan planNode = planner.createPlan(session, expr);
     LogicalNode plan = planNode.getRootBlock().getRoot();
     assertEquals(NodeType.ROOT, plan.getType());
     TestLogicalNode.testCloneLogicalNode(plan);
@@ -587,7 +604,7 @@ public class TestLogicalPlanner {
 
     assertEquals(NodeType.SCAN, selNode.getChild().getType());
     ScanNode scanNode = selNode.getChild();
-    assertEquals("employee", scanNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), scanNode.getTableName());
   }
 
   static final String ALIAS [] = {
@@ -599,7 +616,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testAlias1() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(ALIAS[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     LogicalRootNode root = (LogicalRootNode) plan;
     testJsonSerDerObject(root);
 
@@ -611,7 +628,7 @@ public class TestLogicalPlanner {
     assertEquals("total", col.getSimpleName());
 
     expr = sqlAnalyzer.parse(ALIAS[1]);
-    plan = planner.createPlan(expr).getRootBlock().getRoot();
+    plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     root = (LogicalRootNode) plan;
 
     finalSchema = root.getOutSchema();
@@ -625,7 +642,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testAlias2() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(ALIAS[1]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     LogicalRootNode root = (LogicalRootNode) plan;
     testJsonSerDerObject(root);
 
@@ -644,7 +661,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testCreateTableDef() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(CREATE_TABLE[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     LogicalRootNode root = (LogicalRootNode) plan;
     testJsonSerDerObject(root);
     assertEquals(NodeType.CREATE_TABLE, root.getChild().getType());
@@ -728,7 +745,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testSetPlan() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(setStatements[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     assertEquals(NodeType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
@@ -747,7 +764,7 @@ public class TestLogicalPlanner {
   @Test
   public void testSetQualifier() throws PlanningException {
     Expr context = sqlAnalyzer.parse(setQualifiers[0]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, context).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     assertEquals(NodeType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
@@ -756,7 +773,7 @@ public class TestLogicalPlanner {
     assertEquals(NodeType.SCAN, projectionNode.getChild().getType());
 
     context = sqlAnalyzer.parse(setQualifiers[1]);
-    plan = planner.createPlan(context).getRootBlock().getRoot();
+    plan = planner.createPlan(session, context).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     assertEquals(NodeType.ROOT, plan.getType());
     root = (LogicalRootNode) plan;
@@ -765,7 +782,7 @@ public class TestLogicalPlanner {
     assertEquals(NodeType.GROUP_BY, projectionNode.getChild().getType());
 
     context = sqlAnalyzer.parse(setQualifiers[2]);
-    plan = planner.createPlan(context).getRootBlock().getRoot();
+    plan = planner.createPlan(session, context).getRootBlock().getRoot();
     testJsonSerDerObject(plan);
     root = (LogicalRootNode) plan;
     assertEquals(NodeType.PROJECTION, root.getChild().getType());
@@ -797,32 +814,32 @@ public class TestLogicalPlanner {
   @Test
   public final void testInsertInto0() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(insertStatements[0]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     assertEquals(1, plan.getQueryBlocks().size());
     InsertNode insertNode = getInsertNode(plan);
     assertFalse(insertNode.isOverwrite());
     assertTrue(insertNode.hasTargetTable());
-    assertEquals("score", insertNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), insertNode.getTableName());
   }
 
   @Test
   public final void testInsertInto1() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(insertStatements[1]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     assertEquals(1, plan.getQueryBlocks().size());
     InsertNode insertNode = getInsertNode(plan);
     assertFalse(insertNode.isOverwrite());
-    assertEquals("score", insertNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), insertNode.getTableName());
   }
 
   @Test
   public final void testInsertInto2() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(insertStatements[2]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     assertEquals(1, plan.getQueryBlocks().size());
     InsertNode insertNode = getInsertNode(plan);
     assertFalse(insertNode.isOverwrite());
-    assertEquals("employee", insertNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), insertNode.getTableName());
     assertTrue(insertNode.hasTargetSchema());
     assertEquals(insertNode.getTargetSchema().getColumn(0).getSimpleName(), "name");
     assertEquals(insertNode.getTargetSchema().getColumn(1).getSimpleName(), "deptname");
@@ -831,7 +848,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testInsertInto3() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(insertStatements[3]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     assertEquals(1, plan.getQueryBlocks().size());
     InsertNode insertNode = getInsertNode(plan);
     assertFalse(insertNode.isOverwrite());
@@ -841,12 +858,12 @@ public class TestLogicalPlanner {
   @Test
   public final void testInsertInto4() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(insertStatements[4]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     assertEquals(1, plan.getQueryBlocks().size());
     InsertNode insertNode = getInsertNode(plan);
     assertTrue(insertNode.isOverwrite());
     assertTrue(insertNode.hasTargetTable());
-    assertEquals("employee", insertNode.getTableName());
+    assertEquals(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), insertNode.getTableName());
     assertTrue(insertNode.hasTargetSchema());
     assertEquals(insertNode.getTargetSchema().getColumn(0).getSimpleName(), "name");
     assertEquals(insertNode.getTargetSchema().getColumn(1).getSimpleName(), "deptname");
@@ -855,7 +872,7 @@ public class TestLogicalPlanner {
   @Test
   public final void testInsertInto5() throws PlanningException {
     Expr expr = sqlAnalyzer.parse(insertStatements[5]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     assertEquals(1, plan.getQueryBlocks().size());
     InsertNode insertNode = getInsertNode(plan);
     assertTrue(insertNode.isOverwrite());

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java
index c113559..a44f5f7 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/TestPlannerUtil.java
@@ -18,6 +18,8 @@
 
 package org.apache.tajo.engine.planner;
 
+import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -29,6 +31,7 @@ import org.apache.tajo.engine.eval.*;
 import org.apache.tajo.engine.function.builtin.SumInt;
 import org.apache.tajo.engine.parser.SQLAnalyzer;
 import org.apache.tajo.engine.planner.logical.*;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.Tuple;
 import org.apache.tajo.storage.TupleComparator;
 import org.apache.tajo.storage.VTuple;
@@ -39,6 +42,8 @@ import org.junit.Test;
 
 import java.util.List;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.*;
 
 public class TestPlannerUtil {
@@ -46,12 +51,15 @@ public class TestPlannerUtil {
   private static CatalogService catalog;
   private static SQLAnalyzer analyzer;
   private static LogicalPlanner planner;
+  private static Session session = LocalTajoTestingUtility.createDummySession();
 
   @BeforeClass
   public static void setUp() throws Exception {
     util = new TajoTestingCluster();
     util.startCatalogCluster();
     catalog = util.getMiniCatalogCluster().getCatalog();
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, "hdfs://localhost:1234/warehouse");
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
 
     Schema schema = new Schema();
     schema.addColumn("name", Type.TEXT);
@@ -67,14 +75,22 @@ public class TestPlannerUtil {
     schema3.addColumn("score", CatalogUtil.newSimpleDataType(Type.INT4));
 
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV);
-    TableDesc people = new TableDesc("employee", schema, meta, CommonTestingUtil.getTestDir());
-    catalog.addTable(people);
-
-    TableDesc student = new TableDesc("dept", schema2, StoreType.CSV, new Options(), CommonTestingUtil.getTestDir());
-    catalog.addTable(student);
-
-    TableDesc score = new TableDesc("score", schema3, StoreType.CSV, new Options(), CommonTestingUtil.getTestDir());
-    catalog.addTable(score);
+    TableDesc people = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
+        CommonTestingUtil.getTestDir());
+    catalog.createTable(people);
+
+    TableDesc student =
+        new TableDesc(
+            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dept"), schema2, StoreType.CSV,
+            new Options(), CommonTestingUtil.getTestDir());
+    catalog.createTable(student);
+
+    TableDesc score =
+        new TableDesc(
+            CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "score"), schema3, StoreType.CSV,
+            new Options(), CommonTestingUtil.getTestDir());
+    catalog.createTable(score);
 
     FunctionDesc funcDesc = new FunctionDesc("sumtest", SumInt.class, FunctionType.AGGREGATION,
         CatalogUtil.newSimpleDataType(Type.INT4),
@@ -94,24 +110,24 @@ public class TestPlannerUtil {
   public final void testFindTopNode() throws CloneNotSupportedException, PlanningException {
     // two relations
     Expr expr = analyzer.parse(TestLogicalPlanner.QUERIES[1]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     assertEquals(NodeType.ROOT, plan.getType());
     LogicalRootNode root = (LogicalRootNode) plan;
     TestLogicalNode.testCloneLogicalNode(root);
 
     assertEquals(NodeType.PROJECTION, root.getChild().getType());
-    ProjectionNode projNode = (ProjectionNode) root.getChild();
+    ProjectionNode projNode = root.getChild();
 
     assertEquals(NodeType.JOIN, projNode.getChild().getType());
-    JoinNode joinNode = (JoinNode) projNode.getChild();
+    JoinNode joinNode = projNode.getChild();
 
     assertEquals(NodeType.SCAN, joinNode.getLeftChild().getType());
-    ScanNode leftNode = (ScanNode) joinNode.getLeftChild();
-    assertEquals("employee", leftNode.getTableName());
+    ScanNode leftNode = joinNode.getLeftChild();
+    assertEquals("default.employee", leftNode.getTableName());
     assertEquals(NodeType.SCAN, joinNode.getRightChild().getType());
-    ScanNode rightNode = (ScanNode) joinNode.getRightChild();
-    assertEquals("dept", rightNode.getTableName());
+    ScanNode rightNode = joinNode.getRightChild();
+    assertEquals("default.dept", rightNode.getTableName());
     
     LogicalNode node = PlannerUtil.findTopNode(root, NodeType.ROOT);
     assertEquals(NodeType.ROOT, node.getType());

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBNLJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBNLJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBNLJoinExec.java
index 572a60a..7092693 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBNLJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBNLJoinExec.java
@@ -45,6 +45,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.JoinEnforce.JoinAlgorithm;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -70,6 +72,8 @@ public class TestBNLJoinExec {
     util = new TajoTestingCluster();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -92,8 +96,8 @@ public class TestBNLJoinExec {
     }
     appender.flush();
     appender.close();
-    employee = CatalogUtil.newTableDesc("employee", schema, employeeMeta, employeePath);
-    catalog.addTable(employee);
+    employee = CatalogUtil.newTableDesc("default.employee", schema, employeeMeta, employeePath);
+    catalog.createTable(employee);
 
     Schema peopleSchema = new Schema();
     peopleSchema.addColumn("empId", Type.INT4);
@@ -115,8 +119,8 @@ public class TestBNLJoinExec {
     appender.flush();
     appender.close();
 
-    people = CatalogUtil.newTableDesc("people", peopleSchema, peopleMeta, peoplePath);
-    catalog.addTable(people);
+    people = CatalogUtil.newTableDesc("default.people", peopleSchema, peopleMeta, peoplePath);
+    catalog.createTable(people);
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
   }
@@ -136,14 +140,14 @@ public class TestBNLJoinExec {
   @Test
   public final void testBNLCrossJoin() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.BLOCK_NESTED_LOOP_JOIN);
 
-    FileFragment[] empFrags = StorageManager.splitNG(conf, "e", employee.getMeta(), employee.getPath(),
+    FileFragment[] empFrags = StorageManager.splitNG(conf, "default.e", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "p", people.getMeta(), people.getPath(),
+    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "default.p", people.getMeta(), people.getPath(),
         Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(empFrags, peopleFrags);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testBNLCrossJoin");
@@ -169,11 +173,12 @@ public class TestBNLJoinExec {
   @Test
   public final void testBNLInnerJoin() throws IOException, PlanningException {
     Expr context = analyzer.parse(QUERIES[1]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(),
+        context).getRootBlock().getRoot();
 
-    FileFragment[] empFrags = StorageManager.splitNG(conf, "e", employee.getMeta(), employee.getPath(),
+    FileFragment[] empFrags = StorageManager.splitNG(conf, "default.e", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "p", people.getMeta(), people.getPath(),
+    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "default.p", people.getMeta(), people.getPath(),
         Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(empFrags, peopleFrags);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBSTIndexExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBSTIndexExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBSTIndexExec.java
index 4839451..bce9d8e 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBSTIndexExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestBSTIndexExec.java
@@ -22,6 +22,7 @@ import com.google.common.base.Preconditions;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -53,6 +54,7 @@ import java.util.List;
 import java.util.Random;
 import java.util.Stack;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 
 public class TestBSTIndexExec {
@@ -85,7 +87,9 @@ public class TestBSTIndexExec {
     util.startCatalogCluster();
     catalog = util.getMiniCatalogCluster().getCatalog();
 
-    Path workDir = CommonTestingUtil.getTestDir("target/test-data/TestPhysicalPlanner");
+    Path workDir = CommonTestingUtil.getTestDir();
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, workDir.toUri().toString());
+    catalog.createDatabase(TajoConstants.DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     sm = StorageManagerFactory.getStorageManager(conf, workDir);
 
     idxPath = new Path(workDir, "test.idx");
@@ -139,8 +143,10 @@ public class TestBSTIndexExec {
     appender.close();
     writer.close();
 
-    TableDesc desc = new TableDesc("employee", schema, meta, sm.getTablePath("employee"));
-    catalog.addTable(desc);
+    TableDesc desc = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, meta,
+        sm.getTablePath("employee"));
+    catalog.createTable(desc);
 
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
@@ -160,12 +166,12 @@ public class TestBSTIndexExec {
     this.rndKey = rnd.nextInt(250);
     final String QUERY = "select * from employee where managerId = " + rndKey;
     
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", meta, tablePath, Integer.MAX_VALUE);
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", meta, tablePath, Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testEqual");
     TaskAttemptContext ctx = new TaskAttemptContext(conf,
         LocalTajoTestingUtility.newQueryUnitAttemptId(), new FileFragment[] { frags[0] }, workDir);
     Expr expr = analyzer.parse(QUERY);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     TmpPlanner phyPlanner = new TmpPlanner(conf, sm);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestExternalSortExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestExternalSortExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestExternalSortExec.java
index 61d56fc..a82eeb9 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestExternalSortExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestExternalSortExec.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.planner.physical;
 
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -43,6 +44,7 @@ import org.junit.Test;
 import java.io.IOException;
 import java.util.Random;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -67,6 +69,8 @@ public class TestExternalSortExec {
     util = new TajoTestingCluster();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(TajoConstants.DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf.setVar(TajoConf.ConfVars.WORKER_TEMPORAL_DIR, testDir.toString());
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -95,8 +99,8 @@ public class TestExternalSortExec {
     System.out.println(appender.getStats().getNumRows() + " rows (" + (appender.getStats().getNumBytes() / 1048576) +
         " MB)");
 
-    employee = new TableDesc("employee", schema, employeeMeta, employeePath);
-    catalog.addTable(employee);
+    employee = new TableDesc("default.employee", schema, employeeMeta, employeePath);
+    catalog.createTable(employee);
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
   }
@@ -113,14 +117,14 @@ public class TestExternalSortExec {
 
   @Test
   public final void testNext() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employee.getMeta(), employee.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
     Path workDir = new Path(testDir, TestExternalSortExec.class.getName());
     TaskAttemptContext ctx = new TaskAttemptContext(conf,
         LocalTajoTestingUtility.newQueryUnitAttemptId(), new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr);
     LogicalNode rootNode = plan.getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java
index e6ffac2..b05688d 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterHashJoinExec.java
@@ -34,6 +34,7 @@ import org.apache.tajo.engine.planner.enforce.Enforcer;
 import org.apache.tajo.engine.planner.logical.JoinNode;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
 import org.apache.tajo.engine.planner.logical.NodeType;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -45,6 +46,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.JoinEnforce.JoinAlgorithm;
 import static org.junit.Assert.*;
 
@@ -57,12 +60,17 @@ public class TestFullOuterHashJoinExec {
   private LogicalPlanner planner;
   private AbstractStorageManager sm;
   private Path testDir;
+  private static Session session = LocalTajoTestingUtility.createDummySession();
 
   private TableDesc dep3;
   private TableDesc job3;
   private TableDesc emp3;
   private TableDesc phone3;
 
+  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String PHONE3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
 
   @Before
   public void setUp() throws Exception {
@@ -70,6 +78,8 @@ public class TestFullOuterHashJoinExec {
     util.initTestDir();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -106,8 +116,8 @@ public class TestFullOuterHashJoinExec {
 
     appender1.flush();
     appender1.close();
-    dep3 = CatalogUtil.newTableDesc("dep3", dep3Schema, dep3Meta, dep3Path);
-    catalog.addTable(dep3);
+    dep3 = CatalogUtil.newTableDesc(DEP3_NAME, dep3Schema, dep3Meta, dep3Path);
+    catalog.createTable(dep3);
 
     //----------------- job3 ------------------------------
     //  job_id  | job_title
@@ -135,8 +145,8 @@ public class TestFullOuterHashJoinExec {
 
     appender2.flush();
     appender2.close();
-    job3 = CatalogUtil.newTableDesc("job3", job3Schema, job3Meta, job3Path);
-    catalog.addTable(job3);
+    job3 = CatalogUtil.newTableDesc(JOB3_NAME, job3Schema, job3Meta, job3Path);
+    catalog.createTable(job3);
 
 
 
@@ -199,8 +209,8 @@ public class TestFullOuterHashJoinExec {
 
     appender3.flush();
     appender3.close();
-    emp3 = CatalogUtil.newTableDesc("emp3", emp3Schema, emp3Meta, emp3Path);
-    catalog.addTable(emp3);
+    emp3 = CatalogUtil.newTableDesc(EMP3_NAME, emp3Schema, emp3Meta, emp3Path);
+    catalog.createTable(emp3);
 
     //---------------------phone3 --------------------
     // emp_id  | phone_number
@@ -220,8 +230,8 @@ public class TestFullOuterHashJoinExec {
 
     appender5.flush();
     appender5.close();
-    phone3 = CatalogUtil.newTableDesc("phone3", phone3Schema, phone3Meta, phone3Path);
-    catalog.addTable(phone3);
+    phone3 = CatalogUtil.newTableDesc(PHONE3_NAME, phone3Schema, phone3Meta, phone3Path);
+    catalog.createTable(phone3);
 
 
 
@@ -249,13 +259,13 @@ public class TestFullOuterHashJoinExec {
   @Test
   public final void testFullOuterHashJoinExec0() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.IN_MEMORY_HASH_JOIN);
 
-    FileFragment[] dep3Frags = StorageManager.splitNG(conf, "dep3", dep3.getMeta(), dep3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] dep3Frags = StorageManager.splitNG(conf, DEP3_NAME, dep3.getMeta(), dep3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(dep3Frags, emp3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/TestFullOuterHashJoinExec0");
@@ -286,13 +296,13 @@ public class TestFullOuterHashJoinExec {
   @Test
   public final void testFullOuterHashJoinExec1() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[1]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.IN_MEMORY_HASH_JOIN);
 
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] job3Frags = StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(job3Frags, emp3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/TestFullOuter_HashJoinExec1");
@@ -322,13 +332,13 @@ public class TestFullOuterHashJoinExec {
   @Test
   public final void testFullOuterHashJoinExec2() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[2]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.IN_MEMORY_HASH_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] job3Frags = StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(emp3Frags, job3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/TestFullOuterHashJoinExec2");
@@ -359,13 +369,13 @@ public class TestFullOuterHashJoinExec {
   @Test
   public final void testFullOuterHashJoinExec3() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[3]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.IN_MEMORY_HASH_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "phone3", phone3.getMeta(), phone3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] phone3Frags = StorageManager.splitNG(conf, PHONE3_NAME, phone3.getMeta(), phone3.getPath(),
         Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(emp3Frags, phone3Frags);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java
index 3519d1c..0386179 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestFullOuterMergeJoinExec.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.planner.physical;
 
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -34,6 +35,7 @@ import org.apache.tajo.engine.planner.enforce.Enforcer;
 import org.apache.tajo.engine.planner.logical.JoinNode;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
 import org.apache.tajo.engine.planner.logical.NodeType;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -45,6 +47,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.JoinEnforce.JoinAlgorithm;
 import static org.junit.Assert.*;
 
@@ -57,7 +61,7 @@ public class TestFullOuterMergeJoinExec {
   private LogicalPlanner planner;
   private AbstractStorageManager sm;
   private Path testDir;
-  private static final int UNGENERATED_PID = -1;
+  private static final Session session = LocalTajoTestingUtility.createDummySession();
 
   private TableDesc dep3;
   private TableDesc dep4;
@@ -65,12 +69,21 @@ public class TestFullOuterMergeJoinExec {
   private TableDesc emp3;
   private TableDesc phone3;
 
+  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String DEP4_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep4");
+  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String PHONE3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
+
   @Before
   public void setUp() throws Exception {
     util = new TajoTestingCluster();
     util.initTestDir();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(TajoConstants.DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
+
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -107,8 +120,8 @@ public class TestFullOuterMergeJoinExec {
 
     appender1.flush();
     appender1.close();
-    dep3 = CatalogUtil.newTableDesc("dep3", dep3Schema, dep3Meta, dep3Path);
-    catalog.addTable(dep3);
+    dep3 = CatalogUtil.newTableDesc(DEP3_NAME, dep3Schema, dep3Meta, dep3Path);
+    catalog.createTable(dep3);
 
 
     //----------------- dep4 ------------------------------
@@ -145,8 +158,8 @@ public class TestFullOuterMergeJoinExec {
 
     appender4.flush();
     appender4.close();
-    dep4 = CatalogUtil.newTableDesc("dep4", dep4Schema, dep4Meta, dep4Path);
-    catalog.addTable(dep4);
+    dep4 = CatalogUtil.newTableDesc(DEP4_NAME, dep4Schema, dep4Meta, dep4Path);
+    catalog.createTable(dep4);
 
 
 
@@ -176,8 +189,8 @@ public class TestFullOuterMergeJoinExec {
 
     appender2.flush();
     appender2.close();
-    job3 = CatalogUtil.newTableDesc("job3", job3Schema, job3Meta, job3Path);
-    catalog.addTable(job3);
+    job3 = CatalogUtil.newTableDesc(JOB3_NAME, job3Schema, job3Meta, job3Path);
+    catalog.createTable(job3);
 
 
 
@@ -240,8 +253,8 @@ public class TestFullOuterMergeJoinExec {
 
     appender3.flush();
     appender3.close();
-    emp3 = CatalogUtil.newTableDesc("emp3", emp3Schema, emp3Meta, emp3Path);
-    catalog.addTable(emp3);
+    emp3 = CatalogUtil.newTableDesc(EMP3_NAME, emp3Schema, emp3Meta, emp3Path);
+    catalog.createTable(emp3);
 
     //---------------------phone3 --------------------
     // emp_id  | phone_number
@@ -260,8 +273,8 @@ public class TestFullOuterMergeJoinExec {
     appender5.init();
     appender5.flush();
     appender5.close();
-    phone3 = CatalogUtil.newTableDesc("phone3", phone3Schema, phone3Meta, phone3Path);
-    catalog.addTable(phone3);
+    phone3 = CatalogUtil.newTableDesc(PHONE3_NAME, phone3Schema, phone3Meta, phone3Path);
+    catalog.createTable(phone3);
 
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
@@ -290,13 +303,15 @@ public class TestFullOuterMergeJoinExec {
   @Test
   public final void testFullOuterMergeJoin0() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] dep3Frags = StorageManager.splitNG(conf, "dep3", dep3.getMeta(), dep3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] dep3Frags =
+        StorageManager.splitNG(conf, DEP3_NAME, dep3.getMeta(), dep3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(emp3Frags, dep3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testFullOuterMergeJoin0");
@@ -325,13 +340,15 @@ public class TestFullOuterMergeJoinExec {
   @Test
   public final void testFullOuterMergeJoin1() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[1]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] job3Frags =
+        StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(job3Frags, emp3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testFullOuterMergeJoin1");
@@ -360,13 +377,15 @@ public class TestFullOuterMergeJoinExec {
   @Test
   public final void testFullOuterMergeJoin2() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[2]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] job3Frags =
+        StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(job3Frags, emp3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testFullOuterMergeJoin2");
@@ -396,13 +415,15 @@ public class TestFullOuterMergeJoinExec {
   @Test
   public final void testFullOuterMergeJoin3() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[3]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] dep4Frags = StorageManager.splitNG(conf, "dep4", dep4.getMeta(), dep4.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] dep4Frags =
+        StorageManager.splitNG(conf, DEP4_NAME, dep4.getMeta(), dep4.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(emp3Frags, dep4Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testFullOuterMergeJoin3");
@@ -434,13 +455,15 @@ public class TestFullOuterMergeJoinExec {
   @Test
   public final void testFullOuterMergeJoin4() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[4]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "phone3", phone3.getMeta(), phone3.getPath(),
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] phone3Frags =
+        StorageManager.splitNG(conf, PHONE3_NAME, phone3.getMeta(), phone3.getPath(),
         Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(emp3Frags, phone3Frags);
 
@@ -471,13 +494,15 @@ public class TestFullOuterMergeJoinExec {
   @Test
   public final void testFullOuterMergeJoin5() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[5]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "phone3", phone3.getMeta(), phone3.getPath(),
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] phone3Frags =
+        StorageManager.splitNG(conf, PHONE3_NAME, phone3.getMeta(), phone3.getPath(),
         Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(phone3Frags,emp3Frags);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashAntiJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashAntiJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashAntiJoinExec.java
index 60d90d9..9d0a86a 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashAntiJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashAntiJoinExec.java
@@ -43,6 +43,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -66,6 +68,8 @@ public class TestHashAntiJoinExec {
     util.initTestDir();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -93,8 +97,8 @@ public class TestHashAntiJoinExec {
 
     appender.flush();
     appender.close();
-    employee = CatalogUtil.newTableDesc("employee", employeeSchema, employeeMeta, employeePath);
-    catalog.addTable(employee);
+    employee = CatalogUtil.newTableDesc("default.employee", employeeSchema, employeeMeta, employeePath);
+    catalog.createTable(employee);
 
     Schema peopleSchema = new Schema();
     peopleSchema.addColumn("empId", Type.INT4);
@@ -118,8 +122,8 @@ public class TestHashAntiJoinExec {
     appender.flush();
     appender.close();
 
-    people = CatalogUtil.newTableDesc("people", peopleSchema, peopleMeta, peoplePath);
-    catalog.addTable(people);
+    people = CatalogUtil.newTableDesc("default.people", peopleSchema, peopleMeta, peoplePath);
+    catalog.createTable(people);
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
     optimizer = new LogicalOptimizer(conf);
@@ -141,9 +145,9 @@ public class TestHashAntiJoinExec {
 
   @Test
   public final void testHashAntiJoin() throws IOException, PlanningException {
-    FileFragment[] empFrags = StorageManager.splitNG(conf, "e", employee.getMeta(), employee.getPath(),
+    FileFragment[] empFrags = StorageManager.splitNG(conf, "default.e", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "p", people.getMeta(), people.getPath(),
+    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "default.p", people.getMeta(), people.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(empFrags, peopleFrags);
@@ -153,7 +157,7 @@ public class TestHashAntiJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr);
     optimizer.optimize(plan);
     LogicalNode rootNode = plan.getRootBlock().getRoot();
 
@@ -169,7 +173,7 @@ public class TestHashAntiJoinExec {
       SeqScanExec scanRightChild = sortRightChild.getChild();
 
       // 'people' should be outer table. So, the below code guarantees that people becomes the outer table.
-      if (scanLeftChild.getTableName().equals("people")) {
+      if (scanLeftChild.getTableName().equals("default.people")) {
         exec = new HashLeftAntiJoinExec(ctx, join.getPlan(), scanRightChild, scanLeftChild);
       } else {
         exec = new HashLeftAntiJoinExec(ctx, join.getPlan(), scanLeftChild, scanRightChild);
@@ -179,7 +183,7 @@ public class TestHashAntiJoinExec {
       SeqScanExec scanLeftChild = (SeqScanExec) join.getLeftChild();
 
       // 'people' should be outer table. So, the below code guarantees that people becomes the outer table.
-      if (scanLeftChild.getTableName().equals("people")) {
+      if (scanLeftChild.getTableName().equals("default.people")) {
         exec = new HashLeftAntiJoinExec(ctx, join.getPlan(), join.getRightChild(), join.getLeftChild());
       } else {
         exec = new HashLeftAntiJoinExec(ctx, join.getPlan(), join.getLeftChild(), join.getRightChild());

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashJoinExec.java
index 6f0b4e2..da7fce0 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashJoinExec.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.planner.physical;
 
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -34,6 +35,7 @@ import org.apache.tajo.engine.planner.enforce.Enforcer;
 import org.apache.tajo.engine.planner.logical.JoinNode;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
 import org.apache.tajo.engine.planner.logical.NodeType;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -45,6 +47,7 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.JoinEnforce.JoinAlgorithm;
 import static org.junit.Assert.*;
 
@@ -57,6 +60,7 @@ public class TestHashJoinExec {
   private LogicalPlanner planner;
   private AbstractStorageManager sm;
   private Path testDir;
+  private final Session session = LocalTajoTestingUtility.createDummySession();
 
   private TableDesc employee;
   private TableDesc people;
@@ -67,6 +71,8 @@ public class TestHashJoinExec {
     util.initTestDir();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(TajoConstants.DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -91,8 +97,8 @@ public class TestHashJoinExec {
 
     appender.flush();
     appender.close();
-    employee = CatalogUtil.newTableDesc("employee", employeeSchema, employeeMeta, employeePath);
-    catalog.addTable(employee);
+    employee = CatalogUtil.newTableDesc("default.employee", employeeSchema, employeeMeta, employeePath);
+    catalog.createTable(employee);
 
     Schema peopleSchema = new Schema();
     peopleSchema.addColumn("empId", Type.INT4);
@@ -115,8 +121,8 @@ public class TestHashJoinExec {
     appender.flush();
     appender.close();
 
-    people = CatalogUtil.newTableDesc("people", peopleSchema, peopleMeta, peoplePath);
-    catalog.addTable(people);
+    people = CatalogUtil.newTableDesc("default.people", peopleSchema, peopleMeta, peoplePath);
+    catalog.createTable(people);
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
   }
@@ -134,14 +140,14 @@ public class TestHashJoinExec {
   @Test
   public final void testHashInnerJoin() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.IN_MEMORY_HASH_JOIN);
 
-    FileFragment[] empFrags = StorageManager.splitNG(conf, "e", employee.getMeta(), employee.getPath(), Integer.MAX_VALUE);
-    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "p", people.getMeta(), people.getPath(), Integer.MAX_VALUE);
+    FileFragment[] empFrags = StorageManager.splitNG(conf, "default.e", employee.getMeta(), employee.getPath(), Integer.MAX_VALUE);
+    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "default.p", people.getMeta(), people.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(empFrags, peopleFrags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testHashInnerJoin");
@@ -175,15 +181,15 @@ public class TestHashJoinExec {
   @Test
   public final void testCheckIfInMemoryInnerJoinIsPossible() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.IN_MEMORY_HASH_JOIN);
 
-    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "p", people.getMeta(), people.getPath(),
+    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "default.p", people.getMeta(), people.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] empFrags = StorageManager.splitNG(conf, "e", employee.getMeta(), employee.getPath(),
+    FileFragment[] empFrags = StorageManager.splitNG(conf, "default.e", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(empFrags, peopleFrags);
 
@@ -220,7 +226,7 @@ public class TestHashJoinExec {
     String [] right = PlannerUtil.getRelationLineage(joinNode.getRightChild());
 
     boolean leftSmaller;
-    if (left[0].equals("p")) {
+    if (left[0].equals("default.p")) {
       leftSmaller = true;
     } else {
       leftSmaller = false;
@@ -244,16 +250,16 @@ public class TestHashJoinExec {
       assertEquals(ordered[0], joinExec.getLeftChild());
       assertEquals(ordered[1], joinExec.getRightChild());
 
-      assertEquals("p", left[0]);
-      assertEquals("e", right[0]);
+      assertEquals("default.p", left[0]);
+      assertEquals("default.e", right[0]);
     } else {
       PhysicalExec [] ordered = phyPlanner.switchJoinSidesIfNecessary(ctx, joinNode, joinExec.getLeftChild(),
           joinExec.getRightChild());
       assertEquals(ordered[1], joinExec.getLeftChild());
       assertEquals(ordered[0], joinExec.getRightChild());
 
-      assertEquals("e", left[0]);
-      assertEquals("p", right[0]);
+      assertEquals("default.e", left[0]);
+      assertEquals("default.p", right[0]);
     }
 
     if (leftSmaller) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashSemiJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashSemiJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashSemiJoinExec.java
index ebc35d3..75a27db 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashSemiJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestHashSemiJoinExec.java
@@ -43,6 +43,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -66,6 +68,8 @@ public class TestHashSemiJoinExec {
     util.initTestDir();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -93,8 +97,8 @@ public class TestHashSemiJoinExec {
 
     appender.flush();
     appender.close();
-    employee = CatalogUtil.newTableDesc("employee", employeeSchema, employeeMeta, employeePath);
-    catalog.addTable(employee);
+    employee = CatalogUtil.newTableDesc("default.employee", employeeSchema, employeeMeta, employeePath);
+    catalog.createTable(employee);
 
     Schema peopleSchema = new Schema();
     peopleSchema.addColumn("empId", Type.INT4);
@@ -122,8 +126,8 @@ public class TestHashSemiJoinExec {
     appender.flush();
     appender.close();
 
-    people = CatalogUtil.newTableDesc("people", peopleSchema, peopleMeta, peoplePath);
-    catalog.addTable(people);
+    people = CatalogUtil.newTableDesc("default.people", peopleSchema, peopleMeta, peoplePath);
+    catalog.createTable(people);
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
     optimizer = new LogicalOptimizer(conf);
@@ -145,9 +149,9 @@ public class TestHashSemiJoinExec {
 
   @Test
   public final void testHashSemiJoin() throws IOException, PlanningException {
-    FileFragment[] empFrags = StorageManager.splitNG(conf, "e", employee.getMeta(), employee.getPath(),
+    FileFragment[] empFrags = StorageManager.splitNG(conf, "default.e", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "p", people.getMeta(), people.getPath(),
+    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "default.p", people.getMeta(), people.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(empFrags, peopleFrags);
@@ -157,7 +161,7 @@ public class TestHashSemiJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr);
     optimizer.optimize(plan);
     LogicalNode rootNode = plan.getRootBlock().getRoot();
 
@@ -173,7 +177,7 @@ public class TestHashSemiJoinExec {
       SeqScanExec scanRightChild = (SeqScanExec) sortRightChild.getChild();
 
       // 'people' should be outer table. So, the below code guarantees that people becomes the outer table.
-      if (scanLeftChild.getTableName().equals("people")) {
+      if (scanLeftChild.getTableName().equals("default.people")) {
         exec = new HashLeftSemiJoinExec(ctx, join.getPlan(), scanRightChild, scanLeftChild);
       } else {
         exec = new HashLeftSemiJoinExec(ctx, join.getPlan(), scanLeftChild, scanRightChild);
@@ -183,7 +187,7 @@ public class TestHashSemiJoinExec {
       SeqScanExec scanLeftChild = (SeqScanExec) join.getLeftChild();
 
       // 'people' should be outer table. So, the below code guarantees that people becomes the outer table.
-      if (scanLeftChild.getTableName().equals("people")) {
+      if (scanLeftChild.getTableName().equals("default.people")) {
         exec = new HashLeftSemiJoinExec(ctx, join.getPlan(), join.getRightChild(), join.getLeftChild());
       } else {
         exec = new HashLeftSemiJoinExec(ctx, join.getPlan(), join.getLeftChild(), join.getRightChild());


[03/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java
index bee7547..de3d298 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterHashJoinExec.java
@@ -34,6 +34,7 @@ import org.apache.tajo.engine.planner.enforce.Enforcer;
 import org.apache.tajo.engine.planner.logical.JoinNode;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
 import org.apache.tajo.engine.planner.logical.NodeType;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -45,6 +46,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.JoinEnforce.JoinAlgorithm;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -58,18 +61,26 @@ public class TestLeftOuterHashJoinExec {
   private LogicalPlanner planner;
   private AbstractStorageManager sm;
   private Path testDir;
+  private Session session = LocalTajoTestingUtility.createDummySession();
 
   private TableDesc dep3;
   private TableDesc job3;
   private TableDesc emp3;
   private TableDesc phone3;
 
+  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String PHONE3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
+
   @Before
   public void setUp() throws Exception {
     util = new TajoTestingCluster();
     util.initTestDir();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -106,8 +117,8 @@ public class TestLeftOuterHashJoinExec {
 
     appender1.flush();
     appender1.close();
-    dep3 = CatalogUtil.newTableDesc("dep3", dep3Schema, dep3Meta, dep3Path);
-    catalog.addTable(dep3);
+    dep3 = CatalogUtil.newTableDesc(DEP3_NAME, dep3Schema, dep3Meta, dep3Path);
+    catalog.createTable(dep3);
 
     //----------------- job3 ------------------------------
     //  job_id  | job_title
@@ -135,8 +146,8 @@ public class TestLeftOuterHashJoinExec {
 
     appender2.flush();
     appender2.close();
-    job3 = CatalogUtil.newTableDesc("job3", job3Schema, job3Meta, job3Path);
-    catalog.addTable(job3);
+    job3 = CatalogUtil.newTableDesc(JOB3_NAME, job3Schema, job3Meta, job3Path);
+    catalog.createTable(job3);
 
 
 
@@ -199,8 +210,8 @@ public class TestLeftOuterHashJoinExec {
 
     appender3.flush();
     appender3.close();
-    emp3 = CatalogUtil.newTableDesc("emp3", emp3Schema, emp3Meta, emp3Path);
-    catalog.addTable(emp3);
+    emp3 = CatalogUtil.newTableDesc(EMP3_NAME, emp3Schema, emp3Meta, emp3Path);
+    catalog.createTable(emp3);
 
     //---------------------phone3 --------------------
     // emp_id  | phone_number
@@ -220,8 +231,8 @@ public class TestLeftOuterHashJoinExec {
     
     appender5.flush();
     appender5.close();
-    phone3 = CatalogUtil.newTableDesc("phone3", phone3Schema, phone3Meta, phone3Path);
-    catalog.addTable(phone3);
+    phone3 = CatalogUtil.newTableDesc(PHONE3_NAME, phone3Schema, phone3Meta, phone3Path);
+    catalog.createTable(phone3);
 
 
 
@@ -250,13 +261,13 @@ public class TestLeftOuterHashJoinExec {
   @Test
   public final void testLeftOuterHashJoinExec0() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.IN_MEMORY_HASH_JOIN);
 
-    FileFragment[] dep3Frags = StorageManager.splitNG(conf, "dep3", dep3.getMeta(), dep3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] dep3Frags = StorageManager.splitNG(conf, DEP3_NAME, dep3.getMeta(), dep3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(dep3Frags, emp3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/TestLeftOuterHashJoinExec0");
@@ -283,9 +294,9 @@ public class TestLeftOuterHashJoinExec {
 
   @Test
   public final void testLeftOuter_HashJoinExec1() throws IOException, PlanningException {
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(),
+    FileFragment[] job3Frags = StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(job3Frags, emp3Frags);
@@ -295,7 +306,7 @@ public class TestLeftOuterHashJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[1]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
     PhysicalExec exec = phyPlanner.createPlan(ctx, plan);
@@ -324,9 +335,9 @@ public class TestLeftOuterHashJoinExec {
     @Test
   public final void testLeftOuter_HashJoinExec2() throws IOException, PlanningException {
     
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(),
+    FileFragment[] job3Frags = StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(emp3Frags, job3Frags);
@@ -336,7 +347,7 @@ public class TestLeftOuterHashJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[2]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
     PhysicalExec exec = phyPlanner.createPlan(ctx, plan);
@@ -366,9 +377,9 @@ public class TestLeftOuterHashJoinExec {
    @Test
   public final void testLeftOuter_HashJoinExec3() throws IOException, PlanningException {
     
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "phone3", phone3.getMeta(), phone3.getPath(),
+    FileFragment[] phone3Frags = StorageManager.splitNG(conf, PHONE3_NAME, phone3.getMeta(), phone3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(emp3Frags, phone3Frags);
@@ -378,7 +389,7 @@ public class TestLeftOuterHashJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[3]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
     PhysicalExec exec = phyPlanner.createPlan(ctx, plan);
@@ -408,9 +419,9 @@ public class TestLeftOuterHashJoinExec {
    @Test
   public final void testLeftOuter_HashJoinExec4() throws IOException, PlanningException {
     
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "default.emp3", emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "phone3", phone3.getMeta(), phone3.getPath(),
+    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "default.phone3", phone3.getMeta(), phone3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(phone3Frags, emp3Frags);
@@ -420,7 +431,7 @@ public class TestLeftOuterHashJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[4]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
     PhysicalExec exec = phyPlanner.createPlan(ctx, plan);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterNLJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterNLJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterNLJoinExec.java
index 1ac202e..e806e55 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterNLJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestLeftOuterNLJoinExec.java
@@ -35,6 +35,7 @@ import org.apache.tajo.engine.planner.PhysicalPlannerImpl;
 import org.apache.tajo.engine.planner.PlanningException;
 import org.apache.tajo.engine.planner.enforce.Enforcer;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -46,6 +47,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
@@ -56,6 +59,7 @@ public class TestLeftOuterNLJoinExec {
   private CatalogService catalog;
   private SQLAnalyzer analyzer;
   private LogicalPlanner planner;
+  private static final Session session = LocalTajoTestingUtility.createDummySession();
   private AbstractStorageManager sm;
   private Path testDir;
 
@@ -64,11 +68,18 @@ public class TestLeftOuterNLJoinExec {
   private TableDesc emp3;
   private TableDesc phone3;
 
+  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String PHONE3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
+
   @Before
   public void setUp() throws Exception {
     util = new TajoTestingCluster();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -105,8 +116,8 @@ public class TestLeftOuterNLJoinExec {
 
     appender1.flush();
     appender1.close();
-    dep3 = CatalogUtil.newTableDesc("dep3", dep3Schema, dep3Meta, dep3Path);
-    catalog.addTable(dep3);
+    dep3 = CatalogUtil.newTableDesc(DEP3_NAME, dep3Schema, dep3Meta, dep3Path);
+    catalog.createTable(dep3);
 
     //----------------- job3 ------------------------------
     //  job_id  | job_title
@@ -134,8 +145,8 @@ public class TestLeftOuterNLJoinExec {
 
     appender2.flush();
     appender2.close();
-    job3 = CatalogUtil.newTableDesc("job3", job3Schema, job3Meta, job3Path);
-    catalog.addTable(job3);
+    job3 = CatalogUtil.newTableDesc(JOB3_NAME, job3Schema, job3Meta, job3Path);
+    catalog.createTable(job3);
 
 
 
@@ -198,8 +209,8 @@ public class TestLeftOuterNLJoinExec {
 
     appender3.flush();
     appender3.close();
-    emp3 = CatalogUtil.newTableDesc("emp3", emp3Schema, emp3Meta, emp3Path);
-    catalog.addTable(emp3);
+    emp3 = CatalogUtil.newTableDesc(EMP3_NAME, emp3Schema, emp3Meta, emp3Path);
+    catalog.createTable(emp3);
 
     // ---------------------phone3 --------------------
     // emp_id  | phone_number
@@ -219,8 +230,8 @@ public class TestLeftOuterNLJoinExec {
     
     appender5.flush();
     appender5.close();
-    phone3 = CatalogUtil.newTableDesc("phone3", phone3Schema, phone3Meta, phone3Path);
-    catalog.addTable(phone3);
+    phone3 = CatalogUtil.newTableDesc(PHONE3_NAME, phone3Schema, phone3Meta, phone3Path);
+    catalog.createTable(phone3);
 
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
@@ -241,9 +252,9 @@ public class TestLeftOuterNLJoinExec {
 
   @Test
   public final void testLeftOuterNLJoinExec0() throws IOException, PlanningException {
-    FileFragment[] dep3Frags = StorageManager.splitNG(conf, "dep3", dep3.getMeta(), dep3.getPath(),
+    FileFragment[] dep3Frags = StorageManager.splitNG(conf, DEP3_NAME, dep3.getMeta(), dep3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(dep3Frags, emp3Frags);
@@ -253,7 +264,7 @@ public class TestLeftOuterNLJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context =  analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, context).getRootBlock().getRoot();
 
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
@@ -282,9 +293,9 @@ public class TestLeftOuterNLJoinExec {
 
   @Test
   public final void testLeftOuterNLJoinExec1() throws IOException, PlanningException {
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(),
+    FileFragment[] job3Frags = StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(job3Frags, emp3Frags);
@@ -295,7 +306,7 @@ public class TestLeftOuterNLJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context =  analyzer.parse(QUERIES[1]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, context).getRootBlock().getRoot();
 
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
@@ -327,9 +338,9 @@ public class TestLeftOuterNLJoinExec {
 
   @Test
   public final void testLeftOuter_NLJoinExec2() throws IOException, PlanningException {
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(),
+    FileFragment[] job3Frags = StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(emp3Frags, job3Frags);
@@ -339,7 +350,7 @@ public class TestLeftOuterNLJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context =  analyzer.parse(QUERIES[2]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, context).getRootBlock().getRoot();
 
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
@@ -372,9 +383,9 @@ public class TestLeftOuterNLJoinExec {
 
   @Test
   public final void testLeftOuter_NLJoinExec3() throws IOException, PlanningException {
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "phone3", phone3.getMeta(), phone3.getPath(),
+    FileFragment[] phone3Frags = StorageManager.splitNG(conf, PHONE3_NAME, phone3.getMeta(), phone3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(emp3Frags, phone3Frags);
@@ -384,7 +395,7 @@ public class TestLeftOuterNLJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context =  analyzer.parse(QUERIES[3]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, context).getRootBlock().getRoot();
 
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
@@ -416,9 +427,9 @@ public class TestLeftOuterNLJoinExec {
 
     @Test
   public final void testLeftOuter_NLJoinExec4() throws IOException, PlanningException {
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "phone3", phone3.getMeta(), phone3.getPath(),
+    FileFragment[] phone3Frags = StorageManager.splitNG(conf, PHONE3_NAME, phone3.getMeta(), phone3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(phone3Frags, emp3Frags);
@@ -428,7 +439,7 @@ public class TestLeftOuterNLJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context =  analyzer.parse(QUERIES[4]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, context).getRootBlock().getRoot();
 
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestMergeJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestMergeJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestMergeJoinExec.java
index 5977c95..2ed057c 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestMergeJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestMergeJoinExec.java
@@ -21,6 +21,7 @@ package org.apache.tajo.engine.planner.physical;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -46,6 +47,7 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.JoinEnforce.JoinAlgorithm;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -68,6 +70,8 @@ public class TestMergeJoinExec {
     util.initTestDir();
     catalog = util.startCatalogCluster().getCatalog();
     Path testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(TajoConstants.DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     FileSystem fs = testDir.getFileSystem(conf);
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
@@ -99,8 +103,8 @@ public class TestMergeJoinExec {
 
     appender.flush();
     appender.close();
-    employee = CatalogUtil.newTableDesc("employee", employeeSchema, employeeMeta, employeePath);
-    catalog.addTable(employee);
+    employee = CatalogUtil.newTableDesc("default.employee", employeeSchema, employeeMeta, employeePath);
+    catalog.createTable(employee);
 
     Schema peopleSchema = new Schema();
     peopleSchema.addColumn("empId", Type.INT4);
@@ -130,8 +134,8 @@ public class TestMergeJoinExec {
     appender.flush();
     appender.close();
 
-    people = CatalogUtil.newTableDesc("people", peopleSchema, peopleMeta, peoplePath);
-    catalog.addTable(people);
+    people = CatalogUtil.newTableDesc("default.people", peopleSchema, peopleMeta, peoplePath);
+    catalog.createTable(people);
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
   }
@@ -149,15 +153,15 @@ public class TestMergeJoinExec {
   @Test
   public final void testMergeInnerJoin() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr);
     LogicalNode root = plan.getRootBlock().getRoot();
 
     JoinNode joinNode = PlannerUtil.findTopNode(root, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] empFrags = sm.splitNG(conf, "e", employee.getMeta(), employee.getPath(), Integer.MAX_VALUE);
-    FileFragment[] peopleFrags = sm.splitNG(conf, "p", people.getMeta(), people.getPath(), Integer.MAX_VALUE);
+    FileFragment[] empFrags = sm.splitNG(conf, "default.e", employee.getMeta(), employee.getPath(), Integer.MAX_VALUE);
+    FileFragment[] peopleFrags = sm.splitNG(conf, "default.p", people.getMeta(), people.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(empFrags, peopleFrags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testMergeInnerJoin");

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestNLJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestNLJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestNLJoinExec.java
index 601621d..7fdfb44 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestNLJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestNLJoinExec.java
@@ -47,6 +47,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -70,6 +72,8 @@ public class TestNLJoinExec {
     util = new TajoTestingCluster();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -94,8 +98,8 @@ public class TestNLJoinExec {
     }
     appender.flush();
     appender.close();
-    employee = CatalogUtil.newTableDesc("employee", schema, employeeMeta, employeePath);
-    catalog.addTable(employee);
+    employee = CatalogUtil.newTableDesc("default.employee", schema, employeeMeta, employeePath);
+    catalog.createTable(employee);
     
     Schema peopleSchema = new Schema();
     peopleSchema.addColumn("empId", Type.INT4);
@@ -118,8 +122,8 @@ public class TestNLJoinExec {
     appender.flush();
     appender.close();
     
-    people = CatalogUtil.newTableDesc("people", peopleSchema, peopleMeta, peoplePath);
-    catalog.addTable(people);
+    people = CatalogUtil.newTableDesc("default.people", peopleSchema, peopleMeta, peoplePath);
+    catalog.createTable(people);
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
 
@@ -139,9 +143,9 @@ public class TestNLJoinExec {
   
   @Test
   public final void testNLCrossJoin() throws IOException, PlanningException {
-    FileFragment[] empFrags = StorageManager.splitNG(conf, "e", employee.getMeta(), employee.getPath(),
+    FileFragment[] empFrags = StorageManager.splitNG(conf, "default.e", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "p", people.getMeta(), people.getPath(),
+    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "default.p", people.getMeta(), people.getPath(),
         Integer.MAX_VALUE);
     
     FileFragment[] merged = TUtil.concat(empFrags, peopleFrags);
@@ -151,7 +155,8 @@ public class TestNLJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context = analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(),
+        context).getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
     PhysicalExec exec = phyPlanner.createPlan(ctx, plan);
@@ -167,9 +172,9 @@ public class TestNLJoinExec {
 
   @Test
   public final void testNLInnerJoin() throws IOException, PlanningException {
-    FileFragment[] empFrags = StorageManager.splitNG(conf, "e", employee.getMeta(), employee.getPath(),
+    FileFragment[] empFrags = StorageManager.splitNG(conf, "default.e", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "p", people.getMeta(), people.getPath(),
+    FileFragment[] peopleFrags = StorageManager.splitNG(conf, "default.p", people.getMeta(), people.getPath(),
         Integer.MAX_VALUE);
     
     FileFragment[] merged = TUtil.concat(empFrags, peopleFrags);
@@ -179,7 +184,8 @@ public class TestNLJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context =  analyzer.parse(QUERIES[1]);
-    LogicalNode plan = planner.createPlan(context).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(),
+        context).getRootBlock().getRoot();
     //LogicalOptimizer.optimize(ctx, plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java
index 1975a57..c7aa33d 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestPhysicalPlanner.java
@@ -27,6 +27,7 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.LocalTajoTestingUtility;
 import org.apache.tajo.QueryUnitAttemptId;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -45,6 +46,7 @@ import org.apache.tajo.engine.planner.global.MasterPlan;
 import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.ipc.TajoWorkerProtocol;
 import org.apache.tajo.master.TajoMaster;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.storage.index.bst.BSTIndex;
@@ -63,6 +65,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.ColumnPartitionEnforcer.ColumnPartitionAlgorithm;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.ShuffleType;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.SortEnforce.SortAlgorithm;
@@ -77,6 +81,7 @@ public class TestPhysicalPlanner {
   private static LogicalOptimizer optimizer;
   private static AbstractStorageManager sm;
   private static Path testDir;
+  private static Session session = LocalTajoTestingUtility.createDummySession();
 
   private static TableDesc employee = null;
   private static TableDesc score = null;
@@ -92,6 +97,8 @@ public class TestPhysicalPlanner {
     testDir = CommonTestingUtil.getTestDir("target/test-data/TestPhysicalPlanner");
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
     catalog = util.getMiniCatalogCluster().getCatalog();
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
       catalog.createFunction(funcDesc);
     }
@@ -123,14 +130,18 @@ public class TestPhysicalPlanner {
     appender.flush();
     appender.close();
 
-    employee = new TableDesc("employee", employeeSchema, employeeMeta, employeePath);
-    catalog.addTable(employee);
+    employee = new TableDesc(
+        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "employee"), employeeSchema, employeeMeta,
+        employeePath);
+    catalog.createTable(employee);
 
     Path scorePath = new Path(testDir, "score");
     TableMeta scoreMeta = CatalogUtil.newTableMeta(StoreType.CSV, new Options());
     appender = StorageManagerFactory.getStorageManager(conf).getAppender(scoreMeta, scoreSchema, scorePath);
     appender.init();
-    score = new TableDesc("score", scoreSchema, scoreMeta, scorePath);
+    score = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "score"), scoreSchema, scoreMeta,
+        scorePath);
     tuple = new VTuple(scoreSchema.size());
     int m = 0;
     for (int i = 1; i <= 5; i++) {
@@ -149,7 +160,7 @@ public class TestPhysicalPlanner {
     }
     appender.flush();
     appender.close();
-    catalog.addTable(score);
+    catalog.createTable(score);
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
     optimizer = new LogicalOptimizer(conf);
@@ -184,14 +195,14 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testCreateScanPlan() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employee.getMeta(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employee.getMeta(),
         employee.getPath(), Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testCreateScanPlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     LogicalNode rootNode =plan.getRootBlock().getRoot();
     optimizer.optimize(plan);
 
@@ -214,14 +225,14 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testCreateScanWithFilterPlan() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employee.getMeta(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employee.getMeta(),
         employee.getPath(), Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testCreateScanWithFilterPlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[16]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     LogicalNode rootNode =plan.getRootBlock().getRoot();
     optimizer.optimize(plan);
 
@@ -242,14 +253,14 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testGroupByPlan() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testGroupByPlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context = analyzer.parse(QUERIES[7]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     optimizer.optimize(plan);
     LogicalNode rootNode = plan.getRootBlock().getRoot();
 
@@ -272,7 +283,7 @@ public class TestPhysicalPlanner {
   @Test
   public final void testHashGroupByPlanWithALLField() throws IOException, PlanningException {
     // TODO - currently, this query does not use hash-based group operator.
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir(
         "target/test-data/testHashGroupByPlanWithALLField");
@@ -280,7 +291,7 @@ public class TestPhysicalPlanner {
         new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[15]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf,sm);
@@ -301,14 +312,14 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testSortGroupByPlan() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testSortGroupByPlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[]{frags[0]}, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context = analyzer.parse(QUERIES[7]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     optimizer.optimize(plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf,sm);
@@ -360,7 +371,7 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testStorePlan() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testStorePlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
@@ -369,7 +380,7 @@ public class TestPhysicalPlanner {
     ctx.setOutputPath(new Path(workDir, "grouped1"));
 
     Expr context = analyzer.parse(CreateTableAsStmts[0]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalNode rootNode = optimizer.optimize(plan);
 
 
@@ -401,7 +412,7 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testStorePlanWithRCFile() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testStorePlanWithRCFile");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
@@ -410,7 +421,7 @@ public class TestPhysicalPlanner {
     ctx.setOutputPath(new Path(workDir, "grouped2"));
 
     Expr context = analyzer.parse(CreateTableAsStmts[1]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     TableMeta outputMeta = CatalogUtil.newTableMeta(StoreType.RCFILE);
@@ -441,7 +452,7 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testEnforceForDefaultColumnPartitionStorePlan() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testStorePlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
@@ -450,7 +461,7 @@ public class TestPhysicalPlanner {
     ctx.setOutputPath(new Path(workDir, "grouped3"));
 
     Expr context = analyzer.parse(CreateTableAsStmts[2]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalNode rootNode = optimizer.optimize(plan);
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf,sm);
     PhysicalExec exec = phyPlanner.createPlan(ctx, rootNode);
@@ -461,13 +472,13 @@ public class TestPhysicalPlanner {
   public final void testEnforceForHashBasedColumnPartitionStorePlan() throws IOException, PlanningException {
 
     Expr context = analyzer.parse(CreateTableAsStmts[2]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalRootNode rootNode = (LogicalRootNode) optimizer.optimize(plan);
     CreateTableNode createTableNode = rootNode.getChild();
     Enforcer enforcer = new Enforcer();
     enforcer.enforceColumnPartitionAlgorithm(createTableNode.getPID(), ColumnPartitionAlgorithm.HASH_PARTITION);
 
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testStorePlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
@@ -484,13 +495,13 @@ public class TestPhysicalPlanner {
   public final void testEnforceForSortBasedColumnPartitionStorePlan() throws IOException, PlanningException {
 
     Expr context = analyzer.parse(CreateTableAsStmts[2]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalRootNode rootNode = (LogicalRootNode) optimizer.optimize(plan);
     CreateTableNode createTableNode = rootNode.getChild();
     Enforcer enforcer = new Enforcer();
     enforcer.enforceColumnPartitionAlgorithm(createTableNode.getPID(), ColumnPartitionAlgorithm.SORT_PARTITION);
 
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testStorePlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
@@ -505,18 +516,18 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testPartitionedStorePlan() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     QueryUnitAttemptId id = LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testPartitionedStorePlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, id, new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context = analyzer.parse(QUERIES[7]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
 
     int numPartitions = 3;
-    Column key1 = new Column("score.deptName", Type.TEXT);
-    Column key2 = new Column("score.class", Type.TEXT);
+    Column key1 = new Column("default.score.deptName", Type.TEXT);
+    Column key2 = new Column("default.score.class", Type.TEXT);
     DataChannel dataChannel = new DataChannel(masterPlan.newExecutionBlockId(), masterPlan.newExecutionBlockId(),
         ShuffleType.HASH_SHUFFLE, numPartitions);
     dataChannel.setShuffleKeys(new Column[]{key1, key2});
@@ -563,7 +574,7 @@ public class TestPhysicalPlanner {
   @Test
   public final void testPartitionedStorePlanWithEmptyGroupingSet()
       throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     QueryUnitAttemptId id = LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan);
 
@@ -572,7 +583,7 @@ public class TestPhysicalPlanner {
     TaskAttemptContext ctx = new TaskAttemptContext(conf, id, new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[14]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     LogicalNode rootNode = plan.getRootBlock().getRoot();
     int numPartitions = 1;
     DataChannel dataChannel = new DataChannel(masterPlan.newExecutionBlockId(), masterPlan.newExecutionBlockId(),
@@ -619,14 +630,14 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testAggregationFunction() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testAggregationFunction");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context = analyzer.parse(QUERIES[8]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     // Set all aggregation functions to the first phase mode
@@ -649,14 +660,14 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testCountFunction() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testCountFunction");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context = analyzer.parse(QUERIES[9]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     // Set all aggregation functions to the first phase mode
@@ -676,14 +687,14 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testGroupByWithNullValue() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testGroupByWithNullValue");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context = analyzer.parse(QUERIES[11]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf,sm);
@@ -700,14 +711,14 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testUnionPlan() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employee.getMeta(), employee.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testUnionPlan");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr  context = analyzer.parse(QUERIES[0]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalNode rootNode = optimizer.optimize(plan);
     LogicalRootNode root = (LogicalRootNode) rootNode;
     UnionNode union = plan.createNode(UnionNode.class);
@@ -733,7 +744,7 @@ public class TestPhysicalPlanner {
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[] { }, workDir);
     Expr expr = analyzer.parse(QUERIES[12]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
@@ -746,7 +757,7 @@ public class TestPhysicalPlanner {
     assertTrue(7.0d == tuple.get(1).asFloat8());
 
     expr = analyzer.parse(QUERIES[13]);
-    plan = planner.createPlan(expr);
+    plan = planner.createPlan(session, expr);
     rootNode = optimizer.optimize(plan);
 
     phyPlanner = new PhysicalPlannerImpl(conf, sm);
@@ -763,13 +774,13 @@ public class TestPhysicalPlanner {
 
   //@Test
   public final void testCreateIndex() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employee.getMeta(), employee.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testCreateIndex");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility.newQueryUnitAttemptId(masterPlan),
         new FileFragment[] {frags[0]}, workDir);
     Expr context = analyzer.parse(createIndexStmt[0]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
@@ -789,7 +800,7 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testDuplicateEliminate() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(),
         Integer.MAX_VALUE);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testDuplicateEliminate");
@@ -797,7 +808,7 @@ public class TestPhysicalPlanner {
         new FileFragment[] {frags[0]}, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(duplicateElimination[0]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(session, expr);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf,sm);
@@ -822,7 +833,7 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testIndexedStoreExec() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employee.getMeta(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employee.getMeta(),
         employee.getPath(), Integer.MAX_VALUE);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testIndexedStoreExec");
@@ -830,7 +841,7 @@ public class TestPhysicalPlanner {
         new FileFragment[] {frags[0]}, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context = analyzer.parse(SORT_QUERY[0]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     SortNode sortNode = PlannerUtil.findTopNode(rootNode, NodeType.SORT);
@@ -913,12 +924,12 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testSortEnforcer() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employee.getMeta(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employee.getMeta(),
         employee.getPath(), Integer.MAX_VALUE);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testSortEnforcer");
     Expr context = analyzer.parse(SORT_QUERY[0]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     optimizer.optimize(plan);
     LogicalNode rootNode = plan.getRootBlock().getRoot();
 
@@ -939,7 +950,7 @@ public class TestPhysicalPlanner {
     assertTrue(exec instanceof MemSortExec);
 
     context = analyzer.parse(SORT_QUERY[0]);
-    plan = planner.createPlan(context);
+    plan = planner.createPlan(session, context);
     optimizer.optimize(plan);
     rootNode = plan.getRootBlock().getRoot();
 
@@ -962,11 +973,11 @@ public class TestPhysicalPlanner {
 
   @Test
   public final void testGroupByEnforcer() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "score", score.getMeta(), score.getPath(), Integer.MAX_VALUE);
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.score", score.getMeta(), score.getPath(), Integer.MAX_VALUE);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testGroupByEnforcer");
     Expr context = analyzer.parse(QUERIES[7]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(session, context);
     optimizer.optimize(plan);
     LogicalNode rootNode = plan.getRootBlock().getRoot();
 
@@ -987,7 +998,7 @@ public class TestPhysicalPlanner {
     assertNotNull(PhysicalPlanUtil.findExecutor(exec, HashAggregateExec.class));
 
     context = analyzer.parse(QUERIES[7]);
-    plan = planner.createPlan(context);
+    plan = planner.createPlan(session, context);
     optimizer.optimize(plan);
     rootNode = plan.getRootBlock().getRoot();
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java
index cb9c419..65b5dba 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestProgressExternalSortExec.java
@@ -21,6 +21,7 @@ package org.apache.tajo.engine.planner.physical;
 
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.algebra.Expr;
 import org.apache.tajo.catalog.*;
@@ -48,6 +49,8 @@ import org.junit.Test;
 import java.util.Random;
 
 import static junit.framework.Assert.assertNotNull;
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -73,6 +76,8 @@ public class TestProgressExternalSortExec {
     util = new TajoTestingCluster();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf.setVar(TajoConf.ConfVars.WORKER_TEMPORAL_DIR, testDir.toString());
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -101,8 +106,10 @@ public class TestProgressExternalSortExec {
     System.out.println(appender.getStats().getNumRows() + " rows (" + appender.getStats().getNumBytes() + " Bytes)");
 
     testDataStats = appender.getStats();
-    employee = new TableDesc("employee", schema, employeeMeta, employeePath);
-    catalog.addTable(employee);
+    employee = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, employeeMeta,
+        employeePath);
+    catalog.createTable(employee);
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
   }
@@ -128,14 +135,14 @@ public class TestProgressExternalSortExec {
   }
 
   private void testProgress(int sortBufferBytesNum) throws Exception {
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employee.getMeta(), employee.getPath(),
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employee.getMeta(), employee.getPath(),
         Integer.MAX_VALUE);
     Path workDir = new Path(testDir, TestExternalSortExec.class.getName());
     TaskAttemptContext ctx = new TaskAttemptContext(conf,
         LocalTajoTestingUtility.newQueryUnitAttemptId(), new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalPlan plan = planner.createPlan(expr);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), expr);
     LogicalNode rootNode = plan.getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java
index d2c29a3..a45e397 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterHashJoinExec.java
@@ -35,6 +35,7 @@ import org.apache.tajo.engine.planner.PhysicalPlannerImpl;
 import org.apache.tajo.engine.planner.PlanningException;
 import org.apache.tajo.engine.planner.enforce.Enforcer;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -46,6 +47,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.junit.Assert.assertEquals;
 
 // this is not a physical operator in itself, but it uses the HashLeftOuterJoinExec with switched inputs order
@@ -58,11 +61,15 @@ public class TestRightOuterHashJoinExec {
   private LogicalPlanner planner;
   private AbstractStorageManager sm;
   private Path testDir;
+  private static Session session = LocalTajoTestingUtility.createDummySession();
 
   private TableDesc dep3;
   private TableDesc job3;
   private TableDesc emp3;
-  
+
+  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
 
   @Before
   public void setUp() throws Exception {
@@ -70,6 +77,8 @@ public class TestRightOuterHashJoinExec {
     util.initTestDir();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -106,8 +115,8 @@ public class TestRightOuterHashJoinExec {
 
     appender1.flush();
     appender1.close();
-    dep3 = CatalogUtil.newTableDesc("dep3", dep3Schema, dep3Meta, dep3Path);
-    catalog.addTable(dep3);
+    dep3 = CatalogUtil.newTableDesc(DEP3_NAME, dep3Schema, dep3Meta, dep3Path);
+    catalog.createTable(dep3);
 
     //----------------- job3 ------------------------------
     //  job_id  | job_title
@@ -135,8 +144,8 @@ public class TestRightOuterHashJoinExec {
 
     appender2.flush();
     appender2.close();
-    job3 = CatalogUtil.newTableDesc("job3", job3Schema, job3Meta, job3Path);
-    catalog.addTable(job3);
+    job3 = CatalogUtil.newTableDesc(JOB3_NAME, job3Schema, job3Meta, job3Path);
+    catalog.createTable(job3);
 
 
 
@@ -199,8 +208,8 @@ public class TestRightOuterHashJoinExec {
 
     appender3.flush();
     appender3.close();
-    emp3 = CatalogUtil.newTableDesc("emp3", emp3Schema, emp3Meta, emp3Path);
-    catalog.addTable(emp3);
+    emp3 = CatalogUtil.newTableDesc(EMP3_NAME, emp3Schema, emp3Meta, emp3Path);
+    catalog.createTable(emp3);
 
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
@@ -219,9 +228,9 @@ public class TestRightOuterHashJoinExec {
 
   @Test
   public final void testRightOuter_HashJoinExec0() throws IOException, PlanningException {
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] dep3Frags = StorageManager.splitNG(conf, "dep3", dep3.getMeta(), dep3.getPath(),
+    FileFragment[] dep3Frags = StorageManager.splitNG(conf, DEP3_NAME, dep3.getMeta(), dep3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(emp3Frags, dep3Frags);
@@ -231,7 +240,7 @@ public class TestRightOuterHashJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
     PhysicalExec exec = phyPlanner.createPlan(ctx, plan);
@@ -260,9 +269,9 @@ public class TestRightOuterHashJoinExec {
 
   @Test
   public final void testRightOuter_HashJoinExec1() throws IOException, PlanningException {
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(),
+    FileFragment[] job3Frags = StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(emp3Frags, job3Frags);
@@ -272,7 +281,7 @@ public class TestRightOuterHashJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[1]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
     PhysicalExec exec = phyPlanner.createPlan(ctx, plan);
@@ -301,9 +310,9 @@ public class TestRightOuterHashJoinExec {
     @Test
   public final void testRightOuter_HashJoinExec2() throws IOException, PlanningException {
     
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(),
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(),
         Integer.MAX_VALUE);
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(),
+    FileFragment[] job3Frags = StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(),
         Integer.MAX_VALUE);
 
     FileFragment[] merged = TUtil.concat(job3Frags, emp3Frags);
@@ -313,7 +322,7 @@ public class TestRightOuterHashJoinExec {
         LocalTajoTestingUtility.newQueryUnitAttemptId(), merged, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr expr = analyzer.parse(QUERIES[2]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);
     PhysicalExec exec = phyPlanner.createPlan(ctx, plan);
@@ -338,7 +347,4 @@ public class TestRightOuterHashJoinExec {
        assertEquals(7, count);
     }
   }
-
-
 }
- //--camelia

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java
index b4b588d..5b504b2 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestRightOuterMergeJoinExec.java
@@ -34,6 +34,7 @@ import org.apache.tajo.engine.planner.enforce.Enforcer;
 import org.apache.tajo.engine.planner.logical.JoinNode;
 import org.apache.tajo.engine.planner.logical.LogicalNode;
 import org.apache.tajo.engine.planner.logical.NodeType;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.*;
 import org.apache.tajo.storage.fragment.FileFragment;
 import org.apache.tajo.util.CommonTestingUtil;
@@ -45,6 +46,8 @@ import org.junit.Test;
 
 import java.io.IOException;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.ipc.TajoWorkerProtocol.JoinEnforce.JoinAlgorithm;
 import static org.junit.Assert.*;
 
@@ -57,7 +60,7 @@ public class TestRightOuterMergeJoinExec {
   private LogicalPlanner planner;
   private AbstractStorageManager sm;
   private Path testDir;
-  private static final int UNGENERATED_PID = -1;
+  private static final Session session = LocalTajoTestingUtility.createDummySession();
 
   private TableDesc dep3;
   private TableDesc dep4;
@@ -65,12 +68,20 @@ public class TestRightOuterMergeJoinExec {
   private TableDesc emp3;
   private TableDesc phone3;
 
+  private final String DEP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep3");
+  private final String DEP4_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "dep4");
+  private final String JOB3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "job3");
+  private final String EMP3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "emp3");
+  private final String PHONE3_NAME = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "phone3");
+
   @Before
   public void setUp() throws Exception {
     util = new TajoTestingCluster();
     util.initTestDir();
     catalog = util.startCatalogCluster().getCatalog();
     testDir = CommonTestingUtil.getTestDir(TEST_PATH);
+    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, testDir.toUri().toString());
+    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
     conf = util.getConfiguration();
     sm = StorageManagerFactory.getStorageManager(conf, testDir);
 
@@ -107,8 +118,8 @@ public class TestRightOuterMergeJoinExec {
 
     appender1.flush();
     appender1.close();
-    dep3 = CatalogUtil.newTableDesc("dep3", dep3Schema, dep3Meta, dep3Path);
-    catalog.addTable(dep3);
+    dep3 = CatalogUtil.newTableDesc(DEP3_NAME, dep3Schema, dep3Meta, dep3Path);
+    catalog.createTable(dep3);
 
 
     //----------------- dep4 ------------------------------
@@ -145,8 +156,8 @@ public class TestRightOuterMergeJoinExec {
 
     appender4.flush();
     appender4.close();
-    dep4 = CatalogUtil.newTableDesc("dep4", dep4Schema, dep4Meta, dep4Path);
-    catalog.addTable(dep4);
+    dep4 = CatalogUtil.newTableDesc(DEP4_NAME, dep4Schema, dep4Meta, dep4Path);
+    catalog.createTable(dep4);
 
 
 
@@ -176,8 +187,8 @@ public class TestRightOuterMergeJoinExec {
 
     appender2.flush();
     appender2.close();
-    job3 = CatalogUtil.newTableDesc("job3", job3Schema, job3Meta, job3Path);
-    catalog.addTable(job3);
+    job3 = CatalogUtil.newTableDesc(JOB3_NAME, job3Schema, job3Meta, job3Path);
+    catalog.createTable(job3);
 
 
 
@@ -240,8 +251,8 @@ public class TestRightOuterMergeJoinExec {
 
     appender3.flush();
     appender3.close();
-    emp3 = CatalogUtil.newTableDesc("emp3", emp3Schema, emp3Meta, emp3Path);
-    catalog.addTable(emp3);
+    emp3 = CatalogUtil.newTableDesc(EMP3_NAME, emp3Schema, emp3Meta, emp3Path);
+    catalog.createTable(emp3);
 
     //---------------------phone3 --------------------
     // emp_id  | phone_number
@@ -261,8 +272,8 @@ public class TestRightOuterMergeJoinExec {
 
     appender5.flush();
     appender5.close();
-    phone3 = CatalogUtil.newTableDesc("phone3", phone3Schema, phone3Meta, phone3Path);
-    catalog.addTable(phone3);
+    phone3 = CatalogUtil.newTableDesc(PHONE3_NAME, phone3Schema, phone3Meta, phone3Path);
+    catalog.createTable(phone3);
 
 
 
@@ -293,13 +304,13 @@ public class TestRightOuterMergeJoinExec {
   @Test
   public final void testRightOuterMergeJoin0() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[0]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] dep3Frags = StorageManager.splitNG(conf, "dep3", dep3.getMeta(), dep3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags = StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] dep3Frags = StorageManager.splitNG(conf, DEP3_NAME, dep3.getMeta(), dep3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(emp3Frags, dep3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testRightOuterMergeJoin0");
@@ -328,13 +339,15 @@ public class TestRightOuterMergeJoinExec {
   @Test
   public final void testRightOuter_MergeJoin1() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[1]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] job3Frags =
+        StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(job3Frags, emp3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testRightOuterMergeJoin1");
@@ -362,13 +375,15 @@ public class TestRightOuterMergeJoinExec {
   @Test
   public final void testRightOuterMergeJoin2() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[2]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] job3Frags = StorageManager.splitNG(conf, "job3", job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] job3Frags =
+        StorageManager.splitNG(conf, JOB3_NAME, job3.getMeta(), job3.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(job3Frags, emp3Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testRightOuterMergeJoin2");
@@ -396,13 +411,15 @@ public class TestRightOuterMergeJoinExec {
   @Test
   public final void testRightOuter_MergeJoin3() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[3]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] dep4Frags = StorageManager.splitNG(conf, "dep4", dep4.getMeta(), dep4.getPath(), Integer.MAX_VALUE);
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] dep4Frags =
+        StorageManager.splitNG(conf, DEP4_NAME, dep4.getMeta(), dep4.getPath(), Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(emp3Frags, dep4Frags);
 
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/testRightOuter_MergeJoin3");
@@ -431,13 +448,15 @@ public class TestRightOuterMergeJoinExec {
   @Test
   public final void testRightOuter_MergeJoin4() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[4]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "phone3", phone3.getMeta(), phone3.getPath(),
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] phone3Frags =
+        StorageManager.splitNG(conf, PHONE3_NAME, phone3.getMeta(), phone3.getPath(),
         Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(emp3Frags, phone3Frags);
 
@@ -466,13 +485,14 @@ public class TestRightOuterMergeJoinExec {
   @Test
   public final void testRightOuterMergeJoin5() throws IOException, PlanningException {
     Expr expr = analyzer.parse(QUERIES[5]);
-    LogicalNode plan = planner.createPlan(expr).getRootBlock().getRoot();
+    LogicalNode plan = planner.createPlan(session, expr).getRootBlock().getRoot();
     JoinNode joinNode = PlannerUtil.findTopNode(plan, NodeType.JOIN);
     Enforcer enforcer = new Enforcer();
     enforcer.enforceJoinAlgorithm(joinNode.getPID(), JoinAlgorithm.MERGE_JOIN);
 
-    FileFragment[] emp3Frags = StorageManager.splitNG(conf, "emp3", emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
-    FileFragment[] phone3Frags = StorageManager.splitNG(conf, "phone3", phone3.getMeta(), phone3.getPath(),
+    FileFragment[] emp3Frags =
+        StorageManager.splitNG(conf, EMP3_NAME, emp3.getMeta(), emp3.getPath(), Integer.MAX_VALUE);
+    FileFragment[] phone3Frags = StorageManager.splitNG(conf, PHONE3_NAME, phone3.getMeta(), phone3.getPath(),
         Integer.MAX_VALUE);
     FileFragment[] merged = TUtil.concat(phone3Frags,emp3Frags);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java
index 00fb386..a33a0e4 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/planner/physical/TestSortExec.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.planner.physical;
 
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.TpchTestBase;
 import org.apache.tajo.algebra.Expr;
@@ -91,8 +92,10 @@ public class TestSortExec {
     appender.flush();
     appender.close();
 
-    TableDesc desc = new TableDesc("employee", schema, employeeMeta, tablePath);
-    catalog.addTable(desc);
+    TableDesc desc = new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "employee"), schema, employeeMeta,
+        tablePath);
+    catalog.createTable(desc);
 
     analyzer = new SQLAnalyzer();
     planner = new LogicalPlanner(catalog);
@@ -104,13 +107,13 @@ public class TestSortExec {
 
   @Test
   public final void testNext() throws IOException, PlanningException {
-    FileFragment[] frags = StorageManager.splitNG(conf, "employee", employeeMeta, tablePath, Integer.MAX_VALUE);
+    FileFragment[] frags = StorageManager.splitNG(conf, "default.employee", employeeMeta, tablePath, Integer.MAX_VALUE);
     Path workDir = CommonTestingUtil.getTestDir("target/test-data/TestSortExec");
     TaskAttemptContext ctx = new TaskAttemptContext(conf, LocalTajoTestingUtility
         .newQueryUnitAttemptId(), new FileFragment[] { frags[0] }, workDir);
     ctx.setEnforcer(new Enforcer());
     Expr context = analyzer.parse(QUERIES[0]);
-    LogicalPlan plan = planner.createPlan(context);
+    LogicalPlan plan = planner.createPlan(LocalTajoTestingUtility.createDummySession(), context);
     LogicalNode rootNode = optimizer.optimize(plan);
 
     PhysicalPlanner phyPlanner = new PhysicalPlannerImpl(conf, sm);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java
index 902a73a..79db68c 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCTASQuery.java
@@ -23,6 +23,7 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.IntegrationTest;
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.TajoTestingCluster;
 import org.apache.tajo.catalog.CatalogService;
 import org.apache.tajo.catalog.TableDesc;
@@ -34,6 +35,8 @@ import org.junit.experimental.categories.Category;
 import java.sql.ResultSet;
 import java.util.Map;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.catalog.CatalogUtil.buildFQName;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -44,16 +47,21 @@ import static org.junit.Assert.assertTrue;
 @Category(IntegrationTest.class)
 public class TestCTASQuery extends QueryTestCaseBase {
 
+  public TestCTASQuery() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public final void testCtasWithoutTableDefinition() throws Exception {
     ResultSet res = executeQuery();
-
     res.close();
+
     CatalogService catalog = testBase.getTestingCluster().getMaster().getCatalog();
-    TableDesc desc = catalog.getTableDesc("testCtasWithoutTableDefinition");
-    assertTrue(catalog.existsTable("testCtasWithoutTableDefinition"));
+    String tableName = buildFQName(DEFAULT_DATABASE_NAME, "testCtasWithoutTableDefinition");
+    TableDesc desc = catalog.getTableDesc(tableName);
+    assertTrue(catalog.existsTable(tableName));
 
-    assertTrue(desc.getSchema().contains("testCtasWithoutTableDefinition.col1"));
+    assertTrue(desc.getSchema().contains("default.testCtasWithoutTableDefinition.col1"));
     PartitionMethodDesc partitionDesc = desc.getPartitionMethod();
     assertEquals(partitionDesc.getPartitionType(), CatalogProtos.PartitionType.COLUMN);
     assertEquals("key", partitionDesc.getExpressionSchema().getColumns().get(0).getSimpleName());
@@ -66,7 +74,9 @@ public class TestCTASQuery extends QueryTestCaseBase {
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/key=38.0")));
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/key=45.0")));
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/key=49.0")));
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
 
     ResultSet res2 = executeFile("check1.sql");
 
@@ -91,8 +101,8 @@ public class TestCTASQuery extends QueryTestCaseBase {
 
     TajoTestingCluster cluster = testBase.getTestingCluster();
     CatalogService catalog = cluster.getMaster().getCatalog();
-    TableDesc desc = catalog.getTableDesc("testCtasWithColumnedPartition");
-    assertTrue(catalog.existsTable("testCtasWithColumnedPartition"));
+    TableDesc desc = catalog.getTableDesc(DEFAULT_DATABASE_NAME, "testCtasWithColumnedPartition");
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, "testCtasWithColumnedPartition"));
     PartitionMethodDesc partitionDesc = desc.getPartitionMethod();
     assertEquals(partitionDesc.getPartitionType(), CatalogProtos.PartitionType.COLUMN);
     assertEquals("key", partitionDesc.getExpressionSchema().getColumns().get(0).getSimpleName());
@@ -105,7 +115,9 @@ public class TestCTASQuery extends QueryTestCaseBase {
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/key=38.0")));
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/key=45.0")));
     assertTrue(fs.isDirectory(new Path(path.toUri() + "/key=49.0")));
-    assertEquals(5, desc.getStats().getNumRows().intValue());
+    if (!cluster.isHCatalogStoreRunning()) {
+      assertEquals(5, desc.getStats().getNumRows().intValue());
+    }
 
     ResultSet res2 = executeFile("check2.sql");
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCaseByCases.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCaseByCases.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCaseByCases.java
index 203d113..6472c68 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCaseByCases.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestCaseByCases.java
@@ -19,11 +19,17 @@
 package org.apache.tajo.engine.query;
 
 import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
 import org.junit.Test;
 
 import java.sql.ResultSet;
 
 public class TestCaseByCases extends QueryTestCaseBase {
+
+  public TestCaseByCases() {
+    super(TajoConstants.DEFAULT_DATABASE_NAME);
+  }
+
   @Test
   public final void testTAJO415Case() throws Exception {
     ResultSet res = executeQuery();


[06/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
index dc70f23..a504e7b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
@@ -27,11 +27,9 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.service.AbstractService;
-import org.apache.tajo.QueryId;
-import org.apache.tajo.QueryIdFactory;
-import org.apache.tajo.TajoIdProtos;
-import org.apache.tajo.TajoProtos;
+import org.apache.tajo.*;
 import org.apache.tajo.catalog.*;
+import org.apache.tajo.catalog.exception.NoSuchDatabaseException;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.conf.TajoConf;
@@ -47,15 +45,22 @@ import org.apache.tajo.master.querymaster.QueryJobEvent;
 import org.apache.tajo.master.querymaster.QueryJobManager;
 import org.apache.tajo.master.rm.Worker;
 import org.apache.tajo.master.rm.WorkerResource;
+import org.apache.tajo.master.session.InvalidSessionException;
+import org.apache.tajo.master.session.NoSuchSessionVariableException;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.rpc.BlockingRpcServer;
+import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.BoolProto;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringProto;
 import org.apache.tajo.util.NetUtils;
+import org.apache.tajo.util.ProtoUtil;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.util.*;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+
 public class TajoMasterClientService extends AbstractService {
   private final static Log LOG = LogFactory.getLog(TajoMasterClientService.class);
   private final MasterContext context;
@@ -111,32 +116,150 @@ public class TajoMasterClientService extends AbstractService {
     return this.bindAddress;
   }
 
-  public int getHttpPort() {
-    return 0;
-  }
   /////////////////////////////////////////////////////////////////////////////
   // TajoMasterClientProtocolService
   /////////////////////////////////////////////////////////////////////////////
   public class TajoMasterClientProtocolServiceHandler implements TajoMasterClientProtocolService.BlockingInterface {
     @Override
-    public BoolProto updateSessionVariables(RpcController controller,
-                                            UpdateSessionVariableRequest request)
+    public CreateSessionResponse createSession(RpcController controller, CreateSessionRequest request)
         throws ServiceException {
-      return null;
+      try {
+        // create a new session with base database name. If no database name is give, we use default database.
+        String databaseName = request.hasBaseDatabaseName() ? request.getBaseDatabaseName() : DEFAULT_DATABASE_NAME;
+
+        if (!context.getCatalog().existDatabase(databaseName)) {
+          LOG.info("Session creation is canceled due to absent base database \"" + databaseName + "\".");
+          throw new NoSuchDatabaseException(databaseName);
+        }
+
+        String sessionId =
+            context.getSessionManager().createSession(request.getUsername(), databaseName);
+        CreateSessionResponse.Builder builder = CreateSessionResponse.newBuilder();
+        builder.setState(CreateSessionResponse.ResultState.SUCCESS);
+        builder.setSessionId(TajoIdProtos.SessionIdProto.newBuilder().setId(sessionId).build());
+        return builder.build();
+      } catch (NoSuchDatabaseException nsde) {
+        CreateSessionResponse.Builder builder = CreateSessionResponse.newBuilder();
+        builder.setState(CreateSessionResponse.ResultState.FAILED);
+        builder.setMessage(nsde.getMessage());
+        return builder.build();
+      } catch (InvalidSessionException e) {
+        CreateSessionResponse.Builder builder = CreateSessionResponse.newBuilder();
+        builder.setState(CreateSessionResponse.ResultState.FAILED);
+        builder.setMessage(e.getMessage());
+        return builder.build();
+      }
     }
 
     @Override
-    public ExplainQueryResponse explainQuery(RpcController controller,
-                                           ExplainQueryRequest request)
+    public BoolProto removeSession(RpcController controller, TajoIdProtos.SessionIdProto request)
+        throws ServiceException {
+      if (request != null) {
+        context.getSessionManager().removeSession(request.getId());
+      }
+      return ProtoUtil.TRUE;
+    }
+
+    @Override
+    public BoolProto updateSessionVariables(RpcController controller, UpdateSessionVariableRequest request)
+        throws ServiceException {
+      try {
+        String sessionId = request.getSessionId().getId();
+        for (CatalogProtos.KeyValueProto kv : request.getSetVariables().getKeyvalList()) {
+          context.getSessionManager().setVariable(sessionId, kv.getKey(), kv.getValue());
+        }
+        for (String unsetVariable : request.getUnsetVariablesList()) {
+          context.getSessionManager().removeVariable(sessionId, unsetVariable);
+        }
+        return ProtoUtil.TRUE;
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
+    }
+
+    @Override
+    public StringProto getSessionVariable(RpcController controller, SessionedStringProto request)
         throws ServiceException {
 
       try {
+        return ProtoUtil.convertString(
+            context.getSessionManager().getVariable(request.getSessionId().getId(), request.getValue()));
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
+    }
+
+    @Override
+    public BoolProto existSessionVariable(RpcController controller, SessionedStringProto request) throws ServiceException {
+      try {
+        String value = context.getSessionManager().getVariable(request.getSessionId().getId(), request.getValue());
+        if (value != null) {
+          return ProtoUtil.TRUE;
+        } else {
+          return ProtoUtil.FALSE;
+        }
+      } catch (NoSuchSessionVariableException nssv) {
+        return ProtoUtil.FALSE;
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
+    }
+
+    @Override
+    public CatalogProtos.KeyValueSetProto getAllSessionVariables(RpcController controller,
+                                                                 TajoIdProtos.SessionIdProto request)
+        throws ServiceException {
+      try {
+        String sessionId = request.getId();
+        Options options = new Options();
+        options.putAll(context.getSessionManager().getAllVariables(sessionId));
+        return options.getProto();
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
+    }
+
+    @Override
+    public StringProto getCurrentDatabase(RpcController controller, TajoIdProtos.SessionIdProto request)
+        throws ServiceException {
+      try {
+        String sessionId = request.getId();
+        return ProtoUtil.convertString(context.getSessionManager().getSession(sessionId).getCurrentDatabase());
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
+    }
+
+    @Override
+    public BoolProto selectDatabase(RpcController controller, SessionedStringProto request) throws ServiceException {
+      try {
+        String sessionId = request.getSessionId().getId();
+        String databaseName = CatalogUtil.normalizeIdentifier(request.getValue());
+
+        if (context.getCatalog().existDatabase(databaseName)) {
+          context.getSessionManager().getSession(sessionId).selectDatabase(databaseName);
+          return ProtoUtil.TRUE;
+        } else {
+          throw new ServiceException(new NoSuchDatabaseException(databaseName));
+        }
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
+    }
+
+    @Override
+    public ExplainQueryResponse explainQuery(RpcController controller,
+                                           SessionedStringProto request) throws ServiceException {
+
+      try {
+        Session session = context.getSessionManager().getSession(request.getSessionId().getId());
+
         if(LOG.isDebugEnabled()) {
-          LOG.debug("ExplainQuery [" + request.getQuery() + "]");
+          LOG.debug("ExplainQuery [" + request.getValue() + "]");
         }
         ClientProtos.ExplainQueryResponse.Builder responseBuilder = ClientProtos.ExplainQueryResponse.newBuilder();
         responseBuilder.setResultCode(ResultCode.OK);
-        String plan = context.getGlobalEngine().explainQuery(request.getQuery());
+        String plan = context.getGlobalEngine().explainQuery(session, request.getValue());
         if(LOG.isDebugEnabled()) {
           LOG.debug("ExplainQuery [" + plan + "]");
         }
@@ -151,15 +274,16 @@ public class TajoMasterClientService extends AbstractService {
       }
     }
     @Override
-    public GetQueryStatusResponse submitQuery(RpcController controller,
-                                           QueryRequest request)
-        throws ServiceException {
+    public GetQueryStatusResponse submitQuery(RpcController controller, QueryRequest request) throws ServiceException {
+
 
       try {
+        Session session = context.getSessionManager().getSession(request.getSessionId().getId());
+
         if(LOG.isDebugEnabled()) {
           LOG.debug("Query [" + request.getQuery() + "] is submitted");
         }
-        return context.getGlobalEngine().executeQuery(request.getQuery());
+        return context.getGlobalEngine().executeQuery(session, request.getQuery());
       } catch (Exception e) {
         LOG.error(e.getMessage(), e);
         ClientProtos.GetQueryStatusResponse.Builder responseBuilder = ClientProtos.GetQueryStatusResponse.newBuilder();
@@ -174,119 +298,135 @@ public class TajoMasterClientService extends AbstractService {
     }
 
     @Override
-    public UpdateQueryResponse updateQuery(RpcController controller,
-                                           QueryRequest request)
-        throws ServiceException {
+    public UpdateQueryResponse updateQuery(RpcController controller, QueryRequest request) throws ServiceException {
 
-      UpdateQueryResponse.Builder builder = UpdateQueryResponse.newBuilder();
       try {
-        context.getGlobalEngine().updateQuery(request.getQuery());
-        builder.setResultCode(ResultCode.OK);
-        return builder.build();
-      } catch (Exception e) {
-        builder.setResultCode(ResultCode.ERROR);
-        if (e.getMessage() == null) {
-          builder.setErrorMessage(ExceptionUtils.getStackTrace(e));
+        Session session = context.getSessionManager().getSession(request.getSessionId().getId());
+        UpdateQueryResponse.Builder builder = UpdateQueryResponse.newBuilder();
+        try {
+          context.getGlobalEngine().updateQuery(session, request.getQuery());
+          builder.setResultCode(ResultCode.OK);
+          return builder.build();
+        } catch (Exception e) {
+          builder.setResultCode(ResultCode.ERROR);
+          if (e.getMessage() == null) {
+            builder.setErrorMessage(ExceptionUtils.getStackTrace(e));
+          }
+          return builder.build();
         }
-        return builder.build();
+      } catch (Throwable t) {
+        throw new ServiceException(t);
       }
     }
 
     @Override
     public GetQueryResultResponse getQueryResult(RpcController controller,
-                                                 GetQueryResultRequest request)
-        throws ServiceException {
-      QueryId queryId = new QueryId(request.getQueryId());
-      QueryInProgress queryInProgress = context.getQueryJobManager().getQueryInProgress(queryId);
-      QueryInfo queryInfo = queryInProgress.getQueryInfo();
-      GetQueryResultResponse.Builder builder
-          = GetQueryResultResponse.newBuilder();
-
+                                                 GetQueryResultRequest request) throws ServiceException {
       try {
-        //TODO After implementation Tajo's user security feature, Should be modified.
-        builder.setTajoUserName(UserGroupInformation.getCurrentUser().getUserName());
-      } catch (IOException e) {
-        LOG.warn("Can't get current user name");
-      }
-      switch (queryInfo.getQueryState()) {
-        case QUERY_SUCCEEDED:
-          // TODO check this logic needed
-          //builder.setTableDesc((TableDescProto) queryJobManager.getResultDesc().getProto());
-          break;
-        case QUERY_FAILED:
-        case QUERY_ERROR:
-          builder.setErrorMessage("Query " + queryId + " is failed");
-        default:
-          builder.setErrorMessage("Query " + queryId + " is still running");
-      }
+        context.getSessionManager().touch(request.getSessionId().getId());
+        QueryId queryId = new QueryId(request.getQueryId());
+        QueryInProgress queryInProgress = context.getQueryJobManager().getQueryInProgress(queryId);
+        QueryInfo queryInfo = queryInProgress.getQueryInfo();
+        GetQueryResultResponse.Builder builder
+            = GetQueryResultResponse.newBuilder();
+
+        try {
+          //TODO After implementation Tajo's user security feature, Should be modified.
+          builder.setTajoUserName(UserGroupInformation.getCurrentUser().getUserName());
+        } catch (IOException e) {
+          LOG.warn("Can't get current user name");
+        }
+        switch (queryInfo.getQueryState()) {
+          case QUERY_SUCCEEDED:
+            // TODO check this logic needed
+            //builder.setTableDesc((TableDescProto) queryJobManager.getResultDesc().getProto());
+            break;
+          case QUERY_FAILED:
+          case QUERY_ERROR:
+            builder.setErrorMessage("Query " + queryId + " is failed");
+          default:
+            builder.setErrorMessage("Query " + queryId + " is still running");
+        }
 
-      return builder.build();
+        return builder.build();
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
     }
 
     @Override
-    public GetQueryListResponse getRunningQueryList(RpcController controller,
-                                             GetQueryListRequest request)
+    public GetQueryListResponse getRunningQueryList(RpcController controller, GetQueryListRequest request)
+
         throws ServiceException {
-      GetQueryListResponse.Builder builder
-        = GetQueryListResponse.newBuilder(); 
-       
-      Collection<QueryInProgress> queries 
-        = context.getQueryJobManager().getRunningQueries();
-
-      BriefQueryInfo.Builder infoBuilder = BriefQueryInfo.newBuilder();
- 
-      for (QueryInProgress queryInProgress : queries) {
-        QueryInfo queryInfo = queryInProgress.getQueryInfo();
 
-        infoBuilder.setQueryId(queryInfo.getQueryId().getProto());
-        infoBuilder.setState(queryInfo.getQueryState());
-        infoBuilder.setQuery(queryInfo.getSql());
-        infoBuilder.setStartTime(queryInfo.getStartTime());
-        long endTime = (queryInfo.getFinishTime() == 0) ? 
-                       System.currentTimeMillis() : queryInfo.getFinishTime();
-        infoBuilder.setFinishTime(endTime);
-        infoBuilder.setProgress(queryInfo.getProgress());
-        infoBuilder.setQueryMasterPort(queryInfo.getQueryMasterPort());
-        infoBuilder.setQueryMasterHost(queryInfo.getQueryMasterHost());
-
-        builder.addQueryList(infoBuilder.build());
-      }
+      try {
+        context.getSessionManager().touch(request.getSessionId().getId());
+        GetQueryListResponse.Builder builder= GetQueryListResponse.newBuilder();
 
-      GetQueryListResponse result = builder.build();
-      return result;
+        Collection<QueryInProgress> queries
+          = context.getQueryJobManager().getRunningQueries();
+
+        BriefQueryInfo.Builder infoBuilder = BriefQueryInfo.newBuilder();
+
+        for (QueryInProgress queryInProgress : queries) {
+          QueryInfo queryInfo = queryInProgress.getQueryInfo();
+
+          infoBuilder.setQueryId(queryInfo.getQueryId().getProto());
+          infoBuilder.setState(queryInfo.getQueryState());
+          infoBuilder.setQuery(queryInfo.getSql());
+          infoBuilder.setStartTime(queryInfo.getStartTime());
+          long endTime = (queryInfo.getFinishTime() == 0) ?
+                         System.currentTimeMillis() : queryInfo.getFinishTime();
+          infoBuilder.setFinishTime(endTime);
+          infoBuilder.setProgress(queryInfo.getProgress());
+          infoBuilder.setQueryMasterPort(queryInfo.getQueryMasterPort());
+          infoBuilder.setQueryMasterHost(queryInfo.getQueryMasterHost());
+
+          builder.addQueryList(infoBuilder.build());
+        }
+
+        GetQueryListResponse result = builder.build();
+        return result;
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
     }
 
     @Override
-    public GetQueryListResponse getFinishedQueryList(RpcController controller,
-                                             GetQueryListRequest request)
+    public GetQueryListResponse getFinishedQueryList(RpcController controller, GetQueryListRequest request)
         throws ServiceException {
-      GetQueryListResponse.Builder builder
-          = GetQueryListResponse.newBuilder();
 
-      Collection<QueryInProgress> queries
-          = context.getQueryJobManager().getFinishedQueries();
+      try {
+        context.getSessionManager().touch(request.getSessionId().getId());
+        GetQueryListResponse.Builder builder = GetQueryListResponse.newBuilder();
 
-      BriefQueryInfo.Builder infoBuilder = BriefQueryInfo.newBuilder();
+        Collection<QueryInProgress> queries
+            = context.getQueryJobManager().getFinishedQueries();
 
-      for (QueryInProgress queryInProgress : queries) {
-        QueryInfo queryInfo = queryInProgress.getQueryInfo();
+        BriefQueryInfo.Builder infoBuilder = BriefQueryInfo.newBuilder();
 
-        infoBuilder.setQueryId(queryInfo.getQueryId().getProto());
-        infoBuilder.setState(queryInfo.getQueryState());
-        infoBuilder.setQuery(queryInfo.getSql());
-        infoBuilder.setStartTime(queryInfo.getStartTime());
-        long endTime = (queryInfo.getFinishTime() == 0) ?
-            System.currentTimeMillis() : queryInfo.getFinishTime();
-        infoBuilder.setFinishTime(endTime);
-        infoBuilder.setProgress(queryInfo.getProgress());
-        infoBuilder.setQueryMasterPort(queryInfo.getQueryMasterPort());
-        infoBuilder.setQueryMasterHost(queryInfo.getQueryMasterHost());
-
-        builder.addQueryList(infoBuilder.build());
-      }
+        for (QueryInProgress queryInProgress : queries) {
+          QueryInfo queryInfo = queryInProgress.getQueryInfo();
 
-      GetQueryListResponse result = builder.build();
-      return result;
+          infoBuilder.setQueryId(queryInfo.getQueryId().getProto());
+          infoBuilder.setState(queryInfo.getQueryState());
+          infoBuilder.setQuery(queryInfo.getSql());
+          infoBuilder.setStartTime(queryInfo.getStartTime());
+          long endTime = (queryInfo.getFinishTime() == 0) ?
+              System.currentTimeMillis() : queryInfo.getFinishTime();
+          infoBuilder.setFinishTime(endTime);
+          infoBuilder.setProgress(queryInfo.getProgress());
+          infoBuilder.setQueryMasterPort(queryInfo.getQueryMasterPort());
+          infoBuilder.setQueryMasterHost(queryInfo.getQueryMasterHost());
+
+          builder.addQueryList(infoBuilder.build());
+        }
+
+        GetQueryListResponse result = builder.build();
+        return result;
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
     }
 
     @Override
@@ -294,136 +434,242 @@ public class TajoMasterClientService extends AbstractService {
                                                  GetQueryStatusRequest request)
         throws ServiceException {
 
-      GetQueryStatusResponse.Builder builder
-          = GetQueryStatusResponse.newBuilder();
-      QueryId queryId = new QueryId(request.getQueryId());
-      builder.setQueryId(request.getQueryId());
+      try {
+        context.getSessionManager().touch(request.getSessionId().getId());
 
-      if (queryId.equals(QueryIdFactory.NULL_QUERY_ID)) {
-        builder.setResultCode(ResultCode.OK);
-        builder.setState(TajoProtos.QueryState.QUERY_SUCCEEDED);
-      } else {
-        QueryInProgress queryInProgress = context.getQueryJobManager().getQueryInProgress(queryId);
-        if (queryInProgress != null) {
-          QueryInfo queryInfo = queryInProgress.getQueryInfo();
+        GetQueryStatusResponse.Builder builder = GetQueryStatusResponse.newBuilder();
+        QueryId queryId = new QueryId(request.getQueryId());
+        builder.setQueryId(request.getQueryId());
+
+        if (queryId.equals(QueryIdFactory.NULL_QUERY_ID)) {
           builder.setResultCode(ResultCode.OK);
-          builder.setState(queryInfo.getQueryState());
-          builder.setProgress(queryInfo.getProgress());
-          builder.setSubmitTime(queryInfo.getStartTime());
-          if(queryInfo.getQueryMasterHost() != null) {
-            builder.setQueryMasterHost(queryInfo.getQueryMasterHost());
-            builder.setQueryMasterPort(queryInfo.getQueryMasterClientPort());
-          }
-          //builder.setInitTime(queryJobManager.getInitializationTime());
-          //builder.setHasResult(!queryJobManager.isCreateTableStmt());
-          if (queryInfo.getQueryState() == TajoProtos.QueryState.QUERY_SUCCEEDED) {
-            builder.setFinishTime(queryInfo.getFinishTime());
+          builder.setState(TajoProtos.QueryState.QUERY_SUCCEEDED);
+        } else {
+          QueryInProgress queryInProgress = context.getQueryJobManager().getQueryInProgress(queryId);
+          if (queryInProgress != null) {
+            QueryInfo queryInfo = queryInProgress.getQueryInfo();
+            builder.setResultCode(ResultCode.OK);
+            builder.setState(queryInfo.getQueryState());
+            builder.setProgress(queryInfo.getProgress());
+            builder.setSubmitTime(queryInfo.getStartTime());
+            if(queryInfo.getQueryMasterHost() != null) {
+              builder.setQueryMasterHost(queryInfo.getQueryMasterHost());
+              builder.setQueryMasterPort(queryInfo.getQueryMasterClientPort());
+            }
+            //builder.setInitTime(queryJobManager.getInitializationTime());
+            //builder.setHasResult(!queryJobManager.isCreateTableStmt());
+            if (queryInfo.getQueryState() == TajoProtos.QueryState.QUERY_SUCCEEDED) {
+              builder.setFinishTime(queryInfo.getFinishTime());
+            } else {
+              builder.setFinishTime(System.currentTimeMillis());
+            }
           } else {
-            builder.setFinishTime(System.currentTimeMillis());
+            builder.setResultCode(ResultCode.ERROR);
+            builder.setErrorMessage("No such query: " + queryId.toString());
           }
-        } else {
-          builder.setResultCode(ResultCode.ERROR);
-          builder.setErrorMessage("No such query: " + queryId.toString());
         }
-      }
+        return builder.build();
 
-      return builder.build();
+      } catch (Throwable t) {
+        throw new  ServiceException(t);
+      }
     }
 
     /**
      * It is invoked by TajoContainerProxy.
      */
     @Override
-    public BoolProto killQuery(RpcController controller, TajoIdProtos.QueryIdProto request) throws ServiceException {
-      QueryId queryId = new QueryId(request);
-      QueryJobManager queryJobManager = context.getQueryJobManager();
-      queryJobManager.getEventHandler().handle(new QueryJobEvent(QueryJobEvent.Type.QUERY_JOB_KILL,
-          new QueryInfo(queryId)));
-      return BOOL_TRUE;
+    public BoolProto killQuery(RpcController controller, KillQueryRequest request) throws ServiceException {
+      try {
+        context.getSessionManager().touch(request.getSessionId().getId());
+        QueryId queryId = new QueryId(request.getQueryId());
+        QueryJobManager queryJobManager = context.getQueryJobManager();
+        queryJobManager.getEventHandler().handle(new QueryJobEvent(QueryJobEvent.Type.QUERY_JOB_KILL,
+            new QueryInfo(queryId)));
+        return BOOL_TRUE;
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
     }
 
     @Override
     public GetClusterInfoResponse getClusterInfo(RpcController controller,
                                                  GetClusterInfoRequest request)
         throws ServiceException {
-      GetClusterInfoResponse.Builder builder
-        = GetClusterInfoResponse.newBuilder(); 
-       
-      Map<String, Worker> workers = context.getResourceManager().getWorkers();
-
-      List<String> wokerKeys = new ArrayList<String>(workers.keySet());
-      Collections.sort(wokerKeys);
-
-      WorkerResourceInfo.Builder workerBuilder
-        = WorkerResourceInfo.newBuilder();
-
-      for(Worker worker: workers.values()) {
-        WorkerResource workerResource = worker.getResource();
-        workerBuilder.setAllocatedHost(worker.getHostName());
-        workerBuilder.setDiskSlots(workerResource.getDiskSlots());
-        workerBuilder.setCpuCoreSlots(workerResource.getCpuCoreSlots());
-        workerBuilder.setMemoryMB(workerResource.getMemoryMB());
-        workerBuilder.setLastHeartbeat(worker.getLastHeartbeatTime());
-        workerBuilder.setUsedMemoryMB(workerResource.getUsedMemoryMB());
-        workerBuilder.setUsedCpuCoreSlots(workerResource.getUsedCpuCoreSlots());
-        workerBuilder.setUsedDiskSlots(workerResource.getUsedDiskSlots());
-        workerBuilder.setWorkerStatus(worker.getState().toString());
-        workerBuilder.setQueryMasterMode(workerResource.isQueryMasterMode());
-        workerBuilder.setTaskRunnerMode(workerResource.isTaskRunnerMode());
-        workerBuilder.setPeerRpcPort(worker.getPeerRpcPort());
-        workerBuilder.setQueryMasterPort(worker.getQueryMasterPort());
-        workerBuilder.setClientPort(worker.getClientPort());
-        workerBuilder.setPullServerPort(worker.getPullServerPort());
-        workerBuilder.setHttpPort(worker.getHttpPort());
-        workerBuilder.setMaxHeap(workerResource.getMaxHeap());
-        workerBuilder.setFreeHeap(workerResource.getFreeHeap());
-        workerBuilder.setTotalHeap(workerResource.getTotalHeap());
-        workerBuilder.setNumRunningTasks(workerResource.getNumRunningTasks());
-        workerBuilder.setNumQueryMasterTasks(workerResource.getNumQueryMasterTasks());
-
-        builder.addWorkerList(workerBuilder.build());
+      try {
+        context.getSessionManager().touch(request.getSessionId().getId());
+        GetClusterInfoResponse.Builder builder= GetClusterInfoResponse.newBuilder();
+
+        Map<String, Worker> workers = context.getResourceManager().getWorkers();
+
+        List<String> wokerKeys = new ArrayList<String>(workers.keySet());
+        Collections.sort(wokerKeys);
+
+        WorkerResourceInfo.Builder workerBuilder
+          = WorkerResourceInfo.newBuilder();
+
+        for(Worker worker: workers.values()) {
+          WorkerResource workerResource = worker.getResource();
+          workerBuilder.setAllocatedHost(worker.getHostName());
+          workerBuilder.setDiskSlots(workerResource.getDiskSlots());
+          workerBuilder.setCpuCoreSlots(workerResource.getCpuCoreSlots());
+          workerBuilder.setMemoryMB(workerResource.getMemoryMB());
+          workerBuilder.setLastHeartbeat(worker.getLastHeartbeatTime());
+          workerBuilder.setUsedMemoryMB(workerResource.getUsedMemoryMB());
+          workerBuilder.setUsedCpuCoreSlots(workerResource.getUsedCpuCoreSlots());
+          workerBuilder.setUsedDiskSlots(workerResource.getUsedDiskSlots());
+          workerBuilder.setWorkerStatus(worker.getState().toString());
+          workerBuilder.setQueryMasterMode(workerResource.isQueryMasterMode());
+          workerBuilder.setTaskRunnerMode(workerResource.isTaskRunnerMode());
+          workerBuilder.setPeerRpcPort(worker.getPeerRpcPort());
+          workerBuilder.setQueryMasterPort(worker.getQueryMasterPort());
+          workerBuilder.setClientPort(worker.getClientPort());
+          workerBuilder.setPullServerPort(worker.getPullServerPort());
+          workerBuilder.setHttpPort(worker.getHttpPort());
+          workerBuilder.setMaxHeap(workerResource.getMaxHeap());
+          workerBuilder.setFreeHeap(workerResource.getFreeHeap());
+          workerBuilder.setTotalHeap(workerResource.getTotalHeap());
+          workerBuilder.setNumRunningTasks(workerResource.getNumRunningTasks());
+          workerBuilder.setNumQueryMasterTasks(workerResource.getNumQueryMasterTasks());
+
+          builder.addWorkerList(workerBuilder.build());
+        }
+
+        return builder.build();
+      } catch (Throwable t) {
+        throw new ServiceException(t);
       }
+    }
 
-      return builder.build();
+    @Override
+    public BoolProto createDatabase(RpcController controller, SessionedStringProto request) throws ServiceException {
+      try {
+        Session session = context.getSessionManager().getSession(request.getSessionId().getId());
+        if (context.getGlobalEngine().createDatabase(session, request.getValue(), null, false)) {
+          return BOOL_TRUE;
+        } else {
+          return BOOL_FALSE;
+        }
+      } catch (Throwable e) {
+        throw new ServiceException(e);
+      }
     }
 
     @Override
-    public BoolProto existTable(RpcController controller,
-                                StringProto tableNameProto)
-        throws ServiceException {
-      String tableName = tableNameProto.getValue();
-      if (catalog.existsTable(tableName)) {
-        return BOOL_TRUE;
-      } else {
-        return BOOL_FALSE;
+    public BoolProto existDatabase(RpcController controller, SessionedStringProto request) throws ServiceException {
+      try {
+        context.getSessionManager().touch(request.getSessionId().getId());
+        if (catalog.existDatabase(request.getValue())) {
+          return BOOL_TRUE;
+        } else {
+          return BOOL_FALSE;
+        }
+      } catch (Throwable e) {
+        throw new ServiceException(e);
+      }
+    }
+
+    @Override
+    public BoolProto dropDatabase(RpcController controller, SessionedStringProto request) throws ServiceException {
+      try {
+        Session session = context.getSessionManager().getSession(request.getSessionId().getId());
+
+        if (context.getGlobalEngine().dropDatabase(session, request.getValue(), false)) {
+          return BOOL_TRUE;
+        } else {
+          return BOOL_FALSE;
+        }
+      } catch (Throwable e) {
+        throw new ServiceException(e);
+      }
+    }
+
+    @Override
+    public PrimitiveProtos.StringListProto getAllDatabases(RpcController controller, TajoIdProtos.SessionIdProto
+        request) throws ServiceException {
+      try {
+        context.getSessionManager().touch(request.getId());
+        return ProtoUtil.convertStrings(catalog.getAllDatabaseNames());
+      } catch (Throwable e) {
+        throw new ServiceException(e);
+      }
+    }
+
+    @Override
+    public BoolProto existTable(RpcController controller, SessionedStringProto request) throws ServiceException {
+      try {
+        Session session = context.getSessionManager().getSession(request.getSessionId().getId());
+
+        String databaseName;
+        String tableName;
+        if (CatalogUtil.isFQTableName(request.getValue())) {
+          String [] splitted = CatalogUtil.splitFQTableName(request.getValue());
+          databaseName = splitted[0];
+          tableName = splitted[1];
+        } else {
+          databaseName = session.getCurrentDatabase();
+          tableName = request.getValue();
+        }
+
+        if (catalog.existsTable(databaseName, tableName)) {
+          return BOOL_TRUE;
+        } else {
+          return BOOL_FALSE;
+        }
+      } catch (Throwable e) {
+        throw new ServiceException(e);
       }
     }
 
     @Override
     public GetTableListResponse getTableList(RpcController controller,
-                                             GetTableListRequest request)
-        throws ServiceException {
-      Collection<String> tableNames = catalog.getAllTableNames();
-      GetTableListResponse.Builder builder = GetTableListResponse.newBuilder();
-      builder.addAllTables(tableNames);
-      return builder.build();
+                                             GetTableListRequest request) throws ServiceException {
+      try {
+        Session session = context.getSessionManager().getSession(request.getSessionId().getId());
+        String databaseName;
+        if (request.hasDatabaseName()) {
+          databaseName = request.getDatabaseName();
+        } else {
+          databaseName = session.getCurrentDatabase();
+        }
+        Collection<String> tableNames = catalog.getAllTableNames(databaseName);
+        GetTableListResponse.Builder builder = GetTableListResponse.newBuilder();
+        builder.addAllTables(tableNames);
+        return builder.build();
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
     }
 
     @Override
-    public TableResponse getTableDesc(RpcController controller,
-                                      GetTableDescRequest request)
-        throws ServiceException {
-      String name = request.getTableName();
-      if (catalog.existsTable(name)) {
-        return TableResponse.newBuilder()
-            .setResultCode(ResultCode.OK)
-            .setTableDesc(catalog.getTableDesc(name).getProto())
-            .build();
-      } else {
-        return TableResponse.newBuilder()
-            .setResultCode(ResultCode.ERROR)
-            .setErrorMessage("ERROR: no such a table: " + request.getTableName())
-            .build();
+    public TableResponse getTableDesc(RpcController controller, GetTableDescRequest request) throws ServiceException {
+      try {
+        Session session = context.getSessionManager().getSession(request.getSessionId().getId());
+
+        String databaseName;
+        String tableName;
+        if (CatalogUtil.isFQTableName(request.getTableName())) {
+          String [] splitted = CatalogUtil.splitFQTableName(request.getTableName());
+          databaseName = splitted[0];
+          tableName = splitted[1];
+        } else {
+          databaseName = session.getCurrentDatabase();
+          tableName = request.getTableName();
+        }
+
+        if (catalog.existsTable(databaseName, tableName)) {
+          return TableResponse.newBuilder()
+              .setResultCode(ResultCode.OK)
+              .setTableDesc(catalog.getTableDesc(databaseName, tableName).getProto())
+              .build();
+        } else {
+          return TableResponse.newBuilder()
+              .setResultCode(ResultCode.ERROR)
+              .setErrorMessage("ERROR: no such a table: " + request.getTableName())
+              .build();
+        }
+      } catch (Throwable t) {
+        throw new ServiceException(t);
       }
     }
 
@@ -431,6 +677,8 @@ public class TajoMasterClientService extends AbstractService {
     public TableResponse createExternalTable(RpcController controller, CreateTableRequest request)
         throws ServiceException {
       try {
+        Session session = context.getSessionManager().getSession(request.getSessionId().getId());
+
         Path path = new Path(request.getPath());
         FileSystem fs = path.getFileSystem(conf);
 
@@ -447,8 +695,8 @@ public class TajoMasterClientService extends AbstractService {
 
         TableDesc desc;
         try {
-          desc = context.getGlobalEngine().createTableOnPath(request.getName(), schema,
-              meta, path, false, partitionDesc);
+          desc = context.getGlobalEngine().createTableOnPath(session, request.getName(), schema,
+              meta, path, true, partitionDesc, false);
         } catch (Exception e) {
           return TableResponse.newBuilder()
               .setResultCode(ResultCode.ERROR)
@@ -458,6 +706,10 @@ public class TajoMasterClientService extends AbstractService {
         return TableResponse.newBuilder()
             .setResultCode(ResultCode.OK)
             .setTableDesc(desc.getProto()).build();
+      } catch (InvalidSessionException ise) {
+        return TableResponse.newBuilder()
+            .setResultCode(ResultCode.ERROR)
+            .setErrorMessage(ise.getMessage()).build();
       } catch (IOException ioe) {
         return TableResponse.newBuilder()
             .setResultCode(ResultCode.ERROR)
@@ -467,30 +719,43 @@ public class TajoMasterClientService extends AbstractService {
 
     @Override
     public BoolProto dropTable(RpcController controller, DropTableRequest dropTable) throws ServiceException {
-      context.getGlobalEngine().dropTable(dropTable.getName(), dropTable.getPurge());
-      return BOOL_TRUE;
+      try {
+        Session session = context.getSessionManager().getSession(dropTable.getSessionId().getId());
+        context.getGlobalEngine().dropTable(session, dropTable.getName(), false, dropTable.getPurge());
+        return BOOL_TRUE;
+      } catch (Throwable t) {
+        throw new ServiceException(t);
+      }
     }
 
     @Override
-    public FunctionResponse getFunctionList(RpcController controller, StringProto request) throws ServiceException {
-      String functionName = request.getValue();
-      Collection<FunctionDesc> functions = catalog.getFunctions();
+    public FunctionResponse getFunctionList(RpcController controller, SessionedStringProto request)
+        throws ServiceException {
 
-      List<CatalogProtos.FunctionDescProto> functionProtos = new ArrayList<CatalogProtos.FunctionDescProto>();
+      try {
+        context.getSessionManager().touch(request.getSessionId().getId());
 
-      for (FunctionDesc eachFunction: functions) {
-        if (functionName == null || functionName.isEmpty()) {
-          functionProtos.add(eachFunction.getProto());
-        } else {
-          if(functionName.equals(eachFunction.getSignature())) {
+        String functionName = request.getValue();
+        Collection<FunctionDesc> functions = catalog.getFunctions();
+
+        List<CatalogProtos.FunctionDescProto> functionProtos = new ArrayList<CatalogProtos.FunctionDescProto>();
+
+        for (FunctionDesc eachFunction: functions) {
+          if (functionName == null || functionName.isEmpty()) {
             functionProtos.add(eachFunction.getProto());
+          } else {
+            if(functionName.equals(eachFunction.getSignature())) {
+              functionProtos.add(eachFunction.getProto());
+            }
           }
         }
+        return FunctionResponse.newBuilder()
+            .setResultCode(ResultCode.OK)
+            .addAllFunctions(functionProtos)
+            .build();
+      } catch (Throwable t) {
+        throw new ServiceException(t);
       }
-      return FunctionResponse.newBuilder()
-          .setResultCode(ResultCode.OK)
-          .addAllFunctions(functionProtos)
-          .build();
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/YarnTaskRunnerLauncherImpl.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/YarnTaskRunnerLauncherImpl.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/YarnTaskRunnerLauncherImpl.java
index 28b5f08..8b18b5a 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/YarnTaskRunnerLauncherImpl.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/YarnTaskRunnerLauncherImpl.java
@@ -185,7 +185,7 @@ public class YarnTaskRunnerLauncherImpl extends AbstractService implements TaskR
 //
 //    @Override
 //    protected String getRunnerClass() {
-//      return TaskRunner.class.getCanonicalName();
+//      return TaskRunner.class.getCanonicalSignature();
 //    }
 //
 //    @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/event/QueryStartEvent.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/event/QueryStartEvent.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/event/QueryStartEvent.java
index 2c8b822..dd996e6 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/event/QueryStartEvent.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/event/QueryStartEvent.java
@@ -21,6 +21,7 @@ package org.apache.tajo.master.event;
 import org.apache.hadoop.yarn.event.AbstractEvent;
 import org.apache.tajo.QueryId;
 import org.apache.tajo.engine.query.QueryContext;
+import org.apache.tajo.master.session.Session;
 
 /**
  * This event is conveyed to QueryMaster.
@@ -30,14 +31,17 @@ public class QueryStartEvent extends AbstractEvent {
     QUERY_START
   }
 
-  private QueryId queryId;
-  private QueryContext queryContext;
-  private String sql;
-  private String logicalPlanJson;
+  private final QueryId queryId;
+  private final Session session;
+  private final QueryContext queryContext;
+  private final String sql;
+  private final String logicalPlanJson;
 
-  public QueryStartEvent(QueryId queryId, QueryContext queryContext, String sql, String logicalPlanJson) {
+  public QueryStartEvent(QueryId queryId, Session session, QueryContext queryContext, String sql,
+                         String logicalPlanJson) {
     super(EventType.QUERY_START);
     this.queryId = queryId;
+    this.session = session;
     this.queryContext = queryContext;
     this.sql = sql;
     this.logicalPlanJson = logicalPlanJson;
@@ -47,6 +51,10 @@ public class QueryStartEvent extends AbstractEvent {
     return queryId;
   }
 
+  public Session getSession() {
+    return this.session;
+  }
+
   public QueryContext getQueryContext() {
     return this.queryContext;
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/metrics/CatalogMetricsGaugeSet.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/metrics/CatalogMetricsGaugeSet.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/metrics/CatalogMetricsGaugeSet.java
index 08fff53..7c3d283 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/metrics/CatalogMetricsGaugeSet.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/metrics/CatalogMetricsGaugeSet.java
@@ -26,6 +26,8 @@ import org.apache.tajo.master.TajoMaster;
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+
 public class CatalogMetricsGaugeSet implements MetricSet {
   TajoMaster.MasterContext tajoMasterContext;
   public CatalogMetricsGaugeSet(TajoMaster.MasterContext tajoMasterContext) {
@@ -38,7 +40,7 @@ public class CatalogMetricsGaugeSet implements MetricSet {
     metricsMap.put("numTables", new Gauge<Integer>() {
       @Override
       public Integer getValue() {
-        return tajoMasterContext.getCatalog().getAllTableNames().size();
+        return tajoMasterContext.getCatalog().getAllTableNames(DEFAULT_DATABASE_NAME).size();
       }
     });
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/Query.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/Query.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/Query.java
index 02ed34e..8467b4b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/Query.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/Query.java
@@ -37,12 +37,12 @@ import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.catalog.TableMeta;
 import org.apache.tajo.catalog.statistics.TableStats;
 import org.apache.tajo.conf.TajoConf;
-import org.apache.tajo.engine.planner.logical.InsertNode;
 import org.apache.tajo.engine.planner.global.DataChannel;
 import org.apache.tajo.engine.planner.global.ExecutionBlock;
 import org.apache.tajo.engine.planner.global.ExecutionBlockCursor;
 import org.apache.tajo.engine.planner.global.MasterPlan;
 import org.apache.tajo.engine.planner.logical.CreateTableNode;
+import org.apache.tajo.engine.planner.logical.InsertNode;
 import org.apache.tajo.engine.planner.logical.NodeType;
 import org.apache.tajo.engine.query.QueryContext;
 import org.apache.tajo.master.event.*;
@@ -134,6 +134,20 @@ public class Query implements EventHandler<QueryEvent> {
               QueryEventType.INTERNAL_ERROR,
               INTERNAL_ERROR_TRANSITION)
 
+          // Transitions from QUERY_SUCCEEDED state
+          .addTransition(QueryState.QUERY_SUCCEEDED, QueryState.QUERY_SUCCEEDED,
+              QueryEventType.DIAGNOSTIC_UPDATE,
+              DIAGNOSTIC_UPDATE_TRANSITION)
+          // ignore-able transitions
+          .addTransition(QueryState.QUERY_SUCCEEDED, QueryState.QUERY_SUCCEEDED,
+              QueryEventType.SUBQUERY_COMPLETED,
+              SUBQUERY_COMPLETED_TRANSITION)
+          .addTransition(QueryState.QUERY_SUCCEEDED, QueryState.QUERY_SUCCEEDED,
+              QueryEventType.KILL)
+          .addTransition(QueryState.QUERY_SUCCEEDED, QueryState.QUERY_ERROR,
+              QueryEventType.INTERNAL_ERROR,
+              INTERNAL_ERROR_TRANSITION)
+
           // Transitions from KILL_WAIT state
           .addTransition(QueryState.QUERY_KILL_WAIT, QueryState.QUERY_KILL_WAIT,
               QueryEventType.SUBQUERY_COMPLETED,
@@ -433,8 +447,8 @@ public class Query implements EventHandler<QueryEvent> {
       }
 
       @Override
-      public void execute(QueryMaster.QueryMasterContext context, QueryContext queryContext, Query query,
-                          ExecutionBlockId finalExecBlockId,
+      public void execute(QueryMaster.QueryMasterContext context, QueryContext queryContext,
+                          Query query, ExecutionBlockId finalExecBlockId,
                           Path finalOutputDir) throws Exception {
         SubQuery lastStage = query.getSubQuery(finalExecBlockId);
         TableMeta meta = lastStage.getTableMeta();
@@ -446,6 +460,7 @@ public class Query implements EventHandler<QueryEvent> {
                 lastStage.getSchema(),
                 meta,
                 finalOutputDir);
+        resultTableDesc.setExternal(true);
 
         stats.setNumBytes(getTableVolume(query.systemConf, finalOutputDir));
         resultTableDesc.setStats(stats);
@@ -463,9 +478,8 @@ public class Query implements EventHandler<QueryEvent> {
       }
 
       @Override
-      public void execute(QueryMaster.QueryMasterContext context, QueryContext queryContext, Query query,
-                          ExecutionBlockId finalExecBlockId,
-                          Path finalOutputDir) throws Exception {
+      public void execute(QueryMaster.QueryMasterContext context, QueryContext queryContext,
+                          Query query, ExecutionBlockId finalExecBlockId, Path finalOutputDir) throws Exception {
         CatalogService catalog = context.getWorkerContext().getCatalog();
         SubQuery lastStage = query.getSubQuery(finalExecBlockId);
         TableMeta meta = lastStage.getTableMeta();
@@ -479,6 +493,7 @@ public class Query implements EventHandler<QueryEvent> {
                 createTableNode.getTableSchema(),
                 meta,
                 finalOutputDir);
+        tableDescTobeCreated.setExternal(createTableNode.isExternal());
 
         if (createTableNode.hasPartition()) {
           tableDescTobeCreated.setPartitionMethod(createTableNode.getPartitionMethod());
@@ -488,7 +503,7 @@ public class Query implements EventHandler<QueryEvent> {
         tableDescTobeCreated.setStats(stats);
         query.setResultDesc(tableDescTobeCreated);
 
-        catalog.addTable(tableDescTobeCreated);
+        catalog.createTable(tableDescTobeCreated);
       }
     }
 
@@ -502,9 +517,8 @@ public class Query implements EventHandler<QueryEvent> {
       }
 
       @Override
-      public void execute(QueryMaster.QueryMasterContext context, QueryContext queryContext, Query query,
-                          ExecutionBlockId finalExecBlockId,
-                          Path finalOutputDir)
+      public void execute(QueryMaster.QueryMasterContext context, QueryContext queryContext,
+                          Query query, ExecutionBlockId finalExecBlockId, Path finalOutputDir)
           throws Exception {
 
         CatalogService catalog = context.getWorkerContext().getCatalog();
@@ -528,8 +542,8 @@ public class Query implements EventHandler<QueryEvent> {
         finalTable.setStats(stats);
 
         if (insertNode.hasTargetTable()) {
-          catalog.deleteTable(insertNode.getTableName());
-          catalog.addTable(finalTable);
+          catalog.dropTable(insertNode.getTableName());
+          catalog.createTable(finalTable);
         }
 
         query.setResultDesc(finalTable);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryInProgress.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryInProgress.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryInProgress.java
index efb9c06..b8f312e 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryInProgress.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryInProgress.java
@@ -37,6 +37,7 @@ import org.apache.tajo.ipc.TajoWorkerProtocol;
 import org.apache.tajo.master.TajoAsyncDispatcher;
 import org.apache.tajo.master.TajoMaster;
 import org.apache.tajo.master.rm.WorkerResourceManager;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.rpc.NettyClientBase;
 import org.apache.tajo.rpc.NullCallback;
 import org.apache.tajo.rpc.RpcConnectionPool;
@@ -52,6 +53,8 @@ public class QueryInProgress extends CompositeService {
 
   private QueryId queryId;
 
+  private Session session;
+
   private QueryContext queryContext;
 
   private TajoAsyncDispatcher dispatcher;
@@ -74,10 +77,12 @@ public class QueryInProgress extends CompositeService {
 
   public QueryInProgress(
       TajoMaster.MasterContext masterContext,
+      Session session,
       QueryContext queryContext,
       QueryId queryId, String sql, LogicalRootNode plan) {
     super(QueryInProgress.class.getName());
     this.masterContext = masterContext;
+    this.session = session;
     this.queryContext = queryContext;
     this.queryId = queryId;
     this.plan = plan;
@@ -229,6 +234,7 @@ public class QueryInProgress extends CompositeService {
           null,
           TajoWorkerProtocol.QueryExecutionRequestProto.newBuilder()
               .setQueryId(queryId.getProto())
+              .setSession(session.getProto())
               .setQueryContext(queryContext.getProto())
               .setSql(PrimitiveProtos.StringProto.newBuilder().setValue(queryInfo.getSql()))
               .setLogicalPlanJson(PrimitiveProtos.StringProto.newBuilder().setValue(plan.toJson()).build())

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryJobManager.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryJobManager.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryJobManager.java
index 6cfb600..aa03501 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryJobManager.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryJobManager.java
@@ -30,6 +30,7 @@ import org.apache.tajo.engine.planner.logical.LogicalRootNode;
 import org.apache.tajo.engine.query.QueryContext;
 import org.apache.tajo.ipc.TajoMasterProtocol;
 import org.apache.tajo.master.TajoMaster;
+import org.apache.tajo.master.session.Session;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -94,9 +95,10 @@ public class QueryJobManager extends CompositeService {
     return Collections.unmodifiableCollection(finishedQueries.values());
   }
 
-  public QueryInfo createNewQueryJob(QueryContext queryContext, String sql, LogicalRootNode plan) throws Exception {
+  public QueryInfo createNewQueryJob(Session session, QueryContext queryContext, String sql, LogicalRootNode plan)
+      throws Exception {
     QueryId queryId = QueryIdFactory.newQueryId(masterContext.getResourceManager().getSeedQueryId());
-    QueryInProgress queryInProgress = new QueryInProgress(masterContext, queryContext, queryId, sql, plan);
+    QueryInProgress queryInProgress = new QueryInProgress(masterContext, session, queryContext, queryId, sql, plan);
 
     synchronized(runningQueries) {
       runningQueries.put(queryId, queryInProgress);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMaster.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMaster.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMaster.java
index 9dddbf7..abdc214 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMaster.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMaster.java
@@ -371,7 +371,7 @@ public class QueryMaster extends CompositeService implements EventHandler {
     public void handle(QueryStartEvent event) {
       LOG.info("Start QueryStartEventHandler:" + event.getQueryId());
       QueryMasterTask queryMasterTask = new QueryMasterTask(queryMasterContext,
-          event.getQueryId(), event.getQueryContext(), event.getSql(), event.getLogicalPlanJson());
+          event.getQueryId(), event.getSession(), event.getQueryContext(), event.getSql(), event.getLogicalPlanJson());
 
       queryMasterTask.init(systemConf);
       queryMasterTask.start();

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterManagerService.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterManagerService.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterManagerService.java
index e3e0260..bf59e9f 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterManagerService.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterManagerService.java
@@ -33,6 +33,7 @@ import org.apache.tajo.ipc.QueryMasterProtocol;
 import org.apache.tajo.ipc.TajoWorkerProtocol;
 import org.apache.tajo.master.LazyTaskScheduler;
 import org.apache.tajo.master.event.*;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.rpc.AsyncRpcServer;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos;
 import org.apache.tajo.util.NetUtils;
@@ -225,6 +226,7 @@ public class QueryMasterManagerService extends CompositeService
       QueryId queryId = new QueryId(request.getQueryId());
       LOG.info("Receive executeQuery request:" + queryId);
       queryMaster.handle(new QueryStartEvent(queryId,
+          new Session(request.getSession()),
           new QueryContext(request.getQueryContext()), request.getSql().getValue(),
           request.getLogicalPlanJson().getValue()));
       done.run(TajoWorker.TRUE_PROTO);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterTask.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterTask.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterTask.java
index 7719a85..39e2177 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterTask.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/querymaster/QueryMasterTask.java
@@ -48,6 +48,7 @@ import org.apache.tajo.master.TajoAsyncDispatcher;
 import org.apache.tajo.master.TajoContainerProxy;
 import org.apache.tajo.master.event.*;
 import org.apache.tajo.master.rm.TajoWorkerResourceManager;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.rpc.CallFuture;
 import org.apache.tajo.rpc.NettyClientBase;
 import org.apache.tajo.rpc.RpcConnectionPool;
@@ -76,6 +77,8 @@ public class QueryMasterTask extends CompositeService {
 
   private QueryId queryId;
 
+  private Session session;
+
   private QueryContext queryContext;
 
   private QueryMasterTaskContext queryTaskContext;
@@ -107,10 +110,13 @@ public class QueryMasterTask extends CompositeService {
   private TajoMetrics queryMetrics;
 
   public QueryMasterTask(QueryMaster.QueryMasterContext queryMasterContext,
-                         QueryId queryId, QueryContext queryContext, String sql, String logicalPlanJson) {
+                         QueryId queryId, Session session, QueryContext queryContext, String sql,
+                         String logicalPlanJson) {
+
     super(QueryMasterTask.class.getName());
     this.queryMasterContext = queryMasterContext;
     this.queryId = queryId;
+    this.session = session;
     this.queryContext = queryContext;
     this.sql = sql;
     this.logicalPlanJson = logicalPlanJson;
@@ -306,7 +312,7 @@ public class QueryMasterTask extends CompositeService {
     }
     LogicalPlan plan = null;
     try {
-      plan = planner.createPlan(expr);
+      plan = planner.createPlan(session, expr);
       optimizer.optimize(plan);
     } catch (PlanningException e) {
       e.printStackTrace();
@@ -400,7 +406,7 @@ public class QueryMasterTask extends CompositeService {
 
       // Create a subdirectories
       defaultFS.mkdirs(new Path(stagingDir, TajoConstants.RESULT_DIR_NAME));
-      LOG.info("The staging dir '" + outputDir + "' is created.");
+      LOG.info("The staging dir '" + stagingDir + "' is created.");
       queryContext.setStagingDir(stagingDir);
 
       /////////////////////////////////////////////////
@@ -481,6 +487,10 @@ public class QueryMasterTask extends CompositeService {
       return queryMasterContext;
     }
 
+    public Session getSession() {
+      return session;
+    }
+
     public QueryContext getQueryContext() {
       return queryContext;
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/rm/TajoResourceTracker.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/rm/TajoResourceTracker.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/rm/TajoResourceTracker.java
index 1bcf38b..4bd7adb 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/rm/TajoResourceTracker.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/rm/TajoResourceTracker.java
@@ -30,7 +30,7 @@ import org.apache.tajo.ipc.TajoMasterProtocol;
 import org.apache.tajo.ipc.TajoResourceTrackerProtocol;
 import org.apache.tajo.rpc.AsyncRpcServer;
 import org.apache.tajo.util.NetUtils;
-import org.apache.tajo.util.ProtoBufUtil;
+import org.apache.tajo.util.ProtoUtil;
 
 import java.io.IOError;
 import java.net.InetSocketAddress;
@@ -109,7 +109,7 @@ public class TajoResourceTracker extends AbstractService implements TajoResource
   }
 
   /** The response builder */
-  private static final Builder builder = TajoHeartbeatResponse.newBuilder().setHeartbeatResult(ProtoBufUtil.TRUE);
+  private static final Builder builder = TajoHeartbeatResponse.newBuilder().setHeartbeatResult(ProtoUtil.TRUE);
 
   private static WorkerStatusEvent createStatusEvent(String workerKey, NodeHeartbeat heartbeat) {
     return new WorkerStatusEvent(

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/InvalidSessionException.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/InvalidSessionException.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/InvalidSessionException.java
new file mode 100644
index 0000000..3f48ca5
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/InvalidSessionException.java
@@ -0,0 +1,25 @@
+/**
+ * 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.master.session;
+
+public class InvalidSessionException extends Exception {
+  public InvalidSessionException(String sessionId) {
+    super("Invalid session id \"" + sessionId + "\"");
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/NoSuchSessionVariableException.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/NoSuchSessionVariableException.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/NoSuchSessionVariableException.java
new file mode 100644
index 0000000..686d860
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/NoSuchSessionVariableException.java
@@ -0,0 +1,25 @@
+/**
+ * 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.master.session;
+
+public class NoSuchSessionVariableException extends Exception {
+  public NoSuchSessionVariableException(String varname) {
+    super("No such session variable \"" + varname + "\"");
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/Session.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/Session.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/Session.java
new file mode 100644
index 0000000..4d244bf
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/Session.java
@@ -0,0 +1,124 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.master.session;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.tajo.catalog.Options;
+import org.apache.tajo.common.ProtoObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.tajo.ipc.TajoWorkerProtocol.SessionProto;
+
+public class Session implements SessionConstants, ProtoObject<SessionProto> {
+  private final String sessionId;
+  private final String userName;
+  private final Map<String, String> sessionVariables;
+
+  // transient status
+  private volatile long lastAccessTime;
+  private volatile String currentDatabase;
+
+  public Session(String sessionId, String userName, String databaseName) {
+    this.sessionId = sessionId;
+    this.userName = userName;
+    this.lastAccessTime = System.currentTimeMillis();
+    this.sessionVariables = new HashMap<String, String>();
+    selectDatabase(databaseName);
+  }
+
+  public Session(SessionProto proto) {
+    sessionId = proto.getSessionId();
+    userName = proto.getUsername();
+    currentDatabase = proto.getCurrentDatabase();
+    lastAccessTime = proto.getLastAccessTime();
+    Options options = new Options(proto.getVariables());
+    sessionVariables = options.getAllKeyValus();
+  }
+
+  public String getSessionId() {
+    return sessionId;
+  }
+
+  public String getUserName() {
+    return userName;
+  }
+
+  public void updateLastAccessTime() {
+    lastAccessTime = System.currentTimeMillis();
+  }
+
+  public long getLastAccessTime() {
+    return lastAccessTime;
+  }
+
+  public void setVariable(String name, String value) {
+    synchronized (sessionVariables) {
+      sessionVariables.put(name, value);
+    }
+  }
+
+  public String getVariable(String name) throws NoSuchSessionVariableException {
+    synchronized (sessionVariables) {
+      if (sessionVariables.containsKey(name)) {
+        return sessionVariables.get(name);
+      } else {
+        throw new NoSuchSessionVariableException(name);
+      }
+    }
+  }
+
+  public void removeVariable(String name) {
+    synchronized (sessionVariables) {
+      sessionVariables.remove(name);
+    }
+  }
+
+  public synchronized Map<String, String> getAllVariables() {
+    synchronized (sessionVariables) {
+      return ImmutableMap.copyOf(sessionVariables);
+    }
+  }
+
+  public void selectDatabase(String databaseName) {
+    this.currentDatabase = databaseName;
+  }
+
+  public String getCurrentDatabase() {
+    return this.currentDatabase;
+  }
+
+  @Override
+  public SessionProto getProto() {
+    SessionProto.Builder builder = SessionProto.newBuilder();
+    builder.setSessionId(sessionId);
+    builder.setUsername(userName);
+    builder.setCurrentDatabase(currentDatabase);
+    builder.setLastAccessTime(lastAccessTime);
+    Options variables = new Options();
+    variables.putAll(this.sessionVariables);
+    builder.setVariables(variables.getProto());
+    return builder.build();
+  }
+
+  public String toString() {
+    return "user=" + userName + ",id=" + sessionId;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionConstants.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionConstants.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionConstants.java
new file mode 100644
index 0000000..46f49a2
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionConstants.java
@@ -0,0 +1,23 @@
+/**
+ * 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.master.session;
+
+public interface SessionConstants {
+
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionEvent.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionEvent.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionEvent.java
new file mode 100644
index 0000000..dce3ba6
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionEvent.java
@@ -0,0 +1,34 @@
+/**
+ * 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.master.session;
+
+import org.apache.hadoop.yarn.event.AbstractEvent;
+
+public class SessionEvent extends AbstractEvent<SessionEventType> {
+  private final String sessionId;
+
+  public SessionEvent(String sessionId, SessionEventType sessionEventType) {
+    super(sessionEventType);
+    this.sessionId = sessionId;
+  }
+
+  public String getSessionId() {
+    return sessionId;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionEventType.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionEventType.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionEventType.java
new file mode 100644
index 0000000..64c6fc6
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionEventType.java
@@ -0,0 +1,24 @@
+/**
+ * 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.master.session;
+
+public enum SessionEventType {
+  EXPIRE,
+  PING
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionLivelinessMonitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionLivelinessMonitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionLivelinessMonitor.java
new file mode 100644
index 0000000..483920f
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionLivelinessMonitor.java
@@ -0,0 +1,53 @@
+/**
+ * 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.master.session;
+
+import com.google.common.base.Preconditions;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.yarn.event.Dispatcher;
+import org.apache.hadoop.yarn.event.EventHandler;
+import org.apache.hadoop.yarn.util.AbstractLivelinessMonitor;
+import org.apache.hadoop.yarn.util.SystemClock;
+import org.apache.tajo.conf.TajoConf;
+
+public class SessionLivelinessMonitor extends AbstractLivelinessMonitor<String> {
+
+  private EventHandler dispatcher;
+
+  public SessionLivelinessMonitor(Dispatcher d) {
+    super(SessionLivelinessMonitor.class.getSimpleName(), new SystemClock());
+    this.dispatcher = d.getEventHandler();
+  }
+
+  public void serviceInit(Configuration conf) throws Exception {
+    Preconditions.checkArgument(conf instanceof TajoConf);
+    TajoConf systemConf = (TajoConf) conf;
+
+    // seconds
+    int expireIntvl = systemConf.getIntVar(TajoConf.ConfVars.CLIENT_SESSION_EXPIRY_TIME);
+    setExpireInterval(expireIntvl);
+    setMonitorInterval(expireIntvl / 3);
+    super.serviceInit(conf);
+  }
+
+  @Override
+  protected void expire(String id) {
+    dispatcher.handle(new SessionEvent(id, SessionEventType.EXPIRE));
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionManager.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionManager.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionManager.java
new file mode 100644
index 0000000..24df9d8
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/session/SessionManager.java
@@ -0,0 +1,139 @@
+/**
+ * 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.master.session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.service.CompositeService;
+import org.apache.hadoop.yarn.event.Dispatcher;
+import org.apache.hadoop.yarn.event.EventHandler;
+
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class SessionManager extends CompositeService implements EventHandler<SessionEvent> {
+  private static final Log LOG = LogFactory.getLog(SessionManager.class);
+
+  public final ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<String, Session>();
+  private final Dispatcher dispatcher;
+  private SessionLivelinessMonitor sessionLivelinessMonitor;
+
+
+  public SessionManager(Dispatcher dispatcher) {
+    super(SessionManager.class.getSimpleName());
+    this.dispatcher = dispatcher;
+  }
+
+  @Override
+  public void serviceInit(Configuration conf) throws Exception {
+    sessionLivelinessMonitor = new SessionLivelinessMonitor(dispatcher);
+    addIfService(sessionLivelinessMonitor);
+    super.serviceInit(conf);
+  }
+
+  @Override
+  public void serviceStop() throws Exception {
+    super.serviceStop();
+  }
+
+  private void assertSessionExistence(String sessionId) throws InvalidSessionException {
+    if (!sessions.containsKey(sessionId)) {
+      throw new InvalidSessionException(sessionId);
+    }
+  }
+
+  public String createSession(String username, String baseDatabaseName) throws InvalidSessionException {
+    String sessionId;
+    Session oldSession;
+
+    sessionId = UUID.randomUUID().toString();
+    Session newSession = new Session(sessionId, username, baseDatabaseName);
+    oldSession = sessions.putIfAbsent(sessionId, newSession);
+    if (oldSession != null) {
+      throw new InvalidSessionException("Session id is duplicated: " + oldSession.getSessionId());
+    }
+    LOG.info("Session " + sessionId + " is created." );
+    return sessionId;
+  }
+
+  public void removeSession(String sessionId) {
+    if (sessions.containsKey(sessionId)) {
+      sessions.remove(sessionId);
+      LOG.info("Session " + sessionId + " is removed.");
+    } else {
+      LOG.error("No such session id: " + sessionId);
+    }
+  }
+
+  public Session getSession(String sessionId) throws InvalidSessionException {
+    assertSessionExistence(sessionId);
+    touch(sessionId);
+    return sessions.get(sessionId);
+  }
+
+  public void setVariable(String sessionId, String name, String value) throws InvalidSessionException {
+    assertSessionExistence(sessionId);
+    touch(sessionId);
+    sessions.get(sessionId).setVariable(name, value);
+  }
+
+  public String getVariable(String sessionId, String name)
+      throws InvalidSessionException, NoSuchSessionVariableException {
+    assertSessionExistence(sessionId);
+    touch(sessionId);
+    return sessions.get(sessionId).getVariable(name);
+  }
+
+  public void removeVariable(String sessionId, String name) throws InvalidSessionException {
+    assertSessionExistence(sessionId);
+    touch(sessionId);
+    sessions.get(sessionId).removeVariable(name);
+  }
+
+  public Map<String, String> getAllVariables(String sessionId) throws InvalidSessionException {
+    assertSessionExistence(sessionId);
+    touch(sessionId);
+    return sessions.get(sessionId).getAllVariables();
+  }
+
+  public void touch(String sessionId) throws InvalidSessionException {
+    assertSessionExistence(sessionId);
+    sessions.get(sessionId).updateLastAccessTime();
+    sessionLivelinessMonitor.receivedPing(sessionId);
+  }
+
+  @Override
+  public void handle(SessionEvent event) {
+    LOG.info("Processing " + event.getSessionId() + " of type " + event.getType());
+
+    try {
+      assertSessionExistence(event.getSessionId());
+      touch(event.getSessionId());
+    } catch (InvalidSessionException e) {
+      LOG.error(e);
+    }
+
+    if (event.getType() == SessionEventType.EXPIRE) {
+      Session session = sessions.remove(event.getSessionId());
+      LOG.info("[Expired] Session username=" + session.getUserName() + ",sessionid=" + event.getSessionId());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/proto/TajoWorkerProtocol.proto
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/proto/TajoWorkerProtocol.proto b/tajo-core/tajo-core-backend/src/main/proto/TajoWorkerProtocol.proto
index 10e8ec2..7c94e33 100644
--- a/tajo-core/tajo-core-backend/src/main/proto/TajoWorkerProtocol.proto
+++ b/tajo-core/tajo-core-backend/src/main/proto/TajoWorkerProtocol.proto
@@ -28,6 +28,14 @@ import "TajoIdProtos.proto";
 import "CatalogProtos.proto";
 import "PrimitiveProtos.proto";
 
+message SessionProto {
+  required string session_id = 1;
+  required string username = 2;
+  required string current_database = 3;
+  required int64 last_access_time = 4;
+  required KeyValueSetProto variables = 5;
+}
+
 message TaskStatusProto {
   required QueryUnitAttemptIdProto id = 1;
   required string workerName = 2;
@@ -109,9 +117,10 @@ message ShuffleFileOutput {
 
 message QueryExecutionRequestProto {
     required QueryIdProto queryId = 1;
-    required KeyValueSetProto queryContext = 2;
-    required StringProto sql = 3;
-    optional StringProto logicalPlanJson = 4;
+    required SessionProto session = 2;
+    required KeyValueSetProto queryContext = 3;
+    required StringProto sql = 4;
+    optional StringProto logicalPlanJson = 5;
 }
 
 message GetTaskRequestProto {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/resources/webapps/admin/catalogview.jsp
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/resources/webapps/admin/catalogview.jsp b/tajo-core/tajo-core-backend/src/main/resources/webapps/admin/catalogview.jsp
index 397146a..29fd05c 100644
--- a/tajo-core/tajo-core-backend/src/main/resources/webapps/admin/catalogview.jsp
+++ b/tajo-core/tajo-core-backend/src/main/resources/webapps/admin/catalogview.jsp
@@ -49,13 +49,13 @@
   TableDesc tableDesc = null;
   String selectedTable = request.getParameter("table");
   if(selectedTable != null && !selectedTable.trim().isEmpty()) {
-    tableDesc = catalog.getTableDesc(selectedTable);
+    tableDesc = catalog.getTableDesc(selectedDatabase, selectedTable);
   } else {
     selectedTable = "";
   }
 
   //TODO filter with database
-  Collection<String> tableNames = catalog.getAllTableNames();
+  Collection<String> tableNames = catalog.getAllTableNames(selectedDatabase);
 %>
 
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
@@ -83,8 +83,16 @@
       <td width="20%" valign="top">
         <div>
           <b>Database:</b>
-          <select width="190" style="width: 190px">
-            <option value="default" selected>default</option>
+          <select width="190" style="width: 190px" onchange="document.location.href='catalogview.jsp?database=' + this.value">
+            <%
+              for (String databaseName : catalog.getAllDatabaseNames()) {
+                if (selectedDatabase.equals(databaseName)) { %>
+                  <option value="<%=databaseName%>" selected><%=databaseName%>
+                <%} else {%>
+                <option value="<%=databaseName%>"><%=databaseName%></option>
+                <%}
+              }
+            %>
           </select>
         </div>
         <!-- table list -->

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java
index 144ca1b..e651313 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/LocalTajoTestingUtility.java
@@ -23,6 +23,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.tajo.benchmark.TPCH;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.proto.CatalogProtos;
@@ -30,10 +31,12 @@ import org.apache.tajo.catalog.statistics.TableStats;
 import org.apache.tajo.client.TajoClient;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.engine.planner.global.MasterPlan;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.util.TajoIdUtils;
 
 import java.io.IOException;
 import java.sql.ResultSet;
+import java.util.UUID;
 
 public class LocalTajoTestingUtility {
   private static final Log LOG = LogFactory.getLog(LocalTajoTestingUtility.class);
@@ -42,6 +45,16 @@ public class LocalTajoTestingUtility {
   private TajoConf conf;
   private TajoClient client;
 
+  private static UserGroupInformation dummyUserInfo;
+
+  static {
+    try {
+      dummyUserInfo = UserGroupInformation.getCurrentUser();
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
+
   private static int taskAttemptId;
 
   public static QueryUnitAttemptId newQueryUnitAttemptId() {
@@ -51,6 +64,9 @@ public class LocalTajoTestingUtility {
   public static QueryUnitAttemptId newQueryUnitAttemptId(MasterPlan plan) {
     return QueryIdFactory.newQueryUnitAttemptId(QueryIdFactory.newQueryUnitId(plan.newExecutionBlockId()), 0);
   }
+  public static Session createDummySession() {
+    return new Session(UUID.randomUUID().toString(), dummyUserInfo.getUserName(), TajoConstants.DEFAULT_DATABASE_NAME);
+  }
 
   /**
    * for test
@@ -88,9 +104,11 @@ public class LocalTajoTestingUtility {
       // It gives more various situations to unit tests.
       TableStats stats = new TableStats();
       stats.setNumBytes(TPCH.tableVolumes.get(names[i]));
-      TableDesc tableDesc = new TableDesc(names[i], schemas[i], meta, tablePath);
+      TableDesc tableDesc = new TableDesc(
+          CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, names[i]), schemas[i], meta,
+          tablePath);
       tableDesc.setStats(stats);
-      util.getMaster().getCatalog().addTable(tableDesc);
+      util.getMaster().getCatalog().createTable(tableDesc);
     }
 
     LOG.info("===================================================");


[12/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchIndexException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchIndexException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchIndexException.java
index e22e8bc..0bb7e32 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchIndexException.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchIndexException.java
@@ -21,31 +21,14 @@ package org.apache.tajo.catalog.exception;
 public class NoSuchIndexException extends CatalogException {
   private static final long serialVersionUID = 3705839985189534673L;
 
-  /**
-   * 
-   */
   public NoSuchIndexException() {
   }
 
-  /**
-   * @param message
-   */
-  public NoSuchIndexException(String message) {
-    super(message);
+  public NoSuchIndexException(String databaseName, String columnName) {
+    super(String.format("ERROR: index \" %s \" in %s does not exist", columnName, databaseName));
   }
 
-  /**
-   * @param cause
-   */
-  public NoSuchIndexException(Throwable cause) {
-    super(cause);
-  }
-
-  /**
-   * @param message
-   * @param cause
-   */
-  public NoSuchIndexException(String message, Throwable cause) {
-    super(message, cause);
+  public NoSuchIndexException(String indexName) {
+    super("ERROR: index \"" + indexName + "\" does not exist");
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchTableException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchTableException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchTableException.java
index 80b3b9f..cc11444 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchTableException.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchTableException.java
@@ -24,6 +24,10 @@ public class NoSuchTableException extends CatalogException {
 
 	public NoSuchTableException() {}
 
+  public NoSuchTableException(String databaseName, String relName) {
+    super(String.format("ERROR: relation \" %s \" in %s does not exist", relName, databaseName));
+  }
+
 	public NoSuchTableException(String relName) {
 		super("ERROR: relation \"" + relName + "\" does not exist");
 	}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchTablespaceException.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchTablespaceException.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchTablespaceException.java
new file mode 100644
index 0000000..8b7d80b
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/exception/NoSuchTablespaceException.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.catalog.exception;
+
+public class NoSuchTablespaceException extends CatalogException {
+	private static final long serialVersionUID = 277182608283894937L;
+
+	public NoSuchTablespaceException() {}
+
+	public NoSuchTablespaceException(String spaceName) {
+		super("ERROR: tablespace \"" + spaceName + "\" does not exist");
+	}
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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
index e89ee72..d775ba8 100644
--- 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
@@ -29,8 +29,6 @@ import org.apache.tajo.json.GsonObject;
  * <code>PartitionDesc</code> presents a table partition.
  */
 public class PartitionDesc implements ProtoObject<CatalogProtos.PartitionDescProto>, Cloneable, GsonObject {
-
-  @Expose protected String tableId;                            // required
   @Expose protected String partitionName;                      // optional
   @Expose protected int ordinalPosition;                       // required
   @Expose protected String partitionValue;                     // optional
@@ -42,7 +40,6 @@ public class PartitionDesc implements ProtoObject<CatalogProtos.PartitionDescPro
   }
 
   public PartitionDesc(PartitionDesc partition) {
-    this.tableId = partition.tableId;
     this.partitionName = partition.partitionName;
     this.ordinalPosition = partition.ordinalPosition;
     this.partitionValue = partition.partitionValue;
@@ -50,7 +47,6 @@ public class PartitionDesc implements ProtoObject<CatalogProtos.PartitionDescPro
   }
 
   public PartitionDesc(CatalogProtos.PartitionDescProto proto) {
-    this.tableId = proto.getTableId();
     if(proto.hasPartitionName()) {
       this.partitionName = proto.getPartitionName();
     }
@@ -63,57 +59,43 @@ public class PartitionDesc implements ProtoObject<CatalogProtos.PartitionDescPro
     }
   }
 
+  public void setName(String partitionName) {
+    this.partitionName = partitionName;
+  }
   public String getName() {
     return partitionName;
   }
 
-  public String getTableId() {
-    return tableId;
-  }
 
+  public void setOrdinalPosition(int ordinalPosition) {
+    this.ordinalPosition = ordinalPosition;
+  }
   public int getOrdinalPosition() {
     return ordinalPosition;
   }
 
-  public String getPartitionValue() {
-    return partitionValue;
-  }
-
   public void setPartitionValue(String partitionValue) {
     this.partitionValue = partitionValue;
   }
-
-  public String getPath() {
-    return path;
-  }
-
-
-  public void setTable(String tableId) {
-    this.tableId = tableId;
-  }
-
-  public void setName(String partitionName) {
-    this.partitionName = partitionName;
-  }
-
-
-  public void setOrdinalPosition(int ordinalPosition) {
-    this.ordinalPosition = ordinalPosition;
+  public String getPartitionValue() {
+    return partitionValue;
   }
 
   public void setPath(String path) {
     this.path = path;
   }
+  public String getPath() {
+    return path;
+  }
 
   public int hashCode() {
-    return Objects.hashCode(tableId, partitionName, ordinalPosition, partitionValue, path);
+    return Objects.hashCode(partitionName, ordinalPosition, partitionValue, path);
   }
 
   public boolean equals(Object o) {
     if (o instanceof PartitionDesc) {
       PartitionDesc another = (PartitionDesc) o;
-      boolean eq = tableId.equals(another.tableId);
-      eq = eq && ((partitionName != null && another.partitionName != null
+      boolean eq = ((partitionName != null && another.partitionName != null
           && partitionName.equals(another.partitionName)) ||
           (partitionName == null && another.partitionName == null));
       eq = eq && (ordinalPosition == another.ordinalPosition);
@@ -134,7 +116,6 @@ public class PartitionDesc implements ProtoObject<CatalogProtos.PartitionDescPro
       builder = CatalogProtos.PartitionDescProto.newBuilder();
     }
 
-    builder.setTableId(tableId);
     if(this.partitionName != null) {
       builder.setPartitionName(partitionName);
     }
@@ -169,7 +150,6 @@ public class PartitionDesc implements ProtoObject<CatalogProtos.PartitionDescPro
   public Object clone() throws CloneNotSupportedException {
     PartitionDesc desc = (PartitionDesc) super.clone();
     desc.builder = CatalogProtos.PartitionDescProto.newBuilder();
-    desc.tableId = tableId;
     desc.partitionName = partitionName;
     desc.ordinalPosition = ordinalPosition;
     desc.partitionValue = partitionValue;

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/PartitionMethodDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/PartitionMethodDesc.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/PartitionMethodDesc.java
index 4a8123a..48a105c 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/PartitionMethodDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/partition/PartitionMethodDesc.java
@@ -29,35 +29,44 @@ import org.apache.tajo.common.ProtoObject;
 import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.util.TUtil;
 
+import static org.apache.tajo.catalog.proto.CatalogProtos.PartitionType;
+import static org.apache.tajo.catalog.proto.CatalogProtos.TableIdentifierProto;
+
 /**
  * <code>PartitionMethodDesc</code> presents a table description, including partition type, and partition keys.
  */
 public class PartitionMethodDesc implements ProtoObject<CatalogProtos.PartitionMethodProto>, Cloneable, GsonObject {
   private CatalogProtos.PartitionMethodProto.Builder builder;
 
-  @Expose private String tableId;                                       // required
-  @Expose private CatalogProtos.PartitionType partitionType;            // required
-  @Expose private String expression;                                    // required
-  @Expose private Schema expressionSchema;                              // required
+  @Expose private String databaseName;                         // required
+  @Expose private String tableName;                            // required
+  @Expose private PartitionType partitionType;                 // required
+  @Expose private String expression;                           // required
+  @Expose private Schema expressionSchema;                     // required
 
   public PartitionMethodDesc() {
     builder = CatalogProtos.PartitionMethodProto.newBuilder();
   }
 
-  public PartitionMethodDesc(String tableId, CatalogProtos.PartitionType partitionType, String expression,
+  public PartitionMethodDesc(String databaseName, String tableName,
+                             PartitionType partitionType, String expression,
                              Schema expressionSchema) {
-    this.tableId = tableId;
+    this.databaseName = databaseName;
+    this.tableName = tableName;
     this.partitionType = partitionType;
     this.expression = expression;
     this.expressionSchema = expressionSchema;
   }
 
   public PartitionMethodDesc(CatalogProtos.PartitionMethodProto proto) {
-    this(proto.getTableId(), proto.getPartitionType(), proto.getExpression(), new Schema(proto.getExpressionSchema()));
+    this(proto.getTableIdentifier().getDatabaseName(),
+        proto.getTableIdentifier().getTableName(),
+        proto.getPartitionType(), proto.getExpression(),
+        new Schema(proto.getExpressionSchema()));
   }
 
-  public String getTableId() {
-    return tableId;
+  public String getTableName() {
+    return tableName;
   }
 
   public String getExpression() {
@@ -68,19 +77,19 @@ public class PartitionMethodDesc implements ProtoObject<CatalogProtos.PartitionM
     return expressionSchema;
   }
 
-  public CatalogProtos.PartitionType getPartitionType() {
+  public PartitionType getPartitionType() {
     return partitionType;
   }
 
-  public void setTableId(String tableId) {
-    this.tableId = tableId;
+  public void setTableName(String tableId) {
+    this.tableName = tableId;
   }
 
   public void setExpressionSchema(Schema expressionSchema) {
     this.expressionSchema = expressionSchema;
   }
 
-  public void setPartitionType(CatalogProtos.PartitionType partitionsType) {
+  public void setPartitionType(PartitionType partitionsType) {
     this.partitionType = partitionsType;
   }
 
@@ -92,7 +101,7 @@ public class PartitionMethodDesc implements ProtoObject<CatalogProtos.PartitionM
   public boolean equals(Object object) {
     if(object instanceof PartitionMethodDesc) {
       PartitionMethodDesc other = (PartitionMethodDesc) object;
-      boolean eq = tableId.equals(other.tableId);
+      boolean eq = tableName.equals(other.tableName);
       eq = eq && partitionType.equals(other.partitionType);
       eq = eq && expression.equals(other.expression);
       eq = eq && TUtil.checkEquals(expressionSchema, other.expressionSchema);
@@ -104,7 +113,7 @@ public class PartitionMethodDesc implements ProtoObject<CatalogProtos.PartitionM
 
   @Override
   public int hashCode() {
-    return Objects.hashCode(tableId, partitionType, expression, expressionSchema);
+    return Objects.hashCode(tableName, partitionType, expression, expressionSchema);
   }
 
   @Override
@@ -112,7 +121,17 @@ public class PartitionMethodDesc implements ProtoObject<CatalogProtos.PartitionM
     if(builder == null) {
       builder = CatalogProtos.PartitionMethodProto.newBuilder();
     }
-    builder.setTableId(tableId);
+
+    TableIdentifierProto.Builder tableIdentifierBuilder = TableIdentifierProto.newBuilder();
+    if (databaseName != null) {
+      tableIdentifierBuilder.setDatabaseName(databaseName);
+    }
+    if (tableName != null) {
+      tableIdentifierBuilder.setTableName(tableName);
+    }
+
+    CatalogProtos.PartitionMethodProto.Builder builder = CatalogProtos.PartitionMethodProto.newBuilder();
+    builder.setTableIdentifier(tableIdentifierBuilder.build());
     builder.setPartitionType(partitionType);
     builder.setExpression(expression);
     builder.setExpressionSchema(expressionSchema.getProto());
@@ -123,7 +142,7 @@ public class PartitionMethodDesc implements ProtoObject<CatalogProtos.PartitionM
   public Object clone() throws CloneNotSupportedException {
     PartitionMethodDesc desc = (PartitionMethodDesc) super.clone();
     desc.builder = builder;
-    desc.tableId = tableId;
+    desc.tableName = tableName;
     desc.partitionType = partitionType;
     desc.expression = expression;
     desc.expressionSchema = (Schema) expressionSchema.clone();

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 35171cc..14fb39f 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
+++ b/tajo-catalog/tajo-catalog-common/src/main/proto/CatalogProtos.proto
@@ -40,16 +40,6 @@ enum OrderType {
     DSC = 2;
 }
 
-enum CompressType {
-    COMP_NONE = 0;
-    NULL_SUPPRESS = 1;
-    RUN_LENGTH = 2;
-    BIT_VECTOR = 3;
-    DICTIONARY = 4;
-    SNAPPY = 5;
-    LZ = 6;
-}
-
 enum PartitionType {
     RANGE = 0;
     HASH = 1;
@@ -57,18 +47,6 @@ enum PartitionType {
     COLUMN = 3;
 }
 
-message ColumnMetaProto {
-    required DataType dataType = 1;
-    required bool compressed = 2;
-    required bool sorted = 3;
-    required bool contiguous = 4;
-    required StoreType storeType = 5;
-    required CompressType compType = 6;
-    required int64 startRid = 7;
-    required int32 recordNum = 8;
-    required int32 offsetToIndex = 9;
-}
-
 message ColumnProto {
 	required string name = 1;
 	required DataType dataType = 3;
@@ -102,17 +80,38 @@ message FileFragmentProto {
 }
 
 message TableProto {
-    required StoreType storeType = 1;
-    optional KeyValueSetProto params = 2;
+  required StoreType storeType = 1;
+  optional KeyValueSetProto params = 2;
+}
+
+message CreateTablespaceRequest {
+  required string tablespace_name = 1;
+  required string tablespace_uri = 2;
+}
+
+message CreateDatabaseRequest {
+  required string database_name = 1;
+  optional string tablespace_name = 2;
 }
 
 message TableDescProto {
-	required string id = 1;
-	required string path = 2;
-	required TableProto meta = 3;
-	required SchemaProto schema = 4;
-	optional TableStatsProto stats = 5;
-  optional PartitionMethodProto partition = 6;
+	required string table_name = 2;
+	optional string path = 3;
+	required TableProto meta = 4;
+	required SchemaProto schema = 5;
+	optional TableStatsProto stats = 6;
+  optional PartitionMethodProto partition = 7;
+  optional bool isExternal = 8 [default = false];
+}
+
+message TableIdentifierProto {
+  required string database_name = 1;
+  required string table_name = 3;
+}
+
+message NamespaceProto {
+  required string database_name = 1;
+  optional string namespace = 2;
 }
 
 enum FunctionType {
@@ -136,8 +135,8 @@ message FunctionDescProto {
 }
 
 message IndexDescProto {
-    required string name = 1;
-    required string tableId = 2;
+    required TableIdentifierProto tableIdentifier = 1;
+    required string indexName = 2;
     required ColumnProto column = 3;
     required IndexMethod indexMethod = 4;
     optional bool isUnique = 5 [default = false];
@@ -156,11 +155,17 @@ message GetAllTableNamesResponse {
     repeated string tableName = 1;
 }
 
-message GetIndexRequest {
-    required string tableName = 1;
+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;
 }
@@ -239,18 +244,18 @@ message SortSpecProto {
 
 
 message PartitionsProto {
-  repeated PartitionDescProto partition = 1;
+  required TableIdentifierProto tableIdentifier = 1;
+  repeated PartitionDescProto partition = 2;
 }
 
 message PartitionMethodProto {
-  required string tableId = 1;
+  required TableIdentifierProto tableIdentifier = 1;
   required PartitionType partitionType = 2;
   required string expression = 3;
   required SchemaProto expressionSchema = 4;
 }
 
 message PartitionDescProto {
-  required string tableId = 1;
   optional string partitionName = 2;
   required int32  ordinalPosition = 3;
   optional string partitionValue = 4;

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
index 065ec9d..f2d9f89 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestCatalogUtil.java
@@ -26,7 +26,8 @@ import static org.junit.Assert.assertEquals;
 public class TestCatalogUtil {
   @Test
   public final void testGetCanonicalName() {
-    String canonical = CatalogUtil.getCanonicalName("sum", CatalogUtil.newSimpleDataTypeArray(Type.INT4, Type.INT8));
+    String canonical = CatalogUtil.getCanonicalSignature("sum", CatalogUtil.newSimpleDataTypeArray(Type.INT4,
+        Type.INT8));
     assertEquals("sum(int4,int8)", canonical);
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 6a9adc7..3fa8f53 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
@@ -18,13 +18,14 @@
 
 package org.apache.tajo.catalog;
 
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
 import org.apache.tajo.catalog.proto.CatalogProtos.IndexDescProto;
 import org.apache.tajo.catalog.proto.CatalogProtos.IndexMethod;
 import org.apache.tajo.common.TajoDataTypes.Type;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotSame;
 
@@ -35,15 +36,15 @@ public class TestIndexDesc {
   
   static {
     desc1 = new IndexDesc(
-        "idx_test", "indexed", new Column("id", Type.INT4),
+        "idx_test", DEFAULT_DATABASE_NAME, "indexed", new Column("id", Type.INT4),
         IndexMethod.TWO_LEVEL_BIN_TREE, true, true, true);
     
     desc2 = new IndexDesc(
-        "idx_test2", "indexed", new Column("score", Type.FLOAT8),
+        "idx_test2", DEFAULT_DATABASE_NAME, "indexed", new Column("score", Type.FLOAT8),
         IndexMethod.TWO_LEVEL_BIN_TREE, false, false, false);
     
     desc3 = new IndexDesc(
-        "idx_test", "indexed", new Column("id", Type.INT4),
+        "idx_test", DEFAULT_DATABASE_NAME, "indexed", new Column("id", Type.INT4),
         IndexMethod.TWO_LEVEL_BIN_TREE, true, true, true);
   }
 
@@ -64,16 +65,16 @@ public class TestIndexDesc {
 
   @Test
   public void testGetFields() {
-    assertEquals("idx_test", desc1.getName());
-    assertEquals("indexed", desc1.getTableId());
+    assertEquals("idx_test", desc1.getIndexName());
+    assertEquals("indexed", desc1.getTableName());
     assertEquals(new Column("id", Type.INT4), desc1.getColumn());
     assertEquals(IndexMethod.TWO_LEVEL_BIN_TREE, desc1.getIndexMethod());
     assertEquals(true, desc1.isUnique());
     assertEquals(true, desc1.isClustered());
     assertEquals(true, desc1.isAscending());
     
-    assertEquals("idx_test2", desc2.getName());
-    assertEquals("indexed", desc2.getTableId());
+    assertEquals("idx_test2", desc2.getIndexName());
+    assertEquals("indexed", desc2.getTableName());
     assertEquals(new Column("score", Type.FLOAT8), desc2.getColumn());
     assertEquals(IndexMethod.TWO_LEVEL_BIN_TREE, desc2.getIndexMethod());
     assertEquals(false, desc2.isUnique());

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java
index d6f75ba..b7a9906 100644
--- a/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java
+++ b/tajo-catalog/tajo-catalog-common/src/test/java/org/apache/tajo/catalog/TestTableDesc.java
@@ -21,13 +21,13 @@ package org.apache.tajo.catalog;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.catalog.json.CatalogGsonHelper;
 import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import org.apache.tajo.catalog.statistics.ColumnStats;
 import org.apache.tajo.catalog.statistics.TableStats;
+import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.junit.Before;
 import org.junit.Test;
-import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
-import org.apache.tajo.common.TajoDataTypes.Type;
 
 import java.io.IOException;
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 5387673..50726a6 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
@@ -18,78 +18,67 @@
 
 package org.apache.tajo.catalog.store;
 
+import com.google.common.collect.Lists;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hive.metastore.TableType;
 import org.apache.hadoop.hive.metastore.api.*;
 import org.apache.hadoop.hive.serde.serdeConstants;
 import org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe;
 import org.apache.hadoop.hive.serde2.columnar.LazyBinaryColumnarSerDe;
 import org.apache.hcatalog.common.HCatUtil;
-import org.apache.hcatalog.data.Pair;
 import org.apache.hcatalog.data.schema.HCatFieldSchema;
 import org.apache.hcatalog.data.schema.HCatSchema;
+import org.apache.tajo.TajoConstants;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.catalog.exception.AlreadyExistsDatabaseException;
 import org.apache.tajo.catalog.exception.CatalogException;
+import org.apache.tajo.catalog.exception.NoSuchDatabaseException;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.statistics.TableStats;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.exception.NotImplementedException;
+import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.exception.InternalException;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Properties;
+import java.util.*;
 
 import static org.apache.tajo.catalog.proto.CatalogProtos.PartitionType;
 
 public class HCatalogStore extends CatalogConstants implements CatalogStore {
-
   protected final Log LOG = LogFactory.getLog(getClass());
+
+  private static String HIVE_WAREHOUSE_DIR_CONF_KEY = "hive.metastore.warehouse.dir";
+
   protected Configuration conf;
   private static final int CLIENT_POOL_SIZE = 2;
   private final HCatalogStoreClientPool clientPool;
+  private final String defaultTableSpaceUri;
 
-  public HCatalogStore(final Configuration conf)
-      throws InternalException {
-    this(conf, new HCatalogStoreClientPool(CLIENT_POOL_SIZE, conf));
-  }
-
-  public HCatalogStore(final Configuration conf, HCatalogStoreClientPool pool)
-      throws InternalException {
+  public HCatalogStore(final Configuration conf) throws InternalException {
     this.conf = conf;
-    this.clientPool = pool;
+    this.defaultTableSpaceUri = TajoConf.getWarehouseDir((TajoConf) conf).toString();
+    this.clientPool = new HCatalogStoreClientPool(CLIENT_POOL_SIZE, conf);
   }
 
   @Override
-  public boolean existTable(final String name) throws CatalogException {
+  public boolean existTable(final String databaseName, final String tableName) throws CatalogException {
     boolean exist = false;
-
-    String dbName = null, tableName = null;
-    Pair<String, String> tablePair = null;
     org.apache.hadoop.hive.ql.metadata.Table table = null;
     HCatalogStoreClientPool.HCatalogStoreClient client = null;
-    // get db name and table name.
-    try {
-      tablePair = HCatUtil.getDbAndTableName(name);
-      dbName = tablePair.first;
-      tableName = tablePair.second;
-    } catch (Exception ioe) {
-      throw new CatalogException("Table name is wrong.", ioe);
-    }
 
     // get table
     try {
       try {
         client = clientPool.getClient();
-        table = HCatUtil.getTable(client.getHiveClient(), dbName, tableName);
+        table = HCatUtil.getTable(client.getHiveClient(), databaseName, tableName);
         if (table != null) {
           exist = true;
         }
@@ -106,9 +95,7 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
   }
 
   @Override
-  public final CatalogProtos.TableDescProto getTable(final String name) throws CatalogException {
-    String dbName = null, tableName = null;
-    Pair<String, String> tablePair = null;
+  public final CatalogProtos.TableDescProto getTable(String databaseName, final String tableName) throws CatalogException {
     org.apache.hadoop.hive.ql.metadata.Table table = null;
     HCatalogStoreClientPool.HCatalogStoreClient client = null;
     Path path = null;
@@ -118,15 +105,6 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
     TableStats stats = null;
     PartitionMethodDesc partitions = null;
 
-    // get db name and table name.
-    try {
-      tablePair = HCatUtil.getDbAndTableName(name);
-      dbName = tablePair.first;
-      tableName = tablePair.second;
-    } catch (Exception ioe) {
-      throw new CatalogException("Table name is wrong.", ioe);
-    }
-
     //////////////////////////////////
     // set tajo table schema.
     //////////////////////////////////
@@ -134,10 +112,10 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
       // get hive table schema
       try {
         client = clientPool.getClient();
-        table = HCatUtil.getTable(client.getHiveClient(), dbName, tableName);
+        table = HCatUtil.getTable(client.getHiveClient(), databaseName, tableName);
         path = table.getPath();
       } catch (NoSuchObjectException nsoe) {
-        throw new CatalogException("Table not found. - tableName:" + name, nsoe);
+        throw new CatalogException("Table not found. - tableName:" + tableName, nsoe);
       } catch (Exception e) {
         throw new CatalogException(e);
       }
@@ -149,7 +127,7 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
       try {
         tableSchema = HCatUtil.getTableSchemaWithPtnCols(table);
       } catch (IOException ioe) {
-        throw new CatalogException("Fail to get table schema. - tableName:" + name, ioe);
+        throw new CatalogException("Fail to get table schema. - tableName:" + tableName, ioe);
       }
       List<HCatFieldSchema> fieldSchemaList = tableSchema.getFields();
       boolean isPartitionKey = false;
@@ -165,7 +143,7 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
         }
 
         if (!isPartitionKey) {
-          String fieldName = dbName + CatalogUtil.IDENTIFIER_DELIMITER + tableName +
+          String fieldName = databaseName + CatalogUtil.IDENTIFIER_DELIMITER + tableName +
               CatalogUtil.IDENTIFIER_DELIMITER + eachField.getName();
           TajoDataTypes.Type dataType = HCatalogUtil.getTajoFieldType(eachField.getType().toString());
           schema.addColumn(fieldName, dataType);
@@ -180,7 +158,8 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
       }
 
       stats = new TableStats();
-      options = Options.create();
+      options = new Options();
+      options.putAll(table.getParameters());
       Properties properties = table.getMetadata();
       if (properties != null) {
         // set field delimiter
@@ -243,7 +222,7 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
           for(int i = 0; i < partitionKeys.size(); i++) {
             FieldSchema fieldSchema = partitionKeys.get(i);
             TajoDataTypes.Type dataType = HCatalogUtil.getTajoFieldType(fieldSchema.getType().toString());
-            String fieldName = dbName + CatalogUtil.IDENTIFIER_DELIMITER + tableName +
+            String fieldName = databaseName + CatalogUtil.IDENTIFIER_DELIMITER + tableName +
                 CatalogUtil.IDENTIFIER_DELIMITER + fieldSchema.getName();
             expressionSchema.addColumn(new Column(fieldName, dataType));
             if (i > 0) {
@@ -252,7 +231,8 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
             sb.append(fieldSchema.getName());
           }
           partitions = new PartitionMethodDesc(
-              dbName + "." + tableName,
+              databaseName,
+              tableName,
               PartitionType.COLUMN,
               sb.toString(),
               expressionSchema);
@@ -263,7 +243,7 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
     }
     TableMeta meta = new TableMeta(storeType, options);
 
-    TableDesc tableDesc = new TableDesc(dbName + "." + tableName, schema, meta, path);
+    TableDesc tableDesc = new TableDesc(databaseName + "." + tableName, schema, meta, path);
     if (stats != null) {
       tableDesc.setStats(stats);
     }
@@ -284,57 +264,134 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
   }
 
   @Override
-  public final List<String> getAllTableNames() throws CatalogException {
-    List<String> dbs = null;
-    List<String> tables = null;
-    List<String> allTables = new ArrayList<String>();
+  public final List<String> getAllTableNames(String databaseName) throws CatalogException {
     HCatalogStoreClientPool.HCatalogStoreClient client = null;
 
     try {
       client = clientPool.getClient();
-      dbs = client.getHiveClient().getAllDatabases();
-      for(String eachDB: dbs) {
-        tables = client.getHiveClient().getAllTables(eachDB);
-        for(String eachTable: tables) {
-          allTables.add(eachDB + "." + eachTable);
-        }
-      }
+      return client.getHiveClient().getAllTables(databaseName);
     } catch (MetaException e) {
       throw new CatalogException(e);
     } finally {
       client.release();
     }
-    return allTables;
   }
 
   @Override
-  public final void addTable(final CatalogProtos.TableDescProto tableDescProto) throws CatalogException {
-    String dbName = null, tableName = null;
-    Pair<String, String> tablePair = null;
+  public void createTablespace(String spaceName, String spaceUri) throws CatalogException {
+    // SKIP
+  }
+
+  @Override
+  public boolean existTablespace(String spaceName) throws CatalogException {
+    // SKIP
+    return spaceName.equals(TajoConstants.DEFAULT_TABLESPACE_NAME);
+  }
+
+  @Override
+  public void dropTablespace(String spaceName) throws CatalogException {
+    // SKIP
+  }
+
+  @Override
+  public Collection<String> getAllTablespaceNames() throws CatalogException {
+    return Lists.newArrayList(TajoConstants.DEFAULT_TABLESPACE_NAME);
+  }
+
+  @Override
+  public void createDatabase(String databaseName, String tablespaceName) throws CatalogException {
     HCatalogStoreClientPool.HCatalogStoreClient client = null;
 
-    TableDesc tableDesc = new TableDesc(tableDescProto);
-    // get db name and table name.
     try {
-      tablePair = HCatUtil.getDbAndTableName(tableDesc.getName());
-      dbName = tablePair.first;
-      tableName = tablePair.second;
-    } catch (Exception ioe) {
-      throw new CatalogException("Table name is wrong.", ioe);
+      Database database = new Database(
+          databaseName,
+          "",
+          defaultTableSpaceUri + "/" + databaseName,
+          new HashMap<String, String>());
+      client = clientPool.getClient();
+      client.getHiveClient().createDatabase(database);
+    } catch (AlreadyExistsException e) {
+      throw new AlreadyExistsDatabaseException(databaseName);
+    } catch (Throwable t) {
+      throw new CatalogException(t);
+    } finally {
+      if (client != null) {
+        client.release();
+      }
     }
+  }
+
+  @Override
+  public boolean existDatabase(String databaseName) throws CatalogException {
+    HCatalogStoreClientPool.HCatalogStoreClient client = null;
 
     try {
       client = clientPool.getClient();
+      List<String> databaseNames = client.getHiveClient().getAllDatabases();
+      return databaseNames.contains(databaseName);
+    } catch (Throwable t) {
+      throw new CatalogException(t);
+    } finally {
+      if (client != null) {
+        client.release();
+      }
+    }
+  }
 
-      org.apache.hadoop.hive.metastore.api.Table table = new org.apache.hadoop.hive.metastore.api.Table();
+  @Override
+  public void dropDatabase(String databaseName) throws CatalogException {
+    HCatalogStoreClientPool.HCatalogStoreClient client = null;
 
-      table.setDbName(dbName);
+    try {
+      client = clientPool.getClient();
+      client.getHiveClient().dropDatabase(databaseName);
+    } catch (NoSuchObjectException e) {
+      throw new NoSuchDatabaseException(databaseName);
+    } catch (Throwable t) {
+      throw new CatalogException(databaseName);
+    } finally {
+      if (client != null) {
+        client.release();
+      }
+    }
+  }
+
+  @Override
+  public Collection<String> getAllDatabaseNames() throws CatalogException {
+    HCatalogStoreClientPool.HCatalogStoreClient client = null;
+
+    try {
+      client = clientPool.getClient();
+      return client.getHiveClient().getAllDatabases();
+    } catch (MetaException e) {
+      throw new CatalogException(e);
+    } finally {
+      if (client != null) {
+        client.release();
+      }
+    }
+  }
+
+  @Override
+  public final void createTable(final CatalogProtos.TableDescProto tableDescProto) throws CatalogException {
+    HCatalogStoreClientPool.HCatalogStoreClient client = null;
+
+    TableDesc tableDesc = new TableDesc(tableDescProto);
+    String [] splitted = CatalogUtil.splitFQTableName(CatalogUtil.normalizeIdentifier(tableDesc.getName()));
+    String databaseName = splitted[0];
+    String tableName = splitted[1];
+
+    try {
+      client = clientPool.getClient();
+
+      org.apache.hadoop.hive.metastore.api.Table table = new org.apache.hadoop.hive.metastore.api.Table();
+      table.setDbName(databaseName);
       table.setTableName(tableName);
+      table.setParameters(new HashMap<String, String>(tableDesc.getMeta().getOptions().getAllKeyValus()));
       // TODO: set owner
       //table.setOwner();
 
       StorageDescriptor sd = new StorageDescriptor();
-      sd.setParameters(new HashMap<String, String>());
       sd.setSerdeInfo(new SerDeInfo());
       sd.getSerdeInfo().setParameters(new HashMap<String, String>());
       sd.getSerdeInfo().setName(table.getTableName());
@@ -342,7 +399,18 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
       // if tajo set location method, thrift client make exception as follows:
       // Caused by: MetaException(message:java.lang.NullPointerException)
       // If you want to modify table path, you have to modify on Hive cli.
-      // sd.setLocation(tableDesc.getPath().toString());
+      if (tableDesc.isExternal()) {
+        table.setTableType(TableType.EXTERNAL_TABLE.name());
+        table.getParameters().put("EXTERNAL", "TRUE");
+
+        FileSystem fs = tableDesc.getPath().getFileSystem(conf);
+        if (fs.isFile(tableDesc.getPath())) {
+          LOG.warn("A table path is a file, but HCatalog does not allow a file path.");
+          sd.setLocation(tableDesc.getPath().getParent().toString());
+        } else {
+          sd.setLocation(tableDesc.getPath().toString());
+        }
+      }
 
       // set column information
       List<Column> columns = tableDesc.getSchema().getColumns();
@@ -350,7 +418,7 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
 
       for (Column eachField : columns) {
         cols.add(new FieldSchema(eachField.getSimpleName(),
-            HCatalogUtil.getHiveFieldType(eachField.getDataType().getType().name()), ""));
+            HCatalogUtil.getHiveFieldType(eachField.getDataType()), ""));
       }
       sd.setCols(cols);
 
@@ -359,7 +427,7 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
         List<FieldSchema> partitionKeys = new ArrayList<FieldSchema>();
         for(Column eachPartitionKey: tableDesc.getPartitionMethod().getExpressionSchema().getColumns()) {
           partitionKeys.add(new FieldSchema( eachPartitionKey.getSimpleName(),
-              HCatalogUtil.getHiveFieldType(eachPartitionKey.getDataType().getType().name()), ""));
+              HCatalogUtil.getHiveFieldType(eachPartitionKey.getDataType()), ""));
         }
         table.setPartitionKeys(partitionKeys);
       }
@@ -418,23 +486,12 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
   }
 
   @Override
-  public final void deleteTable(final String name) throws CatalogException {
-    String dbName = null, tableName = null;
-    Pair<String, String> tablePair = null;
+  public final void dropTable(String databaseName, final String tableName) throws CatalogException {
     HCatalogStoreClientPool.HCatalogStoreClient client = null;
 
-    // get db name and table name.
-    try {
-      tablePair = HCatUtil.getDbAndTableName(name);
-      dbName = tablePair.first;
-      tableName = tablePair.second;
-    } catch (Exception ioe) {
-      throw new CatalogException("Table name is wrong.", ioe);
-    }
-
     try {
       client = clientPool.getClient();
-      client.getHiveClient().dropTable(dbName, tableName, false, false);
+      client.getHiveClient().dropTable(databaseName, tableName, false, false);
     } catch (NoSuchObjectException nsoe) {
     } catch (Exception e) {
       throw new CatalogException(e);
@@ -449,17 +506,18 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
   }
 
   @Override
-  public CatalogProtos.PartitionMethodProto getPartitionMethod(String tableName) throws CatalogException {
+  public CatalogProtos.PartitionMethodProto getPartitionMethod(String databaseName, String tableName)
+      throws CatalogException {
     return null;  // TODO - not implemented yet
   }
 
   @Override
-  public boolean existPartitionMethod(String tableName) throws CatalogException {
+  public boolean existPartitionMethod(String databaseName, String tableName) throws CatalogException {
     return false;  // TODO - not implemented yet
   }
 
   @Override
-  public void delPartitionMethod(String tableName) throws CatalogException {
+  public void dropPartitionMethod(String databaseName, String tableName) throws CatalogException {
     // TODO - not implemented yet
   }
 
@@ -469,8 +527,8 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
   }
 
   @Override
-  public void addPartition(CatalogProtos.PartitionDescProto partitionDescProto) throws CatalogException {
-    // TODO - not implemented yet
+  public void addPartition(String databaseName, String tableName, CatalogProtos.PartitionDescProto partitionDescProto) throws CatalogException {
+
   }
 
   @Override
@@ -489,10 +547,11 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
   }
 
   @Override
-  public void delPartitions(String tableName) throws CatalogException {
-    // TODO - not implemented yet
+  public void dropPartitions(String tableName) throws CatalogException {
+
   }
 
+
   @Override
   public final void addFunction(final FunctionDesc func) throws CatalogException {
     // TODO - not implemented yet
@@ -515,41 +574,42 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
   }
 
   @Override
-  public void delIndex(String indexName) throws CatalogException {
+  public void dropIndex(String databaseName, String indexName) throws CatalogException {
     // TODO - not implemented yet
   }
 
   @Override
-  public boolean existIndex(String indexName) throws CatalogException {
+  public boolean existIndexByName(String databaseName, String indexName) throws CatalogException {
     // TODO - not implemented yet
     return false;
   }
 
   @Override
-  public CatalogProtos.IndexDescProto[] getIndexes(String tableName) throws CatalogException {
+  public CatalogProtos.IndexDescProto[] getIndexes(String databaseName, String tableName) throws CatalogException {
     // TODO - not implemented yet
     return null;
   }
 
   @Override
-  public void addIndex(CatalogProtos.IndexDescProto proto) throws CatalogException {
+  public void createIndex(CatalogProtos.IndexDescProto proto) throws CatalogException {
     // TODO - not implemented yet
   }
 
   @Override
-  public CatalogProtos.IndexDescProto getIndex(String indexName) throws CatalogException {
+  public CatalogProtos.IndexDescProto getIndexByName(String databaseName, String indexName) throws CatalogException {
     // TODO - not implemented yet
     return null;
   }
 
   @Override
-  public CatalogProtos.IndexDescProto getIndex(String tableName, String columnName) throws CatalogException {
+  public CatalogProtos.IndexDescProto getIndexByColumn(String databaseName, String tableName, String columnName)
+      throws CatalogException {
     // TODO - not implemented yet
     return null;
   }
 
   @Override
-  public boolean existIndex(String tableName, String columnName) throws CatalogException{
+  public boolean existIndexByColumn(String databaseName, String tableName, String columnName) throws CatalogException {
     // TODO - not implemented yet
     return false;
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStoreClientPool.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStoreClientPool.java b/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStoreClientPool.java
index cc8ff08..5c416c6 100644
--- a/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStoreClientPool.java
+++ b/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogStoreClientPool.java
@@ -47,8 +47,9 @@ public class HCatalogStoreClientPool {
 
     private HCatalogStoreClient(HiveConf hiveConf) {
       try {
-        LOG.info("Creating MetaStoreClient. Pool Size = " + clientPool.size());
         this.hiveClient = new HiveMetaStoreClient(hiveConf);
+        clientPool.add(this);
+        LOG.info("MetaStoreClient created (size = " + clientPool.size() + ")");
       } catch (Exception e) {
         // Turn in to an unchecked exception
         throw new IllegalStateException(e);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogUtil.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogUtil.java b/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogUtil.java
index fc2fdda..d426369 100644
--- a/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogUtil.java
+++ b/tajo-catalog/tajo-catalog-drivers/tajo-hcatalog/src/main/java/org/apache/tajo/catalog/store/HCatalogUtil.java
@@ -87,30 +87,30 @@ public class HCatalogUtil {
     }
   }
 
-  public static String getHiveFieldType(String fieldType) {
-    Preconditions.checkNotNull(fieldType);
-    String typeStr = null;
+  public static String getHiveFieldType(TajoDataTypes.DataType dataType) {
+    Preconditions.checkNotNull(dataType);
 
-    if(fieldType.equalsIgnoreCase("INT4"))
-      typeStr = serdeConstants.INT_TYPE_NAME;
-    else if(fieldType.equalsIgnoreCase("INT1"))
-      typeStr = serdeConstants.TINYINT_TYPE_NAME;
-    else if(fieldType.equalsIgnoreCase("INT2"))
-      typeStr = serdeConstants.SMALLINT_TYPE_NAME;
-    else if(fieldType.equalsIgnoreCase("INT8"))
-      typeStr = serdeConstants.BIGINT_TYPE_NAME;
-    else if(fieldType.equalsIgnoreCase("BOOLEAN"))
-      typeStr = serdeConstants.BOOLEAN_TYPE_NAME;
-    else if(fieldType.equalsIgnoreCase("FLOAT4"))
-      typeStr = serdeConstants.FLOAT_TYPE_NAME;
-    else if(fieldType.equalsIgnoreCase("FLOAT8"))
-      typeStr = serdeConstants.DOUBLE_TYPE_NAME;
-    else if(fieldType.equalsIgnoreCase("TEXT"))
-      typeStr = serdeConstants.STRING_TYPE_NAME;
-    else if(fieldType.equalsIgnoreCase("BLOB"))
-      typeStr = serdeConstants.BINARY_TYPE_NAME;
-
-    return typeStr;
+    switch (dataType.getType()) {
+    case CHAR: return serdeConstants.CHAR_TYPE_NAME;
+    case BOOLEAN: return serdeConstants.BOOLEAN_TYPE_NAME;
+    case INT1: return serdeConstants.TINYINT_TYPE_NAME;
+    case INT2: return serdeConstants.SMALLINT_TYPE_NAME;
+    case INT4: return serdeConstants.INT_TYPE_NAME;
+    case INT8: return serdeConstants.BIGINT_TYPE_NAME;
+    case FLOAT4: return serdeConstants.FLOAT_TYPE_NAME;
+    case FLOAT8: return serdeConstants.DOUBLE_TYPE_NAME;
+    case TEXT: return serdeConstants.STRING_TYPE_NAME;
+    case VARCHAR: return serdeConstants.VARCHAR_TYPE_NAME;
+    case NCHAR: return serdeConstants.VARCHAR_TYPE_NAME;
+    case NVARCHAR: return serdeConstants.VARCHAR_TYPE_NAME;
+    case BINARY: return serdeConstants.BINARY_TYPE_NAME;
+    case VARBINARY: return serdeConstants.BINARY_TYPE_NAME;
+    case BLOB: return serdeConstants.BINARY_TYPE_NAME;
+    case DATE: return serdeConstants.DATE_TYPE_NAME;
+    case TIMESTAMP: return serdeConstants.TIMESTAMP_TYPE_NAME;
+    default:
+      throw new CatalogException(dataType + " is not supported.");
+    }
   }
 
   public static String getStoreType(String fileFormat) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 cb3973a..b9a734e 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
@@ -24,7 +24,6 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.conf.HiveConf;
-import org.apache.hadoop.hive.metastore.api.Database;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.proto.CatalogProtos;
@@ -59,36 +58,23 @@ public class TestHCatalogStore {
   @BeforeClass
   public static void setUp() throws Exception {
     Path testPath = CommonTestingUtil.getTestDir();
-    warehousePath = new Path(testPath, DB_NAME);
+    warehousePath = new Path(testPath, "warehouse");
 
     //create local hiveMeta
     HiveConf conf = new HiveConf();
-    String jdbcUri = "jdbc:derby:;databaseName="+testPath.toUri().getPath()+"/metastore_db;create=true";
+    String jdbcUri = "jdbc:derby:;databaseName="+testPath.toUri().getPath()+"metastore_db;create=true";
     conf.set(HiveConf.ConfVars.METASTOREWAREHOUSE.varname, warehousePath.toUri().toString());
     conf.set(HiveConf.ConfVars.METASTORECONNECTURLKEY.varname, jdbcUri);
+    conf.set(TajoConf.ConfVars.WAREHOUSE_DIR.varname, warehousePath.toUri().toString());
 
     // create local HCatalogStore.
     TajoConf tajoConf = new TajoConf(conf);
-    Database db = new Database();
-    db.setLocationUri(warehousePath.toUri().toString());
-    db.setName(DB_NAME);
-    pool = new HCatalogStoreClientPool(1, tajoConf);
-    HCatalogStoreClientPool.HCatalogStoreClient client = pool.getClient();
-    client.getHiveClient().createDatabase(db);
-    client.release();
-
-    store = new HCatalogStore(tajoConf, pool);
+    store = new HCatalogStore(tajoConf);
+    store.createDatabase(DB_NAME, null);
   }
 
   @AfterClass
   public static void tearDown() throws IOException {
-    try {
-      HCatalogStoreClientPool.HCatalogStoreClient client = pool.getClient();
-      client.getHiveClient().dropDatabase(DB_NAME);
-      client.release();
-    } catch (Exception e) {
-      e.printStackTrace();
-    }
     store.close();
   }
 
@@ -106,14 +92,14 @@ public class TestHCatalogStore {
     schema.addColumn("c_mktsegment", TajoDataTypes.Type.TEXT);
     schema.addColumn("c_comment", TajoDataTypes.Type.TEXT);
 
-    String tableName = DB_NAME + "." + CUSTOMER;
-    TableDesc table = new TableDesc(tableName, schema, meta, warehousePath);
-    store.addTable(table.getProto());
-    assertTrue(store.existTable(tableName));
+    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, CUSTOMER), schema, meta,
+        new Path(warehousePath, new Path(DB_NAME, CUSTOMER)));
+    store.createTable(table.getProto());
+    assertTrue(store.existTable(DB_NAME, CUSTOMER));
 
-    TableDesc table1 = new TableDesc(store.getTable(table.getName()));
+    TableDesc table1 = new TableDesc(store.getTable(DB_NAME, CUSTOMER));
     assertEquals(table.getName(), table1.getName());
-    assertEquals(new Path(table.getPath(), CUSTOMER), table1.getPath());
+    assertEquals(table.getPath(), table1.getPath());
     assertEquals(table.getSchema().size(), table1.getSchema().size());
     for (int i = 0; i < table.getSchema().size(); i++) {
       assertEquals(table.getSchema().getColumn(i).getSimpleName(), table1.getSchema().getColumn(i).getSimpleName());
@@ -121,7 +107,7 @@ public class TestHCatalogStore {
 
     assertEquals(StringEscapeUtils.escapeJava(CatalogConstants.CSVFILE_DELIMITER_DEFAULT),
         table1.getMeta().getOption(CatalogConstants.CSVFILE_DELIMITER));
-    store.deleteTable(tableName);
+    store.dropTable(DB_NAME, CUSTOMER);
   }
 
   @Test
@@ -135,14 +121,14 @@ public class TestHCatalogStore {
     schema.addColumn("r_name", TajoDataTypes.Type.TEXT);
     schema.addColumn("r_comment", TajoDataTypes.Type.TEXT);
 
-    String tableName = DB_NAME + "." + REGION;
-    TableDesc table = new TableDesc(tableName, schema, meta, warehousePath);
-    store.addTable(table.getProto());
-    assertTrue(store.existTable(tableName));
+    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, REGION), schema, meta,
+        new Path(warehousePath, new Path(DB_NAME, REGION)));
+    store.createTable(table.getProto());
+    assertTrue(store.existTable(DB_NAME, REGION));
 
-    TableDesc table1 = new TableDesc(store.getTable(table.getName()));
+    TableDesc table1 = new TableDesc(store.getTable(DB_NAME, REGION));
     assertEquals(table.getName(), table1.getName());
-    assertEquals(new Path(table.getPath(), REGION), table1.getPath());
+    assertEquals(table.getPath(), table1.getPath());
     assertEquals(table.getSchema().size(), table1.getSchema().size());
     for (int i = 0; i < table.getSchema().size(); i++) {
       assertEquals(table.getSchema().getColumn(i).getSimpleName(), table1.getSchema().getColumn(i).getSimpleName());
@@ -150,7 +136,7 @@ public class TestHCatalogStore {
 
     assertEquals(CatalogConstants.RCFILE_BINARY_SERDE,
         table1.getMeta().getOption(CatalogConstants.RCFILE_SERDE));
-    store.deleteTable(tableName);
+    store.dropTable(DB_NAME, REGION);
   }
 
   @Test
@@ -164,21 +150,21 @@ public class TestHCatalogStore {
     schema.addColumn("r_name", TajoDataTypes.Type.TEXT);
     schema.addColumn("r_comment", TajoDataTypes.Type.TEXT);
 
-    String tableName = DB_NAME + "." + REGION;
-    TableDesc table = new TableDesc(tableName, schema, meta, warehousePath);
-    store.addTable(table.getProto());
-    assertTrue(store.existTable(tableName));
+    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, REGION), schema, meta,
+        new Path(warehousePath, new Path(DB_NAME, REGION)));
+    store.createTable(table.getProto());
+    assertTrue(store.existTable(DB_NAME, REGION));
 
-    TableDesc table1 = new TableDesc(store.getTable(table.getName()));
+    TableDesc table1 = new TableDesc(store.getTable(DB_NAME, REGION));
     assertEquals(table.getName(), table1.getName());
-    assertEquals(new Path(table.getPath(), REGION), table1.getPath());
+    assertEquals(table.getPath(), table1.getPath());
     assertEquals(table.getSchema().size(), table1.getSchema().size());
     for (int i = 0; i < table.getSchema().size(); i++) {
       assertEquals(table.getSchema().getColumn(i).getSimpleName(), table1.getSchema().getColumn(i).getSimpleName());
     }
 
     assertEquals(CatalogConstants.RCFILE_TEXT_SERDE, table1.getMeta().getOption(CatalogConstants.RCFILE_SERDE));
-    store.deleteTable(tableName);
+    store.dropTable(DB_NAME, REGION);
   }
 
   @Test
@@ -198,16 +184,16 @@ public class TestHCatalogStore {
     schema.addColumn("s_acctbal", TajoDataTypes.Type.FLOAT8);
     schema.addColumn("s_comment", TajoDataTypes.Type.TEXT);
 
-    String tableName = DB_NAME + "." + SUPPLIER;
-    TableDesc table = new TableDesc(tableName, schema, meta, warehousePath);
+    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, SUPPLIER), schema, meta,
+        new Path(warehousePath, new Path(DB_NAME, SUPPLIER)));
 
 
-    store.addTable(table.getProto());
-    assertTrue(store.existTable(tableName));
+    store.createTable(table.getProto());
+    assertTrue(store.existTable(DB_NAME, SUPPLIER));
 
-    TableDesc table1 = new TableDesc(store.getTable(table.getName()));
+    TableDesc table1 = new TableDesc(store.getTable(DB_NAME, SUPPLIER));
     assertEquals(table.getName(), table1.getName());
-    assertEquals(new Path(table.getPath(), SUPPLIER), table1.getPath());
+    assertEquals(table.getPath(), table1.getPath());
     assertEquals(table.getSchema().size(), table1.getSchema().size());
     for (int i = 0; i < table.getSchema().size(); i++) {
       assertEquals(table.getSchema().getColumn(i).getSimpleName(), table1.getSchema().getColumn(i).getSimpleName());
@@ -218,7 +204,7 @@ public class TestHCatalogStore {
 
     assertEquals(table.getMeta().getOption(CatalogConstants.CSVFILE_NULL),
         table1.getMeta().getOption(CatalogConstants.CSVFILE_NULL));
-    store.deleteTable(tableName);
+    store.dropTable(DB_NAME, SUPPLIER);
   }
 
   @Test
@@ -231,22 +217,24 @@ public class TestHCatalogStore {
     schema.addColumn("n_comment", TajoDataTypes.Type.TEXT);
 
 
-    String tableName = DB_NAME + "." + NATION;
-    TableDesc table = new TableDesc(tableName, schema, meta, warehousePath);
+    TableDesc table = new TableDesc(CatalogUtil.buildFQName(DB_NAME, NATION), schema, meta,
+        new Path(warehousePath, new Path(DB_NAME, NATION)));
 
     org.apache.tajo.catalog.Schema expressionSchema = new org.apache.tajo.catalog.Schema();
     expressionSchema.addColumn("n_nationkey", TajoDataTypes.Type.INT4);
 
-    PartitionMethodDesc partitions = new PartitionMethodDesc(table.getName(),
+    PartitionMethodDesc partitions = new PartitionMethodDesc(
+        DB_NAME,
+        NATION,
         CatalogProtos.PartitionType.COLUMN, expressionSchema.getColumn(0).getQualifiedName(), expressionSchema);
     table.setPartitionMethod(partitions);
 
-    store.addTable(table.getProto());
-    assertTrue(store.existTable(table.getName()));
+    store.createTable(table.getProto());
+    assertTrue(store.existTable(DB_NAME, NATION));
 
-    TableDesc table1 = new TableDesc(store.getTable(table.getName()));
+    TableDesc table1 = new TableDesc(store.getTable(DB_NAME, NATION));
     assertEquals(table.getName(), table1.getName());
-    assertEquals(new Path(table.getPath(), NATION), table1.getPath());
+    assertEquals(table.getPath(), table1.getPath());
     assertEquals(table.getSchema().size(), table1.getSchema().size());
     for (int i = 0; i < table.getSchema().size(); i++) {
       assertEquals(table.getSchema().getColumn(i).getSimpleName(), table1.getSchema().getColumn(i).getSimpleName());
@@ -260,7 +248,7 @@ public class TestHCatalogStore {
       assertEquals(partitionSchema.getColumn(i).getSimpleName(), partitionSchema1.getColumn(i).getSimpleName());
     }
 
-    store.deleteTable(tableName);
+    store.dropTable(DB_NAME, NATION);
   }
 
 
@@ -272,14 +260,15 @@ public class TestHCatalogStore {
     schema.addColumn("n_regionkey", TajoDataTypes.Type.INT4);
     schema.addColumn("n_comment", TajoDataTypes.Type.TEXT);
 
-    String[] tableNames = new String[]{"default.table1", "default.table2", "default.table3"};
+    String[] tableNames = new String[]{"table1", "table2", "table3"};
 
     for(String tableName : tableNames){
-      TableDesc table = new TableDesc(tableName, schema, meta, warehousePath);
-      store.addTable(table.getProto());
+      TableDesc table = new TableDesc(CatalogUtil.buildFQName("default", tableName), schema, meta,
+          new Path(warehousePath, new Path(DB_NAME, tableName)));
+      store.createTable(table.getProto());
     }
 
-    List<String> tables = store.getAllTableNames();
+    List<String> tables = store.getAllTableNames("default");
     assertEquals(tableNames.length, tables.size());
 
     for(String tableName : tableNames){
@@ -287,7 +276,7 @@ public class TestHCatalogStore {
     }
 
     for(String tableName : tableNames){
-      store.deleteTable(tableName);
+      store.dropTable("default", tableName);
     }
   }
 
@@ -301,15 +290,15 @@ public class TestHCatalogStore {
 
     String tableName = "table1";
     TableDesc table = new TableDesc(DB_NAME + "." + tableName, schema, meta, warehousePath);
-    store.addTable(table.getProto());
-    assertTrue(store.existTable(table.getName()));
+    store.createTable(table.getProto());
+    assertTrue(store.existTable(DB_NAME, tableName));
 
-    TableDesc table1 = new TableDesc(store.getTable(table.getName()));
+    TableDesc table1 = new TableDesc(store.getTable(DB_NAME, tableName));
     FileSystem fs = FileSystem.getLocal(new Configuration());
     assertTrue(fs.exists(table1.getPath()));
 
-    store.deleteTable(table1.getName());
-    assertFalse(store.existTable(table1.getName()));
+    store.dropTable(DB_NAME, tableName);
+    assertFalse(store.existTable(DB_NAME, tableName));
     fs.close();
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 621b475..d4ee769 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
@@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.service.AbstractService;
+import org.apache.tajo.annotation.ThreadSafe;
 import org.apache.tajo.catalog.CatalogProtocol.CatalogProtocolService;
 import org.apache.tajo.catalog.exception.*;
 import org.apache.tajo.catalog.proto.CatalogProtos.*;
@@ -38,6 +39,7 @@ import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.BoolProto;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.NullProto;
 import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringProto;
 import org.apache.tajo.util.NetUtils;
+import org.apache.tajo.util.ProtoUtil;
 import org.apache.tajo.util.TUtil;
 
 import java.io.IOException;
@@ -49,13 +51,18 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionType.*;
+import static org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringListProto;
 
 /**
  * This class provides the catalog service. The catalog service enables clients
  * to register, unregister and access information about tables, functions, and
  * cluster information.
  */
+@ThreadSafe
 public class CatalogServer extends AbstractService {
+
+  private final static String DEFAULT_NAMESPACE = "public";
+
   private final static Log LOG = LogFactory.getLog(CatalogServer.class);
   private TajoConf conf;
   private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
@@ -96,14 +103,14 @@ public class CatalogServer extends AbstractService {
   }
 
   @Override
-  public void init(Configuration conf) {
+  public void serviceInit(Configuration conf) throws Exception {
 
     Constructor<?> cons;
     try {
       if (conf instanceof TajoConf) {
         this.conf = (TajoConf) conf;
       } else {
-        throw new CatalogException();
+        throw new CatalogException("conf must be a TajoConf instance");
       }
 
       Class<?> storeClass = this.conf.getClass(CatalogConstants.STORE_CLASS, DerbyStore.class);
@@ -120,13 +127,17 @@ public class CatalogServer extends AbstractService {
       throw new CatalogException(t);
     }
 
-    super.init(conf);
+    super.serviceInit(conf);
   }
 
   public TajoConf getConf() {
     return conf;
   }
 
+  public String getStoreClassName() {
+    return store.getClass().getCanonicalName();
+  }
+
   public String getCatalogServerName() {
     String catalogUri = null;
     if(conf.get(CatalogConstants.DEPRECATED_CATALOG_URI) != null) {
@@ -197,42 +208,204 @@ public class CatalogServer extends AbstractService {
   public class CatalogProtocolHandler implements CatalogProtocolService.BlockingInterface {
 
     @Override
-    public TableDescProto getTableDesc(RpcController controller,
-                                       StringProto name)
-        throws ServiceException {
+    public BoolProto createTablespace(RpcController controller, CreateTablespaceRequest request) throws ServiceException {
+      final String tablespaceName = CatalogUtil.normalizeIdentifier(request.getTablespaceName());
+      final String uri = request.getTablespaceUri();
+
+      wlock.lock();
+      try {
+        if (store.existTablespace(tablespaceName)) {
+          throw new AlreadyExistsDatabaseException(tablespaceName);
+        }
+
+        store.createTablespace(tablespaceName, uri);
+        LOG.info(String.format("tablespace \"%s\" (%s) is created", tablespaceName, uri));
+        return ProtoUtil.TRUE;
+
+      } catch (Exception e) {
+        LOG.error(e);
+        throw new ServiceException(e);
+      } finally {
+        wlock.unlock();
+      }
+    }
+
+    @Override
+    public BoolProto dropTablespace(RpcController controller, StringProto request) throws ServiceException {
+      String tablespaceName = CatalogUtil.normalizeIdentifier(request.getValue());
+
+      wlock.lock();
+      try {
+        if (!store.existTablespace(tablespaceName)) {
+          throw new NoSuchTablespaceException(tablespaceName);
+        }
+
+        store.dropTablespace(tablespaceName);
+        return ProtoUtil.TRUE;
+
+      } catch (Exception e) {
+        LOG.error(e);
+        throw new ServiceException(e);
+      } finally {
+        wlock.unlock();
+      }
+    }
+
+    @Override
+    public BoolProto existTablespace(RpcController controller, StringProto request) throws ServiceException {
+      String tablespaceName = CatalogUtil.normalizeIdentifier(request.getValue());
+
       rlock.lock();
       try {
-        String tableId = name.getValue().toLowerCase();
-        if (!store.existTable(tableId)) {
-          throw new NoSuchTableException(tableId);
+        if (store.existTablespace(tablespaceName)) {
+          return ProtoUtil.TRUE;
+        } else {
+          return ProtoUtil.FALSE;
         }
+      } catch (Exception e) {
+        LOG.error(e);
+        throw new ServiceException(e);
+      } finally {
+        rlock.unlock();
+      }
+    }
 
-        return store.getTable(tableId);
+    @Override
+    public StringListProto getAllTablespaceNames(RpcController controller, NullProto request) throws ServiceException {
+      rlock.lock();
+      try {
+        return ProtoUtil.convertStrings(store.getAllDatabaseNames());
       } catch (Exception e) {
-        // TODO - handle exception
         LOG.error(e);
-        return null;
+        throw new ServiceException(e);
       } finally {
         rlock.unlock();
       }
     }
 
     @Override
-    public GetAllTableNamesResponse getAllTableNames(RpcController controller,
-                                                     NullProto request)
+    public BoolProto createDatabase(RpcController controller, CreateDatabaseRequest request) throws ServiceException {
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getDatabaseName());
+      String tablespaceName = CatalogUtil.normalizeIdentifier(request.getTablespaceName());
+
+      wlock.lock();
+      try {
+        if (store.existDatabase(databaseName)) {
+          throw new AlreadyExistsDatabaseException(databaseName);
+        }
+
+        store.createDatabase(databaseName, tablespaceName);
+        LOG.info(String.format("database \"%s\" is created", databaseName));
+        return ProtoUtil.TRUE;
+      } catch (Exception e) {
+        LOG.error(e);
+        throw new ServiceException(e);
+      } finally {
+        wlock.unlock();
+      }
+    }
+
+    @Override
+    public BoolProto dropDatabase(RpcController controller, StringProto request) throws ServiceException {
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getValue());
+
+      wlock.lock();
+      try {
+        if (!store.existDatabase(databaseName)) {
+          throw new NoSuchDatabaseException(databaseName);
+        }
+
+        store.dropDatabase(databaseName);
+        return ProtoUtil.TRUE;
+
+      } catch (Exception e) {
+        LOG.error(e);
+        throw new ServiceException(e);
+      } finally {
+        wlock.unlock();
+      }
+    }
+
+    @Override
+    public BoolProto existDatabase(RpcController controller, StringProto request) throws ServiceException {
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getValue());
+
+      rlock.lock();
+      try {
+        if (store.existDatabase(databaseName)) {
+          return ProtoUtil.TRUE;
+        } else {
+          return ProtoUtil.FALSE;
+        }
+      } catch (Exception e) {
+        LOG.error(e);
+        throw new ServiceException(e);
+      } finally {
+        rlock.unlock();
+      }
+    }
+
+    @Override
+    public StringListProto getAllDatabaseNames(RpcController controller, NullProto request) throws ServiceException {
+      rlock.lock();
+      try {
+        return ProtoUtil.convertStrings(store.getAllDatabaseNames());
+      } catch (Exception e) {
+        LOG.error(e);
+        throw new ServiceException(e);
+      } finally {
+        rlock.unlock();
+      }
+    }
+
+    @Override
+    public TableDescProto getTableDesc(RpcController controller,
+                                       TableIdentifierProto request) throws ServiceException {
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getDatabaseName());
+      String tableName = CatalogUtil.normalizeIdentifier(request.getTableName());
+
+      rlock.lock();
+      try {
+        boolean contain;
+
+        contain = store.existDatabase(databaseName);
+
+        if (contain) {
+          contain = store.existTable(databaseName, tableName);
+          if (contain) {
+            return store.getTable(databaseName, tableName);
+          } else {
+            throw new NoSuchTableException(databaseName);
+          }
+        } else {
+          throw new NoSuchDatabaseException(databaseName);
+        }
+      } catch (Exception e) {
+        LOG.error(e);
+        throw new ServiceException(e);
+      } finally {
+        rlock.unlock();
+      }
+    }
+
+    @Override
+    public StringListProto getAllTableNames(RpcController controller, StringProto request)
         throws ServiceException {
+
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getValue());
+
+      rlock.lock();
       try {
-        Iterator<String> iterator = store.getAllTableNames().iterator();
-        GetAllTableNamesResponse.Builder builder =
-            GetAllTableNamesResponse.newBuilder();
-        while (iterator.hasNext()) {
-          builder.addTableName(iterator.next());
+        if (store.existDatabase(databaseName)) {
+          return ProtoUtil.convertStrings(store.getAllTableNames(databaseName));
+        } else {
+          throw new NoSuchDatabaseException(databaseName);
         }
-        return builder.build();
       } catch (Exception e) {
-        // TODO - handle exception
         LOG.error(e);
-        return null;
+        throw new ServiceException(e);
+      } finally {
+        rlock.unlock();
       }
     }
 
@@ -249,37 +422,61 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public BoolProto addTable(RpcController controller, TableDescProto proto)
-        throws ServiceException {
+    public BoolProto createTable(RpcController controller, TableDescProto request)throws ServiceException {
+
+      String [] splitted =
+          CatalogUtil.splitFQTableName(CatalogUtil.normalizeIdentifier(request.getTableName()));
+
+      String databaseName = splitted[0];
+      String tableName = splitted[1];
 
       wlock.lock();
       try {
-        if (store.existTable(proto.getId().toLowerCase())) {
-          throw new AlreadyExistsTableException(proto.getId());
+
+        boolean contain = store.existDatabase(databaseName);
+
+        if (contain) {
+          if (store.existTable(databaseName, tableName)) {
+            throw new AlreadyExistsTableException(databaseName, tableName);
+          }
+
+          store.createTable(request);
+          LOG.info(String.format("relation \"%s\" is added to the catalog (%s)",
+              CatalogUtil.getCanonicalTableName(databaseName, tableName), bindAddressStr));
+        } else {
+          throw new NoSuchDatabaseException(databaseName);
         }
-        store.addTable(proto);
       } catch (Exception e) {
         LOG.error(e.getMessage(), e);
-        return BOOL_FALSE;
+        return ProtoUtil.FALSE;
       } finally {
         wlock.unlock();
-        LOG.info("Table " + proto.getId() + " is added to the catalog ("
-            + bindAddressStr + ")");
       }
 
-      return BOOL_TRUE;
+      return ProtoUtil.TRUE;
     }
 
     @Override
-    public BoolProto deleteTable(RpcController controller, StringProto name)
-        throws ServiceException {
+    public BoolProto dropTable(RpcController controller, TableIdentifierProto request) throws ServiceException {
+
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getDatabaseName());
+      String tableName = CatalogUtil.normalizeIdentifier(request.getTableName());
+
       wlock.lock();
       try {
-        String tableId = name.getValue().toLowerCase();
-        if (!store.existTable(tableId)) {
-          throw new NoSuchTableException(tableId);
+        boolean contain = store.existDatabase(databaseName);
+
+        if (contain) {
+          if (!store.existTable(databaseName, tableName)) {
+            throw new NoSuchTableException(databaseName, tableName);
+          }
+
+          store.dropTable(databaseName, tableName);
+          LOG.info(String.format("relation \"%s\" is deleted from the catalog (%s)",
+              CatalogUtil.getCanonicalTableName(databaseName, tableName), bindAddressStr));
+        } else {
+          throw new NoSuchDatabaseException(databaseName);
         }
-        store.deleteTable(tableId);
       } catch (Exception e) {
         LOG.error(e.getMessage(), e);
         return BOOL_FALSE;
@@ -291,76 +488,122 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public BoolProto existsTable(RpcController controller, StringProto name)
+    public BoolProto existsTable(RpcController controller, TableIdentifierProto request)
         throws ServiceException {
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getDatabaseName());
+      String tableName = CatalogUtil.normalizeIdentifier(request.getTableName());
+
+      rlock.lock();
       try {
-        String tableId = name.getValue().toLowerCase();
-        if (store.existTable(tableId)) {
-          return BOOL_TRUE;
+
+        boolean contain = store.existDatabase(databaseName);
+
+        if (contain) {
+          if (store.existTable(databaseName, tableName)) {
+            return BOOL_TRUE;
+          } else {
+            return BOOL_FALSE;
+          }
         } else {
-          return BOOL_FALSE;
+          throw new NoSuchDatabaseException(databaseName);
         }
       } catch (Exception e) {
         LOG.error(e);
         throw new ServiceException(e);
+      } finally {
+        rlock.unlock();
       }
+
     }
 
     @Override
     public PartitionMethodProto getPartitionMethodByTableName(RpcController controller,
-                                                              StringProto name)
+                                                              TableIdentifierProto request)
         throws ServiceException {
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getDatabaseName());
+      String tableName = CatalogUtil.normalizeIdentifier(request.getTableName());
+
       rlock.lock();
       try {
-        String tableId = name.getValue().toLowerCase();
-        return store.getPartitionMethod(tableId);
+        boolean contain;
+
+        contain = store.existDatabase(databaseName);
+
+        if (contain) {
+          contain = store.existTable(databaseName, tableName);
+          if (contain) {
+            if (store.existPartitionMethod(databaseName, tableName)) {
+              return store.getPartitionMethod(databaseName, tableName);
+            } else {
+              throw new NoPartitionedTableException(databaseName, tableName);
+            }
+          } else {
+            throw new NoSuchTableException(databaseName);
+          }
+        } else {
+          throw new NoSuchDatabaseException(databaseName);
+        }
       } catch (Exception e) {
-        // TODO - handle exception
         LOG.error(e);
-        return null;
+        throw new ServiceException(e);
       } finally {
         rlock.unlock();
       }
     }
 
     @Override
-    public BoolProto existPartitionMethod(RpcController controller, StringProto tableName)
+    public BoolProto existPartitionMethod(RpcController controller, TableIdentifierProto request)
         throws ServiceException {
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getDatabaseName());
+      String tableName = CatalogUtil.normalizeIdentifier(request.getTableName());
+
       rlock.lock();
       try {
-        String tableId = tableName.getValue().toLowerCase();
-        return BoolProto.newBuilder().setValue(
-            store.existPartitionMethod(tableId)).build();
+        boolean contain;
+
+        contain = store.existDatabase(databaseName);
+
+        if (contain) {
+          contain = store.existTable(databaseName, tableName);
+          if (contain) {
+            if (store.existPartitionMethod(databaseName, tableName)) {
+              return ProtoUtil.TRUE;
+            } else {
+              return ProtoUtil.FALSE;
+            }
+          } else {
+            throw new NoSuchTableException(databaseName);
+          }
+        } else {
+          throw new NoSuchDatabaseException(databaseName);
+        }
       } catch (Exception e) {
         LOG.error(e);
-        return BoolProto.newBuilder().setValue(false).build();
+        throw new ServiceException(e);
       } finally {
         rlock.unlock();
       }
     }
 
     @Override
-    public BoolProto delPartitionMethod(RpcController controller, StringProto request)
+    public BoolProto dropPartitionMethod(RpcController controller, TableIdentifierProto request)
         throws ServiceException {
-      return null;
+      return ProtoUtil.TRUE;
     }
 
     @Override
-    public BoolProto addPartitions(RpcController controller, PartitionsProto request)
-        throws ServiceException {
+    public BoolProto addPartitions(RpcController controller, PartitionsProto request) throws ServiceException {
 
-      return null;
+      return ProtoUtil.TRUE;
     }
 
     @Override
-    public BoolProto addPartition(RpcController controller, PartitionDescProto request)
-        throws ServiceException {
-      return null;
+    public BoolProto addPartition(RpcController controller, PartitionDescProto request) throws ServiceException {
+      return ProtoUtil.TRUE;
     }
 
     @Override
-    public PartitionDescProto getPartitionByPartitionName(RpcController controller,
-                                                          StringProto request)
+    public PartitionDescProto getPartitionByPartitionName(RpcController controller, StringProto request)
         throws ServiceException {
       return null;
     }
@@ -379,16 +622,18 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public BoolProto addIndex(RpcController controller, IndexDescProto indexDesc)
+    public BoolProto createIndex(RpcController controller, IndexDescProto indexDesc)
         throws ServiceException {
       rlock.lock();
       try {
-        if (store.existIndex(indexDesc.getName())) {
-          throw new AlreadyExistsIndexException(indexDesc.getName());
+        if (store.existIndexByName(
+            indexDesc.getTableIdentifier().getDatabaseName(),
+            indexDesc.getIndexName())) {
+          throw new AlreadyExistsIndexException(indexDesc.getIndexName());
         }
-        store.addIndex(indexDesc);
+        store.createIndex(indexDesc);
       } catch (Exception e) {
-        LOG.error("ERROR : cannot add index " + indexDesc.getName(), e);
+        LOG.error("ERROR : cannot add index " + indexDesc.getIndexName(), e);
         LOG.error(indexDesc);
         throw new ServiceException(e);
       } finally {
@@ -399,13 +644,14 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public BoolProto existIndexByName(RpcController controller,
-                                      StringProto indexName)
-        throws ServiceException {
+    public BoolProto existIndexByName(RpcController controller, IndexNameProto request) throws ServiceException {
+
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getDatabaseName());
+      String indexName = CatalogUtil.normalizeIdentifier(request.getIndexName());
+
       rlock.lock();
       try {
-        return BoolProto.newBuilder().setValue(
-            store.existIndex(indexName.getValue())).build();
+        return store.existIndexByName(databaseName, indexName) ? ProtoUtil.TRUE : ProtoUtil.FALSE;
       } catch (Exception e) {
         LOG.error(e);
         return BoolProto.newBuilder().setValue(false).build();
@@ -415,14 +661,18 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public BoolProto existIndex(RpcController controller,
-                                GetIndexRequest request)
+    public BoolProto existIndexByColumn(RpcController controller, GetIndexByColumnRequest request)
         throws ServiceException {
+
+      TableIdentifierProto identifier = request.getTableIdentifier();
+      String databaseName = CatalogUtil.normalizeIdentifier(identifier.getDatabaseName());
+      String tableName = CatalogUtil.normalizeIdentifier(identifier.getTableName());
+      String columnName = CatalogUtil.normalizeIdentifier(request.getColumnName());
+
       rlock.lock();
       try {
-        return BoolProto.newBuilder().setValue(
-            store.existIndex(request.getTableName(),
-                request.getColumnName())).build();
+        return store.existIndexByColumn(databaseName, tableName, columnName) ?
+            ProtoUtil.TRUE : ProtoUtil.FALSE;
       } catch (Exception e) {
         LOG.error(e);
         return BoolProto.newBuilder().setValue(false).build();
@@ -432,15 +682,18 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public IndexDescProto getIndexByName(RpcController controller,
-                                         StringProto indexName)
+    public IndexDescProto getIndexByName(RpcController controller, IndexNameProto request)
         throws ServiceException {
+
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getDatabaseName());
+      String indexName = CatalogUtil.normalizeIdentifier(request.getIndexName());
+
       rlock.lock();
       try {
-        if (!store.existIndex(indexName.getValue())) {
-          throw new NoSuchIndexException(indexName.getValue());
+        if (!store.existIndexByName(databaseName, indexName)) {
+          throw new NoSuchIndexException(databaseName, indexName);
         }
-        return store.getIndex(indexName.getValue());
+        return store.getIndexByName(databaseName, indexName);
       } catch (Exception e) {
         LOG.error("ERROR : cannot get index " + indexName, e);
         return null;
@@ -450,19 +703,22 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public IndexDescProto getIndex(RpcController controller,
-                                   GetIndexRequest request)
+    public IndexDescProto getIndexByColumn(RpcController controller, GetIndexByColumnRequest request)
         throws ServiceException {
+
+      TableIdentifierProto identifier = request.getTableIdentifier();
+      String databaseName = CatalogUtil.normalizeIdentifier(identifier.getDatabaseName());
+      String tableName = CatalogUtil.normalizeIdentifier(identifier.getTableName());
+      String columnName = CatalogUtil.normalizeIdentifier(request.getColumnName());
+
       rlock.lock();
       try {
-        if (!store.existIndex(request.getTableName())) {
-          throw new NoSuchIndexException(request.getTableName() + "."
-              + request.getColumnName());
+        if (!store.existIndexByColumn(databaseName, tableName, columnName)) {
+          throw new NoSuchIndexException(databaseName, columnName);
         }
-        return store.getIndex(request.getTableName(), request.getColumnName());
+        return store.getIndexByColumn(databaseName, tableName, columnName);
       } catch (Exception e) {
-        LOG.error("ERROR : cannot get index " + request.getTableName() + "."
-            + request.getColumnName(), e);
+        LOG.error("ERROR : cannot get index for " + tableName + "." + columnName, e);
         return null;
       } finally {
         rlock.unlock();
@@ -470,14 +726,18 @@ public class CatalogServer extends AbstractService {
     }
 
     @Override
-    public BoolProto delIndex(RpcController controller, StringProto indexName)
+    public BoolProto dropIndex(RpcController controller, IndexNameProto request)
         throws ServiceException {
+
+      String databaseName = CatalogUtil.normalizeIdentifier(request.getDatabaseName());
+      String indexName = CatalogUtil.normalizeIdentifier(request.getIndexName());
+
       wlock.lock();
       try {
-        if (!store.existIndex(indexName.getValue())) {
-          throw new NoSuchIndexException(indexName.getValue());
+        if (!store.existIndexByName(databaseName, indexName)) {
+          throw new NoSuchIndexException(indexName);
         }
-        store.delIndex(indexName.getValue());
+        store.dropIndex(databaseName, indexName);
       } catch (Exception e) {
         LOG.error(e);
       } finally {


[10/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 e384194..974ded9 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
@@ -31,21 +31,34 @@ import java.util.HashMap;
 import java.util.Map;
 
 public class DerbyStore extends AbstractDBStore {
+
+  /** 2014-03-20: First versioning */
+  private static final int DERBY_STORE_VERSION_2 = 2;
+  /** Before 2013-03-20 */
+  private static final int DERBY_STORE_VERSION_1 = 1;
   private static final String CATALOG_DRIVER="org.apache.derby.jdbc.EmbeddedDriver";
 
   protected String getCatalogDriverName(){
     return CATALOG_DRIVER;
   }
 
-  public DerbyStore(final Configuration conf)
-      throws InternalException {
+  public DerbyStore(final Configuration conf) throws InternalException {
     super(conf);
   }
 
+  public int getDriverVersion() {
+    return DERBY_STORE_VERSION_2;
+  }
+
   protected Connection createConnection(Configuration conf) throws SQLException {
     return DriverManager.getConnection(getCatalogUri());
   }
 
+  @Override
+  public String readSchemaFile(String filename) throws CatalogException {
+    return super.readSchemaFile("derby/" + filename);
+  }
+
   // TODO - DDL and index statements should be renamed
   protected void createBaseTable() throws CatalogException {
     Connection conn = null;
@@ -55,62 +68,79 @@ public class DerbyStore extends AbstractDBStore {
       conn = getConnection();
       stmt = conn.createStatement();
 
-      StringBuilder sql = new StringBuilder();
-
       //META
       if (!baseTableMaps.get(TB_META)) {
-        sql.append("CREATE TABLE ");
-        sql.append(TB_META);
-        sql.append(" (version int NOT NULL)");
+
+        String sql = super.readSchemaFile("common/meta.sql");
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.executeUpdate(sql.toString());
-        LOG.info("Table '" + TB_META + " is created.");
+
+        stmt.executeUpdate(sql);
+
+        LOG.info("Table '" + TB_META + "' is created.");
         baseTableMaps.put(TB_META, true);
       }
 
+      // TABLE SPACES
+      if (!baseTableMaps.get(TB_SPACES)) {
+
+        String sql = readSchemaFile("tablespaces.sql");
+
+        if (LOG.isDebugEnabled()) {
+          LOG.debug(sql);
+        }
+
+        stmt.executeUpdate(sql);
+
+        LOG.info("Table '" + TB_SPACES + "' is created.");
+        baseTableMaps.put(TB_SPACES, true);
+      }
+
+      // DATABASES
+      if (!baseTableMaps.get(TB_DATABASES)) {
+        String sql = readSchemaFile("databases.sql");
+        if (LOG.isDebugEnabled()) {
+          LOG.debug(sql);
+        }
+        stmt.addBatch(sql);
+
+        sql = readSchemaFile("databases_idx.sql");
+        if (LOG.isDebugEnabled()) {
+          LOG.debug(sql);
+        }
+        stmt.addBatch(sql);
+
+        stmt.executeBatch();
+        LOG.info("Table '" + TB_DATABASES + "' is created.");
+        baseTableMaps.put(TB_DATABASES, true);
+      }
+
       // TABLES
       if (!baseTableMaps.get(TB_TABLES)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ");
-        sql.append(TB_TABLES);
-        sql.append(" (");
-        sql.append("TID int NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),");
-        sql.append(C_TABLE_ID);
-        sql.append(" VARCHAR(255) NOT NULL CONSTRAINT TABLE_ID_UNIQ UNIQUE, ");
-        sql.append("path VARCHAR(1024), ");
-        sql.append("store_type CHAR(16), ");
-        sql.append("CONSTRAINT TABLES_PK PRIMARY KEY (TID)");
-        sql.append( ")");
 
+        String sql = readSchemaFile("tables.sql");
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
 
-        sql.delete(0, sql.length());
-        sql.append("CREATE UNIQUE INDEX idx_tables_tid on ");
-        sql.append(TB_TABLES);
-        sql.append(" (TID)");
 
+        sql = "CREATE UNIQUE INDEX idx_tables_tid on TABLES (TID)";
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
 
-        sql.delete(0, sql.length());
-        sql.append("CREATE UNIQUE INDEX idx_tables_name on ");
-        sql.append(TB_TABLES);
-        sql.append("(");
-        sql.append(C_TABLE_ID);
-        sql.append(")");
 
+
+        sql = "CREATE UNIQUE INDEX idx_tables_name on TABLES (TABLE_NAME)";
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
+
         stmt.executeBatch();
         LOG.info("Table '" + TB_TABLES + "' is created.");
         baseTableMaps.put(TB_TABLES, true);
@@ -118,42 +148,19 @@ public class DerbyStore extends AbstractDBStore {
 
       // COLUMNS
       if (!baseTableMaps.get(TB_COLUMNS)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ");
-        sql.append(TB_COLUMNS);
-        sql.append(" (");
-        sql.append("TID INT NOT NULL REFERENCES ");
-        sql.append(TB_TABLES);
-        sql.append(" (TID) ON DELETE CASCADE, ");
-        sql.append(C_TABLE_ID);
-        sql.append( " VARCHAR(255) NOT NULL REFERENCES ");
-        sql.append(TB_TABLES);
-        sql.append("(");
-        sql.append(C_TABLE_ID);
-        sql.append(") ON DELETE CASCADE, ");
-        sql.append("column_id INT NOT NULL,");
-        sql.append("column_name VARCHAR(255) NOT NULL, ");
-        sql.append("data_type CHAR(16), type_length INTEGER, ");
-        sql.append("CONSTRAINT C_COLUMN_ID UNIQUE (");
-        sql.append(C_TABLE_ID);
-        sql.append(", column_name))");
+        String sql = readSchemaFile("columns.sql");
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
 
-        sql.delete(0, sql.length());
-        sql.append( "CREATE UNIQUE INDEX idx_fk_columns_table_name on ");
-        sql.append(TB_COLUMNS);
-        sql.append("(");
-        sql.append(C_TABLE_ID);
-        sql.append(", column_name)");
+        sql = "CREATE UNIQUE INDEX idx_fk_columns_table_name on " + TB_COLUMNS + "(TID, COLUMN_NAME)";
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
         stmt.executeBatch();
         LOG.info("Table '" + TB_COLUMNS + " is created.");
         baseTableMaps.put(TB_COLUMNS, true);
@@ -161,104 +168,68 @@ public class DerbyStore extends AbstractDBStore {
 
       // OPTIONS
       if (!baseTableMaps.get(TB_OPTIONS)) {
-        sql.delete(0, sql.length());
-        sql.append( "CREATE TABLE ");
-        sql.append(TB_OPTIONS);
-        sql.append(" (").append(C_TABLE_ID);
-        sql.append(" VARCHAR(255) NOT NULL REFERENCES TABLES (");
-        sql.append(C_TABLE_ID).append(") ON DELETE CASCADE, ");
-        sql.append("key_ VARCHAR(255) NOT NULL, value_ VARCHAR(255) NOT NULL)");
+        String sql = readSchemaFile("table_properties.sql");
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
 
-        sql.delete(0, sql.length());
-        sql.append("CREATE INDEX idx_options_key on ");
-        sql.append(TB_OPTIONS).append( " (").append(C_TABLE_ID).append(")");
 
+        sql = "CREATE INDEX idx_options_key on " + TB_OPTIONS + "(TID)";
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
 
-        sql.delete(0, sql.length());
-        sql.append("CREATE INDEX idx_options_table_name on ").append(TB_OPTIONS);
-        sql.append("(" ).append(C_TABLE_ID).append(")");
-        if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
-        }
-        stmt.addBatch(sql.toString());
         stmt.executeBatch();
+
         LOG.info("Table '" + TB_OPTIONS + " is created.");
         baseTableMaps.put(TB_OPTIONS, true);
       }
 
       // INDEXES
       if (!baseTableMaps.get(TB_INDEXES)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_INDEXES).append("(");
-        sql.append( "index_name VARCHAR(255) NOT NULL PRIMARY KEY, ");
-        sql.append(C_TABLE_ID).append(" VARCHAR(255) NOT NULL REFERENCES TABLES (");
-        sql.append(C_TABLE_ID).append(") ");
-        sql.append("ON DELETE CASCADE, ");
-        sql.append("column_name VARCHAR(255) NOT NULL, ");
-        sql.append("data_type VARCHAR(255) NOT NULL, ");
-        sql.append("index_type CHAR(32) NOT NULL, ");
-        sql.append("is_unique BOOLEAN NOT NULL, ");
-        sql.append("is_clustered BOOLEAN NOT NULL, ");
-        sql.append("is_ascending BOOLEAN NOT NULL)");
+        String sql = readSchemaFile("indexes.sql");
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
 
-        sql.delete(0, sql.length());
-        sql.append("CREATE UNIQUE INDEX idx_indexes_key ON ");
-        sql.append(TB_INDEXES).append(" (index_name)");
+        sql = "CREATE UNIQUE INDEX idx_indexes_pk ON " + TB_INDEXES + "(" + COL_DATABASES_PK + ",index_name)";
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
 
-        sql.delete(0, sql.length());
-        sql.append("CREATE INDEX idx_indexes_columns ON ");
-        sql.append(TB_INDEXES).append(" (").append(C_TABLE_ID).append(", column_name)");
+        sql = "CREATE INDEX idx_indexes_columns ON " + TB_INDEXES + "(" + COL_DATABASES_PK + ",column_name)";
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
         stmt.executeBatch();
         LOG.info("Table '" + TB_INDEXES + "' is created.");
         baseTableMaps.put(TB_INDEXES, true);
       }
 
       if (!baseTableMaps.get(TB_STATISTICS)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_STATISTICS).append( "(");
-        sql.append(C_TABLE_ID).append(" VARCHAR(255) NOT NULL REFERENCES TABLES (");
-        sql.append(C_TABLE_ID).append(") ");
-        sql.append("ON DELETE CASCADE, ");
-        sql.append("num_rows BIGINT, ");
-        sql.append("num_bytes BIGINT)");
+        String sql = readSchemaFile("stats.sql");
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
+
 
-        sql.delete(0, sql.length());
-        sql.append("CREATE INDEX idx_stats_table_name ON ");
-        sql.append(TB_STATISTICS).append(" (").append(C_TABLE_ID).append(")");
+        sql = "CREATE UNIQUE INDEX idx_stats_table_name ON " + TB_STATISTICS + "(TID)";
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
         stmt.executeBatch();
         LOG.info("Table '" + TB_STATISTICS + "' is created.");
         baseTableMaps.put(TB_STATISTICS, true);
@@ -266,28 +237,19 @@ public class DerbyStore extends AbstractDBStore {
 
       // PARTITION_METHODS
       if (!baseTableMaps.get(TB_PARTITION_METHODS)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_PARTITION_METHODS).append(" (");
-        sql.append(C_TABLE_ID).append(" VARCHAR(255) NOT NULL REFERENCES TABLES (");
-        sql.append(C_TABLE_ID).append(") ");
-        sql.append("ON DELETE CASCADE, ");
-        sql.append("partition_type VARCHAR(10) NOT NULL,");
-        sql.append("expression VARCHAR(1024) NOT NULL,");
-        sql.append("expression_schema VARCHAR(1024) FOR BIT DATA NOT NULL)");
+        String sql = readSchemaFile("partition_methods.sql");
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
 
-        sql.delete(0, sql.length());
-        sql.append("CREATE INDEX idx_partition_methods_table_name ON ");
-        sql.append(TB_PARTITION_METHODS).append(" (").append(C_TABLE_ID).append(")");
 
+        sql = "CREATE INDEX idx_partition_methods_table_id ON " + TB_PARTITION_METHODS + "(TID)";
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
         stmt.executeBatch();
         LOG.info("Table '" + TB_PARTITION_METHODS + "' is created.");
         baseTableMaps.put(TB_PARTITION_METHODS, true);
@@ -295,67 +257,54 @@ public class DerbyStore extends AbstractDBStore {
 
       // PARTITIONS
       if (!baseTableMaps.get(TB_PARTTIONS)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_PARTTIONS).append("(");
-        sql.append("PID INT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),");
-        sql.append(C_TABLE_ID).append(" VARCHAR(255) NOT NULL REFERENCES TABLES (");
-        sql.append(C_TABLE_ID).append(")");
-        sql.append("ON DELETE CASCADE, ");
-        sql.append("partition_name VARCHAR(255), ");
-        sql.append("ordinal_position INT NOT NULL,");
-        sql.append("partition_value VARCHAR(1024),");
-        sql.append("path VARCHAR(1024),");
-        sql.append("cache_nodes VARCHAR(255), ");
-        sql.append(" CONSTRAINT PARTITION_PK PRIMARY KEY (PID))");
+        String sql = readSchemaFile("partitions.sql");
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
+
 
-        sql.delete(0, sql.length());
-        sql.append("CREATE INDEX idx_partitions_table_name ON ");
-        sql.append(TB_PARTTIONS).append(" (").append(C_TABLE_ID).append(")");
+        sql = "CREATE INDEX idx_partitions_table_name ON PARTITIONS(TID)";
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
-        stmt.addBatch(sql.toString());
+        stmt.addBatch(sql);
         stmt.executeBatch();
         LOG.info("Table '" + TB_PARTTIONS + "' is created.");
         baseTableMaps.put(TB_PARTTIONS, true);
       }
 
+      insertSchemaVersion();
+
     } catch (SQLException se) {
-      throw new CatalogException(se);
+      throw new CatalogException("failed to create base tables for Derby catalog store.", se);
     } finally {
-      CatalogUtil.closeQuietly(conn, stmt);
+      CatalogUtil.closeQuietly(stmt);
     }
   }
 
   @Override
   protected void dropBaseTable() throws CatalogException {
-    Connection conn = null;
+    Connection conn;
     Statement stmt = null;
     Map<String, Boolean> droppedTable = new HashMap<String, Boolean>();
 
     try {
       conn = getConnection();
       stmt = conn.createStatement();
-      StringBuilder sql = new StringBuilder();
 
       for(Map.Entry<String, Boolean> entry : baseTableMaps.entrySet()) {
         if(entry.getValue() && !entry.getKey().equals(TB_TABLES)) {
-          sql.delete(0, sql.length());
-          sql.append("DROP TABLE ").append(entry.getKey());
-          stmt.addBatch(sql.toString());
+          String sql = "DROP TABLE " + entry.getKey();
+          stmt.addBatch(sql);
           droppedTable.put(entry.getKey(), true);
         }
       }
       if(baseTableMaps.get(TB_TABLES)) {
-        sql.delete(0, sql.length());
-        sql.append("DROP TABLE ").append(TB_TABLES);
-        stmt.addBatch(sql.toString());
+        String sql = "DROP TABLE " + TB_TABLES;
+        stmt.addBatch(sql);
         droppedTable.put(TB_TABLES, true);
       }
       stmt.executeBatch();
@@ -366,15 +315,14 @@ public class DerbyStore extends AbstractDBStore {
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, stmt);
+      CatalogUtil.closeQuietly(stmt);
     }
   }
 
   @Override
   protected boolean isInitialized() throws CatalogException {
-    Connection conn = null;
+    Connection conn;
     ResultSet res = null;
-    int foundCount = 0;
 
     try {
       conn = getConnection();
@@ -382,6 +330,8 @@ public class DerbyStore extends AbstractDBStore {
           new String [] {"TABLE"});
 
       baseTableMaps.put(TB_META, false);
+      baseTableMaps.put(TB_SPACES, false);
+      baseTableMaps.put(TB_DATABASES, false);
       baseTableMaps.put(TB_TABLES, false);
       baseTableMaps.put(TB_COLUMNS, false);
       baseTableMaps.put(TB_OPTIONS, false);
@@ -396,7 +346,7 @@ public class DerbyStore extends AbstractDBStore {
     } catch (SQLException se){
       throw  new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, res);
+      CatalogUtil.closeQuietly(res);
     }
 
     for(Map.Entry<String, Boolean> entry : baseTableMaps.entrySet()) {
@@ -408,28 +358,6 @@ public class DerbyStore extends AbstractDBStore {
     return true;
   }
 
-  final boolean checkInternalTable(final String tableName) throws CatalogException {
-    Connection conn = null;
-    ResultSet res = null;
-    boolean found = false;
-
-    try {
-      conn = getConnection();
-      res = conn.getMetaData().getTables(null, null, null,
-          new String [] {"TABLE"});
-      while(res.next() && !found) {
-        if (tableName.equals(res.getString("TABLE_NAME")))
-          found = true;
-      }
-
-    } catch (SQLException se) {
-      throw new CatalogException(se);
-    } finally {
-      CatalogUtil.closeQuietly(conn, res);
-    }
-    return found;
-  }
-
 
   @Override
   public final void close() {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MemStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MemStore.java b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MemStore.java
index 1fef286..9fc9d2a 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MemStore.java
+++ b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MemStore.java
@@ -25,64 +25,134 @@ import com.google.common.collect.Maps;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.FunctionDesc;
-import org.apache.tajo.catalog.exception.CatalogException;
+import org.apache.tajo.catalog.exception.*;
 import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.IndexDescProto;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
+/**
+ * CatalogServer guarantees that all operations are thread-safe.
+ * So, we don't need to consider concurrency problem here.
+ */
 public class MemStore implements CatalogStore {
-  private final Map<String,CatalogProtos.TableDescProto> tables = Maps.newHashMap();
+  private final Map<String, String> tablespaces = Maps.newHashMap();
+  private final Map<String, Map<String, CatalogProtos.TableDescProto>> databases = Maps.newHashMap();
   private final Map<String, CatalogProtos.FunctionDescProto> functions = Maps.newHashMap();
-  private final Map<String, IndexDescProto> indexes = Maps.newHashMap();
-  private final Map<String, IndexDescProto> indexesByColumn = Maps.newHashMap();
+  private final Map<String, Map<String, IndexDescProto>> indexes = Maps.newHashMap();
+  private final Map<String, Map<String, IndexDescProto>> indexesByColumn = Maps.newHashMap();
   
   public MemStore(Configuration conf) {
   }
 
-  /* (non-Javadoc)
-   * @see java.io.Closeable#close()
-   */
   @Override
   public void close() throws IOException {
-    tables.clear();
+    databases.clear();
     functions.clear();
     indexes.clear();
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#addTable(TableDesc)
-   */
   @Override
-  public void addTable(CatalogProtos.TableDescProto desc) throws CatalogException {
-    synchronized(tables) {
-      String tableId = desc.getId().toLowerCase();
-      tables.put(tableId, desc);
+  public void createTablespace(String spaceName, String spaceUri) throws CatalogException {
+    if (tablespaces.containsKey(spaceName)) {
+      throw new AlreadyExistsTablespaceException(spaceName);
     }
+
+    tablespaces.put(spaceName, spaceUri);
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#existTable(java.lang.String)
-   */
   @Override
-  public boolean existTable(String name) throws CatalogException {
-    synchronized(tables) {
-      String tableId = name.toLowerCase();
-      return tables.containsKey(tableId);
+  public boolean existTablespace(String spaceName) throws CatalogException {
+    return tablespaces.containsKey(spaceName);
+  }
+
+  @Override
+  public void dropTablespace(String spaceName) throws CatalogException {
+    if (!tablespaces.containsKey(spaceName)) {
+      throw new NoSuchTablespaceException(spaceName);
     }
+    tablespaces.remove(spaceName);
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#deleteTable(java.lang.String)
+  @Override
+  public Collection<String> getAllTablespaceNames() throws CatalogException {
+    return tablespaces.keySet();
+  }
+
+  @Override
+  public void createDatabase(String databaseName, String tablespaceName) throws CatalogException {
+    if (databases.containsKey(databaseName)) {
+      throw new AlreadyExistsDatabaseException(databaseName);
+    }
+
+    databases.put(databaseName, new HashMap<String, CatalogProtos.TableDescProto>());
+  }
+
+  @Override
+  public boolean existDatabase(String databaseName) throws CatalogException {
+    return databases.containsKey(databaseName);
+  }
+
+  @Override
+  public void dropDatabase(String databaseName) throws CatalogException {
+    if (!databases.containsKey(databaseName)) {
+      throw new NoSuchDatabaseException(databaseName);
+    }
+    databases.remove(databaseName);
+  }
+
+  @Override
+  public Collection<String> getAllDatabaseNames() throws CatalogException {
+    return databases.keySet();
+  }
+
+  /**
+   * Get a database namespace from a Map instance.
    */
+  private <T> Map<String, T> checkAndGetDatabaseNS(final Map<String, Map<String, T>> databaseMap,
+                                                   String databaseName) {
+    if (databaseMap.containsKey(databaseName)) {
+      return databaseMap.get(databaseName);
+    } else {
+      throw new NoSuchDatabaseException(databaseName);
+    }
+  }
+
+  @Override
+  public void createTable(CatalogProtos.TableDescProto request) throws CatalogException {
+    String [] splitted = CatalogUtil.splitTableName(CatalogUtil.normalizeIdentifier(request.getTableName()));
+    if (splitted.length == 1) {
+      throw new IllegalArgumentException("createTable() requires a qualified table name, but it is \""
+          + request.getTableName() + "\".");
+    }
+    String databaseName = splitted[0];
+    String tableName = splitted[1];
+
+    Map<String, CatalogProtos.TableDescProto> database = checkAndGetDatabaseNS(databases, databaseName);
+
+    String tbName = CatalogUtil.normalizeIdentifier(tableName);
+    if (database.containsKey(tbName)) {
+      throw new AlreadyExistsTableException(tbName);
+    }
+    database.put(tbName, request);
+  }
+
+  @Override
+  public boolean existTable(String dbName, String tbName) throws CatalogException {
+    Map<String, CatalogProtos.TableDescProto> database = checkAndGetDatabaseNS(databases, dbName);
+
+    return database.containsKey(tbName);
+  }
+
   @Override
-  public void deleteTable(String name) throws CatalogException {
-    synchronized(tables) {
-      String tableId = name.toLowerCase();
-      tables.remove(tableId);
+  public void dropTable(String dbName, String tbName) throws CatalogException {
+    Map<String, CatalogProtos.TableDescProto> database = checkAndGetDatabaseNS(databases, dbName);
+
+    if (database.containsKey(tbName)) {
+      database.remove(tbName);
+    } else {
+      throw new NoSuchTableException(tbName);
     }
   }
 
@@ -90,24 +160,30 @@ public class MemStore implements CatalogStore {
    * @see CatalogStore#getTable(java.lang.String)
    */
   @Override
-  public CatalogProtos.TableDescProto getTable(String name) throws CatalogException {
-    String tableId = name.toLowerCase();
-    CatalogProtos.TableDescProto unqualified = tables.get(tableId);
-    if(unqualified == null)
-      return null;
-    CatalogProtos.TableDescProto.Builder builder = CatalogProtos.TableDescProto.newBuilder();
-    CatalogProtos.SchemaProto schemaProto = CatalogUtil.getQualfiedSchema(tableId, unqualified.getSchema());
-    builder.mergeFrom(unqualified);
-    builder.setSchema(schemaProto);
-    return builder.build();
+  public CatalogProtos.TableDescProto getTable(String databaseName, String tableName)
+      throws CatalogException {
+    Map<String, CatalogProtos.TableDescProto> database = checkAndGetDatabaseNS(databases, databaseName);
+
+    if (database.containsKey(tableName)) {
+      CatalogProtos.TableDescProto unqualified = database.get(tableName);
+      CatalogProtos.TableDescProto.Builder builder = CatalogProtos.TableDescProto.newBuilder();
+      CatalogProtos.SchemaProto schemaProto =
+          CatalogUtil.getQualfiedSchema(databaseName + "." + tableName, unqualified.getSchema());
+      builder.mergeFrom(unqualified);
+      builder.setSchema(schemaProto);
+      return builder.build();
+    } else {
+      throw new NoSuchTableException(tableName);
+    }
   }
 
   /* (non-Javadoc)
    * @see CatalogStore#getAllTableNames()
    */
   @Override
-  public List<String> getAllTableNames() throws CatalogException {
-    return new ArrayList<String>(tables.keySet());
+  public List<String> getAllTableNames(String databaseName) throws CatalogException {
+    Map<String, CatalogProtos.TableDescProto> database = checkAndGetDatabaseNS(databases, databaseName);
+    return new ArrayList<String>(database.keySet());
   }
 
   @Override
@@ -116,21 +192,33 @@ public class MemStore implements CatalogStore {
   }
 
   @Override
-  public CatalogProtos.PartitionMethodProto getPartitionMethod(String tableName) throws CatalogException {
-    String tableId = tableName.toLowerCase();
-    CatalogProtos.TableDescProto table = tables.get(tableId);
-    return (table != null && table.hasPartition()) ? table.getPartition() : null;
+  public CatalogProtos.PartitionMethodProto getPartitionMethod(String databaseName, String tableName)
+      throws CatalogException {
+    Map<String, CatalogProtos.TableDescProto> database = checkAndGetDatabaseNS(databases, databaseName);
+
+    if (database.containsKey(tableName)) {
+      CatalogProtos.TableDescProto table = database.get(tableName);
+      return table.hasPartition() ? table.getPartition() : null;
+    } else {
+      throw new NoSuchTableException(tableName);
+    }
   }
 
   @Override
-  public boolean existPartitionMethod(String tableName) throws CatalogException {
-    String tableId = tableName.toLowerCase();
-    CatalogProtos.TableDescProto table = tables.get(tableId);
-    return (table != null && table.hasPartition());
+  public boolean existPartitionMethod(String databaseName, String tableName)
+      throws CatalogException {
+    Map<String, CatalogProtos.TableDescProto> database = checkAndGetDatabaseNS(databases, databaseName);
+
+    if (database.containsKey(tableName)) {
+      CatalogProtos.TableDescProto table = database.get(tableName);
+      return table.hasPartition();
+    } else {
+      throw new NoSuchTableException(tableName);
+    }
   }
 
   @Override
-  public void delPartitionMethod(String tableName) throws CatalogException {
+  public void dropPartitionMethod(String databaseName, String tableName) throws CatalogException {
     throw new RuntimeException("not supported!");
   }
 
@@ -140,7 +228,8 @@ public class MemStore implements CatalogStore {
   }
 
   @Override
-  public void addPartition(CatalogProtos.PartitionDescProto partitionDesc) throws CatalogException {
+  public void addPartition(String databaseName, String tableName, CatalogProtos.PartitionDescProto
+      partitionDescProto) throws CatalogException {
     throw new RuntimeException("not supported!");
   }
 
@@ -160,105 +249,110 @@ public class MemStore implements CatalogStore {
   }
 
   @Override
-  public void delPartitions(String tableName) throws CatalogException {
+  public void dropPartitions(String tableName) throws CatalogException {
     throw new RuntimeException("not supported!");
   }
 
   /* (non-Javadoc)
-   * @see CatalogStore#addIndex(nta.catalog.proto.CatalogProtos.IndexDescProto)
+   * @see CatalogStore#createIndex(nta.catalog.proto.CatalogProtos.IndexDescProto)
    */
   @Override
-  public void addIndex(IndexDescProto proto) throws CatalogException {
-    synchronized(indexes) {
-      indexes.put(proto.getName(), proto);
-      indexesByColumn.put(proto.getTableId() + "." 
-          + CatalogUtil.extractSimpleName(proto.getColumn().getName()), proto);
+  public void createIndex(IndexDescProto proto) throws CatalogException {
+    final String databaseName = proto.getTableIdentifier().getDatabaseName();
+
+    Map<String, IndexDescProto> index = checkAndGetDatabaseNS(indexes, databaseName);
+    Map<String, IndexDescProto> indexByColumn = checkAndGetDatabaseNS(indexesByColumn, databaseName);
+
+    if (index.containsKey(proto.getIndexName())) {
+      throw new AlreadyExistsIndexException(proto.getIndexName());
     }
+
+    index.put(proto.getIndexName(), proto);
+    indexByColumn.put(proto.getTableIdentifier().getTableName() + "."
+        + CatalogUtil.extractSimpleName(proto.getColumn().getName()), proto);
   }
 
   /* (non-Javadoc)
-   * @see CatalogStore#delIndex(java.lang.String)
+   * @see CatalogStore#dropIndex(java.lang.String)
    */
   @Override
-  public void delIndex(String indexName) throws CatalogException {
-    synchronized(indexes) {
-      indexes.remove(indexName);
+  public void dropIndex(String databaseName, String indexName) throws CatalogException {
+    Map<String, IndexDescProto> index = checkAndGetDatabaseNS(indexes, databaseName);
+    if (!index.containsKey(indexName)) {
+      throw new NoSuchIndexException(indexName);
     }
+    index.remove(indexName);
   }
 
   /* (non-Javadoc)
-   * @see CatalogStore#getIndex(java.lang.String)
+   * @see CatalogStore#getIndexByName(java.lang.String)
    */
   @Override
-  public IndexDescProto getIndex(String indexName) throws CatalogException {
-    return indexes.get(indexName);
+  public IndexDescProto getIndexByName(String databaseName, String indexName) throws CatalogException {
+    Map<String, IndexDescProto> index = checkAndGetDatabaseNS(indexes, databaseName);
+    if (!index.containsKey(indexName)) {
+      throw new NoSuchIndexException(indexName);
+    }
+
+    return index.get(indexName);
   }
 
   /* (non-Javadoc)
-   * @see CatalogStore#getIndex(java.lang.String, java.lang.String)
+   * @see CatalogStore#getIndexByName(java.lang.String, java.lang.String)
    */
   @Override
-  public IndexDescProto getIndex(String tableName, String columnName) throws CatalogException {
-    return indexesByColumn.get(tableName+"."+columnName);
+  public IndexDescProto getIndexByColumn(String databaseName, String tableName, String columnName)
+      throws CatalogException {
+
+    Map<String, IndexDescProto> indexByColumn = checkAndGetDatabaseNS(indexesByColumn, databaseName);
+    if (!indexByColumn.containsKey(columnName)) {
+      throw new NoSuchIndexException(columnName);
+    }
+
+    return indexByColumn.get(columnName);
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#existIndex(java.lang.String)
-   */
   @Override
-  public boolean existIndex(String indexName) throws CatalogException {
-    return indexes.containsKey(indexName);
+  public boolean existIndexByName(String databaseName, String indexName) throws CatalogException {
+    Map<String, IndexDescProto> index = checkAndGetDatabaseNS(indexes, databaseName);
+    return index.containsKey(indexName);
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#existIndex(java.lang.String, java.lang.String)
-   */
   @Override
-  public boolean existIndex(String tableName, String columnName) throws CatalogException {
-    return indexesByColumn.containsKey(tableName + "." + columnName);
+  public boolean existIndexByColumn(String databaseName, String tableName, String columnName)
+      throws CatalogException {
+    Map<String, IndexDescProto> indexByColumn = checkAndGetDatabaseNS(indexesByColumn, databaseName);
+    return indexByColumn.containsKey(columnName);
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#getIndexes(java.lang.String)
-   */
   @Override
-  public IndexDescProto[] getIndexes(String tableName) throws CatalogException {
+  public IndexDescProto[] getIndexes(String databaseName, String tableName) throws CatalogException {
     List<IndexDescProto> protos = new ArrayList<IndexDescProto>();
-    for (IndexDescProto proto : indexesByColumn.values()) {
-      if (proto.getTableId().equals(tableName)) {
+    Map<String, IndexDescProto> indexByColumn = checkAndGetDatabaseNS(indexesByColumn, databaseName);
+    for (IndexDescProto proto : indexByColumn.values()) {
+      if (proto.equals(tableName)) {
         protos.add(proto);
       }
     }
+
     return protos.toArray(new IndexDescProto[protos.size()]);
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#addFunction(FunctionDesc)
-   */
   @Override
   public void addFunction(FunctionDesc func) throws CatalogException {
     // to be implemented
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#deleteFunction(FunctionDesc)
-   */
   @Override
   public void deleteFunction(FunctionDesc func) throws CatalogException {
     // to be implemented
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#existFunction(FunctionDesc)
-   */
   @Override
   public void existFunction(FunctionDesc func) throws CatalogException {
     // to be implemented
   }
 
-  /* (non-Javadoc)
-   * @see CatalogStore#getAllFunctionNames()
-   */
   @Override
   public List<String> getAllFunctionNames() throws CatalogException {
     // to be implemented

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MySQLStore.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MySQLStore.java b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MySQLStore.java
index bbcdb72..849afc8 100644
--- a/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MySQLStore.java
+++ b/tajo-catalog/tajo-catalog-server/src/main/java/org/apache/tajo/catalog/store/MySQLStore.java
@@ -31,16 +31,25 @@ import java.util.HashMap;
 import java.util.Map;
 
 public class MySQLStore extends AbstractDBStore  {
+  /** 2014-03-20: First versioning */
+  private static final int MYSQL_CATALOG_STORE_VERSION_2 = 2;
+  /** Before 2013-03-20 */
+  private static final int MYSQL_CATALOG_STORE_VERSION_1 = 1;
 
   private static final String CATALOG_DRIVER = "com.mysql.jdbc.Driver";
   protected String getCatalogDriverName(){
     return CATALOG_DRIVER;
   }
 
-  public MySQLStore(Configuration conf) throws InternalException {
+  public MySQLStore(final Configuration conf) throws InternalException {
     super(conf);
   }
 
+  @Override
+  public int getDriverVersion() {
+    return MYSQL_CATALOG_STORE_VERSION_2;
+  }
+
   protected Connection createConnection(Configuration conf) throws SQLException {
     Connection con = DriverManager.getConnection(getCatalogUri(), this.connectionId,
         this.connectionPassword);
@@ -48,6 +57,11 @@ public class MySQLStore extends AbstractDBStore  {
     return con;
   }
 
+  @Override
+  public String readSchemaFile(String filename) throws CatalogException {
+    return super.readSchemaFile("mysql/" + filename);
+  }
+
   // TODO - DDL and index statements should be renamed
   @Override
   protected void createBaseTable() throws CatalogException {
@@ -58,10 +72,10 @@ public class MySQLStore extends AbstractDBStore  {
       conn = getConnection();
       stmt = conn.createStatement();
 
-      StringBuilder sql = new StringBuilder();
+
       // META
       if (!baseTableMaps.get(TB_META)) {
-        sql.append("CREATE TABLE ").append(TB_META).append(" (version int NOT NULL)");
+        String sql = super.readSchemaFile("common/meta.sql");
 
         if (LOG.isDebugEnabled()) {
           LOG.debug(sql.toString());
@@ -72,40 +86,47 @@ public class MySQLStore extends AbstractDBStore  {
         baseTableMaps.put(TB_META, true);
       }
 
-      // TABLES
-      if (!baseTableMaps.get(TB_TABLES)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_TABLES).append("(");
-        sql.append("TID int NOT NULL AUTO_INCREMENT PRIMARY KEY, ");
-        sql.append(C_TABLE_ID).append(" VARCHAR(255) NOT NULL UNIQUE, ");
-        sql.append("path TEXT, ").append("store_type CHAR(16)").append(")");
+      // TABLE SPACES
+      if (!baseTableMaps.get(TB_SPACES)) {
+        String sql = readSchemaFile("tablespaces.sql");
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
 
-        stmt.executeUpdate(sql.toString());
+        stmt.executeUpdate(sql);
+
+        LOG.info("Table '" + TB_SPACES + "' is created.");
+        baseTableMaps.put(TB_SPACES, true);
+      }
+
+      // DATABASES
+      if (!baseTableMaps.get(TB_DATABASES)) {
+        String sql = readSchemaFile("databases.sql");
+        if (LOG.isDebugEnabled()) {
+          LOG.debug(sql);
+        }
+        LOG.info("Table '" + TB_DATABASES + "' is created.");
+        baseTableMaps.put(TB_DATABASES, true);
+        stmt.executeUpdate(sql);
+      }
+
+      // TABLES
+      if (!baseTableMaps.get(TB_TABLES)) {
+        String sql = readSchemaFile("tables.sql");
+        if (LOG.isDebugEnabled()) {
+          LOG.debug(sql);
+        }
+        stmt.executeUpdate(sql);
         LOG.info("Table '" + TB_TABLES + "' is created.");
         baseTableMaps.put(TB_TABLES, true);
       }
 
       // COLUMNS
       if (!baseTableMaps.get(TB_COLUMNS)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_COLUMNS).append("(");
-        sql.append("TID INT NOT NULL, ");
-        sql.append(C_TABLE_ID).append(" VARCHAR(255) NOT NULL,");
-        sql.append("column_id INT NOT NULL,");
-        sql.append("column_name VARCHAR(255) NOT NULL, ");
-        sql.append("data_type CHAR(16), ");
-        sql.append("type_length INTEGER, ");
-        sql.append("UNIQUE KEY(").append(C_TABLE_ID).append(", column_name),");
-        sql.append("FOREIGN KEY(TID) REFERENCES ").append(TB_TABLES).append("(TID) ON DELETE CASCADE,");
-        sql.append("FOREIGN KEY(").append(C_TABLE_ID).append(") REFERENCES ");
-        sql.append(TB_TABLES).append("(").append(C_TABLE_ID).append(") ON DELETE CASCADE)");
-
+        String sql = readSchemaFile("columns.sql");
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
 
         stmt.executeUpdate(sql.toString());
@@ -115,14 +136,7 @@ public class MySQLStore extends AbstractDBStore  {
 
       // OPTIONS
       if (!baseTableMaps.get(TB_OPTIONS)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_OPTIONS).append("(");
-        sql.append(C_TABLE_ID).append( " VARCHAR(255) NOT NULL,");
-        sql.append("key_ VARCHAR(255) NOT NULL, value_ VARCHAR(255) NOT NULL,");
-        sql.append("INDEX(").append(C_TABLE_ID).append(", key_),");
-        sql.append("FOREIGN KEY(").append(C_TABLE_ID);
-        sql.append(") REFERENCES ").append(TB_TABLES);
-        sql.append("(").append(C_TABLE_ID).append(") ON DELETE CASCADE)");
+        String sql = readSchemaFile("table_properties.sql");
 
         if (LOG.isDebugEnabled()) {
           LOG.debug(sql.toString());
@@ -135,20 +149,7 @@ public class MySQLStore extends AbstractDBStore  {
 
       // INDEXES
       if (!baseTableMaps.get(TB_INDEXES)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_INDEXES).append("(");
-        sql.append("index_name VARCHAR(255) NOT NULL PRIMARY KEY, ");
-        sql.append(C_TABLE_ID).append(" VARCHAR(255) NOT NULL,");
-        sql.append("column_name VARCHAR(255) NOT NULL, ");
-        sql.append("data_type VARCHAR(255) NOT NULL, ");
-        sql.append("index_type CHAR(32) NOT NULL, ");
-        sql.append("is_unique BOOLEAN NOT NULL, ");
-        sql.append("is_clustered BOOLEAN NOT NULL, ");
-        sql.append("is_ascending BOOLEAN NOT NULL,");
-        sql.append("INDEX(").append(C_TABLE_ID).append(", column_name),");
-        sql.append("FOREIGN KEY(").append(C_TABLE_ID);
-        sql.append(") REFERENCES ").append(TB_TABLES);
-        sql.append("(").append(C_TABLE_ID).append(") ON DELETE CASCADE)");
+        String sql = readSchemaFile("indexes.sql");
 
         if (LOG.isDebugEnabled()) {
           LOG.debug(sql.toString());
@@ -160,15 +161,7 @@ public class MySQLStore extends AbstractDBStore  {
       }
 
       if (!baseTableMaps.get(TB_STATISTICS)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_STATISTICS).append("(");
-        sql.append(C_TABLE_ID).append(" VARCHAR(255) NOT NULL,");
-        sql.append("num_rows BIGINT, ");
-        sql.append("num_bytes BIGINT,");
-        sql.append("INDEX(").append(C_TABLE_ID).append("),");
-        sql.append("FOREIGN KEY(").append(C_TABLE_ID);
-        sql.append(") REFERENCES ").append(TB_TABLES);
-        sql.append("(").append(C_TABLE_ID).append(") ON DELETE CASCADE)");
+        String sql = readSchemaFile("stats.sql");
 
         if (LOG.isDebugEnabled()) {
           LOG.debug(sql.toString());
@@ -181,40 +174,20 @@ public class MySQLStore extends AbstractDBStore  {
 
       // PARTITION_METHODS
       if (!baseTableMaps.get(TB_PARTITION_METHODS)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_PARTITION_METHODS).append("(");
-        sql.append(C_TABLE_ID).append(" VARCHAR(255) PRIMARY KEY,");
-        sql.append("partition_type VARCHAR(10) NOT NULL,");
-        sql.append("expression TEXT NOT NULL,");
-        sql.append("expression_schema VARBINARY(1024) NOT NULL, ");
-        sql.append("FOREIGN KEY(").append(C_TABLE_ID);
-        sql.append(") REFERENCES ").append(TB_TABLES);
-        sql.append("(").append(C_TABLE_ID).append(") ON DELETE CASCADE)");
+        String sql = readSchemaFile("partition_methods.sql");
 
         if (LOG.isDebugEnabled()) {
-          LOG.debug(sql.toString());
+          LOG.debug(sql);
         }
 
-        stmt.executeUpdate(sql.toString());
+        stmt.executeUpdate(sql);
         LOG.info("Table '" + TB_PARTITION_METHODS + "' is created.");
         baseTableMaps.put(TB_PARTITION_METHODS, true);
       }
 
       // PARTITIONS
       if (!baseTableMaps.get(TB_PARTTIONS)) {
-        sql.delete(0, sql.length());
-        sql.append("CREATE TABLE ").append(TB_PARTTIONS).append("(");
-        sql.append("PID int NOT NULL AUTO_INCREMENT PRIMARY KEY, ");
-        sql.append(C_TABLE_ID).append( " VARCHAR(255) NOT NULL,");
-        sql.append("partition_name VARCHAR(255), ");
-        sql.append("ordinal_position INT NOT NULL,");
-        sql.append("partition_value TEXT,");
-        sql.append("path TEXT,");
-        sql.append("cache_nodes VARCHAR(255), ");
-        sql.append("UNIQUE KEY(").append(C_TABLE_ID).append(", partition_name),");
-        sql.append("FOREIGN KEY(").append(C_TABLE_ID);
-        sql.append(") REFERENCES ").append(TB_TABLES);
-        sql.append("(").append(C_TABLE_ID).append(") ON DELETE CASCADE)");
+        String sql = readSchemaFile("partitions.sql");
 
         if (LOG.isDebugEnabled()) {
           LOG.debug(sql.toString());
@@ -224,10 +197,13 @@ public class MySQLStore extends AbstractDBStore  {
         LOG.info("Table '" + TB_PARTTIONS + "' is created.");
         baseTableMaps.put(TB_PARTTIONS, true);
       }
+
+      insertSchemaVersion();
+
     } catch (SQLException se) {
-      throw new CatalogException(se);
+      throw new CatalogException("failed to create base tables for MySQL catalog store", se);
     } finally {
-      CatalogUtil.closeQuietly(conn, stmt);
+      CatalogUtil.closeQuietly(stmt);
     }
   }
 
@@ -264,13 +240,13 @@ public class MySQLStore extends AbstractDBStore  {
     } catch (SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, stmt);
+      CatalogUtil.closeQuietly(stmt);
     }
   }
 
   @Override
   protected boolean isInitialized() throws CatalogException {
-    Connection conn = null;
+    Connection conn;
     ResultSet res = null;
 
     try {
@@ -279,6 +255,8 @@ public class MySQLStore extends AbstractDBStore  {
           new String[]{"TABLE"});
 
       baseTableMaps.put(TB_META, false);
+      baseTableMaps.put(TB_SPACES, false);
+      baseTableMaps.put(TB_DATABASES, false);
       baseTableMaps.put(TB_TABLES, false);
       baseTableMaps.put(TB_COLUMNS, false);
       baseTableMaps.put(TB_OPTIONS, false);
@@ -305,10 +283,9 @@ public class MySQLStore extends AbstractDBStore  {
     } catch(SQLException se) {
       throw new CatalogException(se);
     } finally {
-      CatalogUtil.closeQuietly(conn, res);
+      CatalogUtil.closeQuietly(res);
     }
 
     return  true;
   }
-
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/common/meta.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/common/meta.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/common/meta.sql
new file mode 100644
index 0000000..066c5f8
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/common/meta.sql
@@ -0,0 +1 @@
+CREATE TABLE META (VERSION INT NOT NULL)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/columns.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/columns.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/columns.sql
new file mode 100644
index 0000000..e274f3c
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/columns.sql
@@ -0,0 +1,8 @@
+CREATE TABLE COLUMNS (
+  TID INT NOT NULL REFERENCES TABLES (TID) ON DELETE CASCADE,
+  COLUMN_NAME VARCHAR(128) NOT NULL,
+  ORDINAL_POSITION INTEGER NOT NULL,
+  DATA_TYPE CHAR(16),
+  TYPE_LENGTH INTEGER,
+  CONSTRAINT COLUMNS_PK PRIMARY KEY (TID, COLUMN_NAME)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/databases.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/databases.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/databases.sql
new file mode 100644
index 0000000..8cabb14
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/databases.sql
@@ -0,0 +1,6 @@
+CREATE TABLE DATABASES_ (
+  DB_ID int NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  DB_NAME VARCHAR(128) NOT NULL CONSTRAINT DB_NAME_UNIQ UNIQUE,
+  SPACE_ID INT NOT NULL REFERENCES TABLESPACES (SPACE_ID),
+  CONSTRAINT DATABASES_PK PRIMARY KEY (DB_ID)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/databases_idx.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/databases_idx.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/databases_idx.sql
new file mode 100644
index 0000000..c9c7d4e
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/databases_idx.sql
@@ -0,0 +1 @@
+CREATE UNIQUE INDEX idx_database_db_id on DATABASES_ (DB_ID)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/indexes.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/indexes.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/indexes.sql
new file mode 100644
index 0000000..c4cfc25
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/indexes.sql
@@ -0,0 +1,12 @@
+CREATE TABLE INDEXES (
+  DB_ID INT NOT NULL REFERENCES DATABASES_ (DB_ID) ON DELETE CASCADE,
+  TID INT NOT NULL REFERENCES TABLES (TID) ON DELETE CASCADE,
+  INDEX_NAME VARCHAR(128) NOT NULL,
+  COLUMN_NAME VARCHAR(128) NOT NULL,
+  DATA_TYPE VARCHAR(128) NOT NULL,
+  INDEX_TYPE CHAR(32) NOT NULL,
+  IS_UNIQUE BOOLEAN NOT NULL,
+  IS_CLUSTERED BOOLEAN NOT NULL,
+  IS_ASCENDING BOOLEAN NOT NULL,
+  CONSTRAINT C_INDEXES_PK PRIMARY KEY (DB_ID, INDEX_NAME)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/partition_methods.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/partition_methods.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/partition_methods.sql
new file mode 100644
index 0000000..4ad4c60
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/partition_methods.sql
@@ -0,0 +1,6 @@
+CREATE TABLE PARTITION_METHODS (
+  TID INT NOT NULL REFERENCES TABLES (TID) ON DELETE CASCADE,
+  PARTITION_TYPE VARCHAR(10) NOT NULL,
+  EXPRESSION VARCHAR(1024) NOT NULL,
+  EXPRESSION_SCHEMA VARCHAR(1024) FOR BIT DATA NOT NULL
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/partitions.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/partitions.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/partitions.sql
new file mode 100644
index 0000000..24ee422
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/partitions.sql
@@ -0,0 +1,10 @@
+CREATE TABLE PARTITIONS (
+  PID INT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  TID INT NOT NULL REFERENCES TABLES (TID) ON DELETE CASCADE,
+  PARTITION_NAME VARCHAR(255),
+  ORDINAL_POSITION INT NOT NULL,
+  PARTITION_VALUE VARCHAR(1024),
+  PATH VARCHAR(1024),
+  CONSTRAINT C_PARTITION_PK PRIMARY KEY (PID),
+  CONSTRAINT C_PARTITION_UNIQUE UNIQUE (TID, PARTITION_NAME)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/stats.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/stats.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/stats.sql
new file mode 100644
index 0000000..bba8ee7
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/stats.sql
@@ -0,0 +1,6 @@
+CREATE TABLE STATS (
+  TID INT NOT NULL PRIMARY KEY,
+  NUM_ROWS BIGINT,
+  NUM_BYTES BIGINT,
+  FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/table_properties.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/table_properties.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/table_properties.sql
new file mode 100644
index 0000000..2b2d89a
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/table_properties.sql
@@ -0,0 +1,6 @@
+CREATE TABLE OPTIONS (
+  TID INT NOT NULL REFERENCES TABLES (TID) ON DELETE CASCADE,
+  KEY_ VARCHAR(255) NOT NULL,
+  VALUE_ VARCHAR(255) NOT NULL,
+  CONSTRAINT C_OPTIONS_UNIQUE UNIQUE (TID, KEY_, VALUE_)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/tables.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/tables.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/tables.sql
new file mode 100644
index 0000000..2fe0e7d
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/tables.sql
@@ -0,0 +1,10 @@
+CREATE TABLE TABLES (
+  TID int NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  DB_ID int NOT NULL REFERENCES DATABASES_ (DB_ID),
+  TABLE_NAME VARCHAR(128) NOT NULL,
+  TABLE_TYPE VARCHAR(128) NOT NULL,
+  PATH VARCHAR(4096),
+  STORE_TYPE CHAR(16),
+  CONSTRAINT TABLES_PK PRIMARY KEY (TID),
+  CONSTRAINT C_TABLE_ID_UNIQ UNIQUE (TABLE_NAME)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/tablespaces.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/tablespaces.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/tablespaces.sql
new file mode 100644
index 0000000..c2af3ae
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/derby/tablespaces.sql
@@ -0,0 +1,7 @@
+CREATE TABLE TABLESPACES (
+  SPACE_ID int NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  SPACE_NAME VARCHAR(128) NOT NULL CONSTRAINT SPACE_UNIQUE UNIQUE,
+  SPACE_HANDLER VARCHAR (1024) DEFAULT 'HDFS',
+  SPACE_URI VARCHAR (4096) NOT NULL,
+  CONSTRAINT C_SPACE_PK PRIMARY KEY (SPACE_ID)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/columns.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/columns.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/columns.sql
new file mode 100644
index 0000000..51e2a1b
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/columns.sql
@@ -0,0 +1,9 @@
+CREATE TABLE COLUMNS (
+  TID INT NOT NULL,
+  COLUMN_NAME VARCHAR(255) NOT NULL,
+  ORDINAL_POSITION INT NOT NULL,
+  DATA_TYPE CHAR(16),
+  TYPE_LENGTH INTEGER,
+  PRIMARY KEY (TID, COLUMN_NAME),
+  FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/databases.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/databases.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/databases.sql
new file mode 100644
index 0000000..e07e916
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/databases.sql
@@ -0,0 +1,7 @@
+CREATE TABLE DATABASES_ (
+  DB_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+  DB_NAME VARCHAR(128) NOT NULL UNIQUE,
+  SPACE_ID INT NOT NULL,
+  FOREIGN KEY (SPACE_ID) REFERENCES TABLESPACES (SPACE_ID),
+  UNIQUE INDEX IDX_NAME (DB_NAME)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/indexes.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/indexes.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/indexes.sql
new file mode 100644
index 0000000..62feb36
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/indexes.sql
@@ -0,0 +1,16 @@
+CREATE TABLE INDEXES (
+  DB_ID INT NOT NULL,
+  TID INT NOT NULL,
+  INDEX_NAME VARCHAR(128) NOT NULL,
+  COLUMN_NAME VARCHAR(128) NOT NULL,
+  DATA_TYPE VARCHAR(128) NOT NULL,
+  INDEX_TYPE CHAR(32) NOT NULL,
+  IS_UNIQUE BOOLEAN NOT NULL,
+  IS_CLUSTERED BOOLEAN NOT NULL,
+  IS_ASCENDING BOOLEAN NOT NULL,
+  PRIMARY KEY (DB_ID, INDEX_NAME),
+  FOREIGN KEY (DB_ID) REFERENCES DATABASES_ (DB_ID) ON DELETE CASCADE,
+  FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE,
+  UNIQUE INDEX IDX_DB_ID_NAME (DB_ID, INDEX_NAME),
+  INDEX IDX_TID_COLUMN_NAME (TID, COLUMN_NAME)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/partition_methods.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/partition_methods.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/partition_methods.sql
new file mode 100644
index 0000000..060c4c8
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/partition_methods.sql
@@ -0,0 +1,7 @@
+CREATE TABLE PARTITION_METHODS (
+  TID INT NOT NULL PRIMARY KEY,
+  PARTITION_TYPE VARCHAR(10) NOT NULL,
+  EXPRESSION VARCHAR(1024) NOT NULL,
+  EXPRESSION_SCHEMA VARCHAR(1024) NOT NULL,
+  FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/partitions.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/partitions.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/partitions.sql
new file mode 100644
index 0000000..428f5a4
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/partitions.sql
@@ -0,0 +1,12 @@
+CREATE TABLE PARTITIONS (
+  PID INT NOT NULL PRIMARY KEY,
+  TID INT NOT NULL,
+  PARTITION_NAME VARCHAR(128),
+  ORDINAL_POSITION INT NOT NULL,
+  PARTITION_VALUE VARCHAR(1024),
+  PATH VARCHAR(4096),
+  FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE,
+  CONSTRAINT C_PARTITION_UNIQUE UNIQUE (TID, PARTITION_NAME),
+  INDEX IDX_TID (TID),
+  UNIQUE INDEX IDX_TID_NAME (TID, PARTITION_NAME)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/stats.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/stats.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/stats.sql
new file mode 100644
index 0000000..bba8ee7
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/stats.sql
@@ -0,0 +1,6 @@
+CREATE TABLE STATS (
+  TID INT NOT NULL PRIMARY KEY,
+  NUM_ROWS BIGINT,
+  NUM_BYTES BIGINT,
+  FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/table_properties.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/table_properties.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/table_properties.sql
new file mode 100644
index 0000000..78e281e
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/table_properties.sql
@@ -0,0 +1,7 @@
+CREATE TABLE OPTIONS (
+  TID INT NOT NULL,
+  KEY_ VARCHAR(255) NOT NULL,
+  VALUE_ VARCHAR(255) NOT NULL,
+  PRIMARY KEY (TID, KEY_),
+  FOREIGN KEY (TID) REFERENCES TABLES (TID) ON DELETE CASCADE
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/tables.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/tables.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/tables.sql
new file mode 100644
index 0000000..98c0c94
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/tables.sql
@@ -0,0 +1,11 @@
+CREATE TABLE TABLES (
+  TID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+  DB_ID INT NOT NULL,
+  TABLE_NAME VARCHAR(128) NOT NULL UNIQUE,
+  TABLE_TYPE VARCHAR(128) NOT NULL,
+  PATH VARCHAR(4096),
+  STORE_TYPE CHAR(16),
+  FOREIGN KEY (DB_ID) REFERENCES DATABASES_ (DB_ID),
+  INDEX IDX_DB_ID (DB_ID),
+  UNIQUE INDEX IDX_TABLE_ID (TABLE_NAME)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/tablespaces.sql
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/tablespaces.sql b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/tablespaces.sql
new file mode 100644
index 0000000..f2e2299
--- /dev/null
+++ b/tajo-catalog/tajo-catalog-server/src/main/resources/schemas/mysql/tablespaces.sql
@@ -0,0 +1,7 @@
+CREATE TABLE TABLESPACES (
+  SPACE_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+  SPACE_NAME VARCHAR(128) NOT NULL UNIQUE,
+  SPACE_HANDLER VARCHAR (1024) DEFAULT 'HDFS',
+  SPACE_URI VARCHAR (4096) NOT NULL,
+  UNIQUE INDEX IDX_NAME (SPACE_NAME)
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/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 08905dd..cfae15d 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
@@ -18,7 +18,10 @@
 
 package org.apache.tajo.catalog;
 
+import com.google.common.collect.Sets;
 import org.apache.hadoop.fs.Path;
+import org.apache.tajo.TajoConstants;
+import org.apache.tajo.catalog.exception.CatalogException;
 import org.apache.tajo.catalog.exception.NoSuchFunctionException;
 import org.apache.tajo.catalog.function.Function;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
@@ -26,16 +29,22 @@ import org.apache.tajo.catalog.proto.CatalogProtos;
 import org.apache.tajo.catalog.proto.CatalogProtos.FunctionType;
 import org.apache.tajo.catalog.proto.CatalogProtos.IndexMethod;
 import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
+import org.apache.tajo.catalog.store.DerbyStore;
+import org.apache.tajo.catalog.store.MySQLStore;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.util.CommonTestingUtil;
+import org.apache.tajo.util.TUtil;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 import java.io.IOException;
+import java.util.*;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.catalog.CatalogConstants.CATALOG_URI;
 import static org.junit.Assert.*;
 
 public class TestCatalog {
@@ -50,18 +59,53 @@ public class TestCatalog {
 
 	@BeforeClass
 	public static void setUp() throws Exception {
-    TajoConf conf = new TajoConf();
+    final String HCATALOG_CLASS_NAME = "org.apache.tajo.catalog.store.HCatalogStore";
+
+    String driverClass = System.getProperty(CatalogConstants.STORE_CLASS);
+
+    // here, we don't choose HCatalogStore due to some dependency problems.
+    if (driverClass == null || driverClass.equals(HCATALOG_CLASS_NAME)) {
+      driverClass = DerbyStore.class.getCanonicalName();
+    }
+    String catalogURI = System.getProperty(CatalogConstants.CATALOG_URI);
+    if (catalogURI == null) {
+      Path path = CommonTestingUtil.getTestDir();
+      catalogURI = String.format("jdbc:derby:%s/db;create=true", path.toUri().getPath());
+    }
+    String connectionId = System.getProperty(CatalogConstants.CONNECTION_ID);
+    String password = System.getProperty(CatalogConstants.CONNECTION_PASSWORD);
 
-    conf.set(CatalogConstants.CATALOG_URI, "jdbc:derby:target/test-data/TestCatalog/db;create=true");
+    TajoConf conf = new TajoConf();
+    conf.set(CatalogConstants.STORE_CLASS, driverClass);
+    conf.set(CATALOG_URI, catalogURI);
     conf.setVar(TajoConf.ConfVars.CATALOG_ADDRESS, "127.0.0.1:0");
 
+    // MySQLStore requires password
+    if (driverClass.equals(MySQLStore.class.getCanonicalName())) {
+      if (connectionId == null) {
+        throw new CatalogException(String.format("%s driver requires %s", driverClass, CatalogConstants.CONNECTION_ID));
+      }
+      conf.set(CatalogConstants.CONNECTION_ID, connectionId);
+      if (password != null) {
+        conf.set(CatalogConstants.CONNECTION_PASSWORD, password);
+      }
+    }
+
+    Path defaultTableSpace = CommonTestingUtil.getTestDir();
+
 	  server = new CatalogServer();
     server.init(conf);
     server.start();
     catalog = new LocalCatalogWrapper(server);
+    if (!catalog.existTablespace(TajoConstants.DEFAULT_TABLESPACE_NAME)) {
+      catalog.createTablespace(TajoConstants.DEFAULT_TABLESPACE_NAME, defaultTableSpace.toUri().toString());
+    }
+    if (!catalog.existDatabase(DEFAULT_DATABASE_NAME)) {
+      catalog.createDatabase(DEFAULT_DATABASE_NAME, TajoConstants.DEFAULT_TABLESPACE_NAME);
+    }
 
-    for(String table : catalog.getAllTableNames()){
-      catalog.deleteTable(table);
+    for(String table : catalog.getAllTableNames(DEFAULT_DATABASE_NAME)) {
+      catalog.dropTable(table);
     }
 	}
 	
@@ -69,6 +113,161 @@ public class TestCatalog {
 	public static void tearDown() throws IOException {
 	  server.stop();
 	}
+
+  @Test
+  public void testCreateAndDropDatabases() throws Exception {
+    assertFalse(catalog.existDatabase("testCreateAndDropDatabases"));
+    assertTrue(catalog.createDatabase("testCreateAndDropDatabases", TajoConstants.DEFAULT_TABLESPACE_NAME));
+    assertTrue(catalog.existDatabase("testCreateAndDropDatabases"));
+    assertTrue(catalog.dropDatabase("testCreateAndDropDatabases"));
+  }
+
+  @Test
+  public void testCreateAndDropManyDatabases() throws Exception {
+    List<String> createdDatabases = new ArrayList<String>();
+    String namePrefix = "database_";
+    final int NUM = 10;
+    for (int i = 0; i < NUM; i++) {
+      String databaseName = namePrefix + i;
+      assertFalse(catalog.existDatabase(databaseName));
+      assertTrue(catalog.createDatabase(databaseName, TajoConstants.DEFAULT_TABLESPACE_NAME));
+      assertTrue(catalog.existDatabase(databaseName));
+      createdDatabases.add(databaseName);
+    }
+
+    Collection<String> allDatabaseNames = catalog.getAllDatabaseNames();
+    for (String databaseName : allDatabaseNames) {
+      assertTrue(databaseName.equals(DEFAULT_DATABASE_NAME) || createdDatabases.contains(databaseName));
+    }
+    // additional one is 'default' database.
+    assertEquals(NUM + 1, allDatabaseNames.size());
+
+    Collections.shuffle(createdDatabases);
+    for (String tobeDropped : createdDatabases) {
+      assertTrue(catalog.existDatabase(tobeDropped));
+      assertTrue(catalog.dropDatabase(tobeDropped));
+      assertFalse(catalog.existDatabase(tobeDropped));
+    }
+  }
+
+  private TableDesc createMockupTable(String databaseName, String tableName) throws IOException {
+    schema1 = new Schema();
+    schema1.addColumn(FieldName1, Type.BLOB);
+    schema1.addColumn(FieldName2, Type.INT4);
+    schema1.addColumn(FieldName3, Type.INT8);
+    Path path = new Path(CommonTestingUtil.getTestDir(), tableName);
+    TableDesc table = new TableDesc(
+        CatalogUtil.buildFQName(databaseName, tableName),
+        schema1,
+        new TableMeta(StoreType.CSV, new Options()),
+        path, true);
+    return table;
+  }
+
+  @Test
+  public void testCreateAndDropTable() throws Exception {
+    assertTrue(catalog.createDatabase("tmpdb1", TajoConstants.DEFAULT_TABLESPACE_NAME));
+    assertTrue(catalog.existDatabase("tmpdb1"));
+    assertTrue(catalog.createDatabase("tmpdb2", TajoConstants.DEFAULT_TABLESPACE_NAME));
+    assertTrue(catalog.existDatabase("tmpdb2"));
+
+    TableDesc table1 = createMockupTable("tmpdb1", "table1");
+    assertTrue(catalog.createTable(table1));
+
+    TableDesc table2 = createMockupTable("tmpdb2", "table2");
+    assertTrue(catalog.createTable(table2));
+
+    Set<String> tmpdb1 = Sets.newHashSet(catalog.getAllTableNames("tmpdb1"));
+    assertEquals(1, tmpdb1.size());
+    assertTrue(tmpdb1.contains("table1"));
+
+
+    Set<String> tmpdb2 = Sets.newHashSet(catalog.getAllTableNames("tmpdb2"));
+    assertEquals(1, tmpdb2.size());
+    assertTrue(tmpdb2.contains("table2"));
+
+    assertTrue(catalog.dropDatabase("tmpdb1"));
+    assertFalse(catalog.existDatabase("tmpdb1"));
+
+    tmpdb2 = Sets.newHashSet(catalog.getAllTableNames("tmpdb2"));
+    assertEquals(1, tmpdb2.size());
+    assertTrue(tmpdb2.contains("table2"));
+
+    assertTrue(catalog.dropDatabase("tmpdb2"));
+    assertFalse(catalog.existDatabase("tmpdb2"));
+  }
+
+  static String dbPrefix = "db_";
+  static String tablePrefix = "tb_";
+  static final int DB_NUM = 5;
+  static final int TABLE_NUM_PER_DB = 3;
+  static final int TOTAL_TABLE_NUM = DB_NUM * TABLE_NUM_PER_DB;
+
+  private Map<String, List<String>> createBaseDatabaseAndTables() throws IOException {
+
+    Map<String, List<String>> createdDatabaseAndTablesMap = new HashMap<String, List<String>>();
+
+    // add and divide all tables to multiple databases in a round robin manner
+    for (int tableId = 0; tableId < TOTAL_TABLE_NUM; tableId++) {
+      int dbIdx = tableId % DB_NUM;
+      String databaseName = dbPrefix + dbIdx;
+
+      if (!catalog.existDatabase(databaseName)) {
+        assertTrue(catalog.createDatabase(databaseName, TajoConstants.DEFAULT_TABLESPACE_NAME));
+      }
+
+      String tableName = tablePrefix + tableId;
+      TableDesc table = createMockupTable(databaseName, tableName);
+      assertTrue(catalog.createTable(table));
+
+      TUtil.putToNestedList(createdDatabaseAndTablesMap, databaseName, tableName);
+    }
+
+    // checking all tables for each database
+    for (int dbIdx = 0; dbIdx < DB_NUM; dbIdx++) {
+      String databaseName = dbPrefix + dbIdx;
+
+      Collection<String> tableNames = catalog.getAllTableNames(databaseName);
+      assertTrue(createdDatabaseAndTablesMap.containsKey(databaseName));
+
+      assertEquals(createdDatabaseAndTablesMap.get(databaseName).size(), tableNames.size());
+      for (String tableName : tableNames) {
+        assertTrue(createdDatabaseAndTablesMap.get(databaseName).contains(tableName));
+      }
+    }
+
+    return createdDatabaseAndTablesMap;
+  }
+
+  @Test
+  public void testDropDatabaseWithAllTables() throws Exception {
+    Map<String, List<String>> createdTablesMap = createBaseDatabaseAndTables();
+
+    // Each time we drop one database, check all databases and their tables.
+    Iterator<String> it = new ArrayList<String>(createdTablesMap.keySet()).iterator();
+    while(it.hasNext()) {
+      // drop one database
+      String databaseName = it.next();
+      assertTrue(catalog.existDatabase(databaseName));
+      catalog.dropDatabase(databaseName);
+      createdTablesMap.remove(databaseName);
+
+      // check all tables which belong to other databases
+      for (Map.Entry<String, List<String>> entry : createdTablesMap.entrySet()) {
+        assertTrue(catalog.existDatabase(entry.getKey()));
+
+        // checking all tables for this database
+        Collection<String> tablesForThisDatabase = catalog.getAllTableNames(entry.getKey());
+        assertEquals(createdTablesMap.get(entry.getKey()).size(), tablesForThisDatabase.size());
+        for (String tableName : tablesForThisDatabase) {
+          assertTrue(createdTablesMap.get(entry.getKey()).contains(CatalogUtil.extractSimpleName(tableName)));
+        }
+      }
+    }
+
+    // Finally, only default database will remain. So, its result is 1.
+    assertEquals(1, catalog.getAllDatabaseNames().size());
+  }
 	
 	@Test
 	public void testGetTable() throws Exception {
@@ -77,76 +276,78 @@ public class TestCatalog {
 		schema1.addColumn(FieldName2, Type.INT4);
 		schema1.addColumn(FieldName3, Type.INT8);
     Path path = new Path(CommonTestingUtil.getTestDir(), "table1");
-    TableDesc meta = CatalogUtil.newTableDesc(
-        "getTable",
+    TableDesc meta = new TableDesc(
+        CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "getTable"),
         schema1,
         StoreType.CSV,
         new Options(),
         path);
 
-		assertFalse(catalog.existsTable("getTable"));
-    catalog.addTable(meta);
-    assertTrue(catalog.existsTable("getTable"));
+		assertFalse(catalog.existsTable(DEFAULT_DATABASE_NAME, "getTable"));
+    catalog.createTable(meta);
+    assertTrue(catalog.existsTable(DEFAULT_DATABASE_NAME, "getTable"));
 
-    catalog.deleteTable("getTable");
-    assertFalse(catalog.existsTable("getTable"));
+    catalog.dropTable(CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "getTable"));
+    assertFalse(catalog.existsTable(DEFAULT_DATABASE_NAME, "getTable"));
 	}
 
-	@Test
-	public void testAddTableNoName() throws Exception {
-	  schema1 = new Schema();
-    schema1.addColumn(FieldName1, Type.BLOB);
-    schema1.addColumn(FieldName2, Type.INT4);
-    schema1.addColumn(FieldName3, Type.INT8);
-    
-	  TableMeta info = CatalogUtil.newTableMeta(StoreType.CSV);
-	  TableDesc desc = new TableDesc();
-	  desc.setMeta(info);
-
-    assertFalse(catalog.addTable(desc));
-  }
-
   static IndexDesc desc1;
   static IndexDesc desc2;
   static IndexDesc desc3;
 
   static {
     desc1 = new IndexDesc(
-        "idx_test", "indexed", new Column("id", Type.INT4),
+        "idx_test", DEFAULT_DATABASE_NAME, "indexed", new Column("id", Type.INT4),
         IndexMethod.TWO_LEVEL_BIN_TREE, true, true, true);
 
     desc2 = new IndexDesc(
-        "idx_test2", "indexed", new Column("score", Type.FLOAT8),
+        "idx_test2", DEFAULT_DATABASE_NAME, "indexed", new Column("score", Type.FLOAT8),
         IndexMethod.TWO_LEVEL_BIN_TREE, false, false, false);
 
     desc3 = new IndexDesc(
-        "idx_test", "indexed", new Column("id", Type.INT4),
+        "idx_test", DEFAULT_DATABASE_NAME, "indexed", new Column("id", Type.INT4),
         IndexMethod.TWO_LEVEL_BIN_TREE, true, true, true);
   }
+
+  public static TableDesc prepareTable() throws IOException {
+    Schema schema = new Schema();
+    schema.addColumn("indexed.id", Type.INT4)
+        .addColumn("indexed.name", Type.TEXT)
+        .addColumn("indexed.age", Type.INT4)
+        .addColumn("indexed.score", Type.FLOAT8);
+
+    String tableName = "indexed";
+
+    TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV);
+    return new TableDesc(
+        CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, tableName), schema, meta,
+        new Path(CommonTestingUtil.getTestDir(), "indexed"));
+  }
 	
 	@Test
 	public void testAddAndDelIndex() throws Exception {
-	  TableDesc desc = TestDBStore.prepareTable();
-	  assertTrue(catalog.addTable(desc));
+	  TableDesc desc = prepareTable();
+	  assertTrue(catalog.createTable(desc));
 	  
-	  assertFalse(catalog.existIndex(desc1.getName()));
-	  assertFalse(catalog.existIndex("indexed", "id"));
-	  catalog.addIndex(desc1);
-	  assertTrue(catalog.existIndex(desc1.getName()));
-	  assertTrue(catalog.existIndex("indexed", "id"));
+	  assertFalse(catalog.existIndexByName("db1", desc1.getIndexName()));
+	  assertFalse(catalog.existIndexByColumn(DEFAULT_DATABASE_NAME, "indexed", "id"));
+	  catalog.createIndex(desc1);
+	  assertTrue(catalog.existIndexByName(DEFAULT_DATABASE_NAME, desc1.getIndexName()));
+	  assertTrue(catalog.existIndexByColumn(DEFAULT_DATABASE_NAME, "indexed", "id"));
+
+
+	  assertFalse(catalog.existIndexByName(DEFAULT_DATABASE_NAME, desc2.getIndexName()));
+	  assertFalse(catalog.existIndexByColumn(DEFAULT_DATABASE_NAME, "indexed", "score"));
+	  catalog.createIndex(desc2);
+	  assertTrue(catalog.existIndexByName(DEFAULT_DATABASE_NAME, desc2.getIndexName()));
+	  assertTrue(catalog.existIndexByColumn(DEFAULT_DATABASE_NAME, "indexed", "score"));
 	  
-	  assertFalse(catalog.existIndex(desc2.getName()));
-	  assertFalse(catalog.existIndex("indexed", "score"));
-	  catalog.addIndex(desc2);
-	  assertTrue(catalog.existIndex(desc2.getName()));
-	  assertTrue(catalog.existIndex("indexed", "score"));
+	  catalog.dropIndex(DEFAULT_DATABASE_NAME, desc1.getIndexName());
+	  assertFalse(catalog.existIndexByName(DEFAULT_DATABASE_NAME, desc1.getIndexName()));
+	  catalog.dropIndex(DEFAULT_DATABASE_NAME, desc2.getIndexName());
+	  assertFalse(catalog.existIndexByName(DEFAULT_DATABASE_NAME, desc2.getIndexName()));
 	  
-	  catalog.deleteIndex(desc1.getName());
-	  assertFalse(catalog.existIndex(desc1.getName()));
-	  catalog.deleteIndex(desc2.getName());
-	  assertFalse(catalog.existIndex(desc2.getName()));
-	  
-	  catalog.deleteTable(desc.getName());
+	  catalog.dropTable(desc.getName());
     assertFalse(catalog.existsTable(desc.getName()));
   }
 	
@@ -253,24 +454,26 @@ public class TestCatalog {
         .addColumn("age", Type.INT4)
         .addColumn("score", Type.FLOAT8);
 
-    String tableName = "addedtable";
+    String tableName = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "addedtable");
     Options opts = new Options();
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
+
     Schema partSchema = new Schema();
     partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.HASH);
 
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
+    PartitionMethodDesc partitionDesc =
+        new PartitionMethodDesc(DEFAULT_DATABASE_NAME, tableName,
+            CatalogProtos.PartitionType.HASH, "id", partSchema);
+
+    TableDesc desc =
+        new TableDesc(tableName, schema, meta,
+            new Path(CommonTestingUtil.getTestDir(), "addedtable"));
     desc.setPartitionMethod(partitionDesc);
 
     assertFalse(catalog.existsTable(tableName));
-    catalog.addTable(desc);
+    catalog.createTable(desc);
     assertTrue(catalog.existsTable(tableName));
     TableDesc retrieved = catalog.getTableDesc(tableName);
 
@@ -278,7 +481,7 @@ public class TestCatalog {
     assertEquals(retrieved.getPartitionMethod().getPartitionType(), CatalogProtos.PartitionType.HASH);
     assertEquals(retrieved.getPartitionMethod().getExpressionSchema().getColumn(0).getSimpleName(), "id");
 
-    catalog.deleteTable(tableName);
+    catalog.dropTable(tableName);
     assertFalse(catalog.existsTable(tableName));
   }
 
@@ -291,24 +494,24 @@ public class TestCatalog {
         .addColumn("age", Type.INT4)
         .addColumn("score", Type.FLOAT8);
 
-    String tableName = "addedtable";
+    String tableName = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "addedtable");
     Options opts = new Options();
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
     Schema partSchema = new Schema();
     partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.HASH);
+    PartitionMethodDesc partitionDesc =
+        new PartitionMethodDesc(DEFAULT_DATABASE_NAME, tableName,
+            CatalogProtos.PartitionType.HASH, "id", partSchema);
 
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
+    TableDesc desc =
+        new TableDesc(tableName, schema, meta,
+            new Path(CommonTestingUtil.getTestDir(), "addedtable"));
     desc.setPartitionMethod(partitionDesc);
 
     assertFalse(catalog.existsTable(tableName));
-    catalog.addTable(desc);
+    catalog.createTable(desc);
     assertTrue(catalog.existsTable(tableName));
 
     TableDesc retrieved = catalog.getTableDesc(tableName);
@@ -317,7 +520,7 @@ public class TestCatalog {
     assertEquals(retrieved.getPartitionMethod().getPartitionType(), CatalogProtos.PartitionType.HASH);
     assertEquals(retrieved.getPartitionMethod().getExpressionSchema().getColumn(0).getSimpleName(), "id");
 
-    catalog.deleteTable(tableName);
+    catalog.dropTable(tableName);
     assertFalse(catalog.existsTable(tableName));
   }
 
@@ -329,23 +532,23 @@ public class TestCatalog {
         .addColumn("age", Type.INT4)
         .addColumn("score", Type.FLOAT8);
 
-    String tableName = "addedtable";
+    String tableName = CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "addedtable");
     Options opts = new Options();
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
     Schema partSchema = new Schema();
     partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.LIST);
+    PartitionMethodDesc partitionDesc =
+        new PartitionMethodDesc(DEFAULT_DATABASE_NAME, tableName,
+            CatalogProtos.PartitionType.LIST, "id", partSchema);
 
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
+    TableDesc desc =
+        new TableDesc(tableName, schema, meta,
+            new Path(CommonTestingUtil.getTestDir(), "addedtable"));
     desc.setPartitionMethod(partitionDesc);
     assertFalse(catalog.existsTable(tableName));
-    catalog.addTable(desc);
+    catalog.createTable(desc);
     assertTrue(catalog.existsTable(tableName));
 
     TableDesc retrieved = catalog.getTableDesc(tableName);
@@ -354,7 +557,7 @@ public class TestCatalog {
     assertEquals(retrieved.getPartitionMethod().getPartitionType(), CatalogProtos.PartitionType.LIST);
     assertEquals(retrieved.getPartitionMethod().getExpressionSchema().getColumn(0).getSimpleName(), "id");
 
-    catalog.deleteTable(tableName);
+    catalog.dropTable(tableName);
     assertFalse(catalog.existsTable(tableName));
   }
 
@@ -366,24 +569,23 @@ public class TestCatalog {
         .addColumn("age", Type.INT4)
         .addColumn("score", Type.FLOAT8);
 
-    String tableName = "addedtable";
+    String tableName = CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, "addedtable");
     Options opts = new Options();
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
     Schema partSchema = new Schema();
     partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.RANGE);
+    PartitionMethodDesc partitionDesc =
+        new PartitionMethodDesc(DEFAULT_DATABASE_NAME, tableName, CatalogProtos.PartitionType.RANGE,
+            "id", partSchema);
 
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
+    TableDesc desc =
+        new TableDesc(tableName, schema, meta,
+            new Path(CommonTestingUtil.getTestDir(), "addedtable"));
     desc.setPartitionMethod(partitionDesc);
     assertFalse(catalog.existsTable(tableName));
-    catalog.addTable(desc);
+    catalog.createTable(desc);
     assertTrue(catalog.existsTable(tableName));
 
     TableDesc retrieved = catalog.getTableDesc(tableName);
@@ -392,7 +594,7 @@ public class TestCatalog {
     assertEquals(retrieved.getPartitionMethod().getPartitionType(), CatalogProtos.PartitionType.RANGE);
     assertEquals(retrieved.getPartitionMethod().getExpressionSchema().getColumn(0).getSimpleName(), "id");
 
-    catalog.deleteTable(tableName);
+    catalog.dropTable(tableName);
     assertFalse(catalog.existsTable(tableName));
   }
 
@@ -404,23 +606,24 @@ public class TestCatalog {
         .addColumn("age", Type.INT4)
         .addColumn("score", Type.FLOAT8);
 
-    String tableName = "addedtable";
+    String tableName = CatalogUtil.buildFQName(DEFAULT_DATABASE_NAME, "addedtable");
     Options opts = new Options();
     opts.put("file.delimiter", ",");
     TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV, opts);
 
-    PartitionMethodDesc partitionDesc = new PartitionMethodDesc();
-    partitionDesc.setTableId(tableName);
-    partitionDesc.setExpression("id");
     Schema partSchema = new Schema();
     partSchema.addColumn("id", Type.INT4);
-    partitionDesc.setExpressionSchema(partSchema);
-    partitionDesc.setPartitionType(CatalogProtos.PartitionType.COLUMN);
 
-    TableDesc desc = new TableDesc(tableName, schema, meta, new Path(CommonTestingUtil.getTestDir(), "addedtable"));
+    PartitionMethodDesc partitionDesc =
+        new PartitionMethodDesc(DEFAULT_DATABASE_NAME, tableName,
+            CatalogProtos.PartitionType.COLUMN, "id", partSchema);
+
+    TableDesc desc =
+        new TableDesc(tableName, schema, meta,
+            new Path(CommonTestingUtil.getTestDir(), "addedtable"));
     desc.setPartitionMethod(partitionDesc);
     assertFalse(catalog.existsTable(tableName));
-    catalog.addTable(desc);
+    catalog.createTable(desc);
     assertTrue(catalog.existsTable(tableName));
 
     TableDesc retrieved = catalog.getTableDesc(tableName);
@@ -429,8 +632,7 @@ public class TestCatalog {
     assertEquals(retrieved.getPartitionMethod().getPartitionType(), CatalogProtos.PartitionType.COLUMN);
     assertEquals(retrieved.getPartitionMethod().getExpressionSchema().getColumn(0).getSimpleName(), "id");
 
-    catalog.deleteTable(tableName);
+    catalog.dropTable(tableName);
     assertFalse(catalog.existsTable(tableName));
   }
-
 }


[07/13] TAJO-353: Add Database support to Tajo. (hyunsik)

Posted by hy...@apache.org.
http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java
index 305548c..bb8192f 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVerifier.java
@@ -24,10 +24,11 @@ import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.conf.TajoConf;
 import org.apache.tajo.engine.planner.logical.*;
+import org.apache.tajo.master.session.Session;
 
 import java.util.Stack;
 
-public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationState, LogicalNode> {
+public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<LogicalPlanVerifier.Context, LogicalNode> {
   private TajoConf conf;
   private CatalogService catalog;
 
@@ -36,6 +37,22 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
     this.catalog = catalog;
   }
 
+  public static class Context {
+    Session session;
+    VerificationState state;
+
+    public Context(Session session, VerificationState state) {
+      this.session = session;
+      this.state = state;
+    }
+  }
+
+  public VerificationState verify(Session session, VerificationState state, LogicalPlan plan) throws PlanningException {
+    Context context = new Context(session, state);
+    visit(context, plan, plan.getRootBlock());
+    return context.state;
+  }
+
   /**
    * It checks if an output schema of a projectable node and target's output data types are equivalent to each other.
    */
@@ -62,12 +79,12 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitProjection(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitProjection(Context state, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                      ProjectionNode node, Stack<LogicalNode> stack) throws PlanningException {
     super.visitProjection(state, plan, block, node, stack);
 
     for (Target target : node.getTargets()) {
-      ExprsVerifier.verify(state, node, target.getEvalTree());
+      ExprsVerifier.verify(state.state, node, target.getEvalTree());
     }
 
     verifyProjectableOutputSchema(node);
@@ -76,42 +93,42 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitLimit(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitLimit(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                 LimitNode node, Stack<LogicalNode> stack) throws PlanningException {
-    super.visitLimit(state, plan, block, node, stack);
+    super.visitLimit(context, plan, block, node, stack);
 
     if (node.getFetchFirstNum() < 0) {
-      state.addVerification("LIMIT must not be negative");
+      context.state.addVerification("LIMIT must not be negative");
     }
 
     return node;
   }
 
   @Override
-  public LogicalNode visitGroupBy(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitGroupBy(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                   GroupbyNode node, Stack<LogicalNode> stack) throws PlanningException {
-    super.visitGroupBy(state, plan, block, node, stack);
+    super.visitGroupBy(context, plan, block, node, stack);
 
     verifyProjectableOutputSchema(node);
     return node;
   }
 
   @Override
-  public LogicalNode visitFilter(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitFilter(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                  SelectionNode node, Stack<LogicalNode> stack) throws PlanningException {
-    visit(state, plan, block, node.getChild(), stack);
-    ExprsVerifier.verify(state, node, node.getQual());
+    visit(context, plan, block, node.getChild(), stack);
+    ExprsVerifier.verify(context.state, node, node.getQual());
     return node;
   }
 
   @Override
-  public LogicalNode visitJoin(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block, JoinNode node,
+  public LogicalNode visitJoin(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, JoinNode node,
                                Stack<LogicalNode> stack) throws PlanningException {
-    visit(state, plan, block, node.getLeftChild(), stack);
-    visit(state, plan, block, node.getRightChild(), stack);
+    visit(context, plan, block, node.getLeftChild(), stack);
+    visit(context, plan, block, node.getRightChild(), stack);
 
     if (node.hasJoinQual()) {
-      ExprsVerifier.verify(state, node, node.getJoinQual());
+      ExprsVerifier.verify(context.state, node, node.getJoinQual());
     }
 
     verifyProjectableOutputSchema(node);
@@ -143,40 +160,40 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitUnion(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitUnion(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                 UnionNode node, Stack<LogicalNode> stack) throws PlanningException {
-    super.visitUnion(state, plan, block, node, stack);
-    verifySetStatement(state, node);
+    super.visitUnion(context, plan, block, node, stack);
+    verifySetStatement(context.state, node);
     return node;
   }
 
   @Override
-  public LogicalNode visitExcept(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitExcept(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                  ExceptNode node, Stack<LogicalNode> stack) throws PlanningException {
-    super.visitExcept(state, plan, block, node, stack);
-    verifySetStatement(state, node);
+    super.visitExcept(context, plan, block, node, stack);
+    verifySetStatement(context.state, node);
     return node;
   }
 
   @Override
-  public LogicalNode visitIntersect(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitIntersect(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                     IntersectNode node, Stack<LogicalNode> stack) throws PlanningException {
-    super.visitIntersect(state, plan, block, node, stack);
-    verifySetStatement(state, node);
+    super.visitIntersect(context, plan, block, node, stack);
+    verifySetStatement(context.state, node);
     return node;
   }
 
   @Override
-  public LogicalNode visitScan(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode node,
+  public LogicalNode visitScan(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block, ScanNode node,
                                Stack<LogicalNode> stack) throws PlanningException {
     if (node.hasTargets()) {
       for (Target target : node.getTargets()) {
-        ExprsVerifier.verify(state, node, target.getEvalTree());
+        ExprsVerifier.verify(context.state, node, target.getEvalTree());
       }
     }
 
     if (node.hasQual()) {
-      ExprsVerifier.verify(state, node, node.getQual());
+      ExprsVerifier.verify(context.state, node, node.getQual());
     }
 
     verifyProjectableOutputSchema(node);
@@ -185,16 +202,16 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitStoreTable(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitStoreTable(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                      StoreTableNode node, Stack<LogicalNode> stack) throws PlanningException {
-    super.visitStoreTable(state, plan, block, node, stack);
+    super.visitStoreTable(context, plan, block, node, stack);
     return node;
   }
 
   @Override
-  public LogicalNode visitInsert(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitInsert(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                  InsertNode node, Stack<LogicalNode> stack) throws PlanningException {
-    super.visitInsert(state, plan, block, node, stack);
+    super.visitInsert(context, plan, block, node, stack);
     return node;
   }
 
@@ -216,24 +233,17 @@ public class LogicalPlanVerifier extends BasicLogicalPlanVisitor<VerificationSta
   }
 
   @Override
-  public LogicalNode visitCreateTable(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitCreateTable(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                       CreateTableNode node, Stack<LogicalNode> stack) throws PlanningException {
-    super.visitCreateTable(state, plan, block, node, stack);
-
-    if (catalog.existsTable(node.getTableName())) {
-      state.addVerification("relation \"" + node.getTableName() + "\" already exists");
-    }
-
+    super.visitCreateTable(context, plan, block, node, stack);
+    // here, we don't need check table existence because this check is performed in PreLogicalPlanVerifier.
     return node;
   }
 
   @Override
-  public LogicalNode visitDropTable(VerificationState state, LogicalPlan plan, LogicalPlan.QueryBlock block,
+  public LogicalNode visitDropTable(Context context, LogicalPlan plan, LogicalPlan.QueryBlock block,
                                     DropTableNode node, Stack<LogicalNode> stack) {
-    if (!catalog.existsTable(node.getTableName())) {
-      state.addVerification("table \"" + node.getTableName() + "\" does not exist");
-    }
-
+    // here, we don't need check table existence because this check is performed in PreLogicalPlanVerifier.
     return node;
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java
index bf41996..76454b9 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanVisitor.java
@@ -71,6 +71,12 @@ public interface LogicalPlanVisitor<CONTEXT, RESULT> {
   RESULT visitInsert(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, InsertNode node,
                      Stack<LogicalNode> stack) throws PlanningException;
 
+  RESULT visitCreateDatabase(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, CreateDatabaseNode node,
+                          Stack<LogicalNode> stack) throws PlanningException;
+
+  RESULT visitDropDatabase(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, DropDatabaseNode node,
+                             Stack<LogicalNode> stack) throws PlanningException;
+
   RESULT visitCreateTable(CONTEXT context, LogicalPlan plan, LogicalPlan.QueryBlock block, CreateTableNode node,
                           Stack<LogicalNode> stack) throws PlanningException;
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
index 01bacc0..48e3c93 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
@@ -42,6 +42,7 @@ import org.apache.tajo.engine.planner.LogicalPlan.QueryBlock;
 import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.engine.planner.rewrite.ProjectionPushDownRule;
 import org.apache.tajo.engine.utils.SchemaUtil;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.util.TUtil;
 
 import java.util.*;
@@ -69,6 +70,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
   }
 
   public class PlanContext {
+    Session session;
     LogicalPlan plan;
 
     // transient data for each query block
@@ -76,13 +78,15 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
 
     boolean debugOrUnitTests;
 
-    public PlanContext(LogicalPlan plan, QueryBlock block, boolean debugOrUnitTests) {
+    public PlanContext(Session session, LogicalPlan plan, QueryBlock block, boolean debugOrUnitTests) {
+      this.session = session;
       this.plan = plan;
       this.queryBlock = block;
       this.debugOrUnitTests = debugOrUnitTests;
     }
 
     public PlanContext(PlanContext context, QueryBlock block) {
+      this.session = context.session;
       this.plan = context.plan;
       this.queryBlock = block;
       this.debugOrUnitTests = context.debugOrUnitTests;
@@ -100,20 +104,20 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
    * @param expr A relational algebraic expression for a query.
    * @return A logical plan
    */
-  public LogicalPlan createPlan(Expr expr) throws PlanningException {
-    return createPlan(expr, false);
+  public LogicalPlan createPlan(Session session, Expr expr) throws PlanningException {
+    return createPlan(session, expr, false);
   }
 
   @VisibleForTesting
-  public LogicalPlan createPlan(Expr expr, boolean debug) throws PlanningException {
+  public LogicalPlan createPlan(Session session, Expr expr, boolean debug) throws PlanningException {
 
-    LogicalPlan plan = new LogicalPlan(this);
+    LogicalPlan plan = new LogicalPlan(session.getCurrentDatabase(), this);
 
     QueryBlock rootBlock = plan.newAndGetBlock(LogicalPlan.ROOT_BLOCK);
-    PreprocessContext preProcessorCtx = new PreprocessContext(plan, rootBlock);
+    PreprocessContext preProcessorCtx = new PreprocessContext(session, plan, rootBlock);
     preprocessor.visit(preProcessorCtx, new Stack<Expr>(), expr);
 
-    PlanContext context = new PlanContext(plan, plan.getRootBlock(), debug);
+    PlanContext context = new PlanContext(session, plan, plan.getRootBlock(), debug);
     LogicalNode topMostNode = this.visit(context, new Stack<Expr>(), expr);
 
     // Add Root Node
@@ -1148,7 +1152,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
   private InsertNode buildInsertIntoTablePlan(PlanContext context, InsertNode insertNode, Insert expr)
       throws PlanningException {
     // Get and set a target table
-    TableDesc desc = catalog.getTableDesc(expr.getTableName());
+    TableDesc desc = catalog.getTableDesc(context.session.getCurrentDatabase(), expr.getTableName());
     insertNode.setTargetTable(desc);
 
     //
@@ -1272,13 +1276,36 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
    ===============================================================================================*/
 
   @Override
+  public LogicalNode visitCreateDatabase(PlanContext context, Stack<Expr> stack, CreateDatabase expr)
+      throws PlanningException {
+    CreateDatabaseNode createDatabaseNode = context.queryBlock.getNodeFromExpr(expr);
+    createDatabaseNode.init(expr.getDatabaseName(), expr.isIfNotExists());
+    return createDatabaseNode;
+  }
+
+  @Override
+  public LogicalNode visitDropDatabase(PlanContext context, Stack<Expr> stack, DropDatabase expr)
+      throws PlanningException {
+    DropDatabaseNode dropDatabaseNode = context.plan.createNode(DropDatabaseNode.class);
+    dropDatabaseNode.init(expr.getDatabaseName(), expr.isIfExists());
+    return dropDatabaseNode;
+  }
+
+  @Override
   public LogicalNode visitCreateTable(PlanContext context, Stack<Expr> stack, CreateTable expr)
       throws PlanningException {
 
     CreateTableNode createTableNode = context.queryBlock.getNodeFromExpr(expr);
+    createTableNode.setIfNotExists(expr.isIfNotExists());
 
     // Set a table name to be created.
-    createTableNode.setTableName(expr.getTableName());
+    if (CatalogUtil.isFQTableName(expr.getTableName())) {
+      createTableNode.setTableName(expr.getTableName());
+    } else {
+      createTableNode.setTableName(
+          CatalogUtil.buildFQName(context.session.getCurrentDatabase(), expr.getTableName()));
+    }
+
 
     if (expr.hasStorageType()) { // If storage type (using clause) is specified
       createTableNode.setStorageType(CatalogUtil.getStoreType(expr.getStorageType()));
@@ -1359,18 +1386,16 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
   private PartitionMethodDesc getPartitionMethod(PlanContext context,
                                                  String tableName,
                                                  CreateTable.PartitionMethodDescExpr expr) throws PlanningException {
-    PartitionMethodDesc partitionMethodDesc = new PartitionMethodDesc();
-    partitionMethodDesc.setTableId(tableName);
+    PartitionMethodDesc partitionMethodDesc;
 
     if(expr.getPartitionType() == PartitionType.COLUMN) {
       CreateTable.ColumnPartition partition = (CreateTable.ColumnPartition) expr;
       String partitionExpression = Joiner.on(',').join(partition.getColumns());
-      partitionMethodDesc.setPartitionType(CatalogProtos.PartitionType.COLUMN);
-      partitionMethodDesc.setExpression(partitionExpression);
-      partitionMethodDesc.setExpressionSchema(convertColumnsToSchema(partition.getColumns()));
+
+      partitionMethodDesc = new PartitionMethodDesc(context.session.getCurrentDatabase(), tableName,
+          CatalogProtos.PartitionType.COLUMN, partitionExpression, convertColumnsToSchema(partition.getColumns()));
     } else {
-      throw new PlanningException(String.format("Not supported PartitonType: %s",
-          expr.getPartitionType()));
+      throw new PlanningException(String.format("Not supported PartitonType: %s", expr.getPartitionType()));
     }
     return partitionMethodDesc;
   }
@@ -1426,7 +1451,13 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
   @Override
   public LogicalNode visitDropTable(PlanContext context, Stack<Expr> stack, DropTable dropTable) {
     DropTableNode dropTableNode = context.queryBlock.getNodeFromExpr(dropTable);
-    dropTableNode.init(dropTable.getTableName(), dropTable.isPurge());
+    String qualified;
+    if (CatalogUtil.isFQTableName(dropTable.getTableName())) {
+      qualified = dropTable.getTableName();
+    } else {
+      qualified = CatalogUtil.buildFQName(context.session.getCurrentDatabase(), dropTable.getTableName());
+    }
+    dropTableNode.init(qualified, dropTable.isIfExists(), dropTable.isPurge());
     return dropTableNode;
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
index a928fb5..fbd65a9 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
@@ -21,10 +21,7 @@ package org.apache.tajo.engine.planner;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-import org.apache.tajo.algebra.CountRowsFunctionExpr;
-import org.apache.tajo.algebra.Expr;
-import org.apache.tajo.algebra.GeneralSetFunctionExpr;
-import org.apache.tajo.algebra.JoinType;
+import org.apache.tajo.algebra.*;
 import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
@@ -48,7 +45,12 @@ public class PlannerUtil {
       baseNode = ((LogicalRootNode) node).getChild();
     }
 
-    return (baseNode.getType() == NodeType.CREATE_TABLE && !((CreateTableNode)baseNode).hasSubQuery()) ||
+    NodeType type = baseNode.getType();
+
+    return
+        type == NodeType.CREATE_DATABASE ||
+        type == NodeType.DROP_DATABASE ||
+        (type == NodeType.CREATE_TABLE && !((CreateTableNode)baseNode).hasSubQuery()) ||
         baseNode.getType() == NodeType.DROP_TABLE;
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
index 508740f..fef9dc1 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/PreLogicalPlanVerifier.java
@@ -21,22 +21,40 @@ package org.apache.tajo.engine.planner;
 import com.google.common.collect.ObjectArrays;
 import org.apache.tajo.algebra.*;
 import org.apache.tajo.catalog.CatalogService;
+import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.util.TUtil;
 
 import java.util.Arrays;
 import java.util.Set;
 import java.util.Stack;
 
-public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <VerificationState, Expr> {
+public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <PreLogicalPlanVerifier.Context, Expr> {
   private CatalogService catalog;
 
   public PreLogicalPlanVerifier(CatalogService catalog) {
     this.catalog = catalog;
   }
 
-  public Expr visitProjection(VerificationState state, Stack<Expr> stack, Projection expr) throws PlanningException {
-    super.visitProjection(state, stack, expr);
+  public static class Context {
+    Session session;
+    VerificationState state;
+
+    public Context(Session session, VerificationState state) {
+      this.session = session;
+      this.state = state;
+    }
+  }
+
+  public VerificationState verify(Session session, VerificationState state, Expr expr) throws PlanningException {
+    Context context = new Context(session, state);
+    visit(context, new Stack<Expr>(), expr);
+    return context.state;
+  }
+
+  public Expr visitProjection(Context context, Stack<Expr> stack, Projection expr) throws PlanningException {
+    super.visitProjection(context, stack, expr);
 
     Set<String> names = TUtil.newHashSet();
     Expr [] distinctValues = null;
@@ -45,7 +63,8 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <VerificationStat
 
       if (namedExpr.hasAlias()) {
         if (names.contains(namedExpr.getAlias())) {
-          state.addVerification(String.format("column name \"%s\" specified more than once", namedExpr.getAlias()));
+          context.state.addVerification(String.format("column name \"%s\" specified more than once",
+              namedExpr.getAlias()));
         } else {
           names.add(namedExpr.getAlias());
         }
@@ -92,13 +111,13 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <VerificationStat
   }
 
   @Override
-  public Expr visitGroupBy(VerificationState ctx, Stack<Expr> stack, Aggregation expr) throws PlanningException {
-    super.visitGroupBy(ctx, stack, expr);
+  public Expr visitGroupBy(Context context, Stack<Expr> stack, Aggregation expr) throws PlanningException {
+    super.visitGroupBy(context, stack, expr);
 
     // Enforcer only ordinary grouping set.
     for (Aggregation.GroupElement groupingElement : expr.getGroupSet()) {
       if (groupingElement.getType() != Aggregation.GroupType.OrdinaryGroup) {
-        ctx.addVerification(groupingElement.getType() + " is not supported yet");
+        context.state.addVerification(groupingElement.getType() + " is not supported yet");
       }
     }
 
@@ -118,22 +137,37 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <VerificationStat
   }
 
   @Override
-  public Expr visitRelation(VerificationState state, Stack<Expr> stack, Relation expr) throws PlanningException {
-    assertRelationExistence(state, expr.getName());
+  public Expr visitRelation(Context context, Stack<Expr> stack, Relation expr) throws PlanningException {
+    assertRelationExistence(context, expr.getName());
     return expr;
   }
 
-  private boolean assertRelationExistence(VerificationState state, String name) {
-    if (!catalog.existsTable(name)) {
-      state.addVerification(String.format("relation \"%s\" does not exist", name));
+  private boolean assertRelationExistence(Context context, String tableName) {
+    String qualifiedName;
+
+    if (CatalogUtil.isFQTableName(tableName)) {
+      qualifiedName = tableName;
+    } else {
+      qualifiedName = CatalogUtil.buildFQName(context.session.getCurrentDatabase(), tableName);
+    }
+
+    if (!catalog.existsTable(qualifiedName)) {
+      context.state.addVerification(String.format("relation \"%s\" does not exist", qualifiedName));
       return false;
     }
     return true;
   }
 
-  private boolean assertRelationNoExistence(VerificationState state, String name) {
-    if (catalog.existsTable(name)) {
-      state.addVerification(String.format("relation \"%s\" already exists", name));
+  private boolean assertRelationNoExistence(Context context, String tableName) {
+    String qualifiedName;
+
+    if (CatalogUtil.isFQTableName(tableName)) {
+      qualifiedName = tableName;
+    } else {
+      qualifiedName = CatalogUtil.buildFQName(context.session.getCurrentDatabase(), tableName);
+    }
+    if (catalog.existsTable(qualifiedName)) {
+      context.state.addVerification(String.format("relation \"%s\" already exists", qualifiedName));
       return false;
     }
     return true;
@@ -147,15 +181,62 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <VerificationStat
     return true;
   }
 
+  private boolean assertDatabaseExistence(VerificationState state, String name) {
+    if (!catalog.existDatabase(name)) {
+      state.addVerification(String.format("database \"%s\" does not exist", name));
+      return false;
+    }
+    return true;
+  }
+
+  private boolean assertDatabaseNoExistence(VerificationState state, String name) {
+    if (catalog.existDatabase(name)) {
+      state.addVerification(String.format("database \"%s\" already exists", name));
+      return false;
+    }
+    return true;
+  }
+
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
   // Data Definition Language Section
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
+
+  @Override
+  public Expr visitCreateDatabase(Context context, Stack<Expr> stack, CreateDatabase expr)
+      throws PlanningException {
+    super.visitCreateDatabase(context, stack, expr);
+    if (!expr.isIfNotExists()) {
+      assertDatabaseNoExistence(context.state, expr.getDatabaseName());
+    }
+    return expr;
+  }
+
   @Override
-  public Expr visitCreateTable(VerificationState state, Stack<Expr> stack, CreateTable expr) throws PlanningException {
-    super.visitCreateTable(state, stack, expr);
-    assertRelationNoExistence(state, expr.getTableName());
-    assertUnsupportedStoreType(state, expr.getStorageType());
+  public Expr visitDropDatabase(Context context, Stack<Expr> stack, DropDatabase expr) throws PlanningException {
+    super.visitDropDatabase(context, stack, expr);
+    if (!expr.isIfExists()) {
+      assertDatabaseExistence(context.state, expr.getDatabaseName());
+    }
+    return expr;
+  }
+
+  @Override
+  public Expr visitCreateTable(Context context, Stack<Expr> stack, CreateTable expr) throws PlanningException {
+    super.visitCreateTable(context, stack, expr);
+    if (!expr.isIfNotExists()) {
+      assertRelationNoExistence(context, expr.getTableName());
+    }
+    assertUnsupportedStoreType(context.state, expr.getStorageType());
+    return expr;
+  }
+
+  @Override
+  public Expr visitDropTable(Context context, Stack<Expr> stack, DropTable expr) throws PlanningException {
+    super.visitDropTable(context, stack, expr);
+    if (!expr.isIfExists()) {
+      assertRelationExistence(context, expr.getTableName());
+    }
     return expr;
   }
 
@@ -163,11 +244,11 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <VerificationStat
   // Insert or Update Section
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public Expr visitInsert(VerificationState state, Stack<Expr> stack, Insert expr) throws PlanningException {
-    Expr child = super.visitInsert(state, stack, expr);
+  public Expr visitInsert(Context context, Stack<Expr> stack, Insert expr) throws PlanningException {
+    Expr child = super.visitInsert(context, stack, expr);
 
     if (expr.hasTableName()) {
-      assertRelationExistence(state, expr.getTableName());
+      assertRelationExistence(context, expr.getTableName());
     }
 
     if (child != null && child.getType() == OpType.Projection) {
@@ -177,9 +258,9 @@ public class PreLogicalPlanVerifier extends BaseAlgebraVisitor <VerificationStat
         int targetColumnNum = expr.getTargetColumns().length;
 
         if (targetColumnNum > projectColumnNum)  {
-          state.addVerification("INSERT has more target columns than expressions");
+          context.state.addVerification("INSERT has more target columns than expressions");
         } else if (targetColumnNum < projectColumnNum) {
-          state.addVerification("INSERT has more expressions than target columns");
+          context.state.addVerification("INSERT has more expressions than target columns");
         }
       }
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/VerificationState.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/VerificationState.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/VerificationState.java
index e1b136d..18882b8 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/VerificationState.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/VerificationState.java
@@ -19,13 +19,18 @@
 package org.apache.tajo.engine.planner;
 
 import com.google.common.collect.Lists;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tajo.util.TUtil;
 
 import java.util.List;
 
 public class VerificationState {
+  private static final Log LOG = LogFactory.getLog(VerificationState.class);
   List<String> errorMessages = Lists.newArrayList();
 
   public void addVerification(String error) {
+    LOG.warn(TUtil.getCurrentCodePoint(1) + " causes: " + error);
     errorMessages.add(error);
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
index 461c5d5..73de079 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/global/GlobalPlanner.java
@@ -129,7 +129,7 @@ public class GlobalPlanner {
     }
 
     masterPlan.setTerminal(terminalBlock);
-    LOG.info(masterPlan);
+    LOG.info(masterPlan.toString());
   }
 
   private static void setFinalOutputChannel(DataChannel outputChannel, Schema outputSchema) {
@@ -141,7 +141,8 @@ public class GlobalPlanner {
 
   public static ScanNode buildInputExecutor(LogicalPlan plan, DataChannel channel) {
     Preconditions.checkArgument(channel.getSchema() != null,
-        "Channel schema (" + channel.getSrcId().getId() + " -> " + channel.getTargetId().getId() + ") is not initialized");
+        "Channel schema (" + channel.getSrcId().getId() + " -> " + channel.getTargetId().getId() +
+            ") is not initialized");
     TableMeta meta = new TableMeta(channel.getStoreType(), new Options());
     TableDesc desc = new TableDesc(channel.getSrcId().toString(), channel.getSchema(), meta, new Path("/"));
     ScanNode scanNode = plan.createNode(ScanNode.class);

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateDatabaseNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateDatabaseNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateDatabaseNode.java
new file mode 100644
index 0000000..e0b2f0f
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateDatabaseNode.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.planner.logical;
+
+import com.google.common.base.Objects;
+import org.apache.tajo.engine.planner.PlanString;
+
+public class CreateDatabaseNode extends LogicalNode implements Cloneable {
+  private String databaseName;
+  private boolean ifNotExists;
+
+  public CreateDatabaseNode(int pid) {
+    super(pid, NodeType.CREATE_DATABASE);
+  }
+
+  public void init(String databaseName, boolean ifNotExists) {
+    this.databaseName = databaseName;
+    this.ifNotExists = ifNotExists;
+  }
+
+  public String getDatabaseName() {
+    return this.databaseName;
+  }
+
+  public boolean isIfNotExists() {
+    return ifNotExists;
+  }
+
+  @Override
+  public PlanString getPlanString() {
+    return new PlanString(this).appendTitle(ifNotExists ? " IF NOT EXISTS " : " ").appendTitle(databaseName);
+  }
+
+  public int hashCode() {
+    return Objects.hashCode(databaseName, ifNotExists);
+  }
+
+  public boolean equals(Object obj) {
+    if (obj instanceof CreateDatabaseNode) {
+      CreateDatabaseNode other = (CreateDatabaseNode) obj;
+      return super.equals(other) && this.databaseName.equals(other.databaseName) && ifNotExists == other.ifNotExists;
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    CreateDatabaseNode newNode = (CreateDatabaseNode) super.clone();
+    newNode.databaseName = databaseName;
+    newNode.ifNotExists = ifNotExists;
+    return newNode;
+  }
+
+  @Override
+  public String toString() {
+    return "CREATE DATABASE " + (ifNotExists ? " IF NOT EXISTS " : "") + databaseName;
+  }
+
+  @Override
+  public void preOrder(LogicalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+
+  @Override
+  public void postOrder(LogicalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
index b8e7143..c70fb10 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/CreateTableNode.java
@@ -18,6 +18,7 @@
 
 package org.apache.tajo.engine.planner.logical;
 
+import com.google.common.base.Objects;
 import com.google.gson.annotations.Expose;
 import org.apache.hadoop.fs.Path;
 import org.apache.tajo.catalog.Options;
@@ -29,6 +30,7 @@ public class CreateTableNode extends StoreTableNode implements Cloneable {
   @Expose private Schema schema;
   @Expose private Path path;
   @Expose private boolean external;
+  @Expose private boolean ifNotExists;
 
   public CreateTableNode(int pid) {
     super(pid, NodeType.CREATE_TABLE);
@@ -76,10 +78,22 @@ public class CreateTableNode extends StoreTableNode implements Cloneable {
     return child != null;
   }
 
+  public void setIfNotExists(boolean ifNotExists) {
+    this.ifNotExists = ifNotExists;
+  }
+
+  public boolean isIfNotExists() {
+    return ifNotExists;
+  }
+
   @Override
   public PlanString getPlanString() {
     return new PlanString(this);
   }
+
+  public int hashCode() {
+    return super.hashCode() ^ Objects.hashCode(schema, path, external, ifNotExists) * 31;
+  }
   
   @Override
   public boolean equals(Object obj) {
@@ -88,7 +102,8 @@ public class CreateTableNode extends StoreTableNode implements Cloneable {
       return super.equals(other)
           && this.schema.equals(other.schema)
           && this.external == other.external
-          && TUtil.checkEquals(path, other.path);
+          && TUtil.checkEquals(path, other.path)
+          && ifNotExists == other.ifNotExists;
     } else {
       return false;
     }
@@ -96,18 +111,20 @@ public class CreateTableNode extends StoreTableNode implements Cloneable {
   
   @Override
   public Object clone() throws CloneNotSupportedException {
-    CreateTableNode store = (CreateTableNode) super.clone();
-    store.tableName = tableName;
-    store.schema = (Schema) schema.clone();
-    store.storageType = storageType;
-    store.external = external;
-    store.path = path != null ? new Path(path.toString()) : null;
-    store.options = (Options) (options != null ? options.clone() : null);
-    return store;
+    CreateTableNode createTableNode = (CreateTableNode) super.clone();
+    createTableNode.tableName = tableName;
+    createTableNode.schema = (Schema) schema.clone();
+    createTableNode.storageType = storageType;
+    createTableNode.external = external;
+    createTableNode.path = path != null ? new Path(path.toString()) : null;
+    createTableNode.options = (Options) (options != null ? options.clone() : null);
+    createTableNode.ifNotExists = ifNotExists;
+    return createTableNode;
   }
 
   public String toString() {
-    return "CreateTable (table=" + tableName + ", external=" + external + ", storeType=" + storageType + ")";
+    return "CreateTable (table=" + tableName + ", external=" + external + ", storeType=" + storageType +
+        ", ifNotExists=" + ifNotExists +")";
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropDatabaseNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropDatabaseNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropDatabaseNode.java
new file mode 100644
index 0000000..1578759
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropDatabaseNode.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.planner.logical;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.engine.planner.PlanString;
+
+public class DropDatabaseNode extends LogicalNode implements Cloneable {
+  @Expose private String databaseName;
+  @Expose private boolean ifExists;
+
+  public DropDatabaseNode(int pid) {
+    super(pid, NodeType.DROP_DATABASE);
+  }
+
+  public void init(String databaseName, boolean ifExists) {
+    this.databaseName = databaseName;
+    this.ifExists = ifExists;
+  }
+
+  public String getDatabaseName() {
+    return this.databaseName;
+  }
+
+  public boolean isIfExists() {
+    return ifExists;
+  }
+
+  @Override
+  public PlanString getPlanString() {
+    return new PlanString(this).appendTitle(ifExists ? " IF EXISTS " : " ").appendTitle(databaseName);
+  }
+
+  public int hashCode() {
+    return Objects.hashCode(databaseName, ifExists);
+  }
+
+  public boolean equals(Object obj) {
+    if (obj instanceof DropDatabaseNode) {
+      DropDatabaseNode other = (DropDatabaseNode) obj;
+      return super.equals(other) && this.databaseName.equals(other.databaseName) && ifExists == other.ifExists;
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    DropDatabaseNode dropTableNode = (DropDatabaseNode) super.clone();
+    dropTableNode.databaseName = databaseName;
+    return dropTableNode;
+  }
+
+  @Override
+  public String toString() {
+    return "DROP DATABASE " + (ifExists ? "IF EXISTS ":"") + databaseName;
+  }
+
+  @Override
+  public void preOrder(LogicalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+
+  @Override
+  public void postOrder(LogicalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
index 0c6675f..ac68a9c 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/DropTableNode.java
@@ -18,18 +18,21 @@
 
 package org.apache.tajo.engine.planner.logical;
 
+import com.google.common.base.Objects;
 import org.apache.tajo.engine.planner.PlanString;
 
-public class DropTableNode extends LogicalNode {
+public class DropTableNode extends LogicalNode implements Cloneable {
   private String tableName;
+  private boolean ifExists;
   private boolean purge;
 
   public DropTableNode(int pid) {
     super(pid, NodeType.DROP_TABLE);
   }
 
-  public void init(String tableName, boolean purge) {
+  public void init(String tableName, boolean ifExists, boolean purge) {
     this.tableName = tableName;
+    this.ifExists = ifExists;
     this.purge = purge;
   }
 
@@ -37,19 +40,30 @@ public class DropTableNode extends LogicalNode {
     return this.tableName;
   }
 
+  public boolean isIfExists() {
+    return this.ifExists;
+  }
+
   public boolean isPurge() {
     return this.purge;
   }
 
   @Override
   public PlanString getPlanString() {
-    return new PlanString(this).appendTitle(purge ? " (PURGE)" : "");
+    return new PlanString(this).appendTitle(ifExists ? " IF EXISTS" : "").appendTitle(purge ? " PURGE" : "");
+  }
+
+  public int hashCode() {
+    return Objects.hashCode(tableName, ifExists, purge);
   }
 
   public boolean equals(Object obj) {
     if (obj instanceof DropTableNode) {
       DropTableNode other = (DropTableNode) obj;
-      return super.equals(other) && this.tableName.equals(other.tableName) && this.purge == other.purge;
+      return super.equals(other) &&
+          this.tableName.equals(other.tableName) &&
+          this.ifExists == other.ifExists &&
+          this.purge == other.purge;
     } else {
       return false;
     }
@@ -59,13 +73,14 @@ public class DropTableNode extends LogicalNode {
   public Object clone() throws CloneNotSupportedException {
     DropTableNode dropTableNode = (DropTableNode) super.clone();
     dropTableNode.tableName = tableName;
+    dropTableNode.ifExists = ifExists;
     dropTableNode.purge = purge;
     return dropTableNode;
   }
 
   @Override
   public String toString() {
-    return "DROP TABLE " + tableName + (purge ? " PURGE" : "");
+    return "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + tableName + (purge ? " PURGE" : "");
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
index acaf85b..2b453fb 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/NodeType.java
@@ -43,6 +43,9 @@ public enum NodeType {
   BST_INDEX_SCAN(IndexScanNode.class),
   STORE(StoreTableNode.class),
   INSERT(InsertNode.class),
+
+  CREATE_DATABASE(CreateDatabaseNode.class),
+  DROP_DATABASE(DropDatabaseNode.class),
   CREATE_TABLE(CreateTableNode.class),
   DROP_TABLE(DropTableNode.class)
   ;

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
index 80a0d7a..8e4911f 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/logical/ScanNode.java
@@ -30,7 +30,7 @@ import org.apache.tajo.engine.planner.Target;
 import org.apache.tajo.engine.utils.SchemaUtil;
 import org.apache.tajo.util.TUtil;
 
-public class ScanNode extends RelationNode implements Projectable {
+public class ScanNode extends RelationNode implements Projectable, Cloneable {
 	@Expose protected TableDesc tableDesc;
   @Expose protected String alias;
   @Expose protected Schema logicalSchema;
@@ -55,10 +55,18 @@ public class ScanNode extends RelationNode implements Projectable {
 	public void init(TableDesc desc, String alias) {
     this.tableDesc = desc;
     this.alias = CatalogUtil.normalizeIdentifier(alias);
+
+    if (!CatalogUtil.isFQTableName(this.tableDesc.getName())) {
+      throw new IllegalArgumentException("the name in TableDesc must be qualified, but it is \"" +
+          desc.getName() + "\"");
+    }
+
+    String databaseName = CatalogUtil.extractQualifier(this.tableDesc.getName());
+    String qualifiedAlias = CatalogUtil.buildFQName(databaseName, alias);
     this.setInSchema(tableDesc.getSchema());
-    this.getInSchema().setQualifier(alias);
+    this.getInSchema().setQualifier(qualifiedAlias);
     this.setOutSchema(new Schema(getInSchema()));
-    logicalSchema = SchemaUtil.getQualifiedLogicalSchema(tableDesc, alias);
+    logicalSchema = SchemaUtil.getQualifiedLogicalSchema(tableDesc, qualifiedAlias);
 	}
 	
 	public String getTableName() {
@@ -70,7 +78,12 @@ public class ScanNode extends RelationNode implements Projectable {
 	}
 
   public String getCanonicalName() {
-    return hasAlias() ? alias : tableDesc.getName();
+    if (CatalogUtil.isFQTableName(this.tableDesc.getName())) {
+      String databaseName = CatalogUtil.extractQualifier(this.tableDesc.getName());
+      return hasAlias() ? CatalogUtil.buildFQName(databaseName, alias) : tableDesc.getName();
+    } else {
+      return hasAlias() ? alias : tableDesc.getName();
+    }
   }
 
   public Schema getTableSchema() {

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryContext.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryContext.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryContext.java
index 1db4c4b..5076b87 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryContext.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/query/QueryContext.java
@@ -28,7 +28,6 @@ import org.apache.tajo.engine.planner.logical.NodeType;
 import static org.apache.tajo.catalog.proto.CatalogProtos.KeyValueSetProto;
 
 public class QueryContext extends Options {
-
   public static final String COMMAND_TYPE = "tajo.query.command";
 
   public static final String STAGING_DIR = "tajo.query.staging_dir";

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/utils/ProtoUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/utils/ProtoUtil.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/utils/ProtoUtil.java
deleted file mode 100644
index 93eca22..0000000
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/utils/ProtoUtil.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.engine.utils;
-
-import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringProto;
-
-public class ProtoUtil {
-  public static StringProto newProto(String val) {
-    StringProto.Builder builder = StringProto.newBuilder();
-    builder.setValue(val);
-    return builder.build();
-  }
-}

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
index d7ded93..d0e8dc4 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/GlobalEngine.java
@@ -29,9 +29,9 @@ import org.apache.tajo.QueryId;
 import org.apache.tajo.QueryIdFactory;
 import org.apache.tajo.TajoProtos;
 import org.apache.tajo.algebra.Expr;
+import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.*;
-import org.apache.tajo.catalog.exception.AlreadyExistsTableException;
-import org.apache.tajo.catalog.exception.NoSuchTableException;
+import org.apache.tajo.catalog.exception.*;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.catalog.statistics.TableStats;
 import org.apache.tajo.conf.TajoConf;
@@ -46,14 +46,16 @@ import org.apache.tajo.ipc.ClientProtos;
 import org.apache.tajo.master.TajoMaster.MasterContext;
 import org.apache.tajo.master.querymaster.QueryInfo;
 import org.apache.tajo.master.querymaster.QueryJobManager;
+import org.apache.tajo.master.session.Session;
 import org.apache.tajo.storage.AbstractStorageManager;
+import org.apache.tajo.storage.StorageUtil;
 
 import java.io.IOException;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Stack;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
 import static org.apache.tajo.ipc.ClientProtos.GetQueryStatusResponse;
 
 public class GlobalEngine extends AbstractService {
@@ -101,7 +103,7 @@ public class GlobalEngine extends AbstractService {
     super.stop();
   }
 
-  public GetQueryStatusResponse executeQuery(String sql)
+  public GetQueryStatusResponse executeQuery(Session session, String sql)
       throws InterruptedException, IOException, IllegalQueryStatusException {
 
     LOG.info("SQL: " + sql);
@@ -133,13 +135,13 @@ public class GlobalEngine extends AbstractService {
       context.getSystemMetrics().counter("Query", "totalQuery").inc();
 
       Expr planningContext = hiveQueryMode ? converter.parse(sql) : analyzer.parse(sql);
-      LogicalPlan plan = createLogicalPlan(planningContext);
+      LogicalPlan plan = createLogicalPlan(session, planningContext);
       LogicalRootNode rootNode = plan.getRootBlock().getRoot();
 
       GetQueryStatusResponse.Builder responseBuilder = GetQueryStatusResponse.newBuilder();
       if (PlannerUtil.checkIfDDLPlan(rootNode)) {
         context.getSystemMetrics().counter("Query", "numDDLQuery").inc();
-        updateQuery(rootNode.getChild());
+        updateQuery(session, rootNode.getChild());
         responseBuilder.setQueryId(QueryIdFactory.NULL_QUERY_ID.getProto());
         responseBuilder.setResultCode(ClientProtos.ResultCode.OK);
         responseBuilder.setState(TajoProtos.QueryState.QUERY_SUCCEEDED);
@@ -150,7 +152,7 @@ public class GlobalEngine extends AbstractService {
         QueryJobManager queryJobManager = this.context.getQueryJobManager();
         QueryInfo queryInfo;
 
-        queryInfo = queryJobManager.createNewQueryJob(queryContext, sql, rootNode);
+        queryInfo = queryJobManager.createNewQueryJob(session, queryContext, sql, rootNode);
 
         if(queryInfo == null) {
           responseBuilder.setQueryId(QueryIdFactory.NULL_QUERY_ID.getProto());
@@ -186,7 +188,7 @@ public class GlobalEngine extends AbstractService {
     }
   }
 
-  public String explainQuery(String sql) throws IOException, SQLException, PlanningException {
+  public String explainQuery(Session session, String sql) throws IOException, SQLException, PlanningException {
     LOG.info("SQL: " + sql);
     // parse the query
 
@@ -194,35 +196,44 @@ public class GlobalEngine extends AbstractService {
     Expr planningContext = hiveQueryMode ? converter.parse(sql) : analyzer.parse(sql);
     LOG.info("hive.query.mode:" + hiveQueryMode);
 
-    LogicalPlan plan = createLogicalPlan(planningContext);
+    LogicalPlan plan = createLogicalPlan(session, planningContext);
     return plan.toString();
   }
 
-  public QueryId updateQuery(String sql) throws IOException, SQLException, PlanningException {
+  public QueryId updateQuery(Session session, String sql) throws IOException, SQLException, PlanningException {
     LOG.info("SQL: " + sql);
     // parse the query
     Expr expr = analyzer.parse(sql);
-    LogicalPlan plan = createLogicalPlan(expr);
+
+    LogicalPlan plan = createLogicalPlan(session, expr);
     LogicalRootNode rootNode = plan.getRootBlock().getRoot();
 
     if (!PlannerUtil.checkIfDDLPlan(rootNode)) {
       throw new SQLException("This is not update query:\n" + sql);
     } else {
-      updateQuery(rootNode.getChild());
+      updateQuery(session, rootNode.getChild());
       return QueryIdFactory.NULL_QUERY_ID;
     }
   }
 
-  private boolean updateQuery(LogicalNode root) throws IOException {
+  private boolean updateQuery(Session session, LogicalNode root) throws IOException {
 
     switch (root.getType()) {
+      case CREATE_DATABASE:
+        CreateDatabaseNode createDatabase = (CreateDatabaseNode) root;
+        createDatabase(session, createDatabase.getDatabaseName(), null, createDatabase.isIfNotExists());
+        return true;
+      case DROP_DATABASE:
+        DropDatabaseNode dropDatabaseNode = (DropDatabaseNode) root;
+        dropDatabase(session, dropDatabaseNode.getDatabaseName(), dropDatabaseNode.isIfExists());
+        return true;
       case CREATE_TABLE:
         CreateTableNode createTable = (CreateTableNode) root;
-        createTable(createTable);
+        createTable(session, createTable, createTable.isIfNotExists());
         return true;
       case DROP_TABLE:
         DropTableNode dropTable = (DropTableNode) root;
-        dropTable(dropTable.getTableName(), dropTable.isPurge());
+        dropTable(session, dropTable.getTableName(), dropTable.isIfExists(), dropTable.isPurge());
         return true;
 
       default:
@@ -230,10 +241,10 @@ public class GlobalEngine extends AbstractService {
     }
   }
 
-  private LogicalPlan createLogicalPlan(Expr expression) throws PlanningException {
+  private LogicalPlan createLogicalPlan(Session session, Expr expression) throws PlanningException {
 
     VerificationState state = new VerificationState();
-    preVerifier.visit(state, new Stack<Expr>(), expression);
+    preVerifier.verify(session, state, expression);
     if (!state.verified()) {
       StringBuilder sb = new StringBuilder();
       for (String error : state.getErrorMessages()) {
@@ -242,7 +253,7 @@ public class GlobalEngine extends AbstractService {
       throw new VerifyException(sb.toString());
     }
 
-    LogicalPlan plan = planner.createPlan(expression);
+    LogicalPlan plan = planner.createPlan(session, expression);
     LOG.info("=============================================");
     LOG.info("Non Optimized Query: \n" + plan.toString());
     LOG.info("=============================================");
@@ -251,7 +262,7 @@ public class GlobalEngine extends AbstractService {
     LOG.info("Optimized Query: \n" + plan.toString());
     LOG.info("=============================================");
 
-    annotatedPlanVerifier.visit(state, plan, plan.getRootBlock());
+    annotatedPlanVerifier.verify(session, state, plan);
 
     if (!state.verified()) {
       StringBuilder sb = new StringBuilder();
@@ -264,7 +275,7 @@ public class GlobalEngine extends AbstractService {
     return plan;
   }
 
-  private TableDesc createTable(CreateTableNode createTable) throws IOException {
+  private TableDesc createTable(Session session, CreateTableNode createTable, boolean ifNotExists) throws IOException {
     TableMeta meta;
 
     if (createTable.hasOptions()) {
@@ -280,26 +291,46 @@ public class GlobalEngine extends AbstractService {
       createTable.setPath(tablePath);
     }
 
-    return createTableOnPath(createTable.getTableName(), createTable.getTableSchema(), meta,
-        createTable.getPath(), !createTable.isExternal(), createTable.getPartitionMethod());
+    return createTableOnPath(session, createTable.getTableName(), createTable.getTableSchema(),
+        meta, createTable.getPath(), createTable.isExternal(), createTable.getPartitionMethod(), ifNotExists);
   }
 
-  public TableDesc createTableOnPath(String tableName, Schema schema, TableMeta meta,
-                                     Path path, boolean isCreated, PartitionMethodDesc partitionDesc)
+  public TableDesc createTableOnPath(Session session, String tableName, Schema schema, TableMeta meta,
+                                     Path path, boolean isExternal, PartitionMethodDesc partitionDesc,
+                                     boolean ifNotExists)
       throws IOException {
-    if (catalog.existsTable(tableName)) {
-      throw new AlreadyExistsTableException(tableName);
+    String databaseName;
+    String simpleTableName;
+    if (CatalogUtil.isFQTableName(tableName)) {
+      String [] splitted = CatalogUtil.splitFQTableName(tableName);
+      databaseName = splitted[0];
+      simpleTableName = splitted[1];
+    } else {
+      databaseName = session.getCurrentDatabase();
+      simpleTableName = tableName;
     }
+    String qualifiedName = CatalogUtil.buildFQName(databaseName, simpleTableName);
 
-    FileSystem fs = path.getFileSystem(context.getConf());
+    boolean exists = catalog.existsTable(databaseName, simpleTableName);
 
-    if (isCreated) {
-      fs.mkdirs(path);
+    if (exists) {
+      if (ifNotExists) {
+        LOG.info("relation \"" + qualifiedName + "\" is already exists." );
+        return catalog.getTableDesc(databaseName, simpleTableName);
+      } else {
+        throw new AlreadyExistsTableException(CatalogUtil.buildFQName(databaseName, tableName));
+      }
     }
 
-    if(!fs.exists(path)) {
-      LOG.error("ERROR: " + path.toUri() + " does not exist");
-      throw new IOException("ERROR: " + path.toUri() + " does not exist");
+    FileSystem fs = path.getFileSystem(context.getConf());
+
+    if (isExternal) {
+      if(!fs.exists(path)) {
+        LOG.error("ERROR: " + path.toUri() + " does not exist");
+        throw new IOException("ERROR: " + path.toUri() + " does not exist");
+      }
+    } else {
+      fs.mkdirs(path);
     }
 
     long totalSize = 0;
@@ -312,16 +343,73 @@ public class GlobalEngine extends AbstractService {
 
     TableStats stats = new TableStats();
     stats.setNumBytes(totalSize);
-    TableDesc desc = CatalogUtil.newTableDesc(tableName, schema, meta, path);
+    TableDesc desc = new TableDesc(CatalogUtil.buildFQName(databaseName, simpleTableName),
+        schema, meta, path, isExternal);
     desc.setStats(stats);
     if (partitionDesc != null) {
       desc.setPartitionMethod(partitionDesc);
     }
-    catalog.addTable(desc);
 
-    LOG.info("Table " + desc.getName() + " is created (" + desc.getStats().getNumBytes() + ")");
+    if (catalog.createTable(desc)) {
+      LOG.info("Table " + desc.getName() + " is created (" + desc.getStats().getNumBytes() + ")");
+      return desc;
+    } else {
+      LOG.info("Table creation " + tableName + " is failed.");
+      throw new CatalogException("Cannot create table \"" + tableName + "\".");
+    }
+  }
+
+  public boolean createDatabase(@Nullable Session session, String databaseName,
+                                @Nullable String tablespace,
+                                boolean ifNotExists) throws IOException {
 
-    return desc;
+    String tablespaceName;
+    if (tablespace == null) {
+      tablespaceName = DEFAULT_TABLESPACE_NAME;
+    } else {
+      tablespaceName = tablespace;
+    }
+
+    // CREATE DATABASE IF NOT EXISTS
+    boolean exists = catalog.existDatabase(databaseName);
+    if (exists) {
+      if (ifNotExists) {
+        LOG.info("database \"" + databaseName + "\" is already exists." );
+        return true;
+      } else {
+        throw new AlreadyExistsDatabaseException(databaseName);
+      }
+    }
+
+    if (catalog.createDatabase(databaseName, tablespaceName)) {
+      String normalized = CatalogUtil.normalizeIdentifier(databaseName);
+      Path databaseDir = StorageUtil.concatPath(context.getConf().getVar(TajoConf.ConfVars.WAREHOUSE_DIR), normalized);
+      FileSystem fs = databaseDir.getFileSystem(context.getConf());
+      fs.mkdirs(databaseDir);
+    }
+
+    return true;
+  }
+
+  public boolean dropDatabase(Session session, String databaseName, boolean ifExists) {
+
+    boolean exists = catalog.existDatabase(databaseName);
+    if(!exists) {
+      if (ifExists) { // DROP DATABASE IF EXISTS
+        LOG.info("database \"" + databaseName + "\" does not exists." );
+        return true;
+      } else { // Otherwise, it causes an exception.
+        throw new NoSuchDatabaseException(databaseName);
+      }
+    }
+
+    if (session.getCurrentDatabase().equals(databaseName)) {
+      throw new RuntimeException("ERROR: Cannot drop the current open database");
+    }
+
+    boolean result = catalog.dropDatabase(databaseName);
+    LOG.info("database " + databaseName + " is dropped.");
+    return result;
   }
 
   /**
@@ -330,15 +418,33 @@ public class GlobalEngine extends AbstractService {
    * @param tableName to be dropped
    * @param purge Remove all data if purge is true.
    */
-  public void dropTable(String tableName, boolean purge) {
+  public boolean dropTable(Session session, String tableName, boolean ifExists, boolean purge) {
     CatalogService catalog = context.getCatalog();
 
-    if (!catalog.existsTable(tableName)) {
-      throw new NoSuchTableException(tableName);
+    String databaseName;
+    String simpleTableName;
+    if (CatalogUtil.isFQTableName(tableName)) {
+      String [] splitted = CatalogUtil.splitFQTableName(tableName);
+      databaseName = splitted[0];
+      simpleTableName = splitted[1];
+    } else {
+      databaseName = session.getCurrentDatabase();
+      simpleTableName = tableName;
+    }
+    String qualifiedName = CatalogUtil.buildFQName(databaseName, simpleTableName);
+
+    boolean exists = catalog.existsTable(qualifiedName);
+    if(!exists) {
+      if (ifExists) { // DROP TABLE IF EXISTS
+        LOG.info("relation \"" + qualifiedName + "\" is already exists." );
+        return true;
+      } else { // Otherwise, it causes an exception.
+        throw new NoSuchTableException(qualifiedName);
+      }
     }
 
-    Path path = catalog.getTableDesc(tableName).getPath();
-    catalog.deleteTable(tableName);
+    Path path = catalog.getTableDesc(qualifiedName).getPath();
+    catalog.dropTable(qualifiedName);
 
     if (purge) {
       try {
@@ -349,7 +455,8 @@ public class GlobalEngine extends AbstractService {
       }
     }
 
-    LOG.info("Table \"" + tableName + "\" is " + (purge ? " purged." : " dropped."));
+    LOG.info(String.format("relation \"%s\" is " + (purge ? " purged." : " dropped."), qualifiedName));
+    return true;
   }
 
   public interface DistributedQueryHook {
@@ -388,9 +495,12 @@ public class GlobalEngine extends AbstractService {
     public void hook(QueryContext queryContext, LogicalPlan plan) throws Exception {
       LogicalRootNode rootNode = plan.getRootBlock().getRoot();
       CreateTableNode createTableNode = rootNode.getChild();
-      String tableName = createTableNode.getTableName();
+      String [] splitted  = CatalogUtil.splitFQTableName(createTableNode.getTableName());
+      String databaseName = splitted[0];
+      String tableName = splitted[1];
       queryContext.setOutputTable(tableName);
-      queryContext.setOutputPath(new Path(TajoConf.getWarehouseDir(context.getConf()), tableName));
+      queryContext.setOutputPath(
+          StorageUtil.concatPath(TajoConf.getWarehouseDir(context.getConf()), databaseName, tableName));
       if(createTableNode.getPartitionMethod() != null) {
         queryContext.setPartitionMethod(createTableNode.getPartitionMethod());
       }

http://git-wip-us.apache.org/repos/asf/tajo/blob/3ba26241/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java
index 9fcfca9..9d54bb5 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java
@@ -51,6 +51,7 @@ import org.apache.tajo.master.metrics.WorkerResourceMetricsGaugeSet;
 import org.apache.tajo.master.querymaster.QueryJobManager;
 import org.apache.tajo.master.rm.TajoWorkerResourceManager;
 import org.apache.tajo.master.rm.WorkerResourceManager;
+import org.apache.tajo.master.session.SessionManager;
 import org.apache.tajo.rpc.RpcChannelFactory;
 import org.apache.tajo.storage.AbstractStorageManager;
 import org.apache.tajo.storage.StorageManagerFactory;
@@ -72,6 +73,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.TajoConstants.DEFAULT_TABLESPACE_NAME;
+
 public class TajoMaster extends CompositeService {
   private static final String METRICS_GROUP_NAME = "tajomaster";
 
@@ -114,6 +118,7 @@ public class TajoMaster extends CompositeService {
   private AsyncDispatcher dispatcher;
   private TajoMasterClientService tajoMasterClientService;
   private TajoMasterService tajoMasterService;
+  private SessionManager sessionManager;
 
   private WorkerResourceManager resourceManager;
   //Web Server
@@ -142,7 +147,7 @@ public class TajoMaster extends CompositeService {
   }
 
   @Override
-  public void init(Configuration _conf) {
+  public void serviceInit(Configuration _conf) throws Exception {
     this.systemConf = (TajoConf) _conf;
 
     context = new MasterContext(systemConf);
@@ -165,6 +170,9 @@ public class TajoMaster extends CompositeService {
       addIfService(catalogServer);
       catalog = new LocalCatalogWrapper(catalogServer, systemConf);
 
+      sessionManager = new SessionManager(dispatcher);
+      addIfService(sessionManager);
+
       globalEngine = new GlobalEngine(context);
       addIfService(globalEngine);
 
@@ -176,13 +184,12 @@ public class TajoMaster extends CompositeService {
 
       tajoMasterService = new TajoMasterService(context);
       addIfService(tajoMasterService);
-
     } catch (Exception e) {
       LOG.error(e.getMessage(), e);
+      throw e;
     }
 
-    super.init(systemConf);
-
+    super.serviceInit(systemConf);
     LOG.info("Tajo Master is initialized.");
   }
 
@@ -336,9 +343,13 @@ public class TajoMaster extends CompositeService {
   }
 
   @Override
-  public void start() {
-    LOG.info("TajoMaster startup");
-    super.start();
+  public void serviceStart() throws Exception {
+    LOG.info("TajoMaster is starting up");
+
+    // check base tablespace and databases
+    checkBaseTBSpaceAndDatabase();
+
+    super.serviceStart();
 
     // Setting the system global configs
     systemConf.setSocketAddr(ConfVars.CATALOG_ADDRESS.varname,
@@ -375,6 +386,20 @@ public class TajoMaster extends CompositeService {
     defaultFS.setReplication(systemConfPath, (short) systemConf.getIntVar(ConfVars.SYSTEM_CONF_REPLICA_COUNT));
   }
 
+  private void checkBaseTBSpaceAndDatabase() throws IOException {
+    if (!catalog.existTablespace(DEFAULT_TABLESPACE_NAME)) {
+      catalog.createTablespace(DEFAULT_TABLESPACE_NAME, context.getConf().getVar(ConfVars.WAREHOUSE_DIR));
+    } else {
+      LOG.info(String.format("Default tablespace (%s) is already prepared.", DEFAULT_TABLESPACE_NAME));
+    }
+
+    if (!catalog.existDatabase(DEFAULT_DATABASE_NAME)) {
+      globalEngine.createDatabase(null, DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME, false);
+    } else {
+      LOG.info(String.format("Default database (%s) is already prepared.", DEFAULT_DATABASE_NAME));
+    }
+  }
+
   @Override
   public void stop() {
     if (webServer != null) {
@@ -448,6 +473,10 @@ public class TajoMaster extends CompositeService {
       return catalog;
     }
 
+    public SessionManager getSessionManager() {
+      return sessionManager;
+    }
+
     public GlobalEngine getGlobalEngine() {
       return globalEngine;
     }