ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [23/26] ignite git commit: IGNITE-5620: Implemented SQLSTATE error code for server-side logic and JDBC thin client. This closes #2541.
Date Mon, 18 Sep 2017 08:43:23 GMT
IGNITE-5620: Implemented SQLSTATE error code for server-side logic and JDBC thin client. This closes #2541.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/7c4d0bc2
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/7c4d0bc2
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/7c4d0bc2

Branch: refs/heads/ignite-6149
Commit: 7c4d0bc2a84cfcc9c240f41c48aa129b5f60eca0
Parents: 9fd8221
Author: Alexander Paschenko <alexander.a.paschenko@gmail.com>
Authored: Sat Sep 16 17:41:34 2017 +0300
Committer: devozerov <ppozerov@gmail.com>
Committed: Sat Sep 16 17:41:34 2017 +0300

----------------------------------------------------------------------
 .../jdbc2/JdbcDynamicIndexAbstractSelfTest.java |  39 +-
 .../jdbc2/JdbcInsertStatementSelfTest.java      |   9 +-
 .../ignite/jdbc/JdbcErrorsAbstractSelfTest.java | 158 +++++++
 .../jdbc/suite/IgniteJdbcDriverTestSuite.java   |   2 +
 .../jdbc/thin/JdbcThinConnectionSelfTest.java   |   2 +-
 .../JdbcThinDynamicIndexAbstractSelfTest.java   |   4 +-
 .../jdbc/thin/JdbcThinErrorsSelfTest.java       | 467 +++++++++++++++++++
 .../thin/JdbcThinInsertStatementSelfTest.java   |   2 +-
 .../jdbc/thin/JdbcThinNoDefaultSchemaTest.java  |   2 +-
 .../jdbc/thin/JdbcThinResultSetSelfTest.java    |   2 +-
 .../internal/jdbc/thin/JdbcThinConnection.java  |  67 ++-
 .../jdbc/thin/JdbcThinDatabaseMetadata.java     | 142 ++----
 .../jdbc/thin/JdbcThinPreparedStatement.java    |  54 +--
 .../internal/jdbc/thin/JdbcThinResultSet.java   | 111 ++---
 .../internal/jdbc/thin/JdbcThinStatement.java   |  39 +-
 .../internal/jdbc/thin/JdbcThinTcpIo.java       | 234 +++-------
 .../cache/query/IgniteQueryErrorCode.java       |  48 +-
 .../internal/processors/odbc/SqlStateCode.java  |  69 +++
 .../odbc/jdbc/JdbcRequestHandler.java           |  74 ++-
 .../processors/query/IgniteSQLException.java    |  84 +++-
 .../query/h2/DmlStatementsProcessor.java        |  79 ++--
 .../query/h2/sql/GridSqlQueryParser.java        |  35 +-
 .../query/h2/sql/GridQueryParsingTest.java      |   2 +-
 23 files changed, 1178 insertions(+), 547 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java
index 7bbda6f..9485d0d 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java
@@ -23,7 +23,6 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Collections;
 import java.util.List;
-import javax.cache.CacheException;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
@@ -31,8 +30,6 @@ import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
-import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
-import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.internal.util.typedef.F;
 
 /**
@@ -176,7 +173,7 @@ public abstract class JdbcDynamicIndexAbstractSelfTest extends JdbcAbstractDmlSt
             @Override public void run() throws Exception {
                 jdbcRun(CREATE_INDEX);
             }
-        }, IgniteQueryErrorCode.INDEX_ALREADY_EXISTS);
+        });
     }
 
     /**
@@ -227,7 +224,7 @@ public abstract class JdbcDynamicIndexAbstractSelfTest extends JdbcAbstractDmlSt
             @Override public void run() throws Exception {
                 jdbcRun(DROP_INDEX);
             }
-        }, IgniteQueryErrorCode.INDEX_NOT_FOUND);
+        });
     }
 
     /**
@@ -312,45 +309,21 @@ public abstract class JdbcDynamicIndexAbstractSelfTest extends JdbcAbstractDmlSt
      * Ensure that SQL exception is thrown.
      *
      * @param r Runnable.
-     * @param expCode Error code.
      */
-    private static void assertSqlException(RunnableX r, int expCode) {
+    private static void assertSqlException(RunnableX r) {
         // We expect IgniteSQLException with given code inside CacheException inside JDBC SQLException.
 
         try {
             r.run();
         }
-        catch (SQLException ex) {
-            if (ex.getCause() != null) {
-                try {
-                    throw ex.getCause();
-                }
-                catch (CacheException ex1) {
-                    if (ex1.getCause() != null) {
-                        try {
-                            throw ex1.getCause();
-                        }
-                        catch (IgniteSQLException e) {
-                            assertEquals("Unexpected error code [expected=" + expCode + ", actual=" + e.statusCode() + ']',
-                                expCode, e.statusCode());
-
-                            return;
-                        }
-                        catch (Throwable t) {
-                            fail("Unexpected exception: " + t);
-                        }
-                    }
-                }
-                catch (Throwable t) {
-                    fail("Unexpected exception: " + t);
-                }
-            }
+        catch (SQLException e) {
+            return;
         }
         catch (Exception e) {
             fail("Unexpected exception: " + e);
         }
 
-        fail(IgniteSQLException.class.getSimpleName() +  " is not thrown.");
+        fail(SQLException.class.getSimpleName() +  " is not thrown.");
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java
index 407d6e2..44a45b7 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java
@@ -164,15 +164,12 @@ public class JdbcInsertStatementSelfTest extends JdbcAbstractDmlStatementSelfTes
             }
         }, SQLException.class, null);
 
-        assertNotNull(reason.getCause());
-
-        reason = reason.getCause().getCause();
+        reason = reason.getCause();
 
         assertNotNull(reason);
 
