tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hyun...@apache.org
Subject tajo git commit: TAJO-1749: Refine JDBC exceptions to better handle exceptional cases.
Date Thu, 03 Sep 2015 13:11:59 GMT
Repository: tajo
Updated Branches:
  refs/heads/master 3e8f4a030 -> 688bc5c11


TAJO-1749: Refine JDBC exceptions to better handle exceptional cases.

Closes #722


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

Branch: refs/heads/master
Commit: 688bc5c1111054cb486cdc915edc8fc0097add4a
Parents: 3e8f4a0
Author: Hyunsik Choi <hyunsik@apache.org>
Authored: Thu Sep 3 22:08:08 2015 +0900
Committer: Hyunsik Choi <hyunsik@apache.org>
Committed: Thu Sep 3 22:08:08 2015 +0900

----------------------------------------------------------------------
 CHANGES                                         |   3 +
 .../apache/tajo/client/SessionConnection.java   |   4 +-
 .../org/apache/tajo/client/TajoClientImpl.java  |   6 +-
 .../v2/exception/ClientConnectionException.java |   5 +-
 .../org/apache/tajo/jdbc/TajoSQLException.java  |  43 +++++
 .../org/apache/tajo/jdbc/WaitingResultSet.java  |  10 +-
 .../apache/tajo/exception/ErrorMessages.java    |   7 +-
 .../apache/tajo/exception/SQLExceptionUtil.java |  94 ++++++++++-
 .../apache/tajo/exception/TajoException.java    |   5 +
 tajo-common/src/main/proto/errors.proto         |  49 +++---
 .../tajo/master/exec/CreateTableExecutor.java   |   1 +
 .../apache/tajo/master/exec/DDLExecutor.java    |   3 +-
 .../org/apache/tajo/jdbc/JdbcConnection.java    |  25 ++-
 .../apache/tajo/jdbc/TajoPreparedStatement.java |  20 +--
 .../org/apache/tajo/jdbc/TajoStatement.java     |  39 ++---
 .../java/org/apache/tajo/jdbc/TestTajoJdbc.java |   6 -
 .../apache/tajo/jdbc/TestTajoJdbcNegative.java  | 156 +++++++++++++++++++
 .../org/apache/tajo/rpc/NettyClientBase.java    |  13 +-
 18 files changed, 396 insertions(+), 93 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 32cf77f..d3d47be 100644
--- a/CHANGES
+++ b/CHANGES
@@ -549,6 +549,9 @@ Release 0.11.0 - unreleased
 
   SUB TASKS
 
+    TAJO-1749: Refine JDBC exceptions to better handle exceptional 
+    cases. (hyunsik)
+
     TAJO-1737: Implement SQL Parser rule for Map type. (hyunsik)
 
     TAJO-1787: Remove unused and legacy exceptions. (hyunsik)

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-client/src/main/java/org/apache/tajo/client/SessionConnection.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/client/SessionConnection.java b/tajo-client/src/main/java/org/apache/tajo/client/SessionConnection.java
index 7f33fdd..b63d35b 100644
--- a/tajo-client/src/main/java/org/apache/tajo/client/SessionConnection.java
+++ b/tajo-client/src/main/java/org/apache/tajo/client/SessionConnection.java
@@ -19,6 +19,7 @@
 package org.apache.tajo.client;
 
 import com.google.protobuf.ServiceException;
+import io.netty.channel.ConnectTimeoutException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.tajo.SessionVars;
@@ -46,6 +47,7 @@ import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.StringResponse;
 import org.apache.tajo.service.ServiceTracker;
 import org.apache.tajo.util.CommonTestingUtil;
 import org.apache.tajo.util.KeyValueSet;
+import org.apache.tajo.util.NetUtils;
 import org.apache.tajo.util.ProtoUtil;
 
 import java.io.Closeable;
@@ -136,7 +138,7 @@ public class SessionConnection implements Closeable {
         connections.incrementAndGet();
 
       } catch (Throwable t) {
-        throw new ClientConnectionException(t);
+        throw new TajoRuntimeException(new ClientConnectionException(t));
       }
 
       return client;

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-client/src/main/java/org/apache/tajo/client/TajoClientImpl.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/client/TajoClientImpl.java b/tajo-client/src/main/java/org/apache/tajo/client/TajoClientImpl.java
index a6c07ea..5a689a1 100644
--- a/tajo-client/src/main/java/org/apache/tajo/client/TajoClientImpl.java
+++ b/tajo-client/src/main/java/org/apache/tajo/client/TajoClientImpl.java
@@ -57,8 +57,7 @@ public class TajoClientImpl extends SessionConnection implements TajoClient,
Que
    * @param properties configurations
    * @throws java.io.IOException
    */
