tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jihoon...@apache.org
Subject [2/3] tajo git commit: TAJO-1832: Well support for self-describing data formats.
Date Wed, 23 Sep 2015 01:12:19 GMT
http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testInSubquery.1.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testInSubquery.1.result b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testInSubquery.1.result
new file mode 100644
index 0000000..c700a7d
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testInSubquery.1.result
@@ -0,0 +1,4 @@
+l_orderkey,l_partkey,l_suppkey,l_linenumber,l_quantity,l_extendedprice,l_discount,l_tax,l_returnflag,l_linestatus,l_shipdate,l_commitdate,l_receiptdate,l_shipinstruct,l_shipmode,l_comment
+-------------------------------
+1,1,7311,2,36.0,45983.16,0.09,0.06,N,O,1996-04-12,1996-02-28,1996-04-20,TAKE BACK RETURN,MAIL,ly final dependencies: slyly bold 
+1,1,7706,1,17.0,21168.23,0.04,0.02,N,O,1996-03-13,1996-02-12,1996-03-22,DELIVER IN PERSON,TRUCK,egular courts above the

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinOfSelfDescTablesWithQualifiedColumns.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinOfSelfDescTablesWithQualifiedColumns.result b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinOfSelfDescTablesWithQualifiedColumns.result
new file mode 100644
index 0000000..9e68a19
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinOfSelfDescTablesWithQualifiedColumns.result
@@ -0,0 +1,3 @@
+?cast
+-------------------------------
+0

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable.result b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable.result
new file mode 100644
index 0000000..1754d7f
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable.result
@@ -0,0 +1,4 @@
+?cast,l_linenumber,l_comment
+-------------------------------
+0,1,egular courts above the
+0,2,ly final dependencies: slyly bold 

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable2.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable2.result b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable2.result
new file mode 100644
index 0000000..ef95de3
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable2.result
@@ -0,0 +1,3 @@
+?cast,l_linenumber,l_comment
+-------------------------------
+0,2,ly final dependencies: slyly bold 

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable4.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable4.result b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable4.result
new file mode 100644
index 0000000..e186cad
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testJoinWithSchemaFullTable4.result
@@ -0,0 +1,5 @@
+?cast,l_linenumber,l_comment
+-------------------------------
+0,2,ly final dependencies: slyly bold 
+0,2,ly final dependencies: slyly bold 
+0,2,ly final dependencies: slyly bold 

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSelect.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSelect.result b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSelect.result
new file mode 100644
index 0000000..9dd2ede
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSelect.result
@@ -0,0 +1,3 @@
+glossary/title,glossary/GlossDiv/title,glossary/GlossDiv/null_expected,glossary/GlossDiv/GlossList/GlossEntry/SortAs,glossary/GlossDiv/GlossList/GlossEntry/Abbrev
+-------------------------------
+example glossary,S,null,SGML,ISO 8879:1986

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSelect2.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSelect2.result b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSelect2.result
new file mode 100644
index 0000000..ae223f2
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSelect2.result
@@ -0,0 +1,3 @@
+glossary/title,glossary/GlossDiv/title,glossary/GlossDiv/null_expected,glossary/GlossDiv/GlossList/GlossEntry/SortAs
+-------------------------------
+example glossary,S,null,SGML

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSort.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSort.result b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSort.result
new file mode 100644
index 0000000..ba68534
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/results/TestQueryOnSelfDescTable/testSort.result
@@ -0,0 +1,6 @@
+created_at,id,user/profile_sidebar_fill_color
+-------------------------------
+Fri Sep 21 22:51:18 +0000 2012,249279667666817024,BFAC83
+Fri Sep 21 23:30:20 +0000 2012,249289491129438208,99CC33
+Fri Sep 21 23:40:54 +0000 2012,249292149810667520,DDFFCC
+Mon Sep 24 03:35:21 +0000 2012,250075927172759552,DDEEF6

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/case_sensitivity1.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/case_sensitivity1.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/case_sensitivity1.result
index 94ba2cd..fd64965 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/case_sensitivity1.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/case_sensitivity1.result
@@ -9,5 +9,6 @@
     }
   ],
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_like_1.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_like_1.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_like_1.result
index c6fbaf2..4f1033f 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_like_1.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_like_1.result
@@ -3,5 +3,6 @@
   "TableName": "new_table",
   "IfNotExists": false,
   "LikeParentTable": "orig_name",
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_1.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_1.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_1.result
index fea61b5..7a7a1a6 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_1.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_1.result
@@ -34,5 +34,6 @@
     }
   ],
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_2.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_2.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_2.result
index 81c0b90..e1923fd 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_2.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_2.result
@@ -48,5 +48,6 @@
     }
   ],
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_3.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_3.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_3.result
index 3259ffb..e3c8047 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_3.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_maptype_3.result
@@ -62,5 +62,6 @@
     }
   ],
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_1.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_1.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_1.result
index 55f79da..200dcd8 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_1.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_1.result
@@ -38,5 +38,6 @@
     }
   ],
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_2.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_2.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_2.result
index 8a95d2c..844621f 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_2.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_nested_2.result
@@ -57,5 +57,6 @@
     }
   ],
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_column.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_column.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_column.result
index 22dc423..f74465e 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_column.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_column.result
@@ -35,5 +35,6 @@
     "PartitionType": "COLUMN"
   },
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_1.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_1.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_1.result
index f4f3716..897d753 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_1.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_1.result
@@ -28,5 +28,6 @@
     "PartitionType": "HASH"
   },
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_2.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_2.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_2.result
index 030a437..d9c0e4d 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_2.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_hash_2.result
@@ -34,5 +34,6 @@
     "PartitionType": "HASH"
   },
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_list.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_list.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_list.result
index 994f408..3a86d96 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_list.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_list.result
@@ -61,5 +61,6 @@
     "PartitionType": "LIST"
   },
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_range.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_range.result b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_range.result
index 9ebb8ab..4112f66 100644
--- a/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_range.result
+++ b/tajo-core-tests/src/test/resources/results/TestSQLAnalyzer/create_table_partition_by_range.result
@@ -51,5 +51,6 @@
     "PartitionType": "RANGE"
   },
   "IfNotExists": false,
+  "HasSelfDescSchema": false,
   "OpType": "CreateTable"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core-tests/src/test/resources/results/TestUnionQuery/testUnionAndFilter.result
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/resources/results/TestUnionQuery/testUnionAndFilter.result b/tajo-core-tests/src/test/resources/results/TestUnionQuery/testUnionAndFilter.result
index 8eb747b..7ef21a8 100644
--- a/tajo-core-tests/src/test/resources/results/TestUnionQuery/testUnionAndFilter.result
+++ b/tajo-core-tests/src/test/resources/results/TestUnionQuery/testUnionAndFilter.result
@@ -1,7 +1,7 @@
 c_custkey,ret
 -------------------------------
-4,2866.83
 1,711.56
-5,794.47
-3,7498.12
 2,121.65
+3,7498.12
+4,2866.83
+5,794.47

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java b/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
index cd43add..227af0b 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/TajoMasterClientService.java
@@ -870,7 +870,11 @@ public class TajoMasterClientService extends AbstractService {
           throw new UnavailableTableLocationException(path.toString(), "no such a directory");
         }
 
-        Schema schema = new Schema(request.getSchema());
+        Schema schema = null;
+        if (request.hasSchema()) {
+          schema = new Schema(request.getSchema());
+        }
+
         TableMeta meta = new TableMeta(request.getMeta());
         PartitionMethodDesc partitionDesc = null;
         if (request.hasPartition()) {
@@ -908,7 +912,7 @@ public class TajoMasterClientService extends AbstractService {
         QueryContext queryContext = new QueryContext(conf, session);
 
         context.getGlobalEngine().getDDLExecutor().dropTable(queryContext, dropTable.getName(), false,
-          dropTable.getPurge());
+            dropTable.getPurge());
         return OK;
 
       } catch (Throwable t) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java b/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
index f7b7bf2..fffee80 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
@@ -24,9 +24,12 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.*;
-import org.apache.tajo.exception.*;
 import org.apache.tajo.catalog.partition.PartitionMethodDesc;
 import org.apache.tajo.engine.query.QueryContext;
+import org.apache.tajo.exception.DuplicateTableException;
+import org.apache.tajo.exception.TajoException;
+import org.apache.tajo.exception.UndefinedTableException;
+import org.apache.tajo.exception.UndefinedTablespaceException;
 import org.apache.tajo.master.TajoMaster;
 import org.apache.tajo.plan.logical.CreateTableNode;
 import org.apache.tajo.plan.util.PlannerUtil;