-        assertEquals(IgniteSQLException.class, reason.getClass());
-
-        assertEquals("Failed to INSERT some keys because they are already in cache [keys=[p2]]", reason.getMessage());
+        assertTrue(reason.getMessage().contains(
+            "Failed to INSERT some keys because they are already in cache [keys=[p2]]"));
 
         assertEquals(3, jcache(0).withKeepBinary().getAll(new HashSet<>(Arrays.asList("p1", "p2", "p3"))).size());
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java
new file mode 100644
index 0000000..f600e73
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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.ignite.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Collections;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.lang.IgniteCallable;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * Test SQLSTATE codes propagation with (any) Ignite JDBC driver.
+ */
+public abstract class JdbcErrorsAbstractSelfTest extends GridCommonAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrid(getConfiguration(getTestIgniteInstanceName(0))
+            .setCacheConfiguration(new CacheConfiguration("test")
+                .setQueryEntities(Collections.singletonList(new QueryEntity(Integer.class, Integer.class)))));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+
+        super.afterTestsStopped();
+    }
+
+    /**
+     * Test that H2 specific error codes get propagated to Ignite SQL exceptions.
+     * @throws SQLException if failed.
+     */
+    public void testParsingErrors() throws SQLException {
+        checkErrorState("gibberish", "42000");
+    }
+
+    /**
+     * Test that error codes from tables related DDL operations get propagated to Ignite SQL exceptions.
+     * @throws SQLException if failed.
+     */
+    public void testTableErrors() throws SQLException {
+        checkErrorState("DROP TABLE \"PUBLIC\".missing", "42000");
+    }
+
+    /**
+     * Test that error codes from indexes related DDL operations get propagated to Ignite SQL exceptions.
+     * @throws SQLException if failed.
+     */
+    public void testIndexErrors() throws SQLException {
+        checkErrorState("DROP INDEX \"PUBLIC\".missing", "42000");
+    }
+
+    /**
+     * Test that error codes from DML operations get propagated to Ignite SQL exceptions.
+     * @throws SQLException if failed.
+     */
+    public void testDmlErrors() throws SQLException {
+        checkErrorState("INSERT INTO \"test\".INTEGER(_key, _val) values(1, null)", "22004");
+
+        checkErrorState("INSERT INTO \"test\".INTEGER(_key, _val) values(1, 'zzz')", "50000");
+    }
+
+    /**
+     * Test error code for the case when user attempts to refer a future currently unsupported.
+     * @throws SQLException if failed.
+     */
+    public void testUnsupportedSql() throws SQLException {
+        checkErrorState("ALTER TABLE \"test\".Integer DROP COLUMN _key", "0A000");
+    }
+
+    /**
+     * @return Connection to execute statements on.
+     * @throws SQLException if failed.
+     */
+    protected abstract Connection getConnection() throws SQLException;
+
+    /**
+     * Test that running given SQL statement yields expected SQLSTATE code.
+     * @param sql statement.
+     * @param expState expected SQLSTATE code.
+     * @throws SQLException if failed.
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    private void checkErrorState(final String sql, String expState) throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (final PreparedStatement stmt = conn.prepareStatement(sql)) {
+                    stmt.execute();
+                }
+            }
+        }, expState);
+    }
+
+    /**
+     * Test that running given closure yields expected SQLSTATE code.
+     * @param clo closure.
+     * @param expState expected SQLSTATE code.
+     * @throws SQLException if failed.
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    protected void checkErrorState(final ConnClosure clo, String expState) throws SQLException {
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                try (final Connection conn = getConnection()) {
+                    clo.run(conn);
+
+                    fail();
+
+                    return null;
+                }
+            }
+        }, expState);
+    }
+
+    /**
+     * Test that running given closure yields expected SQLSTATE code.
+     * @param clo closure.
+     * @param expState expected SQLSTATE code.
+     * @throws SQLException if failed.
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    protected void checkErrorState(final IgniteCallable<Void> clo, String expState) throws SQLException {
+        SQLException ex = (SQLException)GridTestUtils.assertThrows(null, clo, SQLException.class, null);
+
+        assertEquals(expState, ex.getSQLState());
+    }
+
+    /**
+     * Runnable that accepts a {@link Connection} and can throw an exception.
+     */
+    protected interface ConnClosure {
+        /**
+         * @throws Exception On error.
+         */
+        void run(Connection conn) throws Exception;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
index c2ac6cb..424ec21 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
@@ -46,6 +46,7 @@ import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexTransactionalPartitionedN
 import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexTransactionalPartitionedSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexTransactionalReplicatedSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinEmptyCacheSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinErrorsSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinInsertStatementSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinMergeStatementSelfTest;
 import org.apache.ignite.jdbc.thin.JdbcThinMetadataSelfTest;
@@ -124,6 +125,7 @@ public class IgniteJdbcDriverTestSuite extends TestSuite {
         suite.addTest(new TestSuite(JdbcThinNoDefaultSchemaTest.class));
         suite.addTest(new TestSuite(JdbcThinEmptyCacheSelfTest.class));
         suite.addTest(new TestSuite(JdbcThinMetadataSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinErrorsSelfTest.class));
 
         suite.addTest(new TestSuite(JdbcThinInsertStatementSelfTest.class));
         suite.addTest(new TestSuite(JdbcThinUpdateStatementSelfTest.class));

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
index 9bf6282..95068c5 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
@@ -346,7 +346,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     private static JdbcThinTcpIo io(Connection conn) throws Exception {
         JdbcThinConnection conn0 = conn.unwrap(JdbcThinConnection.class);
 
-        return conn0.io();
+        return GridTestUtils.getFieldValue(conn0, JdbcThinConnection.class, "cliIo");
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
index 3f762fc..5089894 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java
@@ -183,7 +183,7 @@ public abstract class JdbcThinDynamicIndexAbstractSelfTest extends JdbcThinAbstr
 
                 return null;
             }
-        }, IgniteCheckedException.class, "Index already exists: IDX");
+        }, SQLException.class, "Index already exists: IDX");
     }
 
     /**
@@ -237,7 +237,7 @@ public abstract class JdbcThinDynamicIndexAbstractSelfTest extends JdbcThinAbstr
 
                 return null;
             }
-        }, IgniteCheckedException.class, "Index doesn't exist: IDX");
+        }, SQLException.class, "Index doesn't exist: IDX");
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java
new file mode 100644
index 0000000..706be27
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java
@@ -0,0 +1,467 @@
+/*
+ * 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.ignite.jdbc.thin;
+
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.List;
+import org.apache.ignite.jdbc.JdbcErrorsAbstractSelfTest;
+import org.apache.ignite.lang.IgniteCallable;
+
+/**
+ * Test SQLSTATE codes propagation with thin client driver.
+ */
+public class JdbcThinErrorsSelfTest extends JdbcErrorsAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected Connection getConnection() throws SQLException {
+        return DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1");
+    }
+
+    /**
+     * Test error code for the case when connection string is fine but client can't reach server
+     * due to <b>communication problems</b> (not due to clear misconfiguration).
+     * @throws SQLException if failed.
+     */
+    public void testConnectionError() throws SQLException {
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection("jdbc:ignite:thin://unknown.host");
+
+                return null;
+            }
+        }, "08001");
+    }
+
+    /**
+     * Test error code for the case when connection string is a mess.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidConnectionStringFormat() throws SQLException {
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                // Invalid port number yields an error.
+                DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:1000000");
+
+                return null;
+            }
+        }, "08001");
+    }
+
+    /* ALL TESTS PAST THIS POINT MUST BE MOVED TO PARENT CLASS JdbcErrorsAbstractSelfTest
+     * ONCE ERROR CODES RELATED WORK ON JDBC2 DRIVER IS FINISHED */
+
+    /**
+     * Test error code for the case when user attempts to use a closed connection.
+     * @throws SQLException if failed.
+     */
+    public void testConnectionClosed() throws SQLException {
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                Connection conn = getConnection();
+
+                conn.close();
+
+                conn.prepareStatement("SELECT 1");
+
+                return null;
+            }
+        }, "08003");
+
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                Connection conn = getConnection();
+
+                conn.close();
+
+                conn.createStatement();
+
+                return null;
+            }
+        }, "08003");
+
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                Connection conn = getConnection();
+
+                conn.close();
+
+                conn.getMetaData();
+
+                return null;
+            }
+        }, "08003");
+
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                Connection conn = getConnection();
+
+                DatabaseMetaData meta = conn.getMetaData();
+
+                conn.close();
+
+                meta.getIndexInfo(null, null, null, false, false);
+
+                return null;
+            }
+        }, "08003");
+
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                Connection conn = getConnection();
+
+                DatabaseMetaData meta = conn.getMetaData();
+
+                conn.close();
+
+                meta.getColumns(null, null, null, null);
+
+                return null;
+            }
+        }, "08003");
+
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                Connection conn = getConnection();
+
+                DatabaseMetaData meta = conn.getMetaData();
+
+                conn.close();
+
+                meta.getPrimaryKeys(null, null, null);
+
+                return null;
+            }
+        }, "08003");
+
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                Connection conn = getConnection();
+
+                DatabaseMetaData meta = conn.getMetaData();
+
+                conn.close();
+
+                meta.getSchemas(null, null);
+
+                return null;
+            }
+        }, "08003");
+
+        checkErrorState(new IgniteCallable<Void>() {
+            @Override public Void call() throws Exception {
+                Connection conn = getConnection();
+
+                DatabaseMetaData meta = conn.getMetaData();
+
+                conn.close();
+
+                meta.getTables(null, null, null, null);
+
+                return null;
+            }
+        }, "08003");
+    }
+
+    /**
+     * Test error code for the case when user attempts to use a closed result set.
+     * @throws SQLException if failed.
+     */
+    public void testResultSetClosed() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 1")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.close();
+
+                    rs.getInt(1);
+                }
+            }
+        }, "24000");
+    }
+
+    /**
+     * Test error code for the case when user attempts to set an invalid isolation level to a connection.
+     * @throws SQLException if failed.
+     */
+    @SuppressWarnings("MagicConstant")
+    public void testInvalidIsolationLevel() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                conn.setTransactionIsolation(1000);
+            }
+        }, "0700E");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@code int} value
+     * from column whose value can't be converted to an {@code int}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidIntFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getLong(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@code long} value
+     * from column whose value can't be converted to an {@code long}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidLongFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getLong(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@code float} value
+     * from column whose value can't be converted to an {@code float}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidFloatFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getFloat(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@code double} value
+     * from column whose value can't be converted to an {@code double}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidDoubleFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getDouble(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@code byte} value
+     * from column whose value can't be converted to an {@code byte}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidByteFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getByte(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@code short} value
+     * from column whose value can't be converted to an {@code short}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidShortFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getShort(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@code BigDecimal} value
+     * from column whose value can't be converted to an {@code BigDecimal}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidBigDecimalFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getBigDecimal(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@code boolean} value
+     * from column whose value can't be converted to an {@code boolean}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidBooleanFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getBoolean(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@code boolean} value
+     * from column whose value can't be converted to an {@code boolean}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidObjectFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getObject(1, List.class);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@link Date} value
+     * from column whose value can't be converted to a {@link Date}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidDateFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getDate(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@link Time} value
+     * from column whose value can't be converted to a {@link Time}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidTimeFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getTime(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@link Timestamp} value
+     * from column whose value can't be converted to a {@link Timestamp}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidTimestampFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getTimestamp(1);
+                }
+            }
+        }, "0700B");
+    }
+
+    /**
+     * Test error code for the case when user attempts to get {@link URL} value
+     * from column whose value can't be converted to a {@link URL}.
+     * @throws SQLException if failed.
+     */
+    public void testInvalidUrlFormat() throws SQLException {
+        checkErrorState(new ConnClosure() {
+            @Override public void run(Connection conn) throws Exception {
+                try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) {
+                    ResultSet rs = stmt.executeQuery();
+
+                    rs.next();
+
+                    rs.getURL(1);
+                }
+            }
+        }, "0700B");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
index 3b86757..8ab5760 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java
@@ -177,7 +177,7 @@ public class JdbcThinInsertStatementSelfTest extends JdbcThinAbstractDmlStatemen
             @Override public Object call() throws Exception {
                 return stmt.execute(SQL);
             }