-  public TajoClientImpl(ServiceTracker tracker, @Nullable String baseDatabase, KeyValueSet
properties)
-      throws SQLException {
+  public TajoClientImpl(ServiceTracker tracker, @Nullable String baseDatabase, KeyValueSet
properties) {
 
     super(tracker, baseDatabase, properties);
 
@@ -75,8 +74,7 @@ public class TajoClientImpl extends SessionConnection implements TajoClient,
Que
    * @param properties configurations
    * @throws java.io.IOException
    */
-  public TajoClientImpl(InetSocketAddress addr, @Nullable String baseDatabase, KeyValueSet
properties)
-      throws SQLException {
+  public TajoClientImpl(InetSocketAddress addr, @Nullable String baseDatabase, KeyValueSet
properties) {
     this(new DummyServiceTracker(addr), baseDatabase, properties);
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-client/src/main/java/org/apache/tajo/client/v2/exception/ClientConnectionException.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/client/v2/exception/ClientConnectionException.java
b/tajo-client/src/main/java/org/apache/tajo/client/v2/exception/ClientConnectionException.java
index a7fb08a..fcbbfe3 100644
--- a/tajo-client/src/main/java/org/apache/tajo/client/v2/exception/ClientConnectionException.java
+++ b/tajo-client/src/main/java/org/apache/tajo/client/v2/exception/ClientConnectionException.java
@@ -19,10 +19,11 @@
 package org.apache.tajo.client.v2.exception;
 
 import org.apache.tajo.error.Errors;
+import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.exception.TajoRuntimeException;
 
-public class ClientConnectionException extends TajoRuntimeException {
+public class ClientConnectionException extends TajoException {
   public ClientConnectionException(Throwable t) {
-    super(Errors.ResultCode.CLIENT_CONNECTION_EXCEPTION, t.getMessage());
+    super(Errors.ResultCode.CLIENT_CONNECTION_EXCEPTION, t, t.getMessage());
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoSQLException.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoSQLException.java b/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoSQLException.java
new file mode 100644
index 0000000..53d39cb
--- /dev/null
+++ b/tajo-client/src/main/java/org/apache/tajo/jdbc/TajoSQLException.java
@@ -0,0 +1,43 @@
+/*
+ * 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 org.apache.tajo.error.Errors;
+import org.apache.tajo.exception.ErrorMessages;
+import org.apache.tajo.exception.ExceptionUtil;
+import org.apache.tajo.exception.SQLExceptionUtil;
+import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos;
+
+import java.sql.SQLException;
+
+public class TajoSQLException extends SQLException {
+
+  public TajoSQLException(PrimitiveProtos.ReturnState returnState) {
+    super(returnState.getMessage(), SQLExceptionUtil.toSQLState(returnState.getReturnCode()),
+        ExceptionUtil.toTajoException(returnState));
+  }
+
+  public TajoSQLException(Errors.ResultCode code, String...args) {
+    super(ErrorMessages.getMessage(code, args), SQLExceptionUtil.toSQLState(code));
+  }
+
+  public TajoSQLException(Errors.ResultCode code, Throwable t, String...args) {
+    super(ErrorMessages.getMessage(code, args), SQLExceptionUtil.toSQLState(code), t);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-client/src/main/java/org/apache/tajo/jdbc/WaitingResultSet.java
----------------------------------------------------------------------
diff --git a/tajo-client/src/main/java/org/apache/tajo/jdbc/WaitingResultSet.java b/tajo-client/src/main/java/org/apache/tajo/jdbc/WaitingResultSet.java
index 68cc2fc..aa26027 100644
--- a/tajo-client/src/main/java/org/apache/tajo/jdbc/WaitingResultSet.java
+++ b/tajo-client/src/main/java/org/apache/tajo/jdbc/WaitingResultSet.java
@@ -18,7 +18,6 @@
 
 package org.apache.tajo.jdbc;
 
-import com.google.protobuf.ServiceException;
 import org.apache.tajo.QueryId;
 import org.apache.tajo.TajoProtos;
 import org.apache.tajo.catalog.CatalogUtil;
@@ -27,6 +26,7 @@ import org.apache.tajo.catalog.TableDesc;
 import org.apache.tajo.client.QueryClient;
 import org.apache.tajo.client.QueryStatus;
 import org.apache.tajo.client.TajoClientUtil;
+import org.apache.tajo.error.Errors.ResultCode;
 import org.apache.tajo.exception.SQLExceptionUtil;
 import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.ipc.ClientProtos;
@@ -59,15 +59,13 @@ public class WaitingResultSet extends FetchResultSet {
       QueryStatus status = TajoClientUtil.waitCompletion(tajoClient, queryId);
 
       if (status.getState() != TajoProtos.QueryState.QUERY_SUCCEEDED) {
-        throw new ServiceException(status.getErrorMessage() != null ? status.getErrorMessage()
:
-            status.getErrorTrace() != null ? status.getErrorTrace() :
-                "Failed to execute query by unknown reason");
+        throw new SQLException(status.getErrorMessage() != null ? status.getErrorMessage()
: "unknown error",
+            SQLExceptionUtil.toSQLState(ResultCode.INTERNAL_ERROR), ResultCode.INTERNAL_ERROR.getNumber());
       }
+
       ClientProtos.GetQueryResultResponse response = tajoClient.getResultResponse(queryId);
       TableDesc tableDesc = CatalogUtil.newTableDesc(response.getTableDesc());
       return tableDesc.getLogicalSchema();
-    } catch (ServiceException e) {
-      throw new SQLException(e);
     } catch (TajoException e) {
       throw SQLExceptionUtil.toSQLException(e);
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-common/src/main/java/org/apache/tajo/exception/ErrorMessages.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/exception/ErrorMessages.java b/tajo-common/src/main/java/org/apache/tajo/exception/ErrorMessages.java
index 3b11eab..a3f18e3 100644
--- a/tajo-common/src/main/java/org/apache/tajo/exception/ErrorMessages.java
+++ b/tajo-common/src/main/java/org/apache/tajo/exception/ErrorMessages.java
@@ -116,8 +116,9 @@ public class ErrorMessages {
     ADD_MESSAGE(INVALID_INPUTS_FOR_CROSS_JOIN, "At least one of both inputs for the cross
join must be a simple " +
         "relation.");
 
-    ADD_MESSAGE(CLIENT_CONNECTION_EXCEPTION, "Client connection to '%s' has error: %s", 2);
+    ADD_MESSAGE(CLIENT_CONNECTION_EXCEPTION, "%s", 1);
     ADD_MESSAGE(CLIENT_UNABLE_TO_ESTABLISH_CONNECTION, "Client is unable to establish connection
to '%s'", 1);
+    ADD_MESSAGE(CLIENT_CONNECTION_DOES_NOT_EXIST, "This connection has been closed.");
   }
 
   private static void ADD_MESSAGE(ResultCode code, String msgFormat) {
@@ -169,7 +170,9 @@ public class ErrorMessages {
         }
 
       } else {
-        throw new TajoInternalError("Argument mismatch: code=" + code.name() + ", args="
+ concat(args));
+        throw new TajoInternalError(
+            "Error message arguments are invalid: code=" + code.name() + ", args=" + concat(args)
+
+                ". Please report this bug to https://issues.apache.org/jira/browse/TAJO.");
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-common/src/main/java/org/apache/tajo/exception/SQLExceptionUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/exception/SQLExceptionUtil.java b/tajo-common/src/main/java/org/apache/tajo/exception/SQLExceptionUtil.java
index e326ae2..0e22a87 100644
--- a/tajo-common/src/main/java/org/apache/tajo/exception/SQLExceptionUtil.java
+++ b/tajo-common/src/main/java/org/apache/tajo/exception/SQLExceptionUtil.java
@@ -32,11 +32,79 @@ public class SQLExceptionUtil {
   private static final Map<ResultCode, String> SQLSTATES = Maps.newHashMap();
 
   static {
-    // TODO - All SQLState should be be filled
-    SQLSTATES.put(ResultCode.FEATURE_NOT_SUPPORTED, "0A000");
-    SQLSTATES.put(ResultCode.NOT_IMPLEMENTED, "0A000");
-
-    SQLSTATES.put(ResultCode.SYNTAX_ERROR, "42601");
+    SQLSTATES.put(ResultCode.INTERNAL_ERROR,                        "XX000");
+    SQLSTATES.put(ResultCode.NOT_IMPLEMENTED,                       "0A000");
+    SQLSTATES.put(ResultCode.FEATURE_NOT_SUPPORTED,                 "0A000");
+    SQLSTATES.put(ResultCode.INVALID_RPC_CALL,                      "08P01"); // Protocol
violation
+
+
+    // Class 61 - Query Management and Scheduler
+    SQLSTATES.put(ResultCode.QUERY_FAILED,                          "61T01");
+    SQLSTATES.put(ResultCode.QUERY_KILLED,                          "61T02");
+    SQLSTATES.put(ResultCode.QUERY_TIMEOUT,                         "61T03");
+    SQLSTATES.put(ResultCode.QUERY_NOT_FOUND,                       "61T04");
+    SQLSTATES.put(ResultCode.NO_DATA,                               "61T05");
+    SQLSTATES.put(ResultCode.INCOMPLETE_QUERY,                      "61T06");
+
+
+    // Class 62 - Session
+    SQLSTATES.put(ResultCode.INVALID_SESSION,                       "62T01");
+    SQLSTATES.put(ResultCode.NO_SUCH_SESSION_VARIABLE,              "62T02");
+    SQLSTATES.put(ResultCode.INVALID_SESSION_VARIABLE,              "62T03");
+
+
+    // Data Exception (SQLState Class - 22)
+    SQLSTATES.put(ResultCode.DIVISION_BY_ZERO,                      "22012");
+
+
+    // Section: Class 42 - Syntax Error or Access Rule Violation
+    SQLSTATES.put(ResultCode.SYNTAX_ERROR,                          "42601");
+
+    SQLSTATES.put(ResultCode.UNDEFINED_DATABASE,                    "42T01");
+    SQLSTATES.put(ResultCode.UNDEFINED_SCHEMA,                      "42T02");
+    SQLSTATES.put(ResultCode.UNDEFINED_TABLE,                       "42P01");
+    SQLSTATES.put(ResultCode.UNDEFINED_COLUMN,                      "42703");
+    SQLSTATES.put(ResultCode.UNDEFINED_FUNCTION,                    "42883");
+    SQLSTATES.put(ResultCode.UNDEFINED_INDEX_FOR_TABLE,             "42T03");
+    SQLSTATES.put(ResultCode.UNDEFINED_INDEX_FOR_COLUMNS,           "42T04");
+    SQLSTATES.put(ResultCode.UNDEFINED_PARTITION,                   "42T05");
+    SQLSTATES.put(ResultCode.UNDEFINED_PARTITION_METHOD,            "42T06");
+    SQLSTATES.put(ResultCode.UNDEFINED_OPERATOR,                    "42883"); // == UNDEFINED_FUNCTION
+    SQLSTATES.put(ResultCode.UNDEFINED_PARTITION_KEY,               "42T07");
+
+    SQLSTATES.put(ResultCode.DUPLICATE_TABLESPACE,                  "42T08");
+    SQLSTATES.put(ResultCode.DUPLICATE_DATABASE,                    "42P04");
+    SQLSTATES.put(ResultCode.DUPLICATE_SCHEMA,                      "42P06");
+    SQLSTATES.put(ResultCode.DUPLICATE_TABLE,                       "42P07");
+    SQLSTATES.put(ResultCode.DUPLICATE_COLUMN,                      "42701");
+    SQLSTATES.put(ResultCode.DUPLICATE_ALIAS,                       "42712");
+    SQLSTATES.put(ResultCode.DUPLICATE_FUNCTION,                    "42723");
+    SQLSTATES.put(ResultCode.DUPLICATE_INDEX,                       "42710");
+    SQLSTATES.put(ResultCode.DUPLICATE_PARTITION,                   "42T09");
+
+    SQLSTATES.put(ResultCode.AMBIGUOUS_TABLE,                       "42723");
+    SQLSTATES.put(ResultCode.AMBIGUOUS_COLUMN,                      "42723");
+    SQLSTATES.put(ResultCode.AMBIGUOUS_FUNCTION,                    "42723");
+    SQLSTATES.put(ResultCode.AMBIGUOUS_PARTITION_DIRECTORY,         "42T10");
+
+    SQLSTATES.put(ResultCode.CANNOT_CAST,                           "42846");
+    SQLSTATES.put(ResultCode.GROUPING_ERROR,                        "42803");
+    SQLSTATES.put(ResultCode.WINDOWING_ERROR,                       "42P20");
+    SQLSTATES.put(ResultCode.INVALID_RECURSION,                     "42P19");
+    SQLSTATES.put(ResultCode.SET_OPERATION_SCHEMA_MISMATCH,         "42601");
+    SQLSTATES.put(ResultCode.SET_OPERATION_DATATYPE_MISMATCH,       "42601");
+    SQLSTATES.put(ResultCode.INVALID_FOREIGN_KEY,                   "42830");
+    SQLSTATES.put(ResultCode.INVALID_NAME,                          "42602");
+    SQLSTATES.put(ResultCode.INVALID_COLUMN_DEFINITION,             "42611");
+    SQLSTATES.put(ResultCode.NAME_TOO_LONG,                         "42622");
+    SQLSTATES.put(ResultCode.RESERVED_NAME,                         "42939");
+    SQLSTATES.put(ResultCode.DATATYPE_MISMATCH,                     "42804");
+    SQLSTATES.put(ResultCode.INDETERMINATE_DATATYPE,                "42P18");
+
+    // Client Connection
+    SQLSTATES.put(ResultCode.CLIENT_CONNECTION_EXCEPTION,           "08001");
+    SQLSTATES.put(ResultCode.CLIENT_UNABLE_TO_ESTABLISH_CONNECTION, "08002");
+    SQLSTATES.put(ResultCode.CLIENT_CONNECTION_DOES_NOT_EXIST,      "08003");
   }
 
   public static boolean isThisError(SQLException e, ResultCode code) {
@@ -73,8 +141,20 @@ public class SQLExceptionUtil {
     }
   }
 
-  public static SQLException toSQLException(TajoException e) throws SQLException {
-    return toSQLException(e.getErrorCode(), e.getMessage());
+  public static String toSQLState(ResultCode code) {
+    if (SQLSTATES.containsKey(code)) {
+      return SQLSTATES.get(code);
+    } else {
+      return "42000";
+    }
+  }
+
+  public static SQLException toSQLException(DefaultTajoException e) throws SQLException {
+    if (e instanceof TajoRuntimeException) {
+      return toSQLException(e.getErrorCode(), ((TajoRuntimeException) e).getCause().getMessage());
+    } else {
+      return toSQLException(e.getErrorCode(), e.getMessage());
+    }
   }
 
   public static SQLException toSQLException(ReturnState state) throws SQLException {

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-common/src/main/java/org/apache/tajo/exception/TajoException.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/exception/TajoException.java b/tajo-common/src/main/java/org/apache/tajo/exception/TajoException.java
index b5d236e..df74072 100644
--- a/tajo-common/src/main/java/org/apache/tajo/exception/TajoException.java
+++ b/tajo-common/src/main/java/org/apache/tajo/exception/TajoException.java
@@ -43,6 +43,11 @@ public class TajoException extends Exception implements DefaultTajoException
{
     this.code = code;
   }
 
+  public TajoException(ResultCode code, Throwable t, String ... args) {
+    super(ErrorMessages.getMessage(code, args), t);
+    this.code = code;
+  }
+
   public TajoException(ResultCode code, String ... args) {
     super(ErrorMessages.getMessage(code, args));
     this.code = code;

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-common/src/main/proto/errors.proto
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/proto/errors.proto b/tajo-common/src/main/proto/errors.proto
index 21746f3..f830b11 100644
--- a/tajo-common/src/main/proto/errors.proto
+++ b/tajo-common/src/main/proto/errors.proto
@@ -68,31 +68,31 @@ import "stacktrace.proto";
 enum ResultCode {
   // Class
   // 00 - Successful Completion
-  OK                            = 0;
+  OK                                    = 0;
 
-  WARNING                       = 100; // Warning
+  WARNING                               = 100; // Warning
 
   // General Errors
-  INTERNAL_ERROR                = 201; // Error caused by internal bugs (See also TajoInternalException.java)
-  NOT_IMPLEMENTED               = 202; // Planned, but not implemented yet.
-  FEATURE_NOT_SUPPORTED         = 203; // SQLState: 0A000 - Unsupported feature (usually
for unreasonable feature)
-  INVALID_RPC_CALL              = 204; // When invalid RPC call is invoked (e.g., wrong message
and absent fields)
+  INTERNAL_ERROR                        = 201; // SQLState: XX000 - Error caused by internal
bugs (See TajoInternalException)
+  NOT_IMPLEMENTED                       = 202; // SQLState: 0A000 - Not implemented yet,
but planned.
+  FEATURE_NOT_SUPPORTED                 = 203; // SQLState: 0A000 - Unsupported feature (usually
for unreasonable feature)
+  INVALID_RPC_CALL                      = 204; // SQLState: 08P01 - When invalid RPC call
is invoked (e.g., wrong message and absent fields)
 
   // Query Management and Scheduler
-  QUERY_FAILED                  = 301; // SQLState: ? - Query failed
-  QUERY_KILLED                  = 302; // SQLState: ? - Query killed
-  QUERY_TIMEOUT                 = 303; // SQLState: ? - Timeout for the query
-  QUERY_NOT_FOUND               = 304; // No such query in TajoMaster
-  NO_DATA                       = 305; // No data due to query fail or error
-  INCOMPLETE_QUERY              = 306; // It occurs when a client requests something of a
completed query.
+  QUERY_FAILED                          = 301; // SQLState: 61T01 - Query failed
+  QUERY_KILLED                          = 302; // SQLState: 61T02 - Query killed
+  QUERY_TIMEOUT                         = 303; // SQLState: 61T03 - Timeout for the query
+  QUERY_NOT_FOUND                       = 304; // SQLState: 61T04 - No such query in TajoMaster
+  NO_DATA                               = 305; // SQLState: 61T05 - No data due to query
fail or error
+  INCOMPLETE_QUERY                      = 306; // SQLState: 61T06 - It occurs when a client
requests something of a completed query.
 
   // Session
-  INVALID_SESSION               = 401; // Session already was invalid
-  NO_SUCH_SESSION_VARIABLE      = 402; // Session variable not found
-  INVALID_SESSION_VARIABLE      = 403; // Session variable is invalid (type mismatch or out
of range)
+  INVALID_SESSION                       = 401; // SQLState: 62T01 - Session already was invalid
+  NO_SUCH_SESSION_VARIABLE              = 402; // SQLState: 62T01 - Session variable not
found
+  INVALID_SESSION_VARIABLE              = 403; // SQLState: 62T01 - Session variable is invalid
(type mismatch or out of range)
 
   // Data Exception (SQLState Class - 22)
-  DIVISION_BY_ZERO              = 451; // SQLState: 22012 - Division by zero
+  DIVISION_BY_ZERO                      = 451; // SQLState: 22012 - Division by zero
 
 
   // Section: Class 42 - Syntax Error or Access Rule Violation
@@ -101,9 +101,9 @@ enum ResultCode {
   INSUFFICIENT_PRIVILEGE                = 503; // SQLState: 42501
 
   UNDEFINED_TABLESPACE                  = 511; // ?
-  UNDEFINED_DATABASE                    = 512; // ?
-  UNDEFINED_SCHEMA                      = 513; // ?
-  UNDEFINED_TABLE                       = 514; // ?
+  UNDEFINED_DATABASE                    = 512; // SQLState: 42T01
+  UNDEFINED_SCHEMA                      = 513; // SQLState:
+  UNDEFINED_TABLE                       = 514; // SQLState: 42P01
   UNDEFINED_COLUMN                      = 515; // SQLState: 42703
   UNDEFINED_FUNCTION                    = 516; // SQLState: 42883
   UNDEFINED_INDEX_FOR_TABLE             = 517; // ?
@@ -121,10 +121,10 @@ enum ResultCode {
   DUPLICATE_COLUMN                      = 535; // SQLState: 42701
   DUPLICATE_ALIAS                       = 536; // SQLState: 42712
   DUPLICATE_FUNCTION                    = 537; // SQLState: 42723
-  DUPLICATE_INDEX                       = 538; // SQLState: ?
-  DUPLICATE_PARTITION                   = 539; // SQLState: ?
+  DUPLICATE_INDEX                       = 538; // SQLState: 42T07
+  DUPLICATE_PARTITION                   = 539; // SQLState: 42T08
 
-  AMBIGUOUS_TABLE                       = 541; // ?
+  AMBIGUOUS_TABLE                       = 541; // SQLState: 42P09
   AMBIGUOUS_COLUMN                      = 542; // SQLState: 42702;
   AMBIGUOUS_FUNCTION                    = 543; // SQLState: 42725;
   AMBIGUOUS_PARTITION_DIRECTORY         = 544; // ?
@@ -170,10 +170,11 @@ enum ResultCode {
   INVALID_TABLE_PROPERTY                = 1004; // SQLState: ? - Invalid Table Property
   MISSING_TABLE_PROPERTY                = 1005; // SQLState: ? - Missing table property
 
-
+  // Client Connection
   CLIENT_CONNECTION_EXCEPTION           = 1101; // SQLState: 08000 - Client connection error
   CLIENT_UNABLE_TO_ESTABLISH_CONNECTION = 1102; // SQLState: 08001 -
-  CLIENT_PROTOCOL_PROTOCOL_VIOLATION    = 1103; // SQLState: ?
+  CLIENT_CONNECTION_DOES_NOT_EXIST      = 1103; // SQLState: 08003 - Client connection has
been closed.
+  CLIENT_PROTOCOL_PROTOCOL_VIOLATION    = 1104; // SQLState: ?
 
   // 53 - Invalid Operand or Inconsistent Specification
   INSUFFICIENT_RESOURCE           = 53000;

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
b/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
index 38f722d..24f420c 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/CreateTableExecutor.java
@@ -108,6 +108,7 @@ public class CreateTableExecutor {
 
     tableSpace.createTable(desc, ifNotExists);
     catalog.createTable(desc);
+    LOG.info("relation '" + qualifiedName + "' created.");
     return desc;
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java b/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java
index e3d91bb..a0f9adc 100644
--- a/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java
+++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/DDLExecutor.java
@@ -251,11 +251,12 @@ public class DDLExecutor {
       }
     }
 
-    catalog.createDatabase(databaseName, tablespaceName);
     String normalized = databaseName;
     Path databaseDir = StorageUtil.concatPath(context.getConf().getVar(TajoConf.ConfVars.WAREHOUSE_DIR),
normalized);
     FileSystem fs = databaseDir.getFileSystem(context.getConf());
     fs.mkdirs(databaseDir);
+    catalog.createDatabase(databaseName, tablespaceName);
+    LOG.info("database \"" + databaseName + "\" created.");
   }
 
   public void dropDatabase(QueryContext queryContext, String databaseName, boolean ifExists)

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/JdbcConnection.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/JdbcConnection.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/JdbcConnection.java
index b098b16..85dbdbe 100644
--- a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/JdbcConnection.java
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/JdbcConnection.java
@@ -27,14 +27,17 @@ import org.apache.tajo.client.CatalogAdminClient;
 import org.apache.tajo.client.QueryClient;
 import org.apache.tajo.client.TajoClient;
 import org.apache.tajo.client.TajoClientImpl;
+import org.apache.tajo.client.v2.exception.ClientConnectionException;
 import org.apache.tajo.conf.TajoConf;
-import org.apache.tajo.exception.SQLExceptionUtil;
-import org.apache.tajo.exception.TajoException;
+import org.apache.tajo.error.Errors;
+import org.apache.tajo.error.Errors.ResultCode;
+import org.apache.tajo.exception.*;
 import org.apache.tajo.jdbc.util.QueryStringDecoder;
 import org.apache.tajo.rpc.RpcUtils;
 import org.apache.tajo.util.KeyValueSet;
 
 import java.io.IOException;
+import java.net.ConnectException;
 import java.net.URI;
 import java.sql.*;
 import java.util.List;
@@ -66,17 +69,19 @@ public class JdbcConnection implements Connection {
     this.properties = properties;
 
     try {
+
       if (!rawURI.startsWith(TajoDriver.TAJO_JDBC_URL_PREFIX)) {
-        throw new SQLException("Invalid URL: " + rawURI, "TAJO-001");
+        // its impossible case
+        throw new TajoInternalError("Invalid URL: " + rawURI);
       }
 
       // URI form: jdbc:tajo://hostname:port/databasename
       int startIdx = rawURI.indexOf(":");
       if (startIdx < 0) {
-        throw new SQLException("Invalid URL: " + rawURI, "TAJO-001");
+        throw new TajoInternalError("Invalid URL: " + rawURI);
       }
 
-      String uri = rawURI.substring(startIdx+1, rawURI.length());
+      String uri = rawURI.substring(startIdx + 1, rawURI.length());
       try {
         this.uri = URI.create(uri);
       } catch (IllegalArgumentException iae) {
@@ -116,8 +121,12 @@ public class JdbcConnection implements Connection {
 
     try {
       tajoClient = new TajoClientImpl(RpcUtils.createSocketAddr(hostName, port), databaseName,
clientProperties);
-    } catch (Exception e) {
-      throw new SQLException("Cannot create TajoClient instance:" + e.getMessage(), "TAJO-002");
+    } catch (Throwable t) {
+      if (t instanceof DefaultTajoException) {
+        throw SQLExceptionUtil.toSQLException((DefaultTajoException) t);
+      } else {
+        throw new TajoSQLException(ResultCode.INTERNAL_ERROR, t, t.getMessage());
+      }
     }
     closed.set(false);
   }
@@ -182,7 +191,7 @@ public class JdbcConnection implements Connection {
   @Override
   public Statement createStatement() throws SQLException {
     if (isClosed()) {
-      throw new SQLException("Can't create Statement, connection is closed");
+      throw new TajoSQLException(ResultCode.CLIENT_CONNECTION_DOES_NOT_EXIST);
     }
     return new TajoStatement(this, tajoClient);
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoPreparedStatement.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoPreparedStatement.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoPreparedStatement.java
index 0574bf9..6b47f97 100644
--- a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoPreparedStatement.java
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoPreparedStatement.java
@@ -61,7 +61,7 @@ public class TajoPreparedStatement extends TajoStatement implements PreparedStat
 
   @Override
   public void clearParameters() throws SQLException {
-    checkConnection("Can't clear parameters");
+    checkConnection();
     this.parameters.clear();
   }
 
@@ -83,7 +83,7 @@ public class TajoPreparedStatement extends TajoStatement implements PreparedStat
   }
 
   protected TajoResultSetBase executeImmediate(String sql) throws SQLException {
-    checkConnection("Can't execute");
+    checkConnection();
 
     try {
       if (sql.contains("?")) {
@@ -152,7 +152,7 @@ public class TajoPreparedStatement extends TajoStatement implements PreparedStat
 
   @Override
   public ResultSetMetaData getMetaData() throws SQLException {
-    checkConnection("Can't get metadata");
+    checkConnection();
     if(resultSet != null) {
       return resultSet.getMetaData();
     } else {
@@ -223,7 +223,7 @@ public class TajoPreparedStatement extends TajoStatement implements PreparedStat
 
   @Override
   public void setBoolean(int parameterIndex, boolean x) throws SQLException {
-    checkConnection("Can't set parameters");
+    checkConnection();
     this.parameters.put(parameterIndex, "" + x);
   }
 
@@ -281,25 +281,25 @@ public class TajoPreparedStatement extends TajoStatement implements
PreparedStat
 
   @Override
   public void setDouble(int parameterIndex, double x) throws SQLException {
-    checkConnection("Can't set parameters");
+    checkConnection();
     this.parameters.put(parameterIndex,"" + x);
   }
 
   @Override
   public void setFloat(int parameterIndex, float x) throws SQLException {
-    checkConnection("Can't set parameters");
+    checkConnection();
     this.parameters.put(parameterIndex,"" + x);
   }
 
   @Override
   public void setInt(int parameterIndex, int x) throws SQLException {
-    checkConnection("Can't set parameters");
+    checkConnection();
     this.parameters.put(parameterIndex,"" + x);
   }
 
   @Override
   public void setLong(int parameterIndex, long x) throws SQLException {
-    checkConnection("Can't set parameters");
+    checkConnection();
     this.parameters.put(parameterIndex,"" + x);
   }
 
@@ -378,13 +378,13 @@ public class TajoPreparedStatement extends TajoStatement implements
PreparedStat
 
   @Override
   public void setShort(int parameterIndex, short x) throws SQLException {
-    checkConnection("Can't set parameters");
+    checkConnection();
     this.parameters.put(parameterIndex,"" + x);
   }
 
   @Override
   public void setString(int parameterIndex, String x) throws SQLException {
-    checkConnection("Can't set parameters");
+    checkConnection();
      x=x.replace("'", "\\'");
      this.parameters.put(parameterIndex,"'" + x +"'");
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/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 5354e60..6039e9c 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
@@ -17,19 +17,16 @@
  */
 package org.apache.tajo.jdbc;
 
-import com.google.common.collect.Lists;
 import org.apache.tajo.QueryId;
 import org.apache.tajo.SessionVars;
 import org.apache.tajo.client.TajoClient;
 import org.apache.tajo.client.TajoClientUtil;
+import org.apache.tajo.error.Errors.ResultCode;
 import org.apache.tajo.exception.SQLExceptionUtil;
+import org.apache.tajo.exception.TajoException;
 import org.apache.tajo.ipc.ClientProtos;
 
 import java.sql.*;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.apache.tajo.client.TajoClientUtil.NULL_RESULT_SET;
 
 public class TajoStatement implements Statement {
   protected JdbcConnection conn;
@@ -79,7 +76,7 @@ public class TajoStatement implements Statement {
 
   @Override
   public void cancel() throws SQLException {
-    checkConnection("Can't cancel query");
+    checkConnection();
     if (resultSet == null || resultSet.getQueryId().isNull()) {
       return;
     }
@@ -99,7 +96,7 @@ public class TajoStatement implements Statement {
 
   @Override
   public void clearWarnings() throws SQLException {
-    checkConnection("Can't clear warnings");
+    checkConnection();
     warningChain = null;
   }
 
@@ -146,7 +143,7 @@ public class TajoStatement implements Statement {
 
   @Override
   public ResultSet executeQuery(String sql) throws SQLException {
-    checkConnection("Can't execute");
+    checkConnection();
     return executeSQL(sql);
   }
 
@@ -173,16 +170,20 @@ public class TajoStatement implements Statement {
     }
   }
 
-  protected void checkConnection(String errorMsg) throws SQLException {
-    if (isClosed) {
-      throw new SQLException(errorMsg + " after statement has been closed");
+  protected void checkConnection() throws SQLException {
+    if (isClosed || conn.isClosed()) {
+      throw new TajoSQLException(ResultCode.CLIENT_CONNECTION_DOES_NOT_EXIST);
     }
   }
 
   @Override
   public int executeUpdate(String sql) throws SQLException {
-    checkConnection("Can't execute update");
-    tajoClient.executeQuery(sql);
+    checkConnection();
+    try {
+      tajoClient.updateQuery(sql);
+    } catch (TajoException e) {
+      throw SQLExceptionUtil.toSQLException(e);
+    }
     return 1;
   }
 
@@ -203,19 +204,19 @@ public class TajoStatement implements Statement {
 
   @Override
   public Connection getConnection() throws SQLException {
-    checkConnection("Can't get connection");
+    checkConnection();
     return conn;
   }
 
   @Override
   public int getFetchDirection() throws SQLException {
-    checkConnection("Can't get fetch direction");
+    checkConnection();
     return ResultSet.FETCH_FORWARD;
   }
 
   @Override
   public int getFetchSize() throws SQLException {
-    checkConnection("Can't get fetch size");
+    checkConnection();
     return fetchSize;
   }
 
@@ -252,7 +253,7 @@ public class TajoStatement implements Statement {
 
   @Override
   public ResultSet getResultSet() throws SQLException {
-    checkConnection("Can't get result set");
+    checkConnection();
     return resultSet;
   }
 
@@ -282,7 +283,7 @@ public class TajoStatement implements Statement {
 
   @Override
   public SQLWarning getWarnings() throws SQLException {
-    checkConnection("Can't get warnings");
+    checkConnection();
     return warningChain;
   }
 
@@ -321,7 +322,7 @@ public class TajoStatement implements Statement {
 
   @Override
   public void setFetchSize(int rows) throws SQLException {
-    checkConnection("Can't set fetch size");
+    checkConnection();
     fetchSize = rows;
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
index e6d01fe..40d7e58 100644
--- a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
+++ b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbc.java
@@ -61,12 +61,6 @@ public class TestTajoJdbc extends QueryTestCaseBase {
     assertFalse(driver.acceptsURL("jdbc:taju:"));
   }
 
-  @Test(expected = SQLException.class)
-  public void testGetConnection() throws SQLException {
-    DriverManager.getConnection("jdbc:taju://" + tajoMasterAddress.getHostName() + ":" +
tajoMasterAddress.getPort()
-      + "/default");
-  }
-
   @Test
   public void testStatement() throws Exception {
     String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbcNegative.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbcNegative.java b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbcNegative.java
new file mode 100644
index 0000000..232292b
--- /dev/null
+++ b/tajo-jdbc/src/test/java/org/apache/tajo/jdbc/TestTajoJdbcNegative.java
@@ -0,0 +1,156 @@
+/*
+ * 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 org.apache.tajo.IntegrationTest;
+import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.error.Errors.ResultCode;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.sql.*;
+
+import static org.apache.tajo.TajoConstants.DEFAULT_DATABASE_NAME;
+import static org.apache.tajo.exception.SQLExceptionUtil.toSQLState;
+import static org.apache.tajo.jdbc.TestTajoJdbc.buildConnectionUri;
+import static org.junit.Assert.*;
+
+@Category(IntegrationTest.class)
+public class TestTajoJdbcNegative 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();
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+  }
+
+  @Test(expected = SQLException.class)
+  public void testGetConnection() throws SQLException {
+    DriverManager.getConnection("jdbc:taju://" + tajoMasterAddress.getHostName() + ":" +
tajoMasterAddress.getPort()
+      + "/default");
+  }
+
+  @Test
+  public void testUnresolvedError() throws SQLException {
+    try {
+      DriverManager.getConnection("jdbc:tajo://tajo-unknown-asdnkl213.asd:2002/default");
+    } catch (SQLException s) {
+      assertEquals(toSQLState(ResultCode.CLIENT_CONNECTION_EXCEPTION), s.getSQLState());
+      assertEquals("Can't resolve host name: tajo-unknown-asdnkl213.asd:2002", s.getMessage());
+    }
+  }
+
+  @Test
+  public void testConnectionRefused() throws SQLException, IOException {
+    Integer port = null;
+    try {
+      ServerSocket s = new ServerSocket(0);
+      port = s.getLocalPort();
+      s.close();
+      DriverManager.getConnection("jdbc:tajo://localhost:" + port + "/default");
+      fail("Must be failed.");
+    } catch (SQLException s) {
+      assertEquals(toSQLState(ResultCode.CLIENT_CONNECTION_EXCEPTION), s.getSQLState());
+      assertEquals("Connection refused: localhost/127.0.0.1:" + port, s.getMessage());
+    }
+  }
+
+  @Test
+  public void testConnectionClosedAtCreateStmt() throws SQLException, IOException {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+    assertTrue(conn.isValid(100));
+
+    conn.close();
+    try (Statement stmt = conn.createStatement()) {
+      fail("Must be failed.");
+      stmt.isClosed();
+    } catch (SQLException s) {
+      assertEquals(toSQLState(ResultCode.CLIENT_CONNECTION_DOES_NOT_EXIST), s.getSQLState());
+      assertEquals("This connection has been closed.", s.getMessage());
+    }
+  }
+
+  @Test
+  public void testConnectionClosed() throws SQLException, IOException {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+    assertTrue(conn.isValid(100));
+
+    try (Statement stmt = conn.createStatement()) {
+      conn.close();
+      stmt.executeUpdate("SELECT 1;");
+      fail("Must be failed.");
+    } catch (SQLException s) {
+      assertEquals(toSQLState(ResultCode.CLIENT_CONNECTION_DOES_NOT_EXIST), s.getSQLState());
+      assertEquals("This connection has been closed.", s.getMessage());
+    }
+  }
+
+  @Test
+  public void testImmediateException() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+    assertTrue(conn.isValid(100));
+
+    try (Statement stmt = conn.createStatement()) {
+      stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS TestTajoJdbcNegative");
+      stmt.executeUpdate("CREATE TABLE TestTajoJdbcNegative.table123u8sd ( name RECORD(last
TEXT, first TEXT) )");
+
+      try (ResultSet resultSet = stmt.executeQuery("select name FROM TestTajoJdbcNegative.table123u8sd"))
{
+        fail("Getting a record type field must be failed");
+      } catch (SQLException s) {
+        assertEquals(toSQLState(ResultCode.NOT_IMPLEMENTED), s.getSQLState());
+      } finally {
+        stmt.executeUpdate("DROP TABLE IF EXISTS TestTajoJdbcNegative.table12u79");
+        stmt.executeUpdate("DROP DATABASE IF EXISTS TestTajoJdbcNegative");
+      }
+    }
+  }
+
+  @Test
+  public void testExceptionDuringProcessing() throws Exception {
+    String connUri = buildConnectionUri(tajoMasterAddress.getHostName(), tajoMasterAddress.getPort(),
+        DEFAULT_DATABASE_NAME);
+    Connection conn = DriverManager.getConnection(connUri);
+    assertTrue(conn.isValid(100));
+
+    try (Statement stmt = conn.createStatement()) {
+      try (ResultSet resultSet =
+               stmt.executeQuery("select fail(3, l_orderkey, 'testQueryFailure') from default.lineitem"))
{
+        fail("Failure must occur here.");
+      } catch (SQLException s) {
+        assertEquals(toSQLState(ResultCode.INTERNAL_ERROR), s.getSQLState());
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/688bc5c1/tajo-rpc/tajo-rpc-protobuf/src/main/java/org/apache/tajo/rpc/NettyClientBase.java
----------------------------------------------------------------------
diff --git a/tajo-rpc/tajo-rpc-protobuf/src/main/java/org/apache/tajo/rpc/NettyClientBase.java
b/tajo-rpc/tajo-rpc-protobuf/src/main/java/org/apache/tajo/rpc/NettyClientBase.java
index 0d86527..5f76bfc 100644
--- a/tajo-rpc/tajo-rpc-protobuf/src/main/java/org/apache/tajo/rpc/NettyClientBase.java
+++ b/tajo-rpc/tajo-rpc-protobuf/src/main/java/org/apache/tajo/rpc/NettyClientBase.java
@@ -39,6 +39,8 @@ import java.lang.reflect.Method;
 import java.net.ConnectException;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.nio.channels.UnresolvedAddressException;
 import java.util.Collection;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -195,7 +197,7 @@ public abstract class NettyClientBase<T> implements ProtoDeclaration,
Closeable
       if (maxRetries > retries) {
         retries++;
 
-        LOG.warn(getErrorMessage(ExceptionUtils.getMessage(future.cause())) + " Try to reconnect
: " + getKey().addr);
+        LOG.warn(getErrorMessage(ExceptionUtils.getMessage(future.cause())) + "\nTry to reconnect
: " + getKey().addr);
         try {
           Thread.sleep(RpcConstants.DEFAULT_PAUSE);
         } catch (InterruptedException e) {
@@ -206,8 +208,13 @@ public abstract class NettyClientBase<T> implements ProtoDeclaration,
Closeable
           break;
         }
       } else {
-        throw new ConnectTimeoutException("Max retry count has been exceeded. attempts="
+ retries
-            + " caused by: " + future.cause());
+        LOG.error("Max retry count has been exceeded. attempts=" + retries + " caused by:
" + future.cause());
+
+        if (future.cause() instanceof UnresolvedAddressException) {
+          throw new ConnectException("Can't resolve host name: " + address.toString());
+        } else {
+          throw new ConnectTimeoutException(future.cause().getMessage());
+        }
       }
     }
   }


Mime
View raw message