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/04/10 11:02:42 UTC

[1/2] TAJO-745: APIs in TajoClient and JDBC should be case sensitive. (hyunsik)

Repository: tajo
Updated Branches:
  refs/heads/master 20cd09201 -> 838b52227


http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 ac122c8..cbdb38b 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
@@ -17,9 +17,11 @@
  */
 package org.apache.tajo.jdbc;
 
+import com.google.common.collect.Lists;
 import com.google.protobuf.ServiceException;
 import org.apache.tajo.TajoConstants;
 import org.apache.tajo.annotation.Nullable;
+import org.apache.tajo.catalog.CatalogConstants;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.TableDesc;
@@ -40,6 +42,12 @@ import static org.apache.tajo.TajoConstants.DEFAULT_SCHEMA_NAME;
 public class TajoDatabaseMetaData implements DatabaseMetaData {
   private static final char SEARCH_STRING_ESCAPE = '\\';
 
+  private static final String KEYWORDS = "add,binary,boolean,explain,index,rename";
+  private static final String NUMERIC_FUNCTIONS =
+      "abs,acos,asin,atan,atan2,ceiling,cos,degrees,exp,,floor,mod,pi,pow," +
+      "radians,round,sign,sin,sqrt,tan";
+  private static final String STRING_FUNCTIONS = "ascii,chr,concat,left,length,ltrim,repeat,rtrim,substring";
+
   private final TajoConnection conn;
 
   public TajoDatabaseMetaData(TajoConnection conn) {
@@ -47,57 +55,47 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public boolean allProceduresAreCallable()
-      throws SQLException {
+  public boolean allProceduresAreCallable() throws SQLException {
     return true;
   }
 
   @Override
-  public boolean allTablesAreSelectable()
-      throws SQLException {
+  public boolean allTablesAreSelectable() throws SQLException {
     return true;
   }
 
   @Override
-  public String getURL()
-      throws SQLException {
+  public String getURL() throws SQLException {
     return conn.getUri();
   }
 
   @Override
-  public String getUserName()
-      throws SQLException {
+  public String getUserName() throws SQLException {
     return "tajo";
   }
 
   @Override
-  public boolean isReadOnly()
-      throws SQLException {
+  public boolean isReadOnly() throws SQLException {
     return true;
   }
 
   @Override
-  public String getDatabaseProductName()
-      throws SQLException {
+  public String getDatabaseProductName() throws SQLException {
     return "Tajo";
   }
 
   @Override
-  public String getDatabaseProductVersion()
-      throws SQLException {
-    //TODO get from tajo master
+  public String getDatabaseProductVersion() throws SQLException {
     return TajoConstants.TAJO_VERSION;
   }
 
   @Override
-  public String getDriverName()
-      throws SQLException {
+  public String getDriverName() throws SQLException {
     return "tajo";
   }
 
   @Override
-  public String getDriverVersion()
-      throws SQLException {
+  public String getDriverVersion() throws SQLException {
     return TajoDriver.MAJOR_VERSION + "." + TajoDriver.MINOR_VERSION;
   }
 
@@ -112,32 +110,27 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public String getIdentifierQuoteString()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getIdentifierQuoteString not supported");
+  public String getIdentifierQuoteString() throws SQLException {
+    return CatalogConstants.IDENTIFIER_QUOTE_STRING;
   }
 
   @Override
-  public String getSQLKeywords()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getSQLKeywords not supported");
+  public String getSQLKeywords() throws SQLException {
+    return KEYWORDS;
   }
 
   @Override
-  public String getNumericFunctions()
-      throws SQLException {
-    return "";
+  public String getNumericFunctions() throws SQLException {
+    return NUMERIC_FUNCTIONS;
   }
 
   @Override
-  public String getStringFunctions()
-      throws SQLException {
-    return "";
+  public String getStringFunctions() throws SQLException {
+    return STRING_FUNCTIONS;
   }
 
   @Override
-  public String getSystemFunctions()
-      throws SQLException {
+  public String getSystemFunctions() throws SQLException {
     return "";
   }
 
@@ -154,164 +147,137 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public String getExtraNameCharacters()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getExtraNameCharacters not supported");
+  public String getExtraNameCharacters() throws SQLException {
+    return "";
   }
 
   @Override
-  public String getSchemaTerm()
-      throws SQLException {
+  public String getSchemaTerm() throws SQLException {
     return "";
   }
 
   @Override
-  public String getProcedureTerm()
-      throws SQLException {
+  public String getProcedureTerm()  throws SQLException {
     throw new SQLFeatureNotSupportedException("getProcedureTerm not supported");
   }
 
   @Override
-  public String getCatalogTerm()
-      throws SQLException {
+  public String getCatalogTerm() throws SQLException {
     return "database";
   }
 
   @Override
-  public String getCatalogSeparator()
-      throws SQLException {
-    return ".";
+  public String getCatalogSeparator() throws SQLException {
+    return CatalogConstants.IDENTIFIER_DELIMITER;
   }
 
   @Override
-  public int getMaxBinaryLiteralLength()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxBinaryLiteralLength not supported");
+  public int getMaxBinaryLiteralLength() throws SQLException {
+    return 0; // no limit
   }
 
   @Override
-  public int getMaxCharLiteralLength()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxCharLiteralLength not supported");
+  public int getMaxCharLiteralLength() throws SQLException {
+    return 0; // no limit
   }
 
   @Override
-  public int getMaxColumnNameLength()
-      throws SQLException {
-    return 128;
+  public int getMaxColumnNameLength() throws SQLException {
+    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
-  public int getMaxColumnsInGroupBy()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxColumnsInGroupBy not supported");
+  public int getMaxColumnsInGroupBy() throws SQLException {
+    return 0; // no limit
   }
 
   @Override
-  public int getMaxColumnsInIndex()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxColumnsInIndex not supported");
+  public int getMaxColumnsInIndex() throws SQLException {
+    return 0; // no limit
   }
 
   @Override
-  public int getMaxColumnsInOrderBy()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxColumnsInOrderBy not supported");
+  public int getMaxColumnsInOrderBy() throws SQLException {
+    return 0; // no limit
   }
 
   @Override
-  public int getMaxColumnsInSelect()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxColumnsInSelect not supported");
+  public int getMaxColumnsInSelect() throws SQLException {
+    return 0; // no limit
   }
 
   @Override
-  public int getMaxColumnsInTable()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxColumnsInTable not supported");
+  public int getMaxColumnsInTable() throws SQLException {
+    return 0; // no limit
   }
 
   @Override
-  public int getMaxConnections()
-      throws SQLException {
+  public int getMaxConnections() throws SQLException {
     throw new SQLFeatureNotSupportedException("getMaxConnections not supported");
   }
 
   @Override
-  public int getMaxCursorNameLength()
-      throws SQLException {
+  public int getMaxCursorNameLength() throws SQLException {
     throw new SQLFeatureNotSupportedException("getMaxCursorNameLength not supported");
   }
 
   @Override
-  public int getMaxIndexLength()
-      throws SQLException {
+  public int getMaxIndexLength() throws SQLException {
     throw new SQLFeatureNotSupportedException("getMaxIndexLength not supported");
   }
 
   @Override
-  public int getMaxSchemaNameLength()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxSchemaNameLength not supported");
+  public int getMaxSchemaNameLength() throws SQLException {
+    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
-  public int getMaxProcedureNameLength()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxProcedureNameLength not supported");
+  public int getMaxProcedureNameLength() throws SQLException {
+    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
-  public int getMaxCatalogNameLength()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxCatalogNameLength not supported");
+  public int getMaxCatalogNameLength() throws SQLException {
+    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
-  public int getMaxRowSize()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxRowSize not supported");
+  public int getMaxRowSize() throws SQLException {
+    return 0; // no limit
   }
 
   @Override
-  public boolean doesMaxRowSizeIncludeBlobs()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("doesMaxRowSizeIncludeBlobs not supported");
+  public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
+    return false;
   }
 
   @Override
-  public int getMaxStatementLength()
-      throws SQLException {
+  public int getMaxStatementLength() throws SQLException {
     throw new SQLFeatureNotSupportedException("getMaxStatementLength not supported");
   }
 
   @Override
-  public int getMaxStatements()
-      throws SQLException {
+  public int getMaxStatements() throws SQLException {
     throw new SQLFeatureNotSupportedException("getMaxStatements not supported");
   }
 
   @Override
-  public int getMaxTableNameLength()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxTableNameLength not supported");
+  public int getMaxTableNameLength() throws SQLException {
+    return CatalogConstants.MAX_IDENTIFIER_LENGTH;
   }
 
   @Override
-  public int getMaxTablesInSelect()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxTablesInSelect not supported");
+  public int getMaxTablesInSelect() throws SQLException {
+    return 0; // no limit
   }
 
   @Override
-  public int getMaxUserNameLength()
-      throws SQLException {
-    throw new SQLFeatureNotSupportedException("getMaxUserNameLength not supported");
+  public int getMaxUserNameLength() throws SQLException {
+    return CatalogConstants.MAX_USERNAME_LENGTH;
   }
 
   @Override
-  public int getDefaultTransactionIsolation()
-      throws SQLException {
+  public int getDefaultTransactionIsolation() throws SQLException {
     return Connection.TRANSACTION_NONE;
   }
 
@@ -334,7 +300,8 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern)
+  public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern,
+                                       String columnNamePattern)
       throws SQLException {
     throw new SQLFeatureNotSupportedException("stored procedures not supported");
   }
@@ -385,36 +352,46 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
                              @Nullable String tableNamePattern, @Nullable String [] types) throws SQLException {
     try {
       final List<MetaDataTuple> resultTables = new ArrayList<MetaDataTuple>();
-      final String resultCatalog;
-      if (catalog == null) {
-        resultCatalog = TajoConstants.DEFAULT_DATABASE_NAME;
-      } else {
-        resultCatalog = CatalogUtil.normalizeIdentifier(catalog);
+      String regtableNamePattern = convertPattern(tableNamePattern == null ? null : tableNamePattern);
+
+      List<String> targetCatalogs = Lists.newArrayList();
+      if (catalog != null) {
+        targetCatalogs.add(catalog);
       }
 
-      String regtableNamePattern =
-          convertPattern(tableNamePattern == null ? null : CatalogUtil.normalizeIdentifier(tableNamePattern));
       try {
         TajoClient tajoClient = conn.getTajoClient();
-        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++, 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);
+
+        // if catalog is null, all databases are targets.
+        if (targetCatalogs.isEmpty()) {
+          targetCatalogs.addAll(tajoClient.getAllDatabaseNames());
+        }
+
+        for (String databaseName : targetCatalogs) {
+          List<String> tableNames = tajoClient.getTableList(databaseName);
+          for (String eachTableName: tableNames) {
+            if (eachTableName.matches(regtableNamePattern)) {
+              MetaDataTuple tuple = new MetaDataTuple(5);
+
+              int index = 0;
+              tuple.put(index++, new TextDatum(databaseName));         // 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);
+            }
           }
         }
         Collections.sort(resultTables, new Comparator<MetaDataTuple> () {
           @Override
           public int compare(MetaDataTuple table1, MetaDataTuple table2) {
-            return table1.getText(2).compareTo(table2.getText(2));
+            int compVal = table1.getText(1).compareTo(table2.getText(1));
+            if (compVal == 0) {
+              compVal = table1.getText(2).compareTo(table2.getText(2));
+            }
+            return compVal;
           }
         });
       } catch (Exception e) {
@@ -475,8 +452,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public ResultSet getTableTypes()
-      throws SQLException {
+  public ResultSet getTableTypes() throws SQLException {
     List<MetaDataTuple> columns = new ArrayList<MetaDataTuple>();
     MetaDataTuple tuple = new MetaDataTuple(1);
     tuple.put(0, new TextDatum("TABLE"));
@@ -506,53 +482,58 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   public ResultSet getColumns(@Nullable String catalog, @Nullable String schemaPattern,
                               @Nullable String tableNamePattern, @Nullable String columnNamePattern)
       throws SQLException {
+
+    List<String> targetCatalogs = Lists.newArrayList();
+    if (catalog != null) {
+      targetCatalogs.add(catalog);
+    }
+
     List<MetaDataTuple> columns = new ArrayList<MetaDataTuple>();
     try {
-      if (catalog == null) {
-        catalog = TajoConstants.DEFAULT_DATABASE_NAME;
+      if (targetCatalogs.isEmpty()) {
+        targetCatalogs.addAll(conn.getTajoClient().getAllDatabaseNames());
       }
-
-      String regtableNamePattern =
-          convertPattern(tableNamePattern == null ? null : CatalogUtil.normalizeIdentifier(tableNamePattern));
-      String regcolumnNamePattern =
-          convertPattern(columnNamePattern == null ? null : CatalogUtil.normalizeIdentifier(columnNamePattern));
-
-      List<String> tables = conn.getTajoClient().getTableList(catalog);
-      for (String table: tables) {
-        if (table.matches(regtableNamePattern)) {
-          TableDesc tableDesc = conn.getTajoClient().getTableDesc(table);
-          int pos = 0;
-          for (Column column: tableDesc.getSchema().getColumns()) {
-            if (column.getSimpleName().matches(regcolumnNamePattern)) {
-              MetaDataTuple tuple = new MetaDataTuple(22);
-
-              int index = 0;
-              tuple.put(index++, new TextDatum(catalog));  //TABLE_CAT
-              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
-              tuple.put(index++, new TextDatum("" + ResultSetUtil.tajoTypeToSqlType(column.getDataType())));
-              tuple.put(index++, new TextDatum(ResultSetUtil.toSqlType(column.getDataType())));  //TYPE_NAME
-              tuple.put(index++, new TextDatum("0"));  //COLUMN_SIZE
-              tuple.put(index++, new TextDatum("0"));  //BUFFER_LENGTH
-              tuple.put(index++, new TextDatum("0"));  //DECIMAL_DIGITS
-              tuple.put(index++, new TextDatum("0"));  //NUM_PREC_RADIX
-              tuple.put(index++, new TextDatum("" + DatabaseMetaData.columnNullable));  //NULLABLE
-              tuple.put(index++, NullDatum.get());  //REMARKS
-              tuple.put(index++, NullDatum.get());  //COLUMN_DEF
-              tuple.put(index++, NullDatum.get());  //SQL_DATA_TYPE
-              tuple.put(index++, NullDatum.get());  //SQL_DATETIME_SUB
-              tuple.put(index++, new TextDatum("0"));  //CHAR_OCTET_LENGTH
-              tuple.put(index++, new TextDatum("" + pos));  //ORDINAL_POSITION
-              tuple.put(index++, new TextDatum("YES"));  //IS_NULLABLE
-              tuple.put(index++, NullDatum.get());  //SCOPE_CATLOG
-              tuple.put(index++, NullDatum.get());  //SCOPE_SCHEMA
-              tuple.put(index++, NullDatum.get());  //SCOPE_TABLE
-              tuple.put(index++, new TextDatum("0"));  //SOURCE_DATA_TYPE
-              columns.add(tuple);
+      for (String databaseName : targetCatalogs) {
+        String regtableNamePattern = convertPattern(tableNamePattern == null ? null : tableNamePattern);
+        String regcolumnNamePattern = convertPattern(columnNamePattern == null ? null : columnNamePattern);
+
+        List<String> tables = conn.getTajoClient().getTableList(databaseName);
+        for (String table: tables) {
+          if (table.matches(regtableNamePattern)) {
+            TableDesc tableDesc = conn.getTajoClient().getTableDesc(CatalogUtil.buildFQName(databaseName, table));
+            int pos = 0;
+            for (Column column: tableDesc.getSchema().getColumns()) {
+              if (column.getSimpleName().matches(regcolumnNamePattern)) {
+                MetaDataTuple tuple = new MetaDataTuple(22);
+
+                int index = 0;
+                tuple.put(index++, new TextDatum(databaseName));            // TABLE_CAT
+                tuple.put(index++, new TextDatum(DEFAULT_SCHEMA_NAME));     // TABLE_SCHEM
+                tuple.put(index++, new TextDatum(table));                   // TABLE_NAME
+                tuple.put(index++, new TextDatum(column.getSimpleName()));  // COLUMN_NAME
+                // TODO - DATA_TYPE
+                tuple.put(index++, new TextDatum("" + ResultSetUtil.tajoTypeToSqlType(column.getDataType())));
+                tuple.put(index++, new TextDatum(ResultSetUtil.toSqlType(column.getDataType())));  //TYPE_NAME
+                tuple.put(index++, new TextDatum("0"));                     // COLUMN_SIZE
+                tuple.put(index++, new TextDatum("0"));                     // BUFFER_LENGTH
+                tuple.put(index++, new TextDatum("0"));                     // DECIMAL_DIGITS
+                tuple.put(index++, new TextDatum("0"));                     // NUM_PREC_RADIX
+                tuple.put(index++, new TextDatum("" + DatabaseMetaData.columnNullable));  // NULLABLE
+                tuple.put(index++, NullDatum.get());                        // REMARKS
+                tuple.put(index++, NullDatum.get());                        // COLUMN_DEF
+                tuple.put(index++, NullDatum.get());                        // SQL_DATA_TYPE
+                tuple.put(index++, NullDatum.get());                        // SQL_DATETIME_SUB
+                tuple.put(index++, new TextDatum("0"));                     // CHAR_OCTET_LENGTH
+                tuple.put(index++, new TextDatum("" + pos));                // ORDINAL_POSITION
+                tuple.put(index++, new TextDatum("YES"));                   // IS_NULLABLE
+                tuple.put(index++, NullDatum.get());                        // SCOPE_CATLOG
+                tuple.put(index++, NullDatum.get());                        // SCOPE_SCHEMA
+                tuple.put(index++, NullDatum.get());                        // SCOPE_TABLE
+                tuple.put(index++, new TextDatum("0"));                     // SOURCE_DATA_TYPE
+                columns.add(tuple);
+              }
+              pos++;
             }
-            pos++;
           }
         }
       }
@@ -618,14 +599,14 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable)
+  public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable,
+                                     String foreignCatalog, String foreignSchema, String foreignTable)
       throws SQLException {
     throw new SQLFeatureNotSupportedException("cross reference not supported");
   }
 
   @Override
-  public ResultSet getTypeInfo()
-      throws SQLException {
+  public ResultSet getTypeInfo() throws SQLException {
     throw new UnsupportedOperationException("getTypeInfo not supported");
   }
 
@@ -642,14 +623,12 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public boolean insertsAreDetected(int type)
-      throws SQLException {
+  public boolean insertsAreDetected(int type) throws SQLException {
     return false;
   }
 
   @Override
-  public Connection getConnection()
-      throws SQLException {
+  public Connection getConnection() throws SQLException {
     return conn;
   }
 
@@ -745,20 +724,19 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern)
-      throws SQLException {
+  public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {
     throw new SQLFeatureNotSupportedException("getFunctions not supported");
   }
 
   @Override
-  public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern)
-      throws SQLException {
+  public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern,
+                                      String columnNamePattern) throws SQLException {
     throw new SQLFeatureNotSupportedException("getFunctionColumns not supported");
   }
 
   @Override
   public boolean isCatalogAtStart() throws SQLException {
-    return false;
+    return true;
   }
 
   @Override
@@ -783,12 +761,12 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public boolean nullsAreSortedHigh() throws SQLException {
-    return true;
+    return false;
   }
 
   @Override
   public boolean nullsAreSortedLow() throws SQLException {
-    return false;
+    return true;
   }
 
   @Override
@@ -868,7 +846,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public boolean supportsAlterTableWithAddColumn() throws SQLException {
-    return false;
+    return true;
   }
 
   @Override
@@ -932,8 +910,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public boolean supportsDataDefinitionAndDataManipulationTransactions()
-      throws SQLException {
+  public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
     return false;
   }
 
@@ -979,7 +956,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public boolean supportsGroupByUnrelated() throws SQLException {
-    return false;
+    return true;
   }
 
   @Override
@@ -1059,7 +1036,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @Override
   public boolean supportsOrderByUnrelated() throws SQLException {
-    return false;
+    return true;
   }
 
   @Override
@@ -1084,8 +1061,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public boolean supportsResultSetHoldability(int holdability)
-      throws SQLException {
+  public boolean supportsResultSetHoldability(int holdability) throws SQLException {
     return false;
   }
 
@@ -1170,8 +1146,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public boolean supportsTransactionIsolationLevel(int level)
-      throws SQLException {
+  public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
     return false;
   }
 
@@ -1207,8 +1182,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
 
   @SuppressWarnings("unchecked")
   @Override
-  public <T> T unwrap(Class<T> iface)
-      throws SQLException {
+  public <T> T unwrap(Class<T> iface) throws SQLException {
     if (isWrapperFor(iface)) {
       return (T) this;
     }
@@ -1216,8 +1190,7 @@ public class TajoDatabaseMetaData implements DatabaseMetaData {
   }
 
   @Override
-  public boolean isWrapperFor(Class<?> iface)
-      throws SQLException {
+  public boolean isWrapperFor(Class<?> iface) throws SQLException {
     return iface.isInstance(this);
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDriver.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDriver.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDriver.java
index c537eb5..ffab2dd 100644
--- a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDriver.java
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDriver.java
@@ -39,7 +39,6 @@ public class TajoDriver implements Driver, Closeable {
     try {
       DriverManager.registerDriver(new TajoDriver());
     } catch (SQLException e) {
-      // TODO Auto-generated catch block
       e.printStackTrace();
     }
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoStatement.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoStatement.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoStatement.java
index b7604a8..776c892 100644
--- a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoStatement.java
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoStatement.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,6 +15,7 @@ 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 org.apache.tajo.client.TajoClient;
 


[2/2] git commit: TAJO-745: APIs in TajoClient and JDBC should be case sensitive. (hyunsik)

Posted by hy...@apache.org.
TAJO-745: APIs in TajoClient and JDBC should be case sensitive. (hyunsik)


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

Branch: refs/heads/master
Commit: 838b52227af33e878ad08e00b8b19a4cd3fa8b26
Parents: 20cd092
Author: Hyunsik Choi <hy...@apache.org>
Authored: Thu Apr 10 17:57:37 2014 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Thu Apr 10 17:57:37 2014 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |   2 +
 .../apache/tajo/catalog/CatalogConstants.java   |   7 +
 .../org/apache/tajo/catalog/CatalogUtil.java    |  29 +-
 .../java/org/apache/tajo/catalog/Column.java    |   2 +-
 .../tajo/catalog/store/HCatalogStore.java       |   8 +-
 .../java/org/apache/tajo/client/TajoClient.java | 115 ++++--
 .../java/org/apache/tajo/util/StringUtils.java  |  11 +
 .../tajo/engine/eval/LikePredicateEval.java     |   9 +-
 .../java/org/apache/tajo/QueryTestCaseBase.java |  33 +-
 .../apache/tajo/engine/query/TestCTASQuery.java |   6 +-
 .../tajo/engine/query/TestCreateTable.java      |  54 +--
 .../tajo/engine/query/TestJoinBroadcast.java    |   6 +-
 .../apache/tajo/engine/query/TestJoinQuery.java |   7 +-
 .../tajo/jdbc/TestTajoDatabaseMetaData.java     | 355 ++++++++++++++++++
 .../java/org/apache/tajo/jdbc/TestTajoJdbc.java | 154 ++------
 .../alter_table_rename_table_ddl.sql            |   2 +-
 .../TestTajoDatabaseMetaData/getTables1.result  |   4 +
 .../TestTajoDatabaseMetaData/getTables2.result  |   4 +
 .../results/TestTajoJdbc/getTables1.result      |   4 -
 .../results/TestTajoJdbc/getTables2.result      |   4 -
 .../org/apache/tajo/jdbc/TajoConnection.java    |  24 +-
 .../apache/tajo/jdbc/TajoDatabaseMetaData.java  | 371 +++++++++----------
 .../java/org/apache/tajo/jdbc/TajoDriver.java   |   1 -
 .../org/apache/tajo/jdbc/TajoStatement.java     |   3 +-
 24 files changed, 775 insertions(+), 440 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index c2d123e..f418fc0 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -143,6 +143,8 @@ Release 0.8.0 - unreleased
 
   IMPROVEMENTS
 
+    TAJO-745: APIs in TajoClient and JDBC should be case sensitive.
+
     TAJO-743: Change the default resource allocation policy of leaf tasks. (jinho)
 
     TAJO-717: Improve file splitting for large number of splits. (jinho)

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 c695fc8..8cad4fe 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
@@ -22,6 +22,13 @@ import parquet.hadoop.ParquetWriter;
 import parquet.hadoop.metadata.CompressionCodecName;
 
 public class CatalogConstants {
+  public final static String IDENTIFIER_DELIMITER_REGEXP = "\\.";
+  public final static String IDENTIFIER_DELIMITER = ".";
+  public final static String IDENTIFIER_QUOTE_STRING = "\"";
+  public final static int MAX_IDENTIFIER_LENGTH = 128;
+  // Linux and BSD's max username length is 32. For compatibility with other systems, we should follow it.
+  public final static int MAX_USERNAME_LENGTH = 32;
+
   public static final String STORE_CLASS="tajo.catalog.store.class";
 
   public static final String CONNECTION_ID = "tajo.catalog.connection.id";

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 5bcb290..7555325 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
@@ -42,8 +42,6 @@ import static org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
 import static org.apache.tajo.common.TajoDataTypes.Type;
 
 public class CatalogUtil {
-  public final static String IDENTIFIER_DELIMITER = ".";
-  public final static String IDENTIFIER_DELIMITER_REGEXP = "\\.";
 
   /**
    * Normalize an identifier. Normalization means a translation from a identifier to be a refined identifier name.
@@ -68,7 +66,10 @@ public class CatalogUtil {
    * @return The normalized identifier
    */
   public static String normalizeIdentifier(String identifier) {
-    String [] splitted = identifier.split(IDENTIFIER_DELIMITER_REGEXP);
+    if (identifier == null || identifier.equals("")) {
+      return identifier;
+    }
+    String [] splitted = identifier.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP);
 
     StringBuilder sb = new StringBuilder();
     boolean first = true;
@@ -76,7 +77,7 @@ public class CatalogUtil {
       if (first) {
         first = false;
       } else {
-        sb.append(IDENTIFIER_DELIMITER);
+        sb.append(CatalogConstants.IDENTIFIER_DELIMITER);
       }
       sb.append(normalizeIdentifierPart(part));
     }
@@ -101,7 +102,7 @@ public class CatalogUtil {
    * @return The denormalized identifier
    */
   public static String denormalizeIdentifier(String identifier) {
-    String [] splitted = identifier.split(IDENTIFIER_DELIMITER_REGEXP);
+    String [] splitted = identifier.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP);
 
     StringBuilder sb = new StringBuilder();
     boolean first = true;
@@ -109,7 +110,7 @@ public class CatalogUtil {
       if (first) {
         first = false;
       } else {
-        sb.append(IDENTIFIER_DELIMITER);
+        sb.append(CatalogConstants.IDENTIFIER_DELIMITER);
       }
       sb.append(denormalizePart(part));
     }
@@ -165,11 +166,11 @@ public class CatalogUtil {
   }
 
   public static boolean isFQColumnName(String tableName) {
-    return tableName.split(IDENTIFIER_DELIMITER_REGEXP).length == 3;
+    return tableName.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP).length == 3;
   }
 
   public static boolean isFQTableName(String tableName) {
-    int lastDelimiterIdx = tableName.lastIndexOf(IDENTIFIER_DELIMITER);
+    int lastDelimiterIdx = tableName.lastIndexOf(CatalogConstants.IDENTIFIER_DELIMITER);
     return lastDelimiterIdx > -1;
   }
 
@@ -183,7 +184,7 @@ public class CatalogUtil {
   }
 
   public static String [] splitTableName(String tableName) {
-    int lastDelimiterIdx = tableName.lastIndexOf(IDENTIFIER_DELIMITER);
+    int lastDelimiterIdx = tableName.lastIndexOf(CatalogConstants.IDENTIFIER_DELIMITER);
     if (lastDelimiterIdx > -1) {
       return new String [] {
           tableName.substring(0, lastDelimiterIdx),
@@ -201,7 +202,7 @@ public class CatalogUtil {
       if (first) {
         first = false;
       } else {
-        sb.append(IDENTIFIER_DELIMITER);
+        sb.append(CatalogConstants.IDENTIFIER_DELIMITER);
       }
 
       sb.append(id);
@@ -220,7 +221,7 @@ public class CatalogUtil {
    * @return The extracted qualifier
    */
   public static String extractQualifier(String name) {
-    int lastDelimiterIdx = name.lastIndexOf(IDENTIFIER_DELIMITER);
+    int lastDelimiterIdx = name.lastIndexOf(CatalogConstants.IDENTIFIER_DELIMITER);
     if (lastDelimiterIdx > -1) {
       return name.substring(0, lastDelimiterIdx);
     } else {
@@ -238,7 +239,7 @@ public class CatalogUtil {
    * @return The extracted simple name
    */
   public static String extractSimpleName(String name) {
-    int lastDelimiterIdx = name.lastIndexOf(IDENTIFIER_DELIMITER);
+    int lastDelimiterIdx = name.lastIndexOf(CatalogConstants.IDENTIFIER_DELIMITER);
     if (lastDelimiterIdx > -1) {
       // plus one means skipping a delimiter.
       return name.substring(lastDelimiterIdx + 1, name.length());
@@ -249,7 +250,7 @@ public class CatalogUtil {
 
   public static String getCanonicalTableName(String databaseName, String tableName) {
     StringBuilder sb = new StringBuilder(databaseName);
-    sb.append(IDENTIFIER_DELIMITER);
+    sb.append(CatalogConstants.IDENTIFIER_DELIMITER);
     sb.append(tableName);
     return sb.toString();
   }
@@ -351,7 +352,7 @@ public class CatalogUtil {
     revisedSchema.clearFields();
     for (ColumnProto col : schema.getFieldsList()) {
       ColumnProto.Builder builder = ColumnProto.newBuilder(col);
-      builder.setName(tableName + IDENTIFIER_DELIMITER + extractSimpleName(col.getName()));
+      builder.setName(tableName + CatalogConstants.IDENTIFIER_DELIMITER + extractSimpleName(col.getName()));
       revisedSchema.addFields(builder.build());
     }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
----------------------------------------------------------------------
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
index 2e29536..aab20c7 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/Column.java
@@ -73,7 +73,7 @@ public class Column implements ProtoObject<ColumnProto>, GsonObject {
    * @return True if a column includes a table name. Otherwise, it returns False.
    */
   public boolean hasQualifier() {
-    return name.split(CatalogUtil.IDENTIFIER_DELIMITER_REGEXP).length > 1;
+    return name.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP).length > 1;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 e6b0bcd..755fca6 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
@@ -146,8 +146,8 @@ public class HCatalogStore extends CatalogConstants implements CatalogStore {
         }
 
         if (!isPartitionKey) {
-          String fieldName = databaseName + CatalogUtil.IDENTIFIER_DELIMITER + tableName +
-              CatalogUtil.IDENTIFIER_DELIMITER + eachField.getName();
+          String fieldName = databaseName + CatalogConstants.IDENTIFIER_DELIMITER + tableName +
+              CatalogConstants.IDENTIFIER_DELIMITER + eachField.getName();
           TajoDataTypes.Type dataType = HCatalogUtil.getTajoFieldType(eachField.getType().toString());
           schema.addColumn(fieldName, dataType);
         }
@@ -234,8 +234,8 @@ 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 = databaseName + CatalogUtil.IDENTIFIER_DELIMITER + tableName +
-                CatalogUtil.IDENTIFIER_DELIMITER + fieldSchema.getName();
+            String fieldName = databaseName + CatalogConstants.IDENTIFIER_DELIMITER + tableName +
+                CatalogConstants.IDENTIFIER_DELIMITER + fieldSchema.getName();
             expressionSchema.addColumn(new Column(fieldName, dataType));
             if (i > 0) {
               sb.append(",");

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 32d09df..81fc227 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
@@ -84,15 +84,24 @@ public class TajoClient implements Closeable {
     this(conf, NetUtils.createSocketAddr(conf.getVar(ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS)), baseDatabase);
   }
 
+  /**
+   * Connect to TajoMaster
+   *
+   * @param conf TajoConf
+   * @param addr TajoMaster address
+   * @param baseDatabase The base database name. It is case sensitive. If it is null,
+   *                     the 'default' database will be used.
+   * @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
+    // Don't share connection pool per client
     connPool = RpcConnectionPool.newPool(conf, getClass().getSimpleName(), workerNum);
     userInfo = UserGroupInformation.getCurrentUser();
-    this.baseDatabase = baseDatabase != null ? CatalogUtil.normalizeIdentifier(baseDatabase) : null;
+    this.baseDatabase = baseDatabase != null ? baseDatabase : null;
   }
 
   public boolean isConnected() {
@@ -204,8 +213,7 @@ public class TajoClient implements Closeable {
         checkSessionAndGet(client);
 
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
-        return tajoMasterService.selectDatabase(null,
-            convertSessionedString(CatalogUtil.normalizeIdentifier(databaseName))).getValue();
+        return tajoMasterService.selectDatabase(null, convertSessionedString(databaseName)).getValue();
       }
     }.withRetries();
   }
@@ -535,35 +543,53 @@ public class TajoClient implements Closeable {
     }.withRetries();
   }
 
+  /**
+   * Create a database.
+   *
+   * @param databaseName The database name to be created. This name is case sensitive.
+   * @return True if created successfully.
+   * @throws ServiceException
+   */
   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(CatalogUtil.normalizeIdentifier(databaseName))).getValue();
+        return tajoMasterService.createDatabase(null, convertSessionedString(databaseName)).getValue();
       }
     }.withRetries();
   }
 
+  /**
+   * Does the database exist?
+   *
+   * @param databaseName The database name to be checked. This name is case sensitive.
+   * @return True if so.
+   * @throws ServiceException
+   */
   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(CatalogUtil.normalizeIdentifier(databaseName))).getValue();
+        return tajoMasterService.existDatabase(null, convertSessionedString(databaseName)).getValue();
       }
     }.withRetries();
   }
 
+  /**
+   * Drop the database
+   *
+   * @param databaseName The database name to be dropped. This name is case sensitive.
+   * @return True if the database is dropped successfully.
+   * @throws ServiceException
+   */
   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(CatalogUtil.normalizeIdentifier(databaseName))).getValue();
+        return tajoMasterService.dropDatabase(null, convertSessionedString(databaseName)).getValue();
       }
     }.withRetries();
   }
@@ -579,26 +605,36 @@ public class TajoClient implements Closeable {
   }
 
   /**
-   * Test for the existence of table in catalog data.
-   * <p/>
-   * This will return true if table exists, false if not.
-   * @param name
-   * @return
-   * @throws ServiceException
+   * Does the table exist?
+   *
+   * @param tableName The table name to be checked. This name is case sensitive.
+   * @return True if so.
    */
-  public boolean existTable(final String name) throws ServiceException {
+  public boolean existTable(final String tableName) 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.existTable(null,
-            convertSessionedString(CatalogUtil.normalizeIdentifier(name))).getValue();
+        return tajoMasterService.existTable(null, convertSessionedString(tableName)).getValue();
       }
     }.withRetries();
   }
 
-  public TableDesc createExternalTable(final String name, final Schema schema, final Path path, final TableMeta meta)
+  /**
+   * Create an external table.
+   *
+   * @param tableName The table name to be created. This name is case sensitive. This name can be qualified or not.
+   *                  If the table name is not qualified, the current database in the session will be used.
+   * @param schema The schema
+   * @param path The external table location
+   * @param meta Table meta
+   * @return the created table description.
+   * @throws SQLException
+   * @throws ServiceException
+   */
+  public TableDesc createExternalTable(final String tableName, final Schema schema, final Path path,
+                                       final TableMeta meta)
       throws SQLException, ServiceException {
     return new ServerCallable<TableDesc>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
@@ -609,7 +645,7 @@ public class TajoClient implements Closeable {
 
         CreateTableRequest.Builder builder = CreateTableRequest.newBuilder();
         builder.setSessionId(sessionId);
-        builder.setName(CatalogUtil.normalizeIdentifier(name));
+        builder.setName(tableName);
         builder.setSchema(schema.getProto());
         builder.setMeta(meta.getProto());
         builder.setPath(path.toUri().toString());
@@ -623,15 +659,22 @@ public class TajoClient implements Closeable {
     }.withRetries();
   }
 
+  /**
+   * Drop a table
+   *
+   * @param tableName The table name to be dropped. This name is case sensitive.
+   * @return True if the table is dropped successfully.
+   */
   public boolean dropTable(final String tableName) throws ServiceException {
     return dropTable(tableName, false);
   }
 
   /**
-   * Deletes table schema from catalog data and deletes data file in hdfs
-   * @param tableName
-   * @return
-   * @throws ServiceException
+   * Drop a table.
+   *
+   * @param tableName The table name to be dropped. This name is case sensitive.
+   * @param purge If purge is true, this call will remove the entry in catalog as well as the table contents.
+   * @return True if the table is dropped successfully.
    */
   public boolean dropTable(final String tableName, final boolean purge) throws ServiceException {
     return new ServerCallable<Boolean>(connPool, tajoMasterAddr,
@@ -643,7 +686,7 @@ public class TajoClient implements Closeable {
 
         DropTableRequest.Builder builder = DropTableRequest.newBuilder();
         builder.setSessionId(sessionId);
-        builder.setName(CatalogUtil.normalizeIdentifier(tableName));
+        builder.setName(tableName);
         builder.setPurge(purge);
         return tajoMasterService.dropTable(null, builder.build()).getValue();
       }
@@ -697,10 +740,10 @@ public class TajoClient implements Closeable {
   }
 
   /**
-   * Get a list of table names. All table and column names are
-   * represented as lower-case letters.
+   * Get a list of table names.
    *
-   * @param databaseName The database name to show all tables. If it is null, this method will show all tables
+   * @param databaseName The database name to show all tables. This name is case sensitive.
+   *                     If it is null, this method will show all tables
    *                     in the current database of this session.
    */
   public List<String> getTableList(@Nullable final String databaseName) throws ServiceException {
@@ -709,14 +752,12 @@ public class TajoClient implements Closeable {
       public List<String> call(NettyClientBase client) throws ServiceException {
         checkSessionAndGet(client);
 
-        final String normalizedDBName = databaseName == null ? null : CatalogUtil.normalizeIdentifier(databaseName);
-
         TajoMasterClientProtocolService.BlockingInterface tajoMasterService = client.getStub();
 
         GetTableListRequest.Builder builder = GetTableListRequest.newBuilder();
         builder.setSessionId(sessionId);
-        if (normalizedDBName != null) {
-          builder.setDatabaseName(normalizedDBName);
+        if (databaseName != null) {
+          builder.setDatabaseName(databaseName);
         }
         GetTableListResponse res = tajoMasterService.getTableList(null, builder.build());
         return res.getTablesList();
@@ -724,6 +765,12 @@ public class TajoClient implements Closeable {
     }.withRetries();
   }
 
+  /**
+   * Get a table description
+   *
+   * @param tableName The table name to get. This name is case sensitive.
+   * @return Table description
+   */
   public TableDesc getTableDesc(final String tableName) throws ServiceException {
     return new ServerCallable<TableDesc>(connPool, tajoMasterAddr,
         TajoMasterClientProtocol.class, false, true) {
@@ -734,7 +781,7 @@ public class TajoClient implements Closeable {
 
         GetTableDescRequest.Builder builder = GetTableDescRequest.newBuilder();
         builder.setSessionId(sessionId);
-        builder.setTableName(CatalogUtil.normalizeIdentifier(tableName));
+        builder.setTableName(tableName);
         TableResponse res = tajoMasterService.getTableDesc(null, builder.build());
         if (res.getResultCode() == ResultCode.OK) {
           return CatalogUtil.newTableDesc(res.getTableDesc());

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 ad607a1..32edc31 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
@@ -19,6 +19,7 @@
 package org.apache.tajo.util;
 
 public class StringUtils {
+
   /**
    *
    * Given the time in long milliseconds, returns a
@@ -86,4 +87,14 @@ public class StringUtils {
   public static boolean isDigit(char character) {
     return '0' <= character && character <= '9';
   }
+
+  private static final String REGEX_SPECIAL_CHARACTERS = "([.*${}?|\\^\\-\\[\\]])";
+  public static String escapeRegexp(String literal) {
+    return literal.replaceAll(REGEX_SPECIAL_CHARACTERS, "\\\\$1");
+  }
+
+  private static final String LIKE_SPECIAL_CHARACTERS = "([_%])";
+  public static String escapeLike(String literal) {
+    return literal.replaceAll(LIKE_SPECIAL_CHARACTERS, "\\\\$1");
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java
index e1c693e..bfac33e 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java
@@ -18,22 +18,19 @@
 
 package org.apache.tajo.engine.eval;
 
+import org.apache.tajo.util.StringUtils;
+
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
 public class LikePredicateEval extends PatternMatchPredicateEval {
-  private static final String LIKE_ESCAPE_SPATIAL_CHARACTERS = "([.*${}?|\\^\\-\\[\\]])";
 
   public LikePredicateEval(boolean not, EvalNode field, ConstEval pattern, boolean caseSensitive) {
     super(EvalType.LIKE, not, field, pattern, caseSensitive);
   }
 
-  private String escapeRegexpForLike(String literal) {
-    return literal.replaceAll(LIKE_ESCAPE_SPATIAL_CHARACTERS, "\\\\$1");
-  }
-  
   protected void compile(String pattern) throws PatternSyntaxException {
-    String escaped = escapeRegexpForLike(pattern);
+    String escaped = StringUtils.escapeRegexp(pattern);
     String regex = escaped.replace("_", ".").replace("%", ".*");
     int flags = Pattern.DOTALL;
     if (caseInsensitive) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 ed943f2..db40169 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
@@ -307,18 +307,41 @@ public class QueryTestCaseBase {
     }
   }
 
+  /**
+   * Assert that the database exists.
+   * @param databaseName The database name to be checked. This name is case sensitive.
+   */
   public void assertDatabaseExists(String databaseName) throws ServiceException {
     assertTrue(client.existDatabase(databaseName));
   }
 
+  /**
+   * Assert that the database does not exists.
+   * @param databaseName The database name to be checked. This name is case sensitive.
+   */
   public void assertDatabaseNotExists(String databaseName) throws ServiceException {
     assertTrue(!client.existDatabase(databaseName));
   }
 
+  /**
+   * Assert that the table exists.
+   *
+   * @param tableName The table name to be checked. This name is case sensitive.
+   * @throws ServiceException
+   */
   public void assertTableExists(String tableName) throws ServiceException {
     assertTrue(client.existTable(tableName));
   }
 
+  /**
+   * Assert that the table does not exist.
+   *
+   * @param tableName The table name to be checked. This name is case sensitive.
+   */
+  public void assertTableNotExists(String tableName) throws ServiceException {
+    assertTrue(!client.existTable(tableName));
+  }
+
   public void assertColumnExists(String tableName,String columnName) throws ServiceException {
     TableDesc tableDesc = fetchTableMetaData(tableName);
     assertTrue(tableDesc.getSchema().containsByName(columnName));
@@ -328,10 +351,6 @@ public class QueryTestCaseBase {
     return client.getTableDesc(tableName);
   }
 
-  public void assertTableNotExists(String tableName) throws ServiceException {
-    assertTrue(!client.existTable(tableName));
-  }
-
   /**
    * It transforms a ResultSet instance to rows represented as strings.
    *
@@ -433,15 +452,15 @@ public class QueryTestCaseBase {
 
       if (expr.getType() == OpType.CreateTable) {
         CreateTable createTable = (CreateTable) expr;
-        String tableName = CatalogUtil.denormalizeIdentifier(createTable.getTableName());
+        String tableName = createTable.getTableName();
         assertTrue("Table [" + tableName + "] creation is failed.", client.updateQuery(parsedResult.getStatement()));
 
         TableDesc createdTable = client.getTableDesc(tableName);
-        String createdTableName = CatalogUtil.denormalizeIdentifier(createdTable.getName());
+        String createdTableName = createdTable.getName();
 
         assertTrue("table '" + createdTableName + "' creation check", client.existTable(createdTableName));
         if (isLocalTable) {
-          createdTableGlobalSet.add(createdTableName);
+          createdTableGlobalSet.add(CatalogUtil.denormalizeIdentifier(createdTableName));
           createdTableNames.add(tableName);
         }
       } else if (expr.getType() == OpType.DropTable) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 ad93738..4dc5728 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
@@ -223,10 +223,10 @@ public class TestCTASQuery extends QueryTestCaseBase {
       assertNotNull(desc);
       assertEquals("managed_table1", desc.getPath().getName());
     } else {
-      assertFalse(client.existTable("MANAGED_TABLE1"));
-      assertTrue(client.existTable("\"MANAGED_TABLE1\""));
+      assertFalse(client.existTable("managed_Table1"));
+      assertTrue(client.existTable("MANAGED_TABLE1"));
 
-      TableDesc desc =  client.getTableDesc("\"MANAGED_TABLE1\"");
+      TableDesc desc =  client.getTableDesc("MANAGED_TABLE1");
 
       assertNotNull(desc);
       assertEquals("MANAGED_TABLE1", desc.getPath().getName());

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 a6bb467..2d289ba 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
@@ -62,30 +62,30 @@ public class TestCreateTable extends QueryTestCaseBase {
 
     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();
+    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("d1.table1");
+    assertTableExists("d1.table2");
+    assertTableNotExists("d2.table1");
+    assertTableNotExists("d2.table2");
 
-    assertTableExists("D2.table3");
-    assertTableExists("D2.table4");
-    assertTableNotExists("D1.table3");
-    assertTableNotExists("D1.table4");
+    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");
+    assertDatabaseExists("d1");
+    assertDatabaseExists("d2");
     executeString("DROP DATABASE D1").close();
     executeString("DROP DATABASE D2").close();
-    assertDatabaseNotExists("D1");
-    assertDatabaseNotExists("D2");
+    assertDatabaseNotExists("d1");
+    assertDatabaseNotExists("d2");
   }
 
   private final void assertPathOfCreatedTable(final String databaseName,
@@ -99,8 +99,8 @@ public class TestCreateTable extends QueryTestCaseBase {
 
     ResultSet res = executeString(createTableStmt);
     res.close();
-    assertTableExists(CatalogUtil.denormalizeIdentifier(oldFQTableName));
-    TableDesc oldTableDesc = client.getTableDesc(CatalogUtil.denormalizeIdentifier(oldFQTableName));
+    assertTableExists(oldFQTableName);
+    TableDesc oldTableDesc = client.getTableDesc(oldFQTableName);
 
 
     // checking the existence of the table directory and validating the path
@@ -115,7 +115,7 @@ public class TestCreateTable extends QueryTestCaseBase {
 
     // checking the existence of the new table directory and validating the path
     final String newFQTableName = CatalogUtil.buildFQName(databaseName, newTableName);
-    TableDesc newTableDesc = client.getTableDesc(CatalogUtil.denormalizeIdentifier(newFQTableName));
+    TableDesc newTableDesc = client.getTableDesc(newFQTableName);
     assertTrue(fs.exists(newTableDesc.getPath()));
     assertEquals(StorageUtil.concatPath(warehouseDir, databaseName, newTableName), newTableDesc.getPath());
   }
@@ -142,12 +142,12 @@ public class TestCreateTable extends QueryTestCaseBase {
   public final void testCreateTableIfNotExists() throws Exception {
     executeString("CREATE DATABASE D3;").close();
 
-    assertTableNotExists("D3.table1");
+    assertTableNotExists("d3.table1");
     executeString("CREATE TABLE D3.table1 (age int);").close();
-    assertTableExists("D3.table1");
+    assertTableExists("d3.table1");
 
     executeString("CREATE TABLE IF NOT EXISTS D3.table1 (age int);").close();
-    assertTableExists("D3.table1");
+    assertTableExists("d3.table1");
 
     executeString("DROP TABLE D3.table1");
   }
@@ -156,15 +156,15 @@ public class TestCreateTable extends QueryTestCaseBase {
   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");
+    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 d4.table1;").close();
+    assertTableNotExists("d4.table1");
 
-    executeString("DROP TABLE IF EXISTS D4.table1");
-    assertTableNotExists("D4.table1");
+    executeString("DROP TABLE IF EXISTS d4.table1");
+    assertTableNotExists("d4.table1");
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinBroadcast.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinBroadcast.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinBroadcast.java
index 78714c5..1b68577 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinBroadcast.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestJoinBroadcast.java
@@ -282,11 +282,11 @@ public class TestJoinBroadcast extends QueryTestCaseBase {
   @Test
   public final void testJoinOnMultipleDatabases() throws Exception {
     executeString("CREATE DATABASE JOINS");
-    assertDatabaseExists("JOINS");
+    assertDatabaseExists("joins");
     executeString("CREATE TABLE JOINS.part_ as SELECT * FROM part");
-    assertTableExists("JOINS.part_");
+    assertTableExists("joins.part_");
     executeString("CREATE TABLE JOINS.supplier_ as SELECT * FROM supplier");
-    assertTableExists("JOINS.supplier_");
+    assertTableExists("joins.supplier_");
     ResultSet res = executeQuery();
     assertResultSet(res);
     cleanupQuery(res);

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 6d72ca7..65187c6 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
@@ -21,7 +21,6 @@ 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.conf.TajoConf;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
@@ -286,11 +285,11 @@ public class TestJoinQuery extends QueryTestCaseBase {
   @Test
   public final void testJoinOnMultipleDatabases() throws Exception {
     executeString("CREATE DATABASE JOINS");
-    assertDatabaseExists("JOINS");
+    assertDatabaseExists("joins");
     executeString("CREATE TABLE JOINS.part_ as SELECT * FROM part");
-    assertTableExists("JOINS.part_");
+    assertTableExists("joins.part_");
     executeString("CREATE TABLE JOINS.supplier_ as SELECT * FROM supplier");
-    assertTableExists("JOINS.supplier_");
+    assertTableExists("joins.supplier_");
     ResultSet res = executeQuery();
     assertResultSet(res);
     cleanupQuery(res);

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestTajoDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestTajoDatabaseMetaData.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestTajoDatabaseMetaData.java
new file mode 100644
index 0000000..295a39f
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/jdbc/TestTajoDatabaseMetaData.java
@@ -0,0 +1,355 @@
+/**
+ * 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.jdbc;
+
+import com.google.common.collect.Sets;
+import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoConstants;
+import org.apache.tajo.util.TUtil;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.net.InetSocketAddress;
+import java.sql.*;
+import java.util.*;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class TestTajoDatabaseMetaData extends QueryTestCaseBase {
+  private static InetSocketAddress tajoMasterAddress;
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    tajoMasterAddress = testingCluster.getMaster().getTajoMasterClientService().getBindAddress();
+    Class.forName("org.apache.tajo.jdbc.TajoDriver").newInstance();
+  }
+
+  public static List<String> getListFromResultSet(ResultSet resultSet, String columnName) throws SQLException {
+    List<String> list = new ArrayList<String>();
+    while(resultSet.next()) {
+      list.add(resultSet.getString(columnName));
+    }
+    return list;
+  }
+
+  @Test
+  public void testSetAndGetCatalog() throws Exception {
+    String connUri = TestTajoJdbc.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();
+
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertDatabaseNotExists("Jdbc_Test2");
+      pstmt = conn.prepareStatement("CREATE DATABASE \"Jdbc_Test2\"");
+      pstmt.executeUpdate();
+      assertDatabaseExists("Jdbc_Test2");
+      pstmt.close();
+    }
+
+    conn.setCatalog("jdbc_test1");
+    assertEquals("jdbc_test1", conn.getCatalog());
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      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();
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      pstmt = conn.prepareStatement("DROP DATABASE \"Jdbc_Test2\"");
+      pstmt.executeUpdate();
+      pstmt.close();
+    }
+
+    conn.close();
+  }
+
+  @Test
+  public void testGetCatalogsAndTables() throws Exception {
+    String connUri = TestTajoJdbc.buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        TajoConstants.DEFAULT_DATABASE_NAME);
+    Connection defaultConnect = DriverManager.getConnection(connUri);
+
+    DatabaseMetaData dbmd = defaultConnect.getMetaData();
+    List<String> existingDatabases = getListFromResultSet(dbmd.getCatalogs(), "TABLE_CAT");
+
+    // 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();
+
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      // create database "jdbc_test2" and its tables
+      assertDatabaseNotExists("Jdbc_Test2");
+      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()
+    dbmd = defaultConnect.getMetaData();
+    List<String> newDatabases = getListFromResultSet(dbmd.getCatalogs(), "TABLE_CAT");
+
+    newDatabases.removeAll(existingDatabases);
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertEquals(2, newDatabases.size());
+    } else {
+      assertEquals(1, newDatabases.size());
+    }
+    assertTrue(newDatabases.contains("jdbc_test1"));
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      assertTrue(newDatabases.contains("Jdbc_Test2"));
+    }
+
+    // verify getTables()
+    ResultSet res = defaultConnect.getMetaData().getTables("jdbc_test1", null, null, null);
+    assertResultSet(res, "getTables1.result");
+    res.close();
+
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      res = defaultConnect.getMetaData().getTables("Jdbc_Test2", null, null, null);
+      assertResultSet(res, "getTables2.result");
+      res.close();
+    }
+
+    defaultConnect.close();
+
+    // jdbc1_test database connection test
+    String jdbcTest1ConnUri =
+        TestTajoJdbc.buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(), "jdbc_test1");
+    Connection jdbcTest1Conn = DriverManager.getConnection(jdbcTest1ConnUri);
+    assertEquals("jdbc_test1", jdbcTest1Conn.getCatalog());
+    jdbcTest1Conn.close();
+
+    client.selectDatabase("default");
+    executeString("DROP TABLE jdbc_test1.table1");
+    executeString("DROP TABLE jdbc_test1.table2");
+    executeString("DROP DATABASE jdbc_test1");
+
+    if (!testingCluster.isHCatalogStoreRunning()) {
+      String jdbcTest2ConnUri =
+          TestTajoJdbc.buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(), "Jdbc_Test2");
+      Connection jdbcTest2Conn = DriverManager.getConnection(jdbcTest2ConnUri);
+      assertEquals("Jdbc_Test2", jdbcTest2Conn.getCatalog());
+      jdbcTest2Conn.close();
+
+      client.selectDatabase("default");
+      executeString("DROP TABLE \"Jdbc_Test2\".table3");
+      executeString("DROP TABLE \"Jdbc_Test2\".table4");
+      executeString("DROP DATABASE \"Jdbc_Test2\"");
+    }
+  }
+
+  @Test
+  public void testGetTablesWithPattern() throws Exception {
+    String connUri = TestTajoJdbc.buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        TajoConstants.DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+
+    Map<String,List<String>> tables = new HashMap<String,List<String>>();
+    assertDatabaseNotExists("db_1");
+    executeString("CREATE DATABASE db_1");
+    assertDatabaseExists("db_1");
+    for (int i = 0; i < 3; i++) {
+      String tableName = "tb_" + i;
+      TUtil.putToNestedList(tables, "db_1", tableName);
+      executeString("CREATE TABLE db_1." + tableName + " (age int)");
+    }
+    for (int i = 0; i < 3; i++) {
+      String tableName = "table_" + i + "_ptn";
+      TUtil.putToNestedList(tables, "db_1", tableName);
+      executeString("CREATE TABLE db_1." + tableName + " (age int)");
+    }
+
+    assertDatabaseNotExists("db_2");
+    executeString("CREATE DATABASE db_2");
+    assertDatabaseExists("db_2");
+    for (int i = 0; i < 3; i++) {
+      String tableName = "tb_" + i;
+      TUtil.putToNestedList(tables, "db_2", tableName);
+      executeString("CREATE TABLE db_2." + tableName + " (age int)");
+    }
+    for (int i = 0; i < 3; i++) {
+      String tableName = "table_" + i + "_ptn";
+      TUtil.putToNestedList(tables, "db_2", tableName);
+      executeString("CREATE TABLE db_2." + tableName + " (age int)");
+    }
+
+    // all wildcard test
+    Set<String> tableList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getTables("db_2", null, "%", null), "TABLE_NAME"));
+    assertEquals(Sets.newHashSet(tables.get("db_2")), tableList);
+
+    // leading wildcard test
+    tableList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getTables("db_2", null, "%_ptn", null), "TABLE_NAME"));
+    assertEquals(Sets.newHashSet("table_0_ptn", "table_1_ptn", "table_2_ptn"), tableList);
+
+    // tailing wildcard test
+    tableList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getTables("db_2", null, "tb_%", null), "TABLE_NAME"));
+    assertEquals(Sets.newHashSet("tb_0", "tb_1", "tb_2"), tableList);
+
+    ResultSet resultSet = conn.getMetaData().getTables(null, null, "tb\\_%", null);
+    int i = 0;
+    while(resultSet.next()) {
+      tables.get(resultSet.getString("TABLE_CAT")).contains(resultSet.getString("TABLE_NAME"));
+      i++;
+    }
+    assertEquals(6, i);
+
+    executeString("DROP DATABASE db_1");
+    executeString("DROP DATABASE db_2");
+  }
+
+  @Test
+  public void testGetColumnsWithPattern() throws Exception {
+    String connUri = TestTajoJdbc.buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        TajoConstants.DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+
+    // Below creates the following 12 tables
+    // db<i>.tb<j>, i = {1,2}, 0 <= j < 2
+    // db<i>.table_<j>, i = {1,2}, 0 <= j < 2
+
+    Map<String,List<String>> tables = new HashMap<String,List<String>>();
+    assertDatabaseNotExists("db1");
+    executeString("CREATE DATABASE db1").close();
+    assertDatabaseExists("db1");
+    for (int i = 3; i < 6; i++) {
+      String tableName = "tb" + i;
+      TUtil.putToNestedList(tables, "db1", tableName);
+      executeString("CREATE TABLE db1." + tableName +
+          " (db1_" + tableName + "_col1 int, db1_" + tableName + "_col2 int)").close();
+      assertTableExists("db1." + tableName);
+    }
+    for (int i = 3; i < 6; i++) {
+      String tableName = "table" + i;
+      TUtil.putToNestedList(tables, "db1", tableName);
+      executeString("CREATE TABLE db1." + tableName +
+          " (db1_" + tableName + "_col1 int, db1_" + tableName + "_col2 int)").close();
+      assertTableExists("db1." + tableName);
+    }
+
+    assertDatabaseNotExists("db2");
+    executeString("CREATE DATABASE db2").close();
+    assertDatabaseExists("db2");
+    for (int i = 3; i < 6; i++) {
+      String tableName = "tb" + i;
+      TUtil.putToNestedList(tables, "db2", tableName);
+      executeString("CREATE TABLE db2." + tableName
+          + " (db2_" + tableName + "_col1 int, db2_" + tableName + "_col2 int)").close();
+      assertTableExists("db2." + tableName);
+    }
+    for (int i = 3; i < 6; i++) {
+      String tableName = "table" + i;
+      TUtil.putToNestedList(tables, "db2", tableName);
+      executeString("CREATE TABLE db2." + tableName +
+          " (db2_" + tableName + "_col1 int, db2_" + tableName + "_col2 int)").close();
+      assertTableExists("db2." + tableName);
+    }
+
+    // all wildcard test on columns
+    Set<String> columnList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getColumns("db2", null, "tb3", "%"),
+            "COLUMN_NAME"));
+    assertEquals(Sets.newHashSet("db2_tb3_col1", "db2_tb3_col2"), columnList);
+
+    // leading wildcard test on columns
+    columnList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getColumns("db2", null, "tb3", "%col1"),
+            "COLUMN_NAME"));
+    assertEquals(Sets.newHashSet("db2_tb3_col1"), columnList);
+
+    // tailing wildcard test on columns
+    columnList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getColumns("db2", null, "tb3", "db2\\_tb3\\_%"),
+            "COLUMN_NAME"));
+    assertEquals(Sets.newHashSet("db2_tb3_col1", "db2_tb3_col2"), columnList);
+    columnList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getColumns("db2", null, "%", "db2\\_tb3\\_%"),
+            "COLUMN_NAME"));
+    assertEquals(Sets.newHashSet("db2_tb3_col1", "db2_tb3_col2"), columnList);
+
+    // leading wildcard test on tables
+    columnList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getColumns("db1", null, "%3", "%"),
+            "COLUMN_NAME"));
+    assertEquals(
+        Sets.newHashSet(
+            "db1_tb3_col1", "db1_tb3_col2",
+            "db1_table3_col1", "db1_table3_col2"),
+        columnList);
+    columnList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getColumns("db2", null, "%3", "%"),
+            "COLUMN_NAME"));
+    assertEquals(
+        Sets.newHashSet(
+            "db2_tb3_col1", "db2_tb3_col2",
+            "db2_table3_col1", "db2_table3_col2"),
+        columnList);
+
+    // tailing wildcard test on tables
+    columnList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getColumns("db2", null, "table%", "%"),
+            "COLUMN_NAME"));
+    assertEquals(
+        Sets.newHashSet(
+            "db2_table3_col1", "db2_table3_col2",
+            "db2_table4_col1", "db2_table4_col2",
+            "db2_table5_col1", "db2_table5_col2"),
+        columnList);
+
+    // wildcard test on database
+    columnList =
+        Sets.newHashSet(getListFromResultSet(conn.getMetaData().getColumns(null, null, "%3", "db1_tb3%"),
+            "COLUMN_NAME"));
+    assertEquals(Sets.newHashSet("db1_tb3_col1", "db1_tb3_col2"), columnList);
+
+    executeString("DROP DATABASE db1");
+    executeString("DROP DATABASE db2");
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/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 9d0352c..7343ef7 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
@@ -22,7 +22,6 @@ 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;
@@ -43,9 +42,8 @@ import static org.junit.Assert.*;
 
 @Category(IntegrationTest.class)
 public class TestTajoJdbc extends QueryTestCaseBase {
-  private static TpchTestBase tpch;
-
   private static InetSocketAddress tajoMasterAddress;
+
   @BeforeClass
   public static void setUp() throws Exception {
     tajoMasterAddress = testingCluster.getMaster().getTajoMasterClientService().getBindAddress();
@@ -56,7 +54,7 @@ public class TestTajoJdbc extends QueryTestCaseBase {
   public static void tearDown() throws Exception {
   }
 
-  private static String buildConnectionUri(String hostName, int port, String databaseNme) {
+  public static String buildConnectionUri(String hostName, int port, String databaseNme) {
     return "jdbc:tajo://" + hostName + ":" + port + "/" + databaseNme;
   }
 
@@ -65,6 +63,7 @@ public class TestTajoJdbc extends QueryTestCaseBase {
     String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
         DEFAULT_DATABASE_NAME);
     Connection conn = DriverManager.getConnection(connUri);
+    assertTrue(conn.isValid(100));
 
     Statement stmt = null;
     ResultSet res = null;
@@ -109,6 +108,7 @@ public class TestTajoJdbc extends QueryTestCaseBase {
     String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
         TajoConstants.DEFAULT_DATABASE_NAME);
     Connection conn = DriverManager.getConnection(connUri);
+    assertTrue(conn.isValid(100));
 
     PreparedStatement stmt = null;
     ResultSet res = null;
@@ -189,18 +189,20 @@ public class TestTajoJdbc extends QueryTestCaseBase {
     String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
         TajoConstants.DEFAULT_DATABASE_NAME);
     Connection conn = DriverManager.getConnection(connUri);
+    assertTrue(conn.isValid(100));
+
     DatabaseMetaData dbmd = conn.getMetaData();
 
     ResultSet rs = null;
 
     try {
-      rs = dbmd.getTables(null, null, null, null);
+      rs = dbmd.getTables("default", null, null, null);
 
       ResultSetMetaData rsmd = rs.getMetaData();
       int numCols = rsmd.getColumnCount();
       assertEquals(5, numCols);
 
-      Set<String> retrivedViaJavaAPI = new HashSet<String>(client.getTableList(DEFAULT_DATABASE_NAME));
+      Set<String> retrivedViaJavaAPI = new HashSet<String>(client.getTableList("default"));
 
       Set<String> retrievedViaJDBC = new HashSet<String>();
       while(rs.next()) {
@@ -212,6 +214,9 @@ public class TestTajoJdbc extends QueryTestCaseBase {
         rs.close();
       }
     }
+
+    assertTrue(conn.isValid(100));
+    conn.close();
   }
 
   @Test
@@ -219,12 +224,13 @@ public class TestTajoJdbc extends QueryTestCaseBase {
     String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
         TajoConstants.DEFAULT_DATABASE_NAME);
     Connection conn = DriverManager.getConnection(connUri);
-    DatabaseMetaData dbmd = conn.getMetaData();
+    assertTrue(conn.isValid(100));
 
+    DatabaseMetaData dbmd = conn.getMetaData();
     ResultSet rs = null;
 
     try {
-      String tableName = CatalogUtil.normalizeIdentifier("lineitem");
+      String tableName = "lineitem";
       rs = dbmd.getColumns(null, null, tableName, null);
 
       ResultSetMetaData rsmd = rs.getMetaData();
@@ -241,7 +247,7 @@ public class TestTajoJdbc extends QueryTestCaseBase {
       while(rs.next()) {
         assertEquals(tableName, rs.getString("TABLE_NAME"));
         assertEquals(columns.get(numColumns).getSimpleName(), rs.getString("COLUMN_NAME"));
-        //TODO assert type
+        // TODO assert type
         numColumns++;
       }
 
@@ -251,6 +257,10 @@ public class TestTajoJdbc extends QueryTestCaseBase {
         rs.close();
       }
     }
+
+    assertTrue(conn.isValid(100));
+    conn.close();
+    assertFalse(conn.isValid(100));
   }
 
   @Test
@@ -302,14 +312,19 @@ public class TestTajoJdbc extends QueryTestCaseBase {
         }
       }
     } finally {
+      assertTrue(conns[0].isValid(100));
       conns[0].close();
+      assertFalse(conns[0].isValid(100));
+      assertTrue(conns[1].isValid(100));
       conns[1].close();
+      assertFalse(conns[1].isValid(100));
     }
   }
 
   @Test
   public void testMultipleConnectionsSequentialClose() throws Exception {
-    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(), DEFAULT_DATABASE_NAME);
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        DEFAULT_DATABASE_NAME);
 
     Connection[] conns = new Connection[2];
     conns[0] = DriverManager.getConnection(connUri);
@@ -357,126 +372,15 @@ public class TestTajoJdbc extends QueryTestCaseBase {
       }
     } finally {
       if(!conns[0].isClosed()) {
+        assertTrue(conns[0].isValid(100));
         conns[0].close();
+        assertFalse(conns[0].isValid(100));
       }
       if(!conns[1].isClosed()) {
+        assertTrue(conns[1].isValid(100));
         conns[1].close();
+        assertFalse(conns[1].isValid(100));
       }
     }
   }
-
-  @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/838b5222/tajo-core/tajo-core-backend/src/test/resources/queries/TestAlterTable/alter_table_rename_table_ddl.sql
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestAlterTable/alter_table_rename_table_ddl.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestAlterTable/alter_table_rename_table_ddl.sql
index eeab457..1808eaa 100644
--- a/tajo-core/tajo-core-backend/src/test/resources/queries/TestAlterTable/alter_table_rename_table_ddl.sql
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestAlterTable/alter_table_rename_table_ddl.sql
@@ -1 +1 @@
- ALTER TABLE ABC RENAME TO DEF;
+ ALTER TABLE ABC RENAME TO "DEF";

http://git-wip-us.apache.org/repos/asf/tajo/blob/838b5222/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoDatabaseMetaData/getTables1.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoDatabaseMetaData/getTables1.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoDatabaseMetaData/getTables1.result
new file mode 100644
index 0000000..2d89f42
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoDatabaseMetaData/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/838b5222/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoDatabaseMetaData/getTables2.result
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoDatabaseMetaData/getTables2.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoDatabaseMetaData/getTables2.result
new file mode 100644
index 0000000..7cc1391
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoDatabaseMetaData/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/838b5222/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
deleted file mode 100644
index 2d89f42..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables1.result
+++ /dev/null
@@ -1,4 +0,0 @@
-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/838b5222/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
deleted file mode 100644
index 042cb52..0000000
--- a/tajo-core/tajo-core-backend/src/test/resources/results/TestTajoJdbc/getTables2.result
+++ /dev/null
@@ -1,4 +0,0 @@
-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/838b5222/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 5d967e8..9439f0f 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
@@ -19,11 +19,14 @@
 package org.apache.tajo.jdbc;
 
 import com.google.protobuf.ServiceException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 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.io.IOException;
 import java.net.URI;
 import java.sql.*;
 import java.util.List;
@@ -33,6 +36,8 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 public class TajoConnection implements Connection {
+  private static Log LOG = LogFactory.getLog(TajoConnection.class);
+
   private final TajoClient tajoClient;
   private final AtomicBoolean closed = new AtomicBoolean(true);
   private final String rawURI;
@@ -247,8 +252,23 @@ public class TajoConnection implements Connection {
 
   @Override
   public boolean isValid(int timeout) throws SQLException {
-    // TODO - It should be changed to submit a simple query.
-    return tajoClient.isConnected();
+    try {
+      if (tajoClient.isConnected()) {
+        ResultSet resultSet = tajoClient.executeQueryAndGetResult("SELECT 1;");
+        boolean next = resultSet.next();
+        boolean valid = next && resultSet.getLong(1) == 1;
+        resultSet.close();
+        return valid;
+      } else {
+        return false;
+      }
+    } catch (ServiceException e) {
+      LOG.error("TajoMaster is not available.");
+      return false;
+    } catch (IOException e) {
+      LOG.error("JDBC connection is not valid.");
+      return false;
+    }
   }
 
   @Override