-        }, IgniteCheckedException.class,
+        }, SQLException.class,
             "Failed to INSERT some keys because they are already in cache [keys=[p2]]");
 
         assertEquals(3, jcache(0).withKeepBinary().getAll(new HashSet<>(Arrays.asList("p1", "p2", "p3"))).size());

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
index 7b226e5..65ebf9a 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
@@ -217,7 +217,7 @@ public class JdbcThinNoDefaultSchemaTest extends JdbcThinAbstractSelfTest {
 
                     return null;
                 }
-            }, SQLException.class, "Failed to query Ignite");
+            }, SQLException.class, "Failed to parse query");
 
             conn.setSchema("cache1");
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
index 76eb5bc..5a3c5df 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
@@ -695,7 +695,7 @@ public class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
 
                 return null;
             }
-        }, IgniteCheckedException.class, "Custom objects are not supported");
+        }, SQLException.class, "Custom objects are not supported");
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
index 23235dc..511eba0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -37,7 +37,14 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
+import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
+import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
+import org.apache.ignite.internal.processors.odbc.SqlStateCode;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteProductVersion;
 
 import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT;
 import static java.sql.ResultSet.CONCUR_READ_ONLY;
@@ -138,7 +145,8 @@ public class JdbcThinConnection implements Connection {
         catch (Exception e) {
             cliIo.close();
 
-            throw new SQLException("Failed to connect to Ignite node [host=" + host + ", port=" + port + ']', e);
+            throw new SQLException("Failed to connect to Ignite cluster [host=" + host + ", port=" + port + ']',
+                SqlStateCode.CLIENT_CONNECTION_FAILED, e);
         }
     }
 