@@ -78,7 +81,7 @@ public class CreateTableExecutor {
   public TableDesc create(QueryContext queryContext,
                           String tableName,
                           @Nullable String tableSpaceName,
-                          Schema schema,
+                          @Nullable Schema schema,
                           TableMeta meta,
                           @Nullable URI uri,
                           boolean isExternal,

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
index 4e3e369..6190cdc 100644
--- a/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
+++ b/tajo-core/src/main/java/org/apache/tajo/parser/sql/SQLAnalyzer.java
@@ -1294,13 +1294,18 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
     if (checkIfExist(ctx.EXTERNAL())) {
       createTable.setExternal();
 
+      if (checkIfExist(ctx.table_elements().asterisk())) {
+        createTable.setHasSelfDescSchema();
+      } else {
+        ColumnDefinition[] elements = getDefinitions(ctx.table_elements());
+        createTable.setTableElements(elements);
+      }
+
       if (checkIfExist(ctx.TABLESPACE())) {
         throw new TajoRuntimeException(new SQLSyntaxError("Tablespace clause is not allowed for an external table."));
       }
 
-      ColumnDefinition[] elements = getDefinitions(ctx.table_elements());
       String storageType = ctx.storage_type.getText();
-      createTable.setTableElements(elements);
       createTable.setStorageType(storageType);
 
       if (checkIfExist(ctx.LOCATION())) {
@@ -1311,8 +1316,12 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
       }
     } else {
       if (checkIfExist(ctx.table_elements())) {
-        ColumnDefinition[] elements = getDefinitions(ctx.table_elements());
-        createTable.setTableElements(elements);
+        if (checkIfExist(ctx.table_elements().asterisk())) {
+          createTable.setHasSelfDescSchema();
+        } else {
+          ColumnDefinition[] elements = getDefinitions(ctx.table_elements());
+          createTable.setTableElements(elements);
+        }
       }
 
       if (checkIfExist(ctx.TABLESPACE())) {
@@ -1328,6 +1337,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
       if (checkIfExist(ctx.query_expression())) {
         Expr subquery = visitQuery_expression(ctx.query_expression());
         createTable.setSubQuery(subquery);
+        createTable.unsetHasSelfDescSchema();
       }
     }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/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 011f42e..c1e9bdb 100644
--- a/tajo-docs/src/main/sphinx/sql_language/ddl.rst
+++ b/tajo-docs/src/main/sphinx/sql_language/ddl.rst
@@ -37,17 +37,19 @@ CREATE TABLE
 
 .. code-block:: sql
 
-  CREATE TABLE [IF NOT EXISTS] <table_name> [(<column_name> <data_type>, ... )] [TABLESPACE tablespace_name]
+  CREATE TABLE [IF NOT EXISTS] <table_name> [(column_list)] [TABLESPACE tablespace_name]
   [using <storage_type> [with (<key> = <value>, ...)]] [AS <select_statement>]
 
-  CREATE EXTERNAL TABLE [IF NOT EXISTS] <table_name> (<column_name> <data_type>, ... )
+  CREATE EXTERNAL TABLE [IF NOT EXISTS] <table_name> (column_list)
   using <storage_type> [with (<key> = <value>, ...)] LOCATION '<path>'
 
 *Description*
 
-In Tajo, there are two types of tables, `managed table` and `external table` (For more information, please refer to :doc:`/table_management/table_overview`.)
+In Tajo, there are two types of tables, `managed table` and `external table`.
+Managed tables are placed on some predefined tablespaces. The ``TABLESPACE`` clause is to specify a tablespace for this table. For external tables, Tajo allows an arbitrary table location with the ``LOCATION`` clause.
+For more information about tables and tablespace, please refer to :doc:`/table_management/table_overview` and :doc:`/table_management/tablespaces`.
 
-Managed tables are placed on some predefined tablespaces. The ``TABLESPACE`` clause is to specify a tablespace for this table. For more information about tablespace, please refer to :doc:`/table_management/tablespaces`. For external tables, Tajo allows an arbitrary table location with the ``LOCATION`` clause.
+``column_list`` is a sequence of the column name and its type like ``<column_name> <data_type>, ...``. Additionally, the `asterisk (*)` is allowed for external tables when their data format is `JSON`. You can find more details at :doc:`/table_management/json`.
 
 ``IF NOT EXISTS`` allows ``CREATE [EXTERNAL] TABLE`` statement to avoid an error which occurs when the table does not exist.
 
@@ -65,7 +67,7 @@ If you want to add an external table that contains compressed data, you should g
   ...
   L_COMMENT text) 
 
-  USING TEXT WITH ('text.delimiter'='|','compression.codec'='org.apache.hadoop.io.compress.DeflateCodec')
+  USING TEXT WITH ('text.delimiter'='|','compression.codec'='org.apache.hadoop.io.compress.SnappyCodec')
   LOCATION 'hdfs://localhost:9010/tajo/warehouse/lineitem_100_snappy';
 
 `compression.codec` parameter can have one of the following compression codecs:

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-docs/src/main/sphinx/table_management/file_formats.rst
----------------------------------------------------------------------
diff --git a/tajo-docs/src/main/sphinx/table_management/file_formats.rst b/tajo-docs/src/main/sphinx/table_management/file_formats.rst
index 7768920..966903c 100644
--- a/tajo-docs/src/main/sphinx/table_management/file_formats.rst
+++ b/tajo-docs/src/main/sphinx/table_management/file_formats.rst
@@ -2,12 +2,13 @@
 File Formats
 *************************************
 
-Currently, Tajo provides four file formats as follows:
+Currently, Tajo provides following file formats:
 
 .. toctree::
     :maxdepth: 1
 
     text
+    json
     rcfile
     parquet
     orc

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-docs/src/main/sphinx/table_management/json.rst
----------------------------------------------------------------------
diff --git a/tajo-docs/src/main/sphinx/table_management/json.rst b/tajo-docs/src/main/sphinx/table_management/json.rst
new file mode 100644
index 0000000..06d1fe6
--- /dev/null
+++ b/tajo-docs/src/main/sphinx/table_management/json.rst
@@ -0,0 +1,100 @@
+****
+JSON
+****
+
+JSON(JavaScript Object Notation) is an open standard format for data (de)serialization. Since it is simple and human-readable, it is popularly used in many fields.
+Tajo supports JSON as its data format. In this section, you will get an overview of how to create JSON tables and query on them.
+
+============================
+How to Create a JSON Table ?
+============================
+
+You can create a JSON table using the ``CREATE TABLE`` statement. (For more information, please refer to :doc:`/sql_language/ddl`.)
+For example, please consider an example data as follows:
+
+.. code-block:: bash
+
+  $ hdfs dfs -cat /table1/table.json
+  { "title" : "Hand of the King", "name" : { "first_name": "Eddard", "last_name": "Stark"}}
+  { "title" : "Assassin", "name" : { "first_name": "Arya", "last_name": "Stark"}}
+  { "title" : "Dancing Master", "name" : { "first_name": "Syrio", "last_name": "Forel"}}
+
+Tajo provides two ways to create a table for this data. First is a traditional way to create tables. Here is an example.
+
+.. code-block:: sql
+
+  CREATE EXTERNAL TABLE table1 (
+    title TEXT,
+    name RECORD (
+      first_name TEXT,
+      last_name TEXT
+    )
+  ) USING JSON LOCATION '/table1/table.json';
+
+With this way, you need to specify every column which they want to use. This will be a tedious work, and not appropriate for flexible JSON schema.
+Second is a simpler alternative to alleviate this problem. When you create an external table of JSON format, you can simply omit the column specification as follows:
+
+.. code-block:: sql
+
+  CREATE EXTERNAL TABLE table1 (*) USING JSON LOCATION '/table1/table.json';
+
+No matter which way you choose, you can submit any queries on this table.
+
+.. code-block:: sql
+
+  > SELECT title, name.last_name from table1 where name.first_name = 'Arya';
+  title,name/last_name
+  -------------------------------
+  Assassin,Stark
+
+.. warning::
+
+  If you create a table with the second way, every column is assumed as the ``TEXT`` type.
+  So, you need to perform type casting if you want to handle them as other types.
+
+===================
+Physical Properties
+===================
+
+Some table storage formats provide parameters for enabling or disabling features and adjusting physical parameters.
+The ``WITH`` clause in the CREATE TABLE statement allows users to set those parameters.
+
+The JSON format provides the following physical properties.
+
+* ``text.delimiter``: delimiter character. ``|`` or ``\u0001`` is usually used, and the default field delimiter is ``|``.
+* ``text.null``: ``NULL`` character. The default ``NULL`` character is an empty string ``''``. Hive's default ``NULL`` character is ``'\\N'``.
+* ``compression.codec``: Compression codec. You can enable compression feature and set specified compression algorithm. The compression algorithm used to compress files. The compression codec name should be the fully qualified class name inherited from `org.apache.hadoop.io.compress.CompressionCodec <https://hadoop.apache.org/docs/current/api/org/apache/hadoop/io/compress/CompressionCodec.html>`_. By default, compression is disabled.
+* ``timezone``: the time zone that the table uses for writting. When table rows are read or written, ```timestamp``` and ```time``` column values are adjusted by this timezone if it is set. Time zone can be an abbreviation form like 'PST' or 'DST'. Also, it accepts an offset-based form like 'UTC+9' or a location-based form like 'Asia/Seoul'.
+* ``text.error-tolerance.max-num``: the maximum number of permissible parsing errors. This value should be an integer value. By default, ``text.error-tolerance.max-num`` is ``0``. According to the value, parsing errors will be handled in different ways.
+
+  * If ``text.error-tolerance.max-num < 0``, all parsing errors are ignored.
+  * If ``text.error-tolerance.max-num == 0``, any parsing error is not allowed. If any error occurs, the query will be failed. (default)
+  * If ``text.error-tolerance.max-num > 0``, the given number of parsing errors in each task will be pemissible.
+
+* ``text.skip.headerlines``: Number of header lines to be skipped. Some text files often have a header which has a kind of metadata(e.g.: column names), thus this option can be useful.
+
+The following example is to set a custom field delimiter, ``NULL`` character, and compression codec:
+
+.. code-block:: sql
+
+  CREATE TABLE table1 (
+    id int,
+    name text,
+    score float,
+    type text
+  ) USING JSON WITH('text.delimiter'='\u0001',
+                    'text.null'='\\N',
+                    'compression.codec'='org.apache.hadoop.io.compress.SnappyCodec');
+
+.. warning::
+
+  Be careful when using ``\n`` as the field delimiter because *TEXT* format tables use ``\n`` as the line delimiter.
+  At the moment, Tajo does not provide a way to specify the line delimiter.
+
+==========================
+Null Value Handling Issues
+==========================
+In default, ``NULL`` character in *TEXT* format is an empty string ``''``.
+In other words, an empty field is basically recognized as a ``NULL`` value in Tajo.
+If a field domain is ``TEXT``, an empty field is recognized as a string value ``''`` instead of ``NULL`` value.
+Besides, You can also use your own ``NULL`` character by specifying a physical property ``text.null``.

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-docs/src/main/sphinx/table_management/text.rst
----------------------------------------------------------------------
diff --git a/tajo-docs/src/main/sphinx/table_management/text.rst b/tajo-docs/src/main/sphinx/table_management/text.rst
index 4755334..b79b0e2 100644
--- a/tajo-docs/src/main/sphinx/table_management/text.rst
+++ b/tajo-docs/src/main/sphinx/table_management/text.rst
@@ -2,8 +2,8 @@
 TEXT
 ****
 
-A character-separated values plain-text file represents a tabular data set consisting of rows and columns.
-Each row is a plan-text line. A line is usually broken by a character line feed ``\n`` or carriage-return ``\r``.
+A character-separated values plain text file represents a tabular data set consisting of rows and columns.
+Each row is a plain text line. A line is usually broken by a character line feed ``\n`` or carriage-return ``\r``.
 The line feed ``\n`` is the default delimiter in Tajo. Each record consists of multiple fields, separated by
 some other character or string, most commonly a literal vertical bar ``|``, comma ``,`` or tab ``\t``.
 The vertical bar is used as the default field delimiter in Tajo.
@@ -72,8 +72,8 @@ Custom (De)serializer
 =====================
 
 The *TEXT* format not only provides reading and writing interfaces for text data but also allows users to process custom
-plan-text file formats with user-defined (De)serializer classes.
-For example, with custom (de)serializers, Tajo can process JSON file formats or any specialized plan-text file formats.
+plain text file formats with user-defined (De)serializer classes.
+With custom (de)serializers, Tajo can process any text files no matter which the internal structure is.
 
 In order to specify a custom (De)serializer, set a physical property ``text.serde``.
 The property value should be a fully qualified class name.

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java b/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java
index b062e8e..89089e0 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java
@@ -76,20 +76,27 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
     LogicalPlan plan;
     LogicalPlan.QueryBlock currentBlock;
     NameResolvingMode columnRsvLevel;
+    boolean includeSelfDescTable;
 
-    public Context(LogicalPlanner.PlanContext planContext, NameResolvingMode colRsvLevel) {
+    public Context(LogicalPlanner.PlanContext planContext, NameResolvingMode colRsvLevel, boolean includeSeflDescTable) {
       this.queryContext = planContext.queryContext;
       this.timeZone = planContext.timeZone;
 
       this.plan = planContext.plan;
       this.currentBlock = planContext.queryBlock;
       this.columnRsvLevel = colRsvLevel;
+      this.includeSelfDescTable = includeSeflDescTable;
     }
   }
 
   public EvalNode createEvalNode(LogicalPlanner.PlanContext planContext, Expr expr,
                                  NameResolvingMode colRsvLevel) throws TajoException {
-    Context context = new Context(planContext, colRsvLevel);
+    return createEvalNode(planContext, expr, colRsvLevel, false);
+  }
+
+  public EvalNode createEvalNode(LogicalPlanner.PlanContext planContext, Expr expr,
+                                 NameResolvingMode colRsvLevel, boolean includeSeflDescTable) throws TajoException {
+    Context context = new Context(planContext, colRsvLevel, includeSeflDescTable);
     return planContext.evalOptimizer.optimize(planContext, visit(context, new Stack<Expr>(), expr));
   }
 
@@ -542,12 +549,10 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
 
     switch (ctx.columnRsvLevel) {
     case LEGACY:
-      column = ctx.plan.resolveColumn(ctx.currentBlock, expr);
-      break;
     case RELS_ONLY:
     case RELS_AND_SUBEXPRS:
     case SUBEXPRS_AND_RELS:
-      column = NameResolver.resolve(ctx.plan, ctx.currentBlock, expr, ctx.columnRsvLevel);
+      column = NameResolver.resolve(ctx.plan, ctx.currentBlock, expr, ctx.columnRsvLevel, ctx.includeSelfDescTable);
       break;
     default:
       throw new TajoInternalError("Unsupported column resolving level: " + ctx.columnRsvLevel.name());

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java b/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java
index 504c625..3531ce7 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java
@@ -1376,7 +1376,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
   }
 
   private static LinkedHashSet<Target> createFieldTargetsFromRelation(QueryBlock block, RelationNode relationNode,
-                                                      Set<String> newlyEvaluatedRefNames) {
+                                                                      Set<String> newlyEvaluatedRefNames) {
     LinkedHashSet<Target> targets = Sets.newLinkedHashSet();
     for (Column column : relationNode.getLogicalSchema().getAllColumns()) {
 
@@ -2000,8 +2000,12 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
       return createTableNode;
 
     } else { // if CREATE AN EMPTY TABLE
-      Schema tableSchema = convertColumnsToSchema(expr.getTableElements());
-      createTableNode.setTableSchema(tableSchema);
+      if (!expr.hasSelfDescSchema()) {
+        Schema tableSchema = convertColumnsToSchema(expr.getTableElements());
+        createTableNode.setTableSchema(tableSchema);
+      } else {
+        createTableNode.setSelfDescSchema(true);
+      }
 
       if (expr.isExternal()) {
         createTableNode.setExternal(true);

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java b/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java
index dfa8079..af413ca 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/TypeDeterminant.java
@@ -31,6 +31,8 @@ import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.exception.TajoInternalError;
 import org.apache.tajo.function.FunctionUtil;
+import org.apache.tajo.plan.nameresolver.NameResolver;
+import org.apache.tajo.plan.nameresolver.NameResolvingMode;
 import org.apache.tajo.plan.visitor.SimpleAlgebraVisitor;
 
 import java.util.Stack;
@@ -142,7 +144,7 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<LogicalPlanner.PlanCon
   public DataType visitColumnReference(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, ColumnReferenceExpr expr)
       throws TajoException {
     stack.push(expr);
-    Column column = ctx.plan.resolveColumn(ctx.queryBlock, expr);
+    Column column = NameResolver.resolve(ctx.plan, ctx.queryBlock, expr, NameResolvingMode.LEGACY, true);
     stack.pop();
     return column.getDataType();
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/algebra/BaseAlgebraVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/algebra/BaseAlgebraVisitor.java b/tajo-plan/src/main/java/org/apache/tajo/plan/algebra/BaseAlgebraVisitor.java
index 2d200fc..135f9ac 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/algebra/BaseAlgebraVisitor.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/algebra/BaseAlgebraVisitor.java
@@ -508,6 +508,7 @@ public class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisitor<CONTE
   // Insert or Update Section
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
+  @Override
   public RESULT visitInsert(CONTEXT ctx, Stack<Expr> stack, Insert expr) throws TajoException {
     stack.push(expr);
     RESULT child = visit(ctx, stack, expr.getSubQuery());

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateTableNode.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateTableNode.java b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateTableNode.java
index 46ea458..9a169dd 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateTableNode.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/CreateTableNode.java
@@ -30,6 +30,7 @@ public class CreateTableNode extends StoreTableNode implements Cloneable {
   @Expose private String tableSpaceName;
   @Expose private boolean external;
   @Expose private boolean ifNotExists;
+  @Expose private boolean selfDescSchema = false;
 
   public CreateTableNode(int pid) {
     super(pid, NodeType.CREATE_TABLE);
@@ -82,6 +83,14 @@ public class CreateTableNode extends StoreTableNode implements Cloneable {
     return ifNotExists;
   }
 
+  public void setSelfDescSchema(boolean selfDescSchema) {
+    this.selfDescSchema = selfDescSchema;
+  }
+
+  public boolean hasSelfDescSchema() {
+    return selfDescSchema;
+  }
+
   @Override
   public PlanString getPlanString() {
     return new PlanString(this);

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/logical/StoreTableNode.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/StoreTableNode.java b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/StoreTableNode.java
index 170e13c..262d497 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/logical/StoreTableNode.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/logical/StoreTableNode.java
@@ -74,6 +74,10 @@ public class StoreTableNode extends PersistentStoreNode implements Cloneable {
     return this.uri;
   }
 
+  public boolean hasTableSchema() {
+    return this.tableSchema != null;
+  }
+
   public void setTableSchema(Schema schema) {
     this.tableSchema = schema;
   }
@@ -117,10 +121,10 @@ public class StoreTableNode extends PersistentStoreNode implements Cloneable {
     if (obj instanceof StoreTableNode) {
       StoreTableNode other = (StoreTableNode) obj;
       boolean eq = super.equals(other);
-      eq = eq && TUtil.checkEquals(this.tableName, other.tableName);
-      eq = eq && TUtil.checkEquals(uri, other.uri);
-      eq = tableSchema.equals(other.tableSchema);
-      eq = eq && TUtil.checkEquals(partitionDesc, other.partitionDesc);
+      eq &= TUtil.checkEquals(this.tableName, other.tableName);
+      eq &= TUtil.checkEquals(uri, other.uri);
+      eq &= TUtil.checkEquals(tableSchema, other.tableSchema);
+      eq &= TUtil.checkEquals(partitionDesc, other.partitionDesc);
       return eq;
     } else {
       return false;

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java
index b41ef76..58ec60c 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolver.java
@@ -26,9 +26,11 @@ import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.NestedPathUtil;
 import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.exception.*;
 import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.logical.RelationNode;
+import org.apache.tajo.plan.logical.ScanNode;
 import org.apache.tajo.util.Pair;
 import org.apache.tajo.util.StringUtils;
 import org.apache.tajo.util.TUtil;
@@ -68,13 +70,19 @@ public abstract class NameResolver {
 
   public static Column resolve(LogicalPlan plan, LogicalPlan.QueryBlock block, ColumnReferenceExpr column,
                                NameResolvingMode mode) throws TajoException {
+    return resolve(plan, block, column, mode, false);
+  }
+
+  public static Column resolve(LogicalPlan plan, LogicalPlan.QueryBlock block, ColumnReferenceExpr column,
+                               NameResolvingMode mode, boolean includeSelfDescTable) throws TajoException {
     if (!resolverMap.containsKey(mode)) {
       throw new RuntimeException("Unsupported name resolving level: " + mode.name());
     }
-    return resolverMap.get(mode).resolve(plan, block, column);
+    return resolverMap.get(mode).resolve(plan, block, column, includeSelfDescTable);
   }
 
-  abstract Column resolve(LogicalPlan plan, LogicalPlan.QueryBlock block, ColumnReferenceExpr columnRef)
+  abstract Column resolve(LogicalPlan plan, LogicalPlan.QueryBlock block, ColumnReferenceExpr columnRef,
+                          boolean includeSelfDescTable)
   throws TajoException;
 
   /**
@@ -143,7 +151,7 @@ public abstract class NameResolver {
    * @return The found column
    */
   static Column resolveFromRelsWithinBlock(LogicalPlan plan, LogicalPlan.QueryBlock block,
-                                           ColumnReferenceExpr columnRef)
+                                           ColumnReferenceExpr columnRef, boolean includeSeflDescTable)
       throws AmbiguousColumnException, AmbiguousTableException, UndefinedColumnException, UndefinedTableException {
     String qualifier;
     String canonicalName;
@@ -151,7 +159,7 @@ public abstract class NameResolver {
     if (columnRef.hasQualifier()) {
       Pair<String, String> normalized;
       try {
-        normalized = lookupQualifierAndCanonicalName(block, columnRef);
+        normalized = lookupQualifierAndCanonicalName(block, columnRef, includeSeflDescTable);
       } catch (UndefinedColumnException udce) {
         // is it correlated subquery?
         // if the search column is not found at the current block, find it at all ancestors of the block.
@@ -178,22 +186,28 @@ public abstract class NameResolver {
         throw new UndefinedTableException(qualifier);
       }
 
-      // Please consider a query case:
-      // select lineitem.l_orderkey from lineitem a order by lineitem.l_orderkey;
-      //
-      // The relation lineitem is already renamed to "a", but lineitem.l_orderkey still should be available.
-      // The below code makes it possible. Otherwise, it cannot find any match in the relation schema.
-      if (block.isAlreadyRenamedTableName(CatalogUtil.extractQualifier(canonicalName))) {
-        canonicalName =
-            CatalogUtil.buildFQName(relationOp.getCanonicalName(), CatalogUtil.extractSimpleName(canonicalName));
-      }
+      Column column;
+      if (includeSeflDescTable && describeSchemaByItself(relationOp)) {
+        column = guessColumn(CatalogUtil.buildFQName(normalized.getFirst(), normalized.getSecond()));
+
+      } else {
+        // Please consider a query case:
+        // select lineitem.l_orderkey from lineitem a order by lineitem.l_orderkey;
+        //
+        // The relation lineitem is already renamed to "a", but lineitem.l_orderkey still should be available.
+        // The below code makes it possible. Otherwise, it cannot find any match in the relation schema.
+        if (block.isAlreadyRenamedTableName(CatalogUtil.extractQualifier(canonicalName))) {
+          canonicalName =
+              CatalogUtil.buildFQName(relationOp.getCanonicalName(), CatalogUtil.extractSimpleName(canonicalName));
+        }
 
-      Schema schema = relationOp.getLogicalSchema();
-      Column column = schema.getColumn(canonicalName);
+        Schema schema = relationOp.getLogicalSchema();
+        column = schema.getColumn(canonicalName);
+      }
 
       return column;
     } else {
-      return lookupColumnFromAllRelsInBlock(block, columnRef.getName());
+      return lookupColumnFromAllRelsInBlock(block, columnRef.getName(), includeSeflDescTable);
     }
   }
 
@@ -231,7 +245,7 @@ public abstract class NameResolver {
    * @return The found column
    */
   static Column lookupColumnFromAllRelsInBlock(LogicalPlan.QueryBlock block,
-                                               String columnName) throws AmbiguousColumnException {
+                                               String columnName, boolean includeSelfDescTable) throws AmbiguousColumnException {
     Preconditions.checkArgument(CatalogUtil.isSimpleIdentifier(columnName));
 
     List<Column> candidates = TUtil.newList();
@@ -248,10 +262,36 @@ public abstract class NameResolver {
     if (!candidates.isEmpty()) {
       return ensureUniqueColumn(candidates);
     } else {
+      if (includeSelfDescTable) {
+        List<RelationNode> candidateRels = TUtil.newList();
+        for (RelationNode rel : block.getRelations()) {
+          if (describeSchemaByItself(rel)) {
+            candidateRels.add(rel);
+          }
+        }
+        if (candidateRels.size() == 1) {
+          return guessColumn(CatalogUtil.buildFQName(candidateRels.get(0).getCanonicalName(), columnName));
+        } else if (candidateRels.size() > 1) {
+          throw new AmbiguousColumnException(columnName);
+        }
+      }
+
       return null;
     }
   }
 
+  static boolean describeSchemaByItself(RelationNode relationNode) {
+    if (relationNode instanceof ScanNode && ((ScanNode) relationNode).getTableDesc().hasEmptySchema()) {
+      return true;
+    }
+    return false;
+  }
+
+  static Column guessColumn(String qualifiedName) {
+    // TODO: other data types must be supported.
+    return new Column(qualifiedName, Type.TEXT);
+  }
+
   /**
    * Trying to find a column from all relations in other blocks
    *
@@ -319,7 +359,7 @@ public abstract class NameResolver {
    * @return A pair of normalized qualifier and column name
    */
   static Pair<String, String> lookupQualifierAndCanonicalName(LogicalPlan.QueryBlock block,
-                                                              ColumnReferenceExpr columnRef)
+                                                              ColumnReferenceExpr columnRef, boolean includeSeflDescTable)
       throws AmbiguousColumnException, AmbiguousTableException, UndefinedColumnException {
 
     Preconditions.checkArgument(columnRef.hasQualifier(), "ColumnReferenceExpr must be qualified.");
@@ -374,13 +414,30 @@ public abstract class NameResolver {
 
     // throw exception if no column cannot be founded or two or more than columns are founded
     if (guessedRelations.size() == 0) {
-      throw new UndefinedColumnException(columnRef.getCanonicalName());
+      if (includeSeflDescTable) {
+        // check self-describing relations
+        for (RelationNode rel : block.getRelations()) {
+          if (describeSchemaByItself(rel)) {
+            columnNamePosition = 0;
+            guessedRelations.add(rel);
+          }
+        }
+
+        if (guessedRelations.size() > 1) {
+          throw new AmbiguousColumnException(columnRef.getCanonicalName());
+        } else if (guessedRelations.size() == 0) {
+          throw new UndefinedColumnException(columnRef.getCanonicalName());
+        }
+      } else {
+        throw new UndefinedColumnException(columnRef.getCanonicalName());
+      }
+
     } else if (guessedRelations.size() > 1) {
       throw new AmbiguousColumnException(columnRef.getCanonicalName());
     }
 
     String qualifier = guessedRelations.iterator().next().getCanonicalName();
-    String columnName = "";
+    String columnName;
 
     if (columnNamePosition >= qualifierParts.length) { // if there is no column in qualifierParts
       columnName = columnRef.getName();
@@ -398,7 +455,7 @@ public abstract class NameResolver {
       columnName += NestedPathUtil.PATH_DELIMITER + columnRef.getName();
     }
 
-    return new Pair<String, String>(qualifier, columnName);
+    return new Pair<>(qualifier, columnName);
   }
 
   static Column ensureUniqueColumn(List<Column> candidates) throws AmbiguousColumnException {

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolvingMode.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolvingMode.java b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolvingMode.java
index 4d9f9a5..6ea2f57 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolvingMode.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/NameResolvingMode.java
@@ -73,8 +73,8 @@ package org.apache.tajo.plan.nameresolver;
  * </ol>
  */
 public enum NameResolvingMode {
-  RELS_ONLY,          // finding from only relations
-  RELS_AND_SUBEXPRS,  // finding from relations and subexprs in a place
-  SUBEXPRS_AND_RELS,  // finding from subexprs and relations in a place
-  LEGACY              // Finding in a legacy manner (globally)
+  RELS_ONLY,                    // finding from only relations excluding self-describing ones
+  RELS_AND_SUBEXPRS,            // finding from relations and subexprs in a place
+  SUBEXPRS_AND_RELS,            // finding from subexprs and relations in a place
+  LEGACY                        // Finding in a legacy manner (globally)
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java
index 8991b60..94e38be 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByLegacy.java
@@ -22,9 +22,9 @@ import org.apache.tajo.algebra.ColumnReferenceExpr;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
-import org.apache.tajo.exception.UndefinedColumnException;
 import org.apache.tajo.exception.AmbiguousColumnException;
 import org.apache.tajo.exception.TajoException;
+import org.apache.tajo.exception.UndefinedColumnException;
 import org.apache.tajo.plan.LogicalPlan;
 import org.apache.tajo.plan.logical.LogicalNode;
 import org.apache.tajo.plan.logical.NodeType;
@@ -36,26 +36,30 @@ import java.util.List;
 
 public class ResolverByLegacy extends NameResolver {
   @Override
-  public Column resolve(LogicalPlan plan, LogicalPlan.QueryBlock block, ColumnReferenceExpr columnRef)
+  public Column resolve(LogicalPlan plan,
+                        LogicalPlan.QueryBlock block,
+                        ColumnReferenceExpr columnRef,
+                        boolean includeSeflDescTable)
       throws TajoException {
 
     if (columnRef.hasQualifier()) {
-      return resolveColumnWithQualifier(plan, block, columnRef);
+      return resolveColumnWithQualifier(plan, block, columnRef, includeSeflDescTable);
     } else {
-      return resolveColumnWithoutQualifier(plan, block, columnRef);
+      return resolveColumnWithoutQualifier(plan, block, columnRef, includeSeflDescTable);
     }
   }
 
   private static Column resolveColumnWithQualifier(LogicalPlan plan, LogicalPlan.QueryBlock block,
-                                                   ColumnReferenceExpr columnRef) throws TajoException {
+                                                   ColumnReferenceExpr columnRef, boolean includeSeflDescTable)
+      throws TajoException {
     final String qualifier;
     final String qualifiedName;
 
-    Pair<String, String> normalized = lookupQualifierAndCanonicalName(block, columnRef);
+    Pair<String, String> normalized = lookupQualifierAndCanonicalName(block, columnRef, includeSeflDescTable);
     qualifier = normalized.getFirst();
     qualifiedName = CatalogUtil.buildFQName(qualifier, columnRef.getName());
 
-    Column found = resolveFromRelsWithinBlock(plan, block, columnRef);
+    Column found = resolveFromRelsWithinBlock(plan, block, columnRef, includeSeflDescTable);
     if (found == null) {
       throw new UndefinedColumnException(columnRef.getCanonicalName());
     }
@@ -84,7 +88,7 @@ public class ResolverByLegacy extends NameResolver {
       List<Column> candidates = TUtil.newList();
       if (block.getNamedExprsManager().isAliased(qualifiedName)) {
         String alias = block.getNamedExprsManager().getAlias(qualifiedName);
-        found = resolve(plan, block, new ColumnReferenceExpr(alias), NameResolvingMode.LEGACY);
+        found = resolve(plan, block, new ColumnReferenceExpr(alias), NameResolvingMode.LEGACY, includeSeflDescTable);
         if (found != null) {
           candidates.add(found);
         }
@@ -98,10 +102,10 @@ public class ResolverByLegacy extends NameResolver {
   }
 
   static Column resolveColumnWithoutQualifier(LogicalPlan plan, LogicalPlan.QueryBlock block,
-                                                     ColumnReferenceExpr columnRef)
+                                              ColumnReferenceExpr columnRef, boolean includeSeflDescTable)
       throws AmbiguousColumnException, UndefinedColumnException {
 
-    Column found = lookupColumnFromAllRelsInBlock(block, columnRef.getName());
+    Column found = lookupColumnFromAllRelsInBlock(block, columnRef.getName(), includeSeflDescTable);
     if (found != null) {
       return found;
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRels.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRels.java b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRels.java
index 82fbc21..4572143 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRels.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRels.java
@@ -28,13 +28,17 @@ import org.apache.tajo.plan.LogicalPlan;
 
 public class ResolverByRels extends NameResolver {
   @Override
-  public Column resolve(LogicalPlan plan, LogicalPlan.QueryBlock block, ColumnReferenceExpr columnRef)
+  public Column resolve(LogicalPlan plan,
+                        LogicalPlan.QueryBlock block,
+                        ColumnReferenceExpr columnRef,
+                        boolean includeSeflDescTable)
       throws AmbiguousColumnException, AmbiguousTableException, UndefinedColumnException, UndefinedTableException {
 
-    Column column = resolveFromRelsWithinBlock(plan, block, columnRef);
-    if (column == null) {
-      throw new UndefinedColumnException(columnRef.getCanonicalName());
+    Column column = resolveFromRelsWithinBlock(plan, block, columnRef, includeSeflDescTable);
+    if (column != null) {
+      return column;
     }
-    return column;
+
+    throw new UndefinedColumnException(columnRef.getCanonicalName());
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRelsAndSubExprs.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRelsAndSubExprs.java b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRelsAndSubExprs.java
index 4bfdaf6..6ce7c67 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRelsAndSubExprs.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverByRelsAndSubExprs.java
@@ -28,17 +28,22 @@ import org.apache.tajo.plan.LogicalPlan;
 
 public class ResolverByRelsAndSubExprs extends NameResolver {
   @Override
-  public Column resolve(LogicalPlan plan, LogicalPlan.QueryBlock block, ColumnReferenceExpr columnRef)
+  public Column resolve(LogicalPlan plan,
+                        LogicalPlan.QueryBlock block,
+                        ColumnReferenceExpr columnRef,
+                        boolean includeSeflDescTable)
       throws AmbiguousColumnException, AmbiguousTableException, UndefinedColumnException, UndefinedTableException {
 
-    Column column = resolveFromRelsWithinBlock(plan, block, columnRef);
-    if (column == null) {
-      column =  resolveFromCurrentAndChildNode(block, columnRef);
+    Column column = resolveFromRelsWithinBlock(plan, block, columnRef, includeSeflDescTable);
+    if (column != null) {
+      return column;
     }
 
-    if (column == null) {
-      throw new UndefinedColumnException(columnRef.getCanonicalName());
+    column = resolveFromCurrentAndChildNode(block, columnRef);
+    if (column != null) {
+      return column;
     }
-    return column;
+
+    throw new UndefinedColumnException(columnRef.getCanonicalName());
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverBySubExprsAndRels.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverBySubExprsAndRels.java b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverBySubExprsAndRels.java
index ea291f4..4ed884e 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverBySubExprsAndRels.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/nameresolver/ResolverBySubExprsAndRels.java
@@ -28,17 +28,22 @@ import org.apache.tajo.plan.LogicalPlan;
 
 public class ResolverBySubExprsAndRels extends NameResolver {
   @Override
-  public Column resolve(LogicalPlan plan, LogicalPlan.QueryBlock block, ColumnReferenceExpr columnRef)
+  public Column resolve(LogicalPlan plan,
+                        LogicalPlan.QueryBlock block,
+                        ColumnReferenceExpr columnRef,
+                        boolean includeSeflDescTable)
       throws AmbiguousColumnException, AmbiguousTableException, UndefinedColumnException, UndefinedTableException {
 
     Column column = resolveFromCurrentAndChildNode(block, columnRef);
-    if (column == null) {
-      column = resolveFromRelsWithinBlock(plan, block, columnRef);
+    if (column != null) {
+      return column;
     }
 
-    if (column == null) {
-      throw new UndefinedColumnException(columnRef.getCanonicalName());
+    column = resolveFromRelsWithinBlock(plan, block, columnRef, includeSeflDescTable);
+    if (column != null) {
+      return column;
     }
-    return column;
+
+    throw new UndefinedColumnException(columnRef.getCanonicalName());
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseLogicalPlanPreprocessPhaseProvider.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseLogicalPlanPreprocessPhaseProvider.java b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseLogicalPlanPreprocessPhaseProvider.java
index 92af709..3f64ae6 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseLogicalPlanPreprocessPhaseProvider.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseLogicalPlanPreprocessPhaseProvider.java
@@ -27,7 +27,8 @@ public class BaseLogicalPlanPreprocessPhaseProvider extends LogicalPlanPreproces
   @Override
   public Collection<Class<? extends LogicalPlanPreprocessPhase>> getPhases() {
     List phases = TUtil.newList(
-        BaseSchemaBuildPhase.class
+        BaseSchemaBuildPhase.class,
+        SelfDescSchemaBuildPhase.class
     );
     return phases;
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java
index 81e9b2c..f26e190 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/BaseSchemaBuildPhase.java
@@ -40,6 +40,13 @@ import org.apache.tajo.util.TUtil;
 
 import java.util.*;
 
+/**
+ * BaseSchemaBuildPhase builds a basic schema information of tables which have pre-defined schema.
+ * For example, tables like the below example have pre-defined schema.
+ *
+ * CREATE TABLE t1 (id int8, name text);
+ * CREATE EXTERNAL TABLE t2 (id int8, score int8, dept text);
+ */
 public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
 
   private final Processor processor;
@@ -178,15 +185,6 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
       return newTargetExprs;
     }
 
-    private static boolean hasAsterisk(NamedExpr [] namedExprs) {
-      for (NamedExpr eachTarget : namedExprs) {
-        if (eachTarget.getExpr().getType() == OpType.Asterisk) {
-          return true;
-        }
-      }
-      return false;
-    }
-
     private static NamedExpr [] voidResolveAsteriskNamedExpr(LogicalPlanner.PlanContext context,
                                                              NamedExpr [] namedExprs) throws TajoException {
       List<NamedExpr> rewrittenTargets = TUtil.newList();
@@ -222,7 +220,7 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
       LogicalNode child = visit(ctx, stack, expr.getChild());
 
       // Resolve the asterisk expression
-      if (hasAsterisk(expr.getNamedExprs())) {
+      if (PlannerUtil.hasAsterisk(expr.getNamedExprs())) {
         expr.setNamedExprs(voidResolveAsteriskNamedExpr(ctx, expr.getNamedExprs()));
       }
 
@@ -239,7 +237,7 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
               namedExpr.getAlias());
         } else if (OpType.isLiteralType(namedExpr.getExpr().getType()) && namedExpr.hasAlias()) {
           Expr constExpr = namedExpr.getExpr();
-          ConstEval constEval = (ConstEval) annotator.createEvalNode(ctx, constExpr, NameResolvingMode.RELS_ONLY);
+          ConstEval constEval = (ConstEval) annotator.createEvalNode(ctx, constExpr, NameResolvingMode.RELS_ONLY, true);
           ctx.getQueryBlock().addConstReference(namedExpr.getAlias(), constExpr, constEval);
         }
       }
@@ -320,13 +318,13 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
       int finalTargetNum = projection.getNamedExprs().length;
       Target [] targets = new Target[finalTargetNum];
 
-      if (hasAsterisk(projection.getNamedExprs())) {
+      if (PlannerUtil.hasAsterisk(projection.getNamedExprs())) {
         projection.setNamedExprs(voidResolveAsteriskNamedExpr(ctx, projection.getNamedExprs()));
       }
 
       for (int i = 0; i < finalTargetNum; i++) {
         NamedExpr namedExpr = projection.getNamedExprs()[i];
-        EvalNode evalNode = annotator.createEvalNode(ctx, namedExpr.getExpr(), NameResolvingMode.SUBEXPRS_AND_RELS);
+        EvalNode evalNode = annotator.createEvalNode(ctx, namedExpr.getExpr(), NameResolvingMode.SUBEXPRS_AND_RELS, true);
 
         if (namedExpr.hasAlias()) {
           targets[i] = new Target(evalNode, namedExpr.getAlias());
@@ -564,7 +562,7 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
       return insertNode;
     }
 
-    static class NameRefInSelectListNormalizer extends SimpleAlgebraVisitor<PlanContext, Object> {
+    public static class NameRefInSelectListNormalizer extends SimpleAlgebraVisitor<PlanContext, Object> {
       private static final NameRefInSelectListNormalizer instance;
 
       static {
@@ -581,7 +579,7 @@ public class BaseSchemaBuildPhase extends LogicalPlanPreprocessPhase {
           throws TajoException {
 
         String normalized = NameResolver.resolve(ctx.getPlan(), ctx.getQueryBlock(), expr,
-            NameResolvingMode.RELS_ONLY).getQualifiedName();
+            NameResolvingMode.RELS_ONLY, true).getQualifiedName();
         expr.setName(normalized);
 
         return expr;

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/LogicalPlanPreprocessPhase.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/LogicalPlanPreprocessPhase.java b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/LogicalPlanPreprocessPhase.java
index 21f8b5c..dfdcb7a 100644
--- a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/LogicalPlanPreprocessPhase.java
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/LogicalPlanPreprocessPhase.java
@@ -49,7 +49,7 @@ public abstract class LogicalPlanPreprocessPhase {
    * @param expr
    * @return
    */
-  public abstract boolean isEligible(PlanContext context, Expr expr);
+  public abstract boolean isEligible(PlanContext context, Expr expr) throws TajoException;
 
   /**
    * Do a pre-process phase for an expression tree and returns it.

http://git-wip-us.apache.org/repos/asf/tajo/blob/5a155861/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/SelfDescSchemaBuildPhase.java
----------------------------------------------------------------------
diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/SelfDescSchemaBuildPhase.java b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/SelfDescSchemaBuildPhase.java
new file mode 100644
index 0000000..310f238
--- /dev/null
+++ b/tajo-plan/src/main/java/org/apache/tajo/plan/rewrite/SelfDescSchemaBuildPhase.java
@@ -0,0 +1,489 @@
+/**
+ * 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.plan.rewrite;
+
+import com.google.common.base.Objects;
+import org.apache.tajo.SessionVars;
+import org.apache.tajo.algebra.*;
+import org.apache.tajo.catalog.*;
+import org.apache.tajo.common.TajoDataTypes.Type;
+import org.apache.tajo.exception.TajoException;
+import org.apache.tajo.exception.TajoInternalError;
+import org.apache.tajo.exception.UnsupportedException;
+import org.apache.tajo.plan.ExprAnnotator;
+import org.apache.tajo.plan.LogicalPlan;
+import org.apache.tajo.plan.LogicalPlan.QueryBlock;
+import org.apache.tajo.plan.LogicalPlanner.PlanContext;
+import org.apache.tajo.plan.algebra.BaseAlgebraVisitor;
+import org.apache.tajo.plan.logical.*;
+import org.apache.tajo.plan.nameresolver.NameResolver;
+import org.apache.tajo.plan.nameresolver.NameResolvingMode;
+import org.apache.tajo.plan.rewrite.BaseSchemaBuildPhase.Processor.NameRefInSelectListNormalizer;
+import org.apache.tajo.plan.util.ExprFinder;
+import org.apache.tajo.plan.util.PlannerUtil;
+import org.apache.tajo.plan.visitor.SimpleAlgebraVisitor;
+import org.apache.tajo.util.StringUtils;
+import org.apache.tajo.util.TUtil;
+import org.apache.tajo.util.graph.DirectedGraphVisitor;
+import org.apache.tajo.util.graph.SimpleDirectedGraph;
+
+import java.util.*;
+
+/**
+ * SelfDescSchemaBuildPhase builds the schema information of tables of self-describing data formats,
+ * such as JSON, Parquet, and ORC.
+ */
+public class SelfDescSchemaBuildPhase extends LogicalPlanPreprocessPhase {
+
+  private Processor processor;
+
+  public SelfDescSchemaBuildPhase(CatalogService catalog, ExprAnnotator annotator) {
+    super(catalog, annotator);
+  }
+
+  @Override
+  public String getName() {
+    return "Self-describing schema build phase";
+  }
+
+  private static String getQualifiedRelationName(PlanContext context, Relation relation) {
+    return CatalogUtil.isFQTableName(relation.getName()) ?
+        relation.getName() :
+        CatalogUtil.buildFQName(context.getQueryContext().get(SessionVars.CURRENT_DATABASE), relation.getName());
+  }
+
+  @Override
+  public boolean isEligible(PlanContext context, Expr expr) throws TajoException {
+    Set<Relation> relations = ExprFinderIncludeSubquery.finds(expr, OpType.Relation);
+    for (Relation eachRelation : relations) {
+      TableDesc tableDesc = catalog.getTableDesc(getQualifiedRelationName(context, eachRelation));
+      if (tableDesc.hasEmptySchema()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static class FinderContext<T> {
+    Set<T> set = new HashSet<>();
+    OpType targetType;
+
+    FinderContext(OpType type) {
+      this.targetType = type;
+    }
+  }
+
+  private static class ExprFinderIncludeSubquery extends SimpleAlgebraVisitor<FinderContext, Object> {
+
+    public static <T extends Expr> Set<T> finds(Expr expr, OpType type) throws TajoException {
+      FinderContext<T> context = new FinderContext<>(type);
+      ExprFinderIncludeSubquery finder = new ExprFinderIncludeSubquery();
+      finder.visit(context, new Stack<Expr>(), expr);
+      return context.set;
+    }
+
+    @Override
+    public Object visit(FinderContext ctx, Stack<Expr> stack, Expr expr) throws TajoException {
+      if (expr instanceof Selection) {
+        preHook(ctx, stack, expr);
+        visit(ctx, stack, ((Selection) expr).getQual());
+        visitUnaryOperator(ctx, stack, (UnaryOperator) expr);
+        postHook(ctx, stack, expr, null);
+      } else if (expr instanceof UnaryOperator) {
+        preHook(ctx, stack, expr);
+        visitUnaryOperator(ctx, stack, (UnaryOperator) expr);
+        postHook(ctx, stack, expr, null);
+      } else if (expr instanceof BinaryOperator) {
+        preHook(ctx, stack, expr);
+        visitBinaryOperator(ctx, stack, (BinaryOperator) expr);
+        postHook(ctx, stack, expr, null);
+      } else if (expr instanceof SimpleTableSubquery) {
+        preHook(ctx, stack, expr);
+        visit(ctx, stack, ((SimpleTableSubquery) expr).getSubQuery());
+        postHook(ctx, stack, expr, null);
+      } else if (expr instanceof TablePrimarySubQuery) {
+        preHook(ctx, stack, expr);
+        visit(ctx, stack, ((TablePrimarySubQuery) expr).getSubQuery());
+        postHook(ctx, stack, expr, null);
+      } else {
+        super.visit(ctx, stack, expr);
+      }
+
+      if (expr != null && ctx.targetType == expr.getType()) {
+        ctx.set.add(expr);
+      }
+
+      return null;
+    }
+  }
+
+  @Override
+  public LogicalNode process(PlanContext context, Expr expr) throws TajoException {
+    if (processor == null) {
+      processor = new Processor();
+    }
+    return processor.visit(new ProcessorContext(context), new Stack<Expr>(), expr);
+  }
+
+  static class ProcessorContext {
+    final PlanContext planContext;
+    final Map<String, List<ColumnReferenceExpr>> projectColumns = new HashMap<>();
+
+    public ProcessorContext(PlanContext planContext) {
+      this.planContext = planContext;
+    }
+  }
+
+  static class Processor extends BaseAlgebraVisitor<ProcessorContext, LogicalNode> {
+
+    private static <T extends LogicalNode> T getNodeFromExpr(LogicalPlan plan, Expr expr) {
+      return plan.getBlockByExpr(expr).getNodeFromExpr(expr);
+    }
+
+    private static <T extends LogicalNode> T getNonRelationListExpr(LogicalPlan plan, Expr expr) {
+      if (expr instanceof RelationList) {
+        return getNodeFromExpr(plan, ((RelationList) expr).getRelations()[0]);
+      } else {
+        return getNodeFromExpr(plan, expr);
+      }
+    }
+
+    @Override
+    public LogicalNode visitProjection(ProcessorContext ctx, Stack<Expr> stack, Projection expr) throws TajoException {
+      if (PlannerUtil.hasAsterisk(expr.getNamedExprs())) {
+        throw new UnsupportedException("Asterisk for self-describing data formats");
+      }
+
+      for (NamedExpr eachNamedExpr : expr.getNamedExprs()) {
+        Set<ColumnReferenceExpr> columns = ExprFinder.finds(eachNamedExpr, OpType.Column);
+        for (ColumnReferenceExpr col : columns) {
+          TUtil.putToNestedList(ctx.projectColumns, col.getQualifier(), col);
+        }
+      }
+
+      super.visitProjection(ctx, stack, expr);
+
+      ProjectionNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getChild());
+      node.setInSchema(child.getOutSchema());
+
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitLimit(ProcessorContext ctx, Stack<Expr> stack, Limit expr) throws TajoException {
+      super.visitLimit(ctx, stack, expr);
+
+      LimitNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getChild());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitSort(ProcessorContext ctx, Stack<Expr> stack, Sort expr) throws TajoException {
+      super.visitSort(ctx, stack, expr);
+
+      SortNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getChild());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitHaving(ProcessorContext ctx, Stack<Expr> stack, Having expr) throws TajoException {
+      super.visitHaving(ctx, stack, expr);
+
+      HavingNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getChild());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitGroupBy(ProcessorContext ctx, Stack<Expr> stack, Aggregation expr) throws TajoException {
+      super.visitGroupBy(ctx, stack, expr);
+
+      GroupbyNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getChild());
+      node.setInSchema(child.getOutSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitJoin(ProcessorContext ctx, Stack<Expr> stack, Join expr) throws TajoException {
+      super.visitJoin(ctx, stack, expr);
+
+      JoinNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode leftChild = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getLeft());
+      LogicalNode rightChild = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getRight());
+      node.setInSchema(SchemaUtil.merge(leftChild.getOutSchema(), rightChild.getOutSchema()));
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitFilter(ProcessorContext ctx, Stack<Expr> stack, Selection expr) throws TajoException {
+      Set<ColumnReferenceExpr> columnSet = ExprFinder.finds(expr.getQual(), OpType.Column);
+      for (ColumnReferenceExpr col : columnSet) {
+        NameRefInSelectListNormalizer.normalize(ctx.planContext, col);
+        TUtil.putToNestedList(ctx.projectColumns, col.getQualifier(), col);
+      }
+
+      super.visitFilter(ctx, stack, expr);
+
+      SelectionNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getChild());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitUnion(ProcessorContext ctx, Stack<Expr> stack, SetOperation expr) throws TajoException {
+      super.visitUnion(ctx, stack, expr);
+
+      UnionNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getLeft());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitExcept(ProcessorContext ctx, Stack<Expr> stack, SetOperation expr) throws TajoException {
+      super.visitExcept(ctx, stack, expr);
+
+      ExceptNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getLeft());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitIntersect(ProcessorContext ctx, Stack<Expr> stack, SetOperation expr) throws TajoException {
+      super.visitIntersect(ctx, stack, expr);
+
+      IntersectNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getLeft());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitSimpleTableSubquery(ProcessorContext ctx, Stack<Expr> stack, SimpleTableSubquery expr)
+        throws TajoException {
+      super.visitSimpleTableSubquery(ctx, stack, expr);
+
+      TableSubQueryNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getSubQuery());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitTableSubQuery(ProcessorContext ctx, Stack<Expr> stack, TablePrimarySubQuery expr)
+        throws TajoException {
+      super.visitTableSubQuery(ctx, stack, expr);
+
+      TableSubQueryNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getSubQuery());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitCreateTable(ProcessorContext ctx, Stack<Expr> stack, CreateTable expr) throws TajoException {
+      super.visitCreateTable(ctx, stack, expr);
+      CreateTableNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+
+      if (expr.hasSubQuery()) {
+        LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getSubQuery());
+        node.setInSchema(child.getOutSchema());
+        node.setOutSchema(node.getInSchema());
+      }
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitInsert(ProcessorContext ctx, Stack<Expr> stack, Insert expr) throws TajoException {
+      super.visitInsert(ctx, stack, expr);
+
+      InsertNode node = getNodeFromExpr(ctx.planContext.getPlan(), expr);
+      LogicalNode child = getNonRelationListExpr(ctx.planContext.getPlan(), expr.getSubQuery());
+      node.setInSchema(child.getOutSchema());
+      node.setOutSchema(node.getInSchema());
+      return node;
+    }
+
+    @Override
+    public LogicalNode visitRelation(ProcessorContext ctx, Stack<Expr> stack, Relation expr) throws TajoException {
+      LogicalPlan plan = ctx.planContext.getPlan();
+      QueryBlock queryBlock = plan.getBlockByExpr(expr);
+      ScanNode scan = queryBlock.getNodeFromExpr(expr);
+      TableDesc desc = scan.getTableDesc();
+
+      if (desc.hasEmptySchema()) {
+        if (ctx.projectColumns.containsKey(getQualifiedRelationName(ctx.planContext, expr))) {
+          Set<Column> columns = new HashSet<>();
+          for (ColumnReferenceExpr col : ctx.projectColumns.get(getQualifiedRelationName(ctx.planContext, expr))) {
+            columns.add(NameResolver.resolve(plan, queryBlock, col, NameResolvingMode.RELS_ONLY, true));
+          }
+
+          desc.setSchema(buildSchemaFromColumnSet(columns));
+          scan.init(desc);
+        } else {
+          // error
+          throw new TajoInternalError(
+              "Columns projected from " + getQualifiedRelationName(ctx.planContext, expr) + " is not found.");
+        }
+      }
+
+      return scan;
+    }
+
+    /**
+     * This method creates a schema from a set of columns.
+     * For a nested column, its ancestors are guessed and added to the schema.
+     * For example, given a column 'glossary.title', the columns of (glossary RECORD (title TEXT)) will be added
+     * to the schema.
+     *
+     * @param columns a set of columns
+     * @return schema build from columns
+     */
+    private Schema buildSchemaFromColumnSet(Set<Column> columns) {
+      SchemaGraph schemaGraph = new SchemaGraph();
+      Set<ColumnVertex> rootVertexes = new HashSet<>();
+      Schema schema = new Schema();
+
+      for (Column eachColumn : columns) {
+        String simpleName = eachColumn.getSimpleName();
+        if (NestedPathUtil.isPath(simpleName)) {
+          String[] paths = simpleName.split(NestedPathUtil.PATH_DELIMITER);
+          for (int i = 0; i < paths.length-1; i++) {
+            String parentName = paths[i];
+            if (i == 0) {
+              parentName = CatalogUtil.buildFQName(eachColumn.getQualifier(), parentName);
+            }
+            // Leaf column type is TEXT; otherwise, RECORD.
+            Type childDataType = (i == paths.length-2) ? Type.TEXT : Type.RECORD;
+            ColumnVertex parentVertex = new ColumnVertex(
+                parentName,
+                StringUtils.join(paths, NestedPathUtil.PATH_DELIMITER, 0, i+1),
+                Type.RECORD);
+            schemaGraph.addEdge(
+                new ColumnEdge(
+                    new ColumnVertex(
+                        paths[i+1],
+                        StringUtils.join(paths, NestedPathUtil.PATH_DELIMITER, 0, i+2), childDataType
+                    ),
+                    parentVertex));
+            if (i == 0) {
+              rootVertexes.add(parentVertex);
+            }
+          }
+        } else {
+          schema.addColumn(eachColumn);
+        }
+      }
+
+      // Build record columns
+      RecordColumnBuilder builder = new RecordColumnBuilder(schemaGraph);
+      for (ColumnVertex eachRoot : rootVertexes) {
+        schemaGraph.accept(eachRoot, builder);
+        schema.addColumn(eachRoot.column);
+      }
+
+      return schema;
+    }
+
+    private static class ColumnVertex {
+      private final String path;
+      private final String name;
+      private final Type type;
+      private Column column;
+
+      public ColumnVertex(String name, String path, Type type) {
+        this.name = name;
+        this.path = path;
+        this.type = type;
+      }
+
+      @Override
+      public boolean equals(Object o) {
+        if (o instanceof ColumnVertex) {
+          ColumnVertex other = (ColumnVertex) o;
+          return this.name.equals(other.name) &&
+              this.type.equals(other.type) &&
+              this.path.equals(other.path);
+        }
+        return false;
+      }
+
+      @Override
+      public int hashCode() {
+        return Objects.hashCode(name, type, path);
+      }
+    }
+
+    private static class ColumnEdge {
+      private final ColumnVertex parent;
+      private final ColumnVertex child;
+
+      public ColumnEdge(ColumnVertex child, ColumnVertex parent) {
+        this.child = child;
+        this.parent = parent;
+      }
+    }
+
+    private static class SchemaGraph extends SimpleDirectedGraph<ColumnVertex, ColumnEdge> {
+      public void addEdge(ColumnEdge edge) {
+        this.addEdge(edge.child, edge.parent, edge);
+      }
+    }
+
+    private static class RecordColumnBuilder implements DirectedGraphVisitor<ColumnVertex> {
+      private final SchemaGraph graph;
+
+      public RecordColumnBuilder(SchemaGraph graph) {
+        this.graph = graph;
+      }
+
+      @Override
+      public void visit(Stack<ColumnVertex> stack, ColumnVertex schemaVertex) {
+        if (graph.isLeaf(schemaVertex)) {
+          schemaVertex.column = new Column(schemaVertex.name, schemaVertex.type);
+        } else {
+          Schema schema = new Schema();
+          for (ColumnVertex eachChild : graph.getChilds(schemaVertex)) {
+            schema.addColumn(eachChild.column);
+          }
+          schemaVertex.column = new Column(schemaVertex.name, new TypeDesc(schema));
+        }
+      }
+    }
+  }
+}


Mime
View raw message