@@ -347,7 +355,7 @@ public class JdbcThinConnection implements Connection {
                 break;
 
             default:
-                throw new SQLException("Invalid transaction isolation level.");
+                throw new SQLException("Invalid transaction isolation level.", SqlStateCode.INVALID_TRANSACTION_LEVEL);
         }
 
         txIsolation = level;
@@ -626,16 +634,49 @@ public class JdbcThinConnection implements Connection {
      *
      * @throws SQLException If connection is closed.
      */
-    private void ensureNotClosed() throws SQLException {
+    public void ensureNotClosed() throws SQLException {
         if (closed)
-            throw new SQLException("Connection is closed.");
+            throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED);
     }
 
     /**
-     * @return Ignite endpoint and I/O protocol.
+     * @return Ignite server version.
      */
-    public JdbcThinTcpIo io() {
-        return cliIo;
+    IgniteProductVersion igniteVersion() {
+        return cliIo.igniteVersion();
+    }
+
+    /**
+     * @return Auto close server cursors flag.
+     */
+    boolean autoCloseServerCursor() {
+        return cliIo.autoCloseServerCursor();
+    }
+
+    /**
+     * Send request for execution via {@link #cliIo}.
+     * @param req Request.
+     * @return Server response.
+     * @throws SQLException On any error.
+     */
+    @SuppressWarnings("unchecked")
+    <R extends JdbcResult> R sendRequest(JdbcRequest req) throws SQLException {
+        try {
+            JdbcResponse res = cliIo.sendRequest(req);
+
+            if (res.status() != ClientListenerResponse.STATUS_SUCCESS)
+                throw new SQLException(res.error(), IgniteQueryErrorCode.codeToSqlState(res.status()));
+
+            return (R)res.response();
+        }
+        catch (SQLException e) {
+            throw e;
+        }
+        catch (Exception e) {
+            close();
+
+            throw new SQLException("Failed to communicate with Ignite cluster.", SqlStateCode.CONNECTION_FAILURE, e);
+        }
     }
 
     /**
@@ -652,7 +693,7 @@ public class JdbcThinConnection implements Connection {
             host = host.trim();
 
         if (F.isEmpty(host))
-            throw new SQLException("Host name is empty.");
+            throw new SQLException("Host name is empty.", SqlStateCode.CLIENT_CONNECTION_FAILED);
 
         return host;
     }
@@ -676,10 +717,10 @@ public class JdbcThinConnection implements Connection {
             port = Integer.parseInt(portStr);
 
             if (port <= 0 || port > 0xFFFF)
-                throw new SQLException("Invalid port: " + portStr);
+                throw new SQLException("Invalid port: " + portStr, SqlStateCode.CLIENT_CONNECTION_FAILED);
         }
         catch (NumberFormatException e) {
-            throw new SQLException("Invalid port: " + portStr, e);
+            throw new SQLException("Invalid port: " + portStr, SqlStateCode.CLIENT_CONNECTION_FAILED);
         }
 
         return port;
@@ -706,7 +747,7 @@ public class JdbcThinConnection implements Connection {
             return false;
         else
             throw new SQLException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) +
-                    ", value=" + strVal + ']');
+                ", value=" + strVal + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
     }
 
     /**
@@ -723,7 +764,7 @@ public class JdbcThinConnection implements Connection {
 
         if (res < 0)
             throw new SQLException("Property cannot be negative [name=" + JdbcThinUtils.trimPrefix(propName) +
-                ", value=" + res + ']');
+                ", value=" + res + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
 
         return res;
     }
@@ -748,7 +789,7 @@ public class JdbcThinConnection implements Connection {
         }
         catch (NumberFormatException e) {
             throw new SQLException("Failed to parse int property [name=" + JdbcThinUtils.trimPrefix(propName) +
-                ", value=" + strVal + ']');
+                ", value=" + strVal + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
index 1f20bb2..d13ef68 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.jdbc.thin;
 
-import java.io.IOException;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
@@ -29,15 +28,19 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
-import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.IgniteVersionUtils;
 import org.apache.ignite.internal.jdbc2.JdbcUtils;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcIndexMeta;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaIndexesRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaIndexesResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaPrimaryKeysRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaPrimaryKeysResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaSchemasRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaSchemasResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaTablesRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaTablesResult;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcPrimaryKeyMeta;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcTableMeta;
@@ -119,7 +122,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
 
     /** {@inheritDoc} */
     @Override public String getDatabaseProductVersion() throws SQLException {
-        return conn.io().igniteVersion().toString();
+        return conn.igniteVersion().toString();
     }
 
     /** {@inheritDoc} */
@@ -702,10 +705,9 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     }
 
     /** {@inheritDoc} */
-    @Override public ResultSet getTables(String catalog, String schemaPtrn, String tblNamePtrn,
-        String[] tblTypes) throws SQLException {
-        if (conn.isClosed())
-            throw new SQLException("Connection is closed.");
+    @Override public ResultSet getTables(String catalog, String schemaPtrn, String tblNamePtrn, String[] tblTypes)
+        throws SQLException {
+        conn.ensureNotClosed();
 
         final List<JdbcColumnMeta> meta = Arrays.asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
@@ -736,24 +738,14 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         if (!validCatalogPattern(catalog) || !tblTypeMatch)
             return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), meta);
 
-        try {
-            JdbcMetaTablesResult res = conn.io().tablesMeta(schemaPtrn, tblNamePtrn);
+        JdbcMetaTablesResult res = conn.sendRequest(new JdbcMetaTablesRequest(schemaPtrn, tblNamePtrn));
 
-            List<List<Object>> rows = new LinkedList<>();
+        List<List<Object>> rows = new LinkedList<>();
 
-            for (JdbcTableMeta tblMeta : res.meta())
-                rows.add(tableRow(tblMeta));
+        for (JdbcTableMeta tblMeta : res.meta())
+            rows.add(tableRow(tblMeta));
 
-            return new JdbcThinResultSet(rows, meta);
-        }
-        catch (IOException e) {
-            conn.close();
-
-            throw new SQLException("Failed to query Ignite.", e);
-        }
-        catch (IgniteCheckedException e) {
-            throw new SQLException("Failed to query Ignite.", e);
-        }
+        return new JdbcThinResultSet(rows, meta);
     }
 
     /**
@@ -797,10 +789,9 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     }
 
     /** {@inheritDoc} */
-    @Override public ResultSet getColumns(String catalog, String schemaPtrn, String tblNamePtrn,
-        String colNamePtrn) throws SQLException {
-        if (conn.isClosed())
-            throw new SQLException("Connection is closed.");
+    @Override public ResultSet getColumns(String catalog, String schemaPtrn, String tblNamePtrn, String colNamePtrn)
+        throws SQLException {
+        conn.ensureNotClosed();
 
         final List<JdbcColumnMeta> meta = Arrays.asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
@@ -827,24 +818,14 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         if (!validCatalogPattern(catalog))
             return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), meta);
 
-        try {
-            JdbcMetaColumnsResult res = conn.io().columnsMeta(schemaPtrn, tblNamePtrn, colNamePtrn);
+        JdbcMetaColumnsResult res = conn.sendRequest(new JdbcMetaColumnsRequest(schemaPtrn, tblNamePtrn, colNamePtrn));
 
-            List<List<Object>> rows = new LinkedList<>();
+        List<List<Object>> rows = new LinkedList<>();
 
-            for (int i = 0; i < res.meta().size(); ++i)
-                rows.add(columnRow(res.meta().get(i), i + 1));
+        for (int i = 0; i < res.meta().size(); ++i)
+            rows.add(columnRow(res.meta().get(i), i + 1));
 
-            return new JdbcThinResultSet(rows, meta);
-        }
-        catch (IOException e) {
-            conn.close();
-
-            throw new SQLException("Failed to query Ignite.", e);
-        }
-        catch (IgniteCheckedException e) {
-            throw new SQLException("Failed to query Ignite.", e);
-        }
+        return new JdbcThinResultSet(rows, meta);
     }
 
     /**
@@ -939,8 +920,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
 
     /** {@inheritDoc} */
     @Override public ResultSet getPrimaryKeys(String catalog, String schema, String tbl) throws SQLException {
-        if (conn.isClosed())
-            throw new SQLException("Connection is closed.");
+        conn.ensureNotClosed();
 
         final List<JdbcColumnMeta> meta = Arrays.asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
@@ -953,24 +933,14 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         if (!validCatalogPattern(catalog))
             return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), meta);
 
-        try {
-            JdbcMetaPrimaryKeysResult res = conn.io().primaryKeysMeta(schema, tbl);
+        JdbcMetaPrimaryKeysResult res = conn.sendRequest(new JdbcMetaPrimaryKeysRequest(schema, tbl));
 
-            List<List<Object>> rows = new LinkedList<>();
+        List<List<Object>> rows = new LinkedList<>();
 
-            for (JdbcPrimaryKeyMeta pkMeta : res.meta())
-                rows.addAll(primaryKeyRows(pkMeta));
-
-            return new JdbcThinResultSet(rows, meta);
-        }
-        catch (IOException e) {
-            conn.close();
+        for (JdbcPrimaryKeyMeta pkMeta : res.meta())
+            rows.addAll(primaryKeyRows(pkMeta));
 
-            throw new SQLException("Failed to query Ignite.", e);
-        }
-        catch (IgniteCheckedException e) {
-            throw new SQLException("Failed to query Ignite.", e);
-        }
+        return new JdbcThinResultSet(rows, meta);
     }
 
     /**
@@ -1170,8 +1140,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
     /** {@inheritDoc} */
     @Override public ResultSet getIndexInfo(String catalog, String schema, String tbl, boolean unique,
         boolean approximate) throws SQLException {
-        if (conn.isClosed())
-            throw new SQLException("Connection is closed.");
+        conn.ensureNotClosed();
 
         final List<JdbcColumnMeta> meta = Arrays.asList(
             new JdbcColumnMeta(null, null, "TABLE_CAT", String.class),
@@ -1191,24 +1160,14 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         if (!validCatalogPattern(catalog))
             return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), meta);
 
-        try {
-            JdbcMetaIndexesResult res = conn.io().indexMeta(schema, tbl);
-
-            List<List<Object>> rows = new LinkedList<>();
+        JdbcMetaIndexesResult res = conn.sendRequest(new JdbcMetaIndexesRequest(schema, tbl));
 
-            for (JdbcIndexMeta idxMeta : res.meta())
-                rows.addAll(indexRows(idxMeta));
+        List<List<Object>> rows = new LinkedList<>();
 
-            return new JdbcThinResultSet(rows, meta);
-        }
-        catch (IOException e) {
-            conn.close();
+        for (JdbcIndexMeta idxMeta : res.meta())
+            rows.addAll(indexRows(idxMeta));
 
-            throw new SQLException("Failed to query Ignite.", e);
-        }
-        catch (IgniteCheckedException e) {
-            throw new SQLException("Failed to query Ignite.", e);
-        }
+        return new JdbcThinResultSet(rows, meta);
     }
 
     /**
@@ -1404,12 +1363,12 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
 
     /** {@inheritDoc} */
     @Override public int getDatabaseMajorVersion() throws SQLException {
-        return conn.io().igniteVersion().major();
+        return conn.igniteVersion().major();
     }
 
     /** {@inheritDoc} */
     @Override public int getDatabaseMinorVersion() throws SQLException {
-        return conn.io().igniteVersion().minor();
+        return conn.igniteVersion().minor();
     }
 
     /** {@inheritDoc} */
@@ -1444,8 +1403,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
 
     /** {@inheritDoc} */
     @Override public ResultSet getSchemas(String catalog, String schemaPtrn) throws SQLException {
-        if (conn.isClosed())
-            throw new SQLException("Connection is closed.");
+        conn.ensureNotClosed();
 
         final List<JdbcColumnMeta> meta = Arrays.asList(
             new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class),
@@ -1455,30 +1413,20 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData {
         if (!validCatalogPattern(catalog))
             return new JdbcThinResultSet(Collections.<List<Object>>emptyList(), meta);
 
-        try {
-            JdbcMetaSchemasResult res = conn.io().schemasMeta(schemaPtrn);
+        JdbcMetaSchemasResult res = conn.sendRequest(new JdbcMetaSchemasRequest(schemaPtrn));
 
-            List<List<Object>> rows = new LinkedList<>();
+        List<List<Object>> rows = new LinkedList<>();
 
-            for (String schema : res.schemas()) {
-                List<Object> row = new ArrayList<>(2);
+        for (String schema : res.schemas()) {
+            List<Object> row = new ArrayList<>(2);
 
-                row.add(schema);
-                row.add(null);
+            row.add(schema);
+            row.add(null);
 
-                rows.add(row);
-            }
-
-            return new JdbcThinResultSet(rows, meta);
+            rows.add(row);
         }
-        catch (IOException e) {
-            conn.close();
 
-            throw new SQLException("Failed to query Ignite.", e);
-        }
-        catch (IgniteCheckedException e) {
-            throw new SQLException("Failed to query Ignite.", e);
-        }
+        return new JdbcThinResultSet(rows, meta);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
index 5aa503c..ce1b65c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.jdbc.thin;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
 import java.math.BigDecimal;
@@ -40,8 +39,9 @@ import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Calendar;
-import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.processors.odbc.SqlStateCode;
 import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsResult;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType;
@@ -79,14 +79,15 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
         ResultSet rs = getResultSet();
 
         if (rs == null)
-            throw new SQLException("The query isn't SELECT query: " + sql);
+            throw new SQLException("The query isn't SELECT query: " + sql, SqlStateCode.PARSING_EXCEPTION);
 
         return rs;
     }
 
     /** {@inheritDoc} */
     @Override public ResultSet executeQuery(String sql) throws SQLException {
-        throw new SQLException("The method 'executeQuery(String)' is called on PreparedStatement instance.");
+        throw new SQLException("The method 'executeQuery(String)' is called on PreparedStatement instance.",
+            SqlStateCode.UNSUPPORTED_OPERATION);
     }
 
     /** {@inheritDoc} */
@@ -96,29 +97,33 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
         int res = getUpdateCount();
 
         if (res == -1)
-            throw new SQLException("The query is not DML statement: " + sql);
+            throw new SQLException("The query is not DML statement: " + sql, SqlStateCode.PARSING_EXCEPTION);
 
         return res;
     }
 
     /** {@inheritDoc} */
     @Override public int executeUpdate(String sql) throws SQLException {
-        throw new SQLException("The method 'executeUpdate(String)' is called on PreparedStatement instance.");
+        throw new SQLException("The method 'executeUpdate(String)' is called on PreparedStatement instance.",
+            SqlStateCode.UNSUPPORTED_OPERATION);
     }
 
     /** {@inheritDoc} */
     @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
-        throw new SQLException("The method 'executeUpdate(String, int)' is called on PreparedStatement instance.");
+        throw new SQLException("The method 'executeUpdate(String, int)' is called on PreparedStatement instance.",
+            SqlStateCode.UNSUPPORTED_OPERATION);
     }
 
     /** {@inheritDoc} */
     @Override public int executeUpdate(String sql, int columnIndexes[]) throws SQLException {
-        throw new SQLException("The method 'executeUpdate(String, int[])' is called on PreparedStatement instance.");
+        throw new SQLException("The method 'executeUpdate(String, int[])' is called on PreparedStatement instance.",
+            SqlStateCode.UNSUPPORTED_OPERATION);
     }
 
     /** {@inheritDoc} */
     @Override public int executeUpdate(String sql, String columnNames[]) throws SQLException {
-        throw new SQLException("The method 'executeUpdate(String, String[])' is called on PreparedStatement instance.");
+        throw new SQLException("The method 'executeUpdate(String, String[])' is called on PreparedStatement " +
+            "instance.", SqlStateCode.UNSUPPORTED_OPERATION);
     }
 
     /** {@inheritDoc} */
@@ -248,7 +253,8 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
 
     /** {@inheritDoc} */
     @Override public boolean execute(String sql) throws SQLException {
-        throw new SQLException("The method 'execute(String)' is called on PreparedStatement instance.");
+        throw new SQLException("The method 'execute(String)' is called on PreparedStatement instance.",
+            SqlStateCode.UNSUPPORTED_OPERATION);
     }
 
     /** {@inheritDoc} */
@@ -268,7 +274,8 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
 
     /** {@inheritDoc} */
     @Override public void addBatch(String sql) throws SQLException {
-        throw new SQLException("The method 'addBatch(String)' is called on PreparedStatement instance.");
+        throw new SQLException("The method 'addBatch(String)' is called on PreparedStatement instance.",
+            SqlStateCode.UNSUPPORTED_OPERATION);
     }
 
     /** {@inheritDoc} */
@@ -346,27 +353,15 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
     /** {@inheritDoc} */
     @Override public ParameterMetaData getParameterMetaData() throws SQLException {
         ensureNotClosed();
-        try {
-            if (conn.isClosed())
-                throw new SQLException("Connection is closed.");
 
-            if (metaData != null)
-                return metaData;
-
-            JdbcMetaParamsResult res = conn.io().parametersMeta(conn.getSchema(), sql);
+        if (metaData != null)
+            return metaData;
 
-            metaData = new JdbcThinParameterMetadata(res.meta());
+        JdbcMetaParamsResult res = conn.sendRequest(new JdbcMetaParamsRequest(conn.getSchema(), sql));
 
-            return metaData;
-        }
-        catch (IOException e) {
-            conn.close();
+        metaData = new JdbcThinParameterMetadata(res.meta());
 
-            throw new SQLException("Failed to query Ignite.", e);
-        }
-        catch (IgniteCheckedException e) {
-            throw new SQLException("Failed to query Ignite.", e);
-        }
+        return metaData;
     }
 
     /** {@inheritDoc} */
@@ -525,7 +520,8 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
         ensureNotClosed();
 
         if (val != null && !SqlListenerUtils.isPlainType(val.getClass()))
-            throw new SQLException("Parameter type is unsupported. [cls=" + val.getClass() + ']');
+            throw new SQLException("Parameter type is unsupported. [cls=" + val.getClass() + ']',
+                SqlStateCode.INVALID_PARAMETER_VALUE);
 
         if (paramIdx < 1)
             throw new SQLException("Parameter index is invalid: " + paramIdx);

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
index 0a0c978..189175b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.jdbc.thin;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
 import java.math.BigDecimal;
@@ -47,9 +46,12 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.processors.odbc.SqlStateCode;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult;
 
 /**
@@ -197,22 +199,12 @@ public class JdbcThinResultSet implements ResultSet {
         ensureNotClosed();
 
         if ((rowsIter == null || !rowsIter.hasNext()) && !finished) {
-            try {
-                JdbcQueryFetchResult res = stmt.connection().io().queryFetch(qryId, fetchSize);
-
-                rows = res.items();
-                finished = res.last();
+            JdbcQueryFetchResult res = stmt.conn.sendRequest(new JdbcQueryFetchRequest(qryId, fetchSize));
 
-                rowsIter = rows.iterator();
-            }
-            catch (IOException e) {
-                stmt.connection().close();
+            rows = res.items();
+            finished = res.last();
 
-                throw new SQLException("Failed to query Ignite.", e);
-            }
-            catch (IgniteCheckedException e) {
-                throw new SQLException("Failed to query Ignite.", e);
-            }
+            rowsIter = rows.iterator();
         }
 
         if (rowsIter != null) {
@@ -249,20 +241,10 @@ public class JdbcThinResultSet implements ResultSet {
         if (isClosed())
             return;
 
-        try {
-            if (!finished || (isQuery && !autoClose))
-                stmt.connection().io().queryClose(qryId);
-
-            closed = true;
-        }
-        catch (IOException e) {
-            stmt.connection().close();
+        if (!finished || (isQuery && !autoClose))
+            stmt.conn.sendRequest(new JdbcQueryCloseRequest(qryId));
 
-            throw new SQLException("Failed to close Ignite query.", e);
-        }
-        catch (IgniteCheckedException e) {
-            throw new SQLException("Failed to close Ignite query.", e);
-        }
+        closed = true;
     }
 
     /** {@inheritDoc} */
@@ -298,11 +280,11 @@ public class JdbcThinResultSet implements ResultSet {
                 return Integer.parseInt(val.toString()) != 0;
             }
             catch (NumberFormatException e) {
-                throw new SQLException("Cannot convert to boolean: " + val, e);
+                throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.CONVERSION_FAILED, e);
             }
         }
         else
-            throw new SQLException("Cannot convert to boolean: " + val);
+            throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -323,11 +305,11 @@ public class JdbcThinResultSet implements ResultSet {
                 return Byte.parseByte(val.toString());
             }
             catch (NumberFormatException e) {
-                throw new SQLException("Cannot convert to byte: " + val, e);
+                throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.CONVERSION_FAILED, e);
             }
         }
         else
-            throw new SQLException("Cannot convert to byte: " + val);
+            throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -348,11 +330,11 @@ public class JdbcThinResultSet implements ResultSet {
                 return Short.parseShort(val.toString());
             }
             catch (NumberFormatException e) {
-                throw new SQLException("Cannot convert to short: " + val, e);
+                throw new SQLException("Cannot convert to short: " + val, SqlStateCode.CONVERSION_FAILED, e);
             }
         }
         else
-            throw new SQLException("Cannot convert to short: " + val);
+            throw new SQLException("Cannot convert to short: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -373,11 +355,11 @@ public class JdbcThinResultSet implements ResultSet {
                 return Integer.parseInt(val.toString());
             }
             catch (NumberFormatException e) {
-                throw new SQLException("Cannot convert to int: " + val, e);
+                throw new SQLException("Cannot convert to int: " + val, SqlStateCode.CONVERSION_FAILED, e);
             }
         }
         else
-            throw new SQLException("Cannot convert to int: " + val);
+            throw new SQLException("Cannot convert to int: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -398,11 +380,11 @@ public class JdbcThinResultSet implements ResultSet {
                 return Long.parseLong(val.toString());
             }
             catch (NumberFormatException e) {
-                throw new SQLException("Cannot convert to long: " + val, e);
+                throw new SQLException("Cannot convert to long: " + val, SqlStateCode.CONVERSION_FAILED, e);
             }
         }
         else
-            throw new SQLException("Cannot convert to long: " + val);
+            throw new SQLException("Cannot convert to long: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -423,11 +405,11 @@ public class JdbcThinResultSet implements ResultSet {
                 return Float.parseFloat(val.toString());
             }
             catch (NumberFormatException e) {
-                throw new SQLException("Cannot convert to float: " + val, e);
+                throw new SQLException("Cannot convert to float: " + val, SqlStateCode.CONVERSION_FAILED, e);
             }
         }
         else
-            throw new SQLException("Cannot convert to float: " + val);
+            throw new SQLException("Cannot convert to float: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -448,11 +430,11 @@ public class JdbcThinResultSet implements ResultSet {
                 return Double.parseDouble(val.toString());
             }
             catch (NumberFormatException e) {
-                throw new SQLException("Cannot convert to double: " + val, e);
+                throw new SQLException("Cannot convert to double: " + val, SqlStateCode.CONVERSION_FAILED, e);
             }
         }
         else
-            throw new SQLException("Cannot convert to double: " + val);
+            throw new SQLException("Cannot convert to double: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -494,7 +476,7 @@ public class JdbcThinResultSet implements ResultSet {
         else if (cls == String.class)
             return ((String)val).getBytes();
         else
-            throw new SQLException("Cannot convert to byte[]: " + val);
+            throw new SQLException("Cannot convert to byte[]: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -511,7 +493,7 @@ public class JdbcThinResultSet implements ResultSet {
         else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.class)
             return new Date(((java.util.Date)val).getTime());
         else
-            throw new SQLException("Cannot convert to date: " + val);
+            throw new SQLException("Cannot convert to date: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -528,7 +510,7 @@ public class JdbcThinResultSet implements ResultSet {
         else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.class)
             return new Time(((java.util.Date)val).getTime());
         else
-            throw new SQLException("Cannot convert to time: " + val);
+            throw new SQLException("Cannot convert to time: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -545,7 +527,7 @@ public class JdbcThinResultSet implements ResultSet {
         else if (cls == java.util.Date.class || cls == Date.class || cls == Time.class)
             return new Timestamp(((java.util.Date)val).getTime());
         else
-            throw new SQLException("Cannot convert to timestamp: " + val);
+            throw new SQLException("Cannot convert to timestamp: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -564,11 +546,11 @@ public class JdbcThinResultSet implements ResultSet {
                 return new URL(val.toString());
             }
             catch (MalformedURLException e) {
-                throw new SQLException("Cannot convert to URL: " + val, e);
+                throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.CONVERSION_FAILED, e);
             }
         }
         else
-            throw new SQLException("Cannot convert to URL: " + val);
+            throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
 
@@ -753,7 +735,7 @@ public class JdbcThinResultSet implements ResultSet {
         Integer order = columnOrder().get(colLb.toUpperCase());
 
         if (order == null)
-            throw new SQLException("Column not found: " + colLb);
+            throw new SQLException("Column not found: " + colLb, SqlStateCode.PARSING_EXCEPTION);
 
         assert order >= 0;
 
@@ -794,11 +776,11 @@ public class JdbcThinResultSet implements ResultSet {
                 return (BigDecimal)decimalFormat.get().parse(val.toString());
             }
             catch (ParseException e) {
-                throw new SQLException("Cannot convert to BigDecimal: " + val, e);
+                throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.CONVERSION_FAILED, e);
             }
         }
         else
-            throw new SQLException("Cannot convert to BigDecimal: " + val);
+            throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -1834,7 +1816,8 @@ public class JdbcThinResultSet implements ResultSet {
             if (targetCls == cls)
                 return val;
             else
-                throw new SQLException("Cannot convert to " + targetCls.getName() + ": " + val);
+                throw new SQLException("Cannot convert to " + targetCls.getName() + ": " + val,
+                    SqlStateCode.CONVERSION_FAILED);
         }
     }
 
@@ -1858,7 +1841,7 @@ public class JdbcThinResultSet implements ResultSet {
             return val;
         }
         catch (IndexOutOfBoundsException e) {
-            throw new SQLException("Invalid column index: " + colIdx, e);
+            throw new SQLException("Invalid column index: " + colIdx, SqlStateCode.PARSING_EXCEPTION, e);
         }
     }
 
@@ -1869,7 +1852,7 @@ public class JdbcThinResultSet implements ResultSet {
      */
     private void ensureNotClosed() throws SQLException {
         if (closed)
-            throw new SQLException("Result set is closed.");
+            throw new SQLException("Result set is closed.", SqlStateCode.INVALID_CURSOR_STATE);
     }
 
     /**
@@ -1888,24 +1871,14 @@ public class JdbcThinResultSet implements ResultSet {
      */
     private List<JdbcColumnMeta> meta() throws SQLException {
         if (finished && (!isQuery || autoClose))
-            throw new SQLException("Server cursor is already closed.");
+            throw new SQLException("Server cursor is already closed.", SqlStateCode.INVALID_CURSOR_STATE);
 
         if (!metaInit) {
-            try {
-                JdbcQueryMetadataResult res = stmt.connection().io().queryMeta(qryId);
+          JdbcQueryMetadataResult res = stmt.conn.sendRequest(new JdbcQueryMetadataRequest(qryId));
 
-                meta = res.meta();
+           meta = res.meta();
 
-                metaInit = true;
-            }
-            catch (IOException e) {
-                stmt.connection().close();
-
-                throw new SQLException("Failed to get query metadata.", e);
-            }
-            catch (IgniteCheckedException e) {
-                throw new SQLException("Failed to get query metadata.", e);
-            }
+           metaInit = true;
         }
 
         return meta;

http://git-wip-us.apache.org/repos/asf/ignite/blob/7c4d0bc2/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
index d9bef54..6ab50de 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.jdbc.thin;
 
-import java.io.IOException;
 import java.sql.BatchUpdateException;
 import java.sql.Connection;
 import java.sql.ResultSet;
@@ -27,11 +26,13 @@ import java.sql.SQLWarning;
 import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.query.SqlQuery;
+import org.apache.ignite.internal.processors.odbc.SqlStateCode;
 import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType;
 
@@ -96,7 +97,7 @@ public class JdbcThinStatement implements Statement {
         ResultSet rs = getResultSet();
 
         if (rs == null)
-            throw new SQLException("The query isn't SELECT query: " + sql);
+            throw new SQLException("The query isn't SELECT query: " + sql, SqlStateCode.PARSING_EXCEPTION);
 
         return rs;
     }
@@ -122,23 +123,13 @@ public class JdbcThinStatement implements Statement {
         if (sql == null || sql.isEmpty())
             throw new SQLException("SQL query is empty.");
 
-        try {
-            JdbcQueryExecuteResult res = conn.io().queryExecute(stmtType, conn.getSchema(), pageSize, maxRows,
-                sql, args);
-
-            assert res != null;
+        JdbcQueryExecuteResult res = conn.sendRequest(new JdbcQueryExecuteRequest(stmtType, conn.getSchema(), pageSize,
+            maxRows, sql, args == null ? null : args.toArray(new Object[args.size()])));
 
-            rs = new JdbcThinResultSet(this, res.getQueryId(), pageSize, res.last(), res.items(),
-                res.isQuery(), conn.io().autoCloseServerCursor(), res.updateCount(), closeOnCompletion);
-        }
-        catch (IOException e) {
-            conn.close();
+        assert res != null;
 
-            throw new SQLException("Failed to query Ignite.", e);
-        }
-        catch (IgniteCheckedException e) {
-            throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e);
-        }
+        rs = new JdbcThinResultSet(this, res.getQueryId(), pageSize, res.last(), res.items(),
+            res.isQuery(), conn.autoCloseServerCursor(), res.updateCount(), closeOnCompletion);
     }
 
     /** {@inheritDoc} */
@@ -148,7 +139,7 @@ public class JdbcThinStatement implements Statement {
         int res = getUpdateCount();
 
         if (res == -1)
-            throw new SQLException("The query is not DML statememt: " + sql);
+            throw new SQLException("The query is not DML statement: " + sql, SqlStateCode.PARSING_EXCEPTION);
 
         return res;
     }
@@ -378,21 +369,13 @@ public class JdbcThinStatement implements Statement {
             throw new SQLException("Batch is empty.");
 
         try {
-            JdbcBatchExecuteResult res = conn.io().batchExecute(conn.getSchema(), batch);
+            JdbcBatchExecuteResult res = conn.sendRequest(new JdbcBatchExecuteRequest(conn.getSchema(), batch));
 
             if (res.errorCode() != ClientListenerResponse.STATUS_SUCCESS)
                 throw new BatchUpdateException(res.errorMessage(), null, res.errorCode(), res.updateCounts());
 
             return res.updateCounts();
         }
-        catch (IOException e) {
-            conn.close();
-
-            throw new SQLException("Failed to query Ignite.", e);
-        }
-        catch (IgniteCheckedException e) {
-            throw new SQLException("Failed to query Ignite.", e);
-        }
         finally {
             batch = null;
         }


Mime
View raw message