ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [12/50] [abbrv] ignite git commit: IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.
Date Tue, 06 Jun 2017 08:59:30 GMT
IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.


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

Branch: refs/heads/ignite-5075
Commit: e92707b65ca9044070a200317079a600c8d92ded
Parents: fd838d5
Author: tledkov-gridgain <tledkov@gridgain.com>
Authored: Fri Jun 2 14:33:33 2017 +0300
Committer: devozerov <vozerov@gridgain.com>
Committed: Fri Jun 2 14:33:34 2017 +0300

----------------------------------------------------------------------
 .../jdbc/suite/IgniteJdbcDriverTestSuite.java   |   17 +-
 .../jdbc/thin/JdbcConnectionSelfTest.java       |  195 --
 .../jdbc/thin/JdbcThinAbstractSelfTest.java     |   41 +
 .../jdbc/thin/JdbcThinComplexQuerySelfTest.java |  330 ++++
 .../jdbc/thin/JdbcThinConnectionSelfTest.java   |  214 +++
 .../jdbc/thin/JdbcThinEmptyCacheSelfTest.java   |  146 ++
 .../jdbc/thin/JdbcThinMetadataSelfTest.java     |  357 ++++
 .../jdbc/thin/JdbcThinNoDefaultSchemaTest.java  |  161 ++
 .../thin/JdbcThinPreparedStatementSelfTest.java |  771 ++++++++
 .../jdbc/thin/JdbcThinResultSetSelfTest.java    |  762 ++++++++
 .../jdbc/thin/JdbcThinStatementSelfTest.java    |  343 ++++
 .../org/apache/ignite/IgniteJdbcDriver.java     |    3 +
 .../org/apache/ignite/IgniteJdbcThinDriver.java |    7 +-
 .../internal/jdbc/thin/JdbcConnection.java      |  529 ------
 .../ignite/internal/jdbc/thin/JdbcTcpIo.java    |  207 ---
 .../internal/jdbc/thin/JdbcThinConnection.java  |  545 ++++++
 .../jdbc/thin/JdbcThinPreparedStatement.java    |  461 +++++
 .../internal/jdbc/thin/JdbcThinResultSet.java   | 1698 ++++++++++++++++++
 .../jdbc/thin/JdbcThinResultSetMetadata.java    |  161 ++
 .../internal/jdbc/thin/JdbcThinStatement.java   |  475 +++++
 .../internal/jdbc/thin/JdbcThinTcpIo.java       |  309 ++++
 .../internal/jdbc/thin/JdbcThinUtils.java       |  152 ++
 .../odbc/OdbcQueryGetColumnsMetaRequest.java    |   74 -
 .../odbc/OdbcQueryGetColumnsMetaResult.java     |   42 -
 .../odbc/OdbcQueryGetParamsMetaRequest.java     |   60 -
 .../odbc/OdbcQueryGetParamsMetaResult.java      |   40 -
 .../odbc/OdbcQueryGetTablesMetaRequest.java     |   85 -
 .../odbc/OdbcQueryGetTablesMetaResult.java      |   42 -
 .../internal/processors/odbc/OdbcTableMeta.java |   88 -
 .../odbc/SqlListenerAbstractMessageParser.java  |  265 ---
 .../odbc/SqlListenerAbstractObjectReader.java   |  137 --
 .../odbc/SqlListenerAbstractObjectWriter.java   |  111 --
 .../processors/odbc/SqlListenerColumnMeta.java  |  110 --
 .../processors/odbc/SqlListenerNioListener.java |   27 +-
 .../odbc/SqlListenerQueryCloseRequest.java      |   49 -
 .../odbc/SqlListenerQueryCloseResult.java       |   40 -
 .../odbc/SqlListenerQueryExecuteRequest.java    |   78 -
 .../odbc/SqlListenerQueryExecuteResult.java     |   54 -
 .../odbc/SqlListenerQueryFetchRequest.java      |   61 -
 .../odbc/SqlListenerQueryFetchResult.java       |   66 -
 .../processors/odbc/SqlListenerRequest.java     |   37 +-
 .../odbc/SqlListenerRequestHandler.java         |    8 +
 .../odbc/SqlListenerRequestHandlerImpl.java     |  494 -----
 .../processors/odbc/SqlListenerResponse.java    |   42 +-
 .../processors/odbc/SqlListenerUtils.java       |  250 +++
 .../processors/odbc/jdbc/JdbcColumnMeta.java    |  129 ++
 .../processors/odbc/jdbc/JdbcMessageParser.java |   53 +-
 .../processors/odbc/jdbc/JdbcObjectReader.java  |   33 -
 .../processors/odbc/jdbc/JdbcObjectWriter.java  |   33 -
 .../odbc/jdbc/JdbcQueryCloseRequest.java        |   72 +
 .../processors/odbc/jdbc/JdbcQueryCursor.java   |  132 ++
 .../odbc/jdbc/JdbcQueryExecuteRequest.java      |  147 ++
 .../odbc/jdbc/JdbcQueryExecuteResult.java       |  150 ++
 .../odbc/jdbc/JdbcQueryFetchRequest.java        |   87 +
 .../odbc/jdbc/JdbcQueryFetchResult.java         |   84 +
 .../odbc/jdbc/JdbcQueryMetadataRequest.java     |   73 +
 .../odbc/jdbc/JdbcQueryMetadataResult.java      |   93 +
 .../odbc/jdbc/JdbcRawBinarylizable.java         |   44 +
 .../processors/odbc/jdbc/JdbcRequest.java       |  108 ++
 .../odbc/jdbc/JdbcRequestHandler.java           |  285 +++
 .../processors/odbc/jdbc/JdbcResponse.java      |  104 ++
 .../processors/odbc/jdbc/JdbcResult.java        |   91 +
 .../processors/odbc/jdbc/JdbcUtils.java         |   73 +
 .../processors/odbc/odbc/OdbcColumnMeta.java    |  111 ++
 .../processors/odbc/odbc/OdbcMessageParser.java |  213 ++-
 .../processors/odbc/odbc/OdbcObjectReader.java  |   33 -
 .../processors/odbc/odbc/OdbcObjectWriter.java  |   32 -
 .../odbc/odbc/OdbcQueryCloseRequest.java        |   49 +
 .../odbc/odbc/OdbcQueryCloseResult.java         |   40 +
 .../odbc/odbc/OdbcQueryExecuteRequest.java      |   78 +
 .../odbc/odbc/OdbcQueryExecuteResult.java       |   54 +
 .../odbc/odbc/OdbcQueryFetchRequest.java        |   61 +
 .../odbc/odbc/OdbcQueryFetchResult.java         |   66 +
 .../odbc/OdbcQueryGetColumnsMetaRequest.java    |   74 +
 .../odbc/OdbcQueryGetColumnsMetaResult.java     |   42 +
 .../odbc/OdbcQueryGetParamsMetaRequest.java     |   60 +
 .../odbc/odbc/OdbcQueryGetParamsMetaResult.java |   40 +
 .../odbc/OdbcQueryGetTablesMetaRequest.java     |   85 +
 .../odbc/odbc/OdbcQueryGetTablesMetaResult.java |   42 +
 .../processors/odbc/odbc/OdbcRequest.java       |   63 +
 .../odbc/odbc/OdbcRequestHandler.java           |  505 ++++++
 .../processors/odbc/odbc/OdbcResponse.java      |   69 +
 .../processors/odbc/odbc/OdbcTableMeta.java     |   89 +
 83 files changed, 10686 insertions(+), 3055 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/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 abfdf90..e0e6f31 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
@@ -31,6 +31,14 @@ import org.apache.ignite.jdbc.JdbcPojoQuerySelfTest;
 import org.apache.ignite.jdbc.JdbcPreparedStatementSelfTest;
 import org.apache.ignite.jdbc.JdbcResultSetSelfTest;
 import org.apache.ignite.jdbc.JdbcStatementSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinComplexQuerySelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinConnectionSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinEmptyCacheSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinMetadataSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinNoDefaultSchemaTest;
+import org.apache.ignite.jdbc.thin.JdbcThinPreparedStatementSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinResultSetSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinStatementSelfTest;
 
 /**
  * JDBC driver test suite.
@@ -85,7 +93,14 @@ public class IgniteJdbcDriverTestSuite extends TestSuite {
         suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcDynamicIndexTransactionalReplicatedSelfTest.class));
 
         // New thin JDBC
-        suite.addTest(new TestSuite(org.apache.ignite.jdbc.thin.JdbcConnectionSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinConnectionSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinStatementSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinResultSetSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinComplexQuerySelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinPreparedStatementSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinNoDefaultSchemaTest.class));
+        suite.addTest(new TestSuite(JdbcThinEmptyCacheSelfTest.class));
+        suite.addTest(new TestSuite(JdbcThinMetadataSelfTest.class));
 
         return suite;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcConnectionSelfTest.java
deleted file mode 100644
index d7e2bef..0000000
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcConnectionSelfTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.jdbc.thin;
-
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.concurrent.Callable;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.OdbcConfiguration;
-import org.apache.ignite.internal.binary.BinaryMarshaller;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
-import org.apache.ignite.testframework.GridTestUtils;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Connection test.
- */
-public class JdbcConnectionSelfTest extends GridCommonAbstractTest {
-    /** IP finder. */
-    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
-
-    /** URL prefix. */
-    private static final String URL_PREFIX = "jdbc:ignite:thin://";
-
-    /** Host. */
-    private static final String HOST = "127.0.0.1";
-
-    /** {@inheritDoc} */
-    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
-        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
-
-        cfg.setCacheConfiguration(cacheConfiguration(DEFAULT_CACHE_NAME));
-
-        TcpDiscoverySpi disco = new TcpDiscoverySpi();
-
-        disco.setIpFinder(IP_FINDER);
-
-        cfg.setDiscoverySpi(disco);
-
-        cfg.setMarshaller(new BinaryMarshaller());
-
-        cfg.setOdbcConfiguration(new OdbcConfiguration());
-
-        return cfg;
-    }
-
-    /**
-     * @param name Cache name.
-     * @return Cache configuration.
-     * @throws Exception In case of error.
-     */
-    private CacheConfiguration cacheConfiguration(@NotNull String name) throws Exception {
-        CacheConfiguration cfg = defaultCacheConfiguration();
-
-        cfg.setName(name);
-
-        return cfg;
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void beforeTestsStarted() throws Exception {
-        try {
-            Driver drv = DriverManager.getDriver("jdbc:ignite://");
-
-            if (drv != null)
-                DriverManager.deregisterDriver(drv);
-        } catch (SQLException ignored) {
-            // No-op.
-        }
-
-        startGridsMultiThreaded(2);
-
-        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void afterTestsStopped() throws Exception {
-        stopAllGrids();
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testDefaults() throws Exception {
-        String url = URL_PREFIX + HOST;
-
-        assert DriverManager.getConnection(url) != null;
-        assert DriverManager.getConnection(url + "/") != null;
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testInvalidUrls() throws Exception {
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:80");
-
-                return null;
-            }
-        }, SQLException.class, "Failed to connect to Ignite cluster [host=127.0.0.1, port=80]");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection("q");
-
-                return null;
-            }
-        }, SQLException.class, "URL is invalid");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:-1");
-
-                return null;
-            }
-        }, SQLException.class, "Invalid port:");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:0");
-
-                return null;
-            }
-        }, SQLException.class, "Invalid port:");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:100000");
-
-                return null;
-            }
-        }, SQLException.class, "Invalid port:");
-
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                DriverManager.getConnection(URL_PREFIX + "     :10000");
-
-                return null;
-            }
-        }, SQLException.class, "Host name is empty");
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testClose() throws Exception {
-        String url = URL_PREFIX + HOST;
-
-        final Connection conn = DriverManager.getConnection(url);
-
-        assert conn != null;
-        assert !conn.isClosed();
-
-        conn.close();
-
-        assert conn.isClosed();
-
-        assert !conn.isValid(2): "Connection must be closed";
-
-        GridTestUtils.assertThrows(
-            log,
-            new Callable<Object>() {
-                @Override public Object call() throws Exception {
-                    conn.isValid(-2);
-
-                    return null;
-                }
-            },
-            SQLException.class,
-            "Invalid timeout"
-        );
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
new file mode 100644
index 0000000..bbefbd4
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * Connection test.
+ */
+public class JdbcThinAbstractSelfTest extends GridCommonAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setOdbcConfiguration(new OdbcConfiguration());
+
+        return cfg;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexQuerySelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexQuerySelfTest.java
new file mode 100644
index 0000000..1714ab1
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexQuerySelfTest.java
@@ -0,0 +1,330 @@
+/*
+ * 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.io.Serializable;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.affinity.AffinityKey;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Tests for complex queries (joins, etc.).
+ */
+public class JdbcThinComplexQuerySelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** Statement. */
+    private Statement stmt;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setCacheConfiguration(cacheConfiguration());
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        return cfg;
+    }
+
+    /**
+     * @return Cache configuration.
+     */
+    protected CacheConfiguration cacheConfiguration() {
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+        cache.setAtomicityMode(TRANSACTIONAL);
+
+        return cache;
+    }
+
+
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrids(3);
+
+        IgniteCache<String, Organization> orgCache = jcache(grid(0), cacheConfiguration(), "org",
+            String.class, Organization.class);
+
+        assert orgCache != null;
+
+        orgCache.put("o1", new Organization(1, "A"));
+        orgCache.put("o2", new Organization(2, "B"));
+
+        IgniteCache<AffinityKey, Person> personCache = jcache(grid(0), cacheConfiguration(), "pers",
+            AffinityKey.class, Person.class);
+
+        assert personCache != null;
+
+        personCache.put(new AffinityKey<>("p1", "o1"), new Person(1, "John White", 25, 1));
+        personCache.put(new AffinityKey<>("p2", "o1"), new Person(2, "Joe Black", 35, 1));
+        personCache.put(new AffinityKey<>("p3", "o2"), new Person(3, "Mike Green", 40, 2));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        Connection conn = DriverManager.getConnection(URL);
+
+        conn.setSchema("pers");
+
+        stmt = conn.createStatement();
+
+        assert stmt != null;
+        assert !stmt.isClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (stmt != null) {
+            stmt.getConnection().close();
+
+            stmt.close();
+
+            assert stmt.isClosed();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testJoin() throws Exception {
+        ResultSet rs = stmt.executeQuery(
+            "select p.id, p.name, o.name as orgName from \"pers\".Person p, \"org\".Organization o where p.orgId = o.id");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            int id = rs.getInt("id");
+
+            if (id == 1) {
+                assert "John White".equals(rs.getString("name"));
+                assert "A".equals(rs.getString("orgName"));
+            }
+            else if (id == 2) {
+                assert "Joe Black".equals(rs.getString("name"));
+                assert "A".equals(rs.getString("orgName"));
+            }
+            else if (id == 3) {
+                assert "Mike Green".equals(rs.getString("name"));
+                assert "B".equals(rs.getString("orgName"));
+            }
+            else
+                assert false : "Wrong ID: " + id;
+
+            cnt++;
+        }
+
+        assert cnt == 3;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testJoinWithoutAlias() throws Exception {
+        ResultSet rs = stmt.executeQuery(
+            "select p.id, p.name, o.name from \"pers\".Person p, \"org\".Organization o where p.orgId = o.id");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            int id = rs.getInt(1);
+
+            if (id == 1) {
+                assert "John White".equals(rs.getString("name"));
+                assert "John White".equals(rs.getString(2));
+                assert "A".equals(rs.getString(3));
+            }
+            else if (id == 2) {
+                assert "Joe Black".equals(rs.getString("name"));
+                assert "Joe Black".equals(rs.getString(2));
+                assert "A".equals(rs.getString(3));
+            }
+            else if (id == 3) {
+                assert "Mike Green".equals(rs.getString("name"));
+                assert "Mike Green".equals(rs.getString(2));
+                assert "B".equals(rs.getString(3));
+            }
+            else
+                assert false : "Wrong ID: " + id;
+
+            cnt++;
+        }
+
+        assert cnt == 3;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testIn() throws Exception {
+        ResultSet rs = stmt.executeQuery("select name from \"pers\".Person where age in (25, 35)");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assert "John White".equals(rs.getString("name")) ||
+                "Joe Black".equals(rs.getString("name"));
+
+            cnt++;
+        }
+
+        assert cnt == 2;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBetween() throws Exception {
+        ResultSet rs = stmt.executeQuery("select name from \"pers\".Person where age between 24 and 36");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assert "John White".equals(rs.getString("name")) ||
+                "Joe Black".equals(rs.getString("name"));
+
+            cnt++;
+        }
+
+        assert cnt == 2;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCalculatedValue() throws Exception {
+        ResultSet rs = stmt.executeQuery("select age * 2 from \"pers\".Person");
+
+        assert rs != null;
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assert rs.getInt(1) == 50 ||
+                rs.getInt(1) == 70 ||
+                rs.getInt(1) == 80;
+
+            cnt++;
+        }
+
+        assert cnt == 3;
+    }
+
+    /**
+     * Person.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Person implements Serializable {
+        /** ID. */
+        @QuerySqlField
+        private final int id;
+
+        /** Name. */
+        @QuerySqlField(index = false)
+        private final String name;
+
+        /** Age. */
+        @QuerySqlField
+        private final int age;
+
+        /** Organization ID. */
+        @QuerySqlField
+        private final int orgId;
+
+        /**
+         * @param id ID.
+         * @param name Name.
+         * @param age Age.
+         * @param orgId Organization ID.
+         */
+        private Person(int id, String name, int age, int orgId) {
+            assert !F.isEmpty(name);
+            assert age > 0;
+            assert orgId > 0;
+
+            this.id = id;
+            this.name = name;
+            this.age = age;
+            this.orgId = orgId;
+        }
+    }
+
+    /**
+     * Organization.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Organization implements Serializable {
+        /** ID. */
+        @QuerySqlField
+        private final int id;
+
+        /** Name. */
+        @QuerySqlField(index = false)
+        private final String name;
+
+        /**
+         * @param id ID.
+         * @param name Name.
+         */
+        private Organization(int id, String name) {
+            this.id = id;
+            this.name = name;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/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
new file mode 100644
index 0000000..c3ce73a
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
@@ -0,0 +1,214 @@
+/*
+ * 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.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.concurrent.Callable;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Connection test.
+ */
+public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL prefix. */
+    private static final String URL_PREFIX = "jdbc:ignite:thin://";
+
+    /** Host. */
+    private static final String HOST = "127.0.0.1";
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setCacheConfiguration(cacheConfiguration(DEFAULT_CACHE_NAME));
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setMarshaller(new BinaryMarshaller());
+
+        return cfg;
+    }
+
+    /**
+     * @param name Cache name.
+     * @return Cache configuration.
+     * @throws Exception In case of error.
+     */
+    private CacheConfiguration cacheConfiguration(@NotNull String name) throws Exception {
+        CacheConfiguration cfg = defaultCacheConfiguration();
+
+        cfg.setName(name);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(2);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDefaults() throws Exception {
+        String url = URL_PREFIX + HOST;
+
+        assert DriverManager.getConnection(url) != null;
+        assert DriverManager.getConnection(url + "/") != null;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFailedHandshake() throws Exception {
+        final ServerSocket srvSock = new ServerSocket(60000, 0, InetAddress.getByName("127.0.0.1"));
+
+        IgniteInternalFuture f = GridTestUtils.runAsync(new Runnable() {
+            @Override public void run() {
+                try {
+                    Socket s = srvSock.accept();
+
+                    s.close();
+                }
+                catch (IOException e) {
+                    log.error("Unexpected exception", e);
+                    fail();
+                }
+            }
+        });
+
+        try {
+            GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    DriverManager.getConnection(URL_PREFIX + "127.0.0.1:60000");
+
+                    return null;
+                }
+            }, SQLException.class, "Failed to connect to Ignite cluster [host=127.0.0.1, port=60000]");
+        }
+        finally {
+            f.get(3000);
+
+            srvSock.close();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testInvalidUrls() throws Exception {
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection("q");
+
+                return null;
+            }
+        }, SQLException.class, "No suitable driver found for q");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:-1");
+
+                return null;
+            }
+        }, SQLException.class, "Invalid port:");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:0");
+
+                return null;
+            }
+        }, SQLException.class, "Invalid port:");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection(URL_PREFIX + "127.0.0.1:100000");
+
+                return null;
+            }
+        }, SQLException.class, "Invalid port:");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                DriverManager.getConnection(URL_PREFIX + "     :10000");
+
+                return null;
+            }
+        }, SQLException.class, "Host name is empty");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testClose() throws Exception {
+        String url = URL_PREFIX + HOST;
+
+        final Connection conn = DriverManager.getConnection(url);
+
+        assert conn != null;
+        assert !conn.isClosed();
+
+        conn.close();
+
+        assert conn.isClosed();
+
+        assert !conn.isValid(2): "Connection must be closed";
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    conn.isValid(-2);
+
+                    return null;
+                }
+            },
+            SQLException.class,
+            "Invalid timeout"
+        );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
new file mode 100644
index 0000000..4775a79
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinEmptyCacheSelfTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Tests for empty cache.
+ */
+public class JdbcThinEmptyCacheSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** Cache name. */
+    private static final String CACHE_NAME = "cache";
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** Statement. */
+    private Statement stmt;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        CacheConfiguration cache = defaultCacheConfiguration();
+
+        cache.setName(CACHE_NAME);
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+        cache.setIndexedTypes(
+            Byte.class, Byte.class
+        );
+
+        cfg.setCacheConfiguration(cache);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setOdbcConfiguration(new OdbcConfiguration());
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrid();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        Connection conn = DriverManager.getConnection(URL);
+
+        conn.setSchema(CACHE_NAME);
+
+        stmt = conn.createStatement();
+
+        assert stmt != null;
+        assert !stmt.isClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (stmt != null) {
+            stmt.getConnection().close();
+
+            stmt.close();
+
+            assert stmt.isClosed();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testSelectNumber() throws Exception {
+        ResultSet rs = stmt.executeQuery("select 1");
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assert rs.getInt(1) == 1;
+            assert "1".equals(rs.getString(1));
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testSelectString() throws Exception {
+        ResultSet rs = stmt.executeQuery("select 'str'");
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            assertEquals("str", rs.getString(1));
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
new file mode 100644
index 0000000..2dae107
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
@@ -0,0 +1,357 @@
+/*
+ * 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.io.Serializable;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.affinity.AffinityKey;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+
+import static java.sql.Types.INTEGER;
+import static java.sql.Types.OTHER;
+import static java.sql.Types.VARCHAR;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Metadata tests.
+ */
+public class JdbcThinMetadataSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        return cfg;
+    }
+
+    /**
+     * @return Cache configuration.
+     */
+    protected CacheConfiguration cacheConfiguration() {
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+
+        return cache;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(3);
+
+        IgniteCache<String, Organization> orgCache = jcache(grid(0), cacheConfiguration(), "org",
+            String.class, Organization.class);
+
+        assert orgCache != null;
+
+        orgCache.put("o1", new Organization(1, "A"));
+        orgCache.put("o2", new Organization(2, "B"));
+
+        IgniteCache<AffinityKey, Person> personCache = jcache(grid(0), cacheConfiguration(), "pers",
+            AffinityKey.class, Person.class);
+
+        assert personCache != null;
+
+        personCache.put(new AffinityKey<>("p1", "o1"), new Person("John White", 25, 1));
+        personCache.put(new AffinityKey<>("p2", "o1"), new Person("Joe Black", 35, 1));
+        personCache.put(new AffinityKey<>("p3", "o2"), new Person("Mike Green", 40, 2));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testResultSetMetaData() throws Exception {
+        Connection conn = DriverManager.getConnection(URL);
+
+        conn.setSchema("pers");
+
+        Statement stmt = conn.createStatement();
+
+        ResultSet rs = stmt.executeQuery(
+            "select p.name, o.id as orgId from \"pers\".Person p, \"org\".Organization o where p.orgId = o.id");
+
+        assert rs != null;
+
+        ResultSetMetaData meta = rs.getMetaData();
+
+        assert meta != null;
+
+        assert meta.getColumnCount() == 2;
+
+        assert "Person".equalsIgnoreCase(meta.getTableName(1));
+        assert "name".equalsIgnoreCase(meta.getColumnName(1));
+        assert "name".equalsIgnoreCase(meta.getColumnLabel(1));
+        assert meta.getColumnType(1) == VARCHAR;
+        assert "VARCHAR".equals(meta.getColumnTypeName(1));
+        assert "java.lang.String".equals(meta.getColumnClassName(1));
+
+        assert "Organization".equalsIgnoreCase(meta.getTableName(2));
+        assert "orgId".equalsIgnoreCase(meta.getColumnName(2));
+        assert "orgId".equalsIgnoreCase(meta.getColumnLabel(2));
+        assert meta.getColumnType(2) == INTEGER;
+        assert "INTEGER".equals(meta.getColumnTypeName(2));
+        assert "java.lang.Integer".equals(meta.getColumnClassName(2));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetTables() throws Exception {
+        fail("https://issues.apache.org/jira/browse/IGNITE-5233");
+
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getTables("", "pers", "%", new String[]{"TABLE"});
+            assertNotNull(rs);
+            assertTrue(rs.next());
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+            assertEquals("PERSON", rs.getString("TABLE_NAME"));
+
+            rs = meta.getTables("", "org", "%", new String[]{"TABLE"});
+            assertNotNull(rs);
+            assertTrue(rs.next());
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+            assertEquals("ORGANIZATION", rs.getString("TABLE_NAME"));
+
+            rs = meta.getTables("", "pers", "%", null);
+            assertNotNull(rs);
+            assertTrue(rs.next());
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+            assertEquals("PERSON", rs.getString("TABLE_NAME"));
+
+            rs = meta.getTables("", "org", "%", null);
+            assertNotNull(rs);
+            assertTrue(rs.next());
+            assertEquals("TABLE", rs.getString("TABLE_TYPE"));
+            assertEquals("ORGANIZATION", rs.getString("TABLE_NAME"));
+
+            rs = meta.getTables("", "PUBLIC", "", new String[]{"WRONG"});
+            assertFalse(rs.next());
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetColumns() throws Exception {
+        fail("https://issues.apache.org/jira/browse/IGNITE-5233");
+
+        try (Connection conn = DriverManager.getConnection(URL)) {
+            conn.setSchema("pers");
+
+            DatabaseMetaData meta = conn.getMetaData();
+
+            ResultSet rs = meta.getColumns("", "pers", "Person", "%");
+
+            assert rs != null;
+
+            Collection<String> names = new ArrayList<>(2);
+
+            names.add("NAME");
+            names.add("AGE");
+            names.add("ORGID");
+
+            int cnt = 0;
+
+            while (rs.next()) {
+                String name = rs.getString("COLUMN_NAME");
+
+                assert names.remove(name);
+
+                if ("NAME".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == VARCHAR;
+                    assert "VARCHAR".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 1;
+                } else if ("AGE".equals(name) || "ORGID".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == INTEGER;
+                    assert "INTEGER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+                if ("_KEY".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == OTHER;
+                    assert "OTHER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+                if ("_VAL".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == OTHER;
+                    assert "OTHER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+
+                cnt++;
+            }
+
+            assert names.isEmpty();
+            assert cnt == 3;
+
+            rs = meta.getColumns("", "org", "Organization", "%");
+
+            assert rs != null;
+
+            names.add("ID");
+            names.add("NAME");
+
+            cnt = 0;
+
+            while (rs.next()) {
+                String name = rs.getString("COLUMN_NAME");
+
+                assert names.remove(name);
+
+                if ("id".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == INTEGER;
+                    assert "INTEGER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                } else if ("name".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == VARCHAR;
+                    assert "VARCHAR".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 1;
+                }
+                if ("_KEY".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == VARCHAR;
+                    assert "VARCHAR".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+                if ("_VAL".equals(name)) {
+                    assert rs.getInt("DATA_TYPE") == OTHER;
+                    assert "OTHER".equals(rs.getString("TYPE_NAME"));
+                    assert rs.getInt("NULLABLE") == 0;
+                }
+
+                cnt++;
+            }
+
+            assert names.isEmpty();
+            assert cnt == 2;
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMetadataResultSetClose() throws Exception {
+        fail("https://issues.apache.org/jira/browse/IGNITE-5233");
+
+        try (Connection conn = DriverManager.getConnection(URL);
+             ResultSet tbls = conn.getMetaData().getTables(null, null, "%", null)) {
+            int colCnt = tbls.getMetaData().getColumnCount();
+
+            while (tbls.next()) {
+                for (int i = 0; i < colCnt; i++)
+                    tbls.getObject(i + 1);
+            }
+        }
+        catch (Exception e) {
+            log.error("Unexpected exception", e);
+
+            fail();
+        }
+    }
+
+    /**
+     * Person.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Person implements Serializable {
+        /** Name. */
+        @QuerySqlField(index = false)
+        private final String name;
+
+        /** Age. */
+        @QuerySqlField
+        private final int age;
+
+        /** Organization ID. */
+        @QuerySqlField
+        private final int orgId;
+
+        /**
+         * @param name Name.
+         * @param age Age.
+         * @param orgId Organization ID.
+         */
+        private Person(String name, int age, int orgId) {
+            assert !F.isEmpty(name);
+            assert age > 0;
+            assert orgId > 0;
+
+            this.name = name;
+            this.age = age;
+            this.orgId = orgId;
+        }
+    }
+
+    /**
+     * Organization.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class Organization implements Serializable {
+        /** ID. */
+        @QuerySqlField
+        private final int id;
+
+        /** Name. */
+        @QuerySqlField(index = false)
+        private final String name;
+
+        /**
+         * @param id ID.
+         * @param name Name.
+         */
+        private Organization(int id, String name) {
+            this.id = id;
+            this.name = name;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/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
new file mode 100644
index 0000000..97008c8
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ *
+ */
+public class JdbcThinNoDefaultSchemaTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** First cache name. */
+    private static final String CACHE1_NAME = "cache1";
+
+    /** Second cache name. */
+    private static final String CACHE2_NAME = "cache2";
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** Grid count. */
+    private static final int GRID_CNT = 2;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setCacheConfiguration(cacheConfiguration(CACHE1_NAME), cacheConfiguration(CACHE2_NAME));
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        return cfg;
+    }
+
+    /**
+     * @param name Cache name.
+     * @return Cache configuration.
+     * @throws Exception In case of error.
+     */
+    @SuppressWarnings("unchecked")
+    private CacheConfiguration cacheConfiguration(@NotNull String name) throws Exception {
+        CacheConfiguration cfg = defaultCacheConfiguration();
+
+        cfg.setIndexedTypes(Integer.class, Integer.class);
+
+        cfg.setName(name);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(GRID_CNT);
+
+        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
+
+        Ignite ignite = ignite(0);
+
+        IgniteCache<Integer, Integer> cache1 = ignite.cache(CACHE1_NAME);
+        IgniteCache<Integer, Integer> cache2 = ignite.cache(CACHE2_NAME);
+
+        for (int i = 0; i < 10; i++) {
+            cache1.put(i, i * 2);
+            cache2.put(i, i * 3);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDefaults() throws Exception {
+        String url = URL;
+
+        try (Connection conn = DriverManager.getConnection(url)) {
+            assertNotNull(conn);
+        }
+
+        try (Connection conn = DriverManager.getConnection(url + '/')) {
+            assertNotNull(conn);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNoCacheNameQuery() throws Exception {
+        Connection conn = DriverManager.getConnection(URL);
+
+        conn.setSchema("cache1");
+
+        Statement stmt = conn.createStatement();
+
+        assertNotNull(stmt);
+        assertFalse(stmt.isClosed());
+
+        stmt.execute("select t._key, t._val from \"cache1\".Integer t");
+
+        ResultSet rs = stmt.getResultSet();
+
+        while(rs.next())
+            assertEquals(rs.getInt(2), rs.getInt(1) * 2);
+
+        stmt.execute("select t._key, t._val from \"cache2\".Integer t");
+
+        rs = stmt.getResultSet();
+
+        while(rs.next())
+            assertEquals(rs.getInt(2), rs.getInt(1) * 3);
+
+        stmt.execute("select t._key, t._val, v._val " +
+            "from \"cache1\".Integer t join \"cache2\".Integer v on t._key = v._key");
+
+        rs = stmt.getResultSet();
+
+        while(rs.next()) {
+            assertEquals(rs.getInt(2), rs.getInt(1) * 2);
+            assertEquals(rs.getInt(3), rs.getInt(1) * 3);
+        }
+
+        stmt.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
new file mode 100644
index 0000000..aead436
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java
@@ -0,0 +1,771 @@
+/*
+ * 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.io.Serializable;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Connection;
+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.Date;
+import java.util.concurrent.Callable;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+
+import static java.sql.Types.BIGINT;
+import static java.sql.Types.BINARY;
+import static java.sql.Types.BOOLEAN;
+import static java.sql.Types.DATE;
+import static java.sql.Types.DOUBLE;
+import static java.sql.Types.FLOAT;
+import static java.sql.Types.INTEGER;
+import static java.sql.Types.OTHER;
+import static java.sql.Types.SMALLINT;
+import static java.sql.Types.TIME;
+import static java.sql.Types.TIMESTAMP;
+import static java.sql.Types.TINYINT;
+import static java.sql.Types.VARCHAR;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Prepared statement test.
+ */
+public class JdbcThinPreparedStatementSelfTest extends JdbcThinAbstractSelfTest {
+    /** IP finder. */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** URL. */
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/";
+
+    /** SQL query. */
+    private static final String SQL_PART =
+        "select id, boolVal, byteVal, shortVal, intVal, longVal, floatVal, " +
+            "doubleVal, bigVal, strVal, arrVal, dateVal, timeVal, tsVal " +
+            "from TestObject ";
+
+    /** Connection. */
+    private Connection conn;
+
+    /** Statement. */
+    private PreparedStatement stmt;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+        cache.setCacheMode(PARTITIONED);
+        cache.setBackups(1);
+        cache.setWriteSynchronizationMode(FULL_SYNC);
+        cache.setIndexedTypes(
+            Integer.class, TestObject.class
+        );
+
+        cfg.setCacheConfiguration(cache);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setOdbcConfiguration(new OdbcConfiguration());
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(3);
+
+        IgniteCache<Integer, TestObject> cache = grid(0).cache(DEFAULT_CACHE_NAME);
+
+        assert cache != null;
+
+        TestObject o = new TestObject(1);
+
+        o.boolVal = true;
+        o.byteVal = 1;
+        o.shortVal = 1;
+        o.intVal = 1;
+        o.longVal = 1L;
+        o.floatVal = 1.0f;
+        o.doubleVal = 1.0d;
+        o.bigVal = new BigDecimal(1);
+        o.strVal = "str";
+        o.arrVal = new byte[] {1};
+        o.dateVal = new Date(1);
+        o.timeVal = new Time(1);
+        o.tsVal = new Timestamp(1);
+        o.urlVal = new URL("http://abc.com/");
+
+        cache.put(1, o);
+        cache.put(2, new TestObject(2));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        conn = DriverManager.getConnection(URL);
+
+        conn.setSchema(DEFAULT_CACHE_NAME);
+
+        assert conn != null;
+        assert !conn.isClosed();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (stmt != null) {
+            stmt.close();
+
+            assert stmt.isClosed();
+        }
+
+        if (conn != null) {
+            conn.close();
+
+            assert conn.isClosed();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testQueryExecuteException() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where boolVal is not distinct from ?");
+
+        stmt.setBoolean(1, true);
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                stmt.executeQuery(SQL_PART);
+
+                return null;
+            }
+        }, SQLException.class, "The method 'executeQuery(String)' is called on PreparedStatement instance.");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                stmt.execute(SQL_PART);
+
+                return null;
+            }
+        }, SQLException.class, "The method 'execute(String)' is called on PreparedStatement instance.");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBoolean() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where boolVal is not distinct from ?");
+
+        stmt.setBoolean(1, true);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, BOOLEAN);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testByte() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where byteVal is not distinct from ?");
+
+        stmt.setByte(1, (byte)1);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, TINYINT);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testShort() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where shortVal is not distinct from ?");
+
+        stmt.setShort(1, (short)1);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, SMALLINT);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testInteger() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where intVal is not distinct from ?");
+
+        stmt.setInt(1, 1);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, INTEGER);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLong() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where longVal is not distinct from ?");
+
+        stmt.setLong(1, 1L);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, BIGINT);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFloat() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where floatVal is not distinct from ?");
+
+        stmt.setFloat(1, 1.0f);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, FLOAT);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDouble() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where doubleVal is not distinct from ?");
+
+        stmt.setDouble(1, 1.0d);
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, DOUBLE);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBigDecimal() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where bigVal is not distinct from ?");
+
+        stmt.setBigDecimal(1, new BigDecimal(1));
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, OTHER);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testString() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where strVal is not distinct from ?");
+
+        stmt.setString(1, "str");
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, VARCHAR);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testArray() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where arrVal is not distinct from ?");
+
+        stmt.setBytes(1, new byte[] {1});
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, BINARY);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDate() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where dateVal is not distinct from ?");
+
+        stmt.setObject(1, new Date(1));
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, DATE);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testTime() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where timeVal is not distinct from ?");
+
+        stmt.setTime(1, new Time(1));
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, TIME);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testTimestamp() throws Exception {
+        stmt = conn.prepareStatement(SQL_PART + " where tsVal is not distinct from ?");
+
+        stmt.setTimestamp(1, new Timestamp(1));
+
+        ResultSet rs = stmt.executeQuery();
+
+        int cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 1;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+
+        stmt.setNull(1, TIMESTAMP);
+
+        stmt.execute();
+
+        rs = stmt.getResultSet();
+
+        cnt = 0;
+
+        while (rs.next()) {
+            if (cnt == 0)
+                assert rs.getInt("id") == 2;
+
+            cnt++;
+        }
+
+        assert cnt == 1;
+    }
+
+    /**
+     * Test object.
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class TestObject implements Serializable {
+        /** */
+        @QuerySqlField(index = false)
+        private final int id;
+
+        /** */
+        @QuerySqlField
+        private Boolean boolVal;
+
+        /** */
+        @QuerySqlField
+        private Byte byteVal;
+
+        /** */
+        @QuerySqlField
+        private Short shortVal;
+
+        /** */
+        @QuerySqlField
+        private Integer intVal;
+
+        /** */
+        @QuerySqlField
+        private Long longVal;
+
+        /** */
+        @QuerySqlField
+        private Float floatVal;
+
+        /** */
+        @QuerySqlField
+        private Double doubleVal;
+
+        /** */
+        @QuerySqlField
+        private BigDecimal bigVal;
+
+        /** */
+        @QuerySqlField
+        private String strVal;
+
+        /** */
+        @QuerySqlField
+        private byte[] arrVal;
+
+        /** */
+        @QuerySqlField
+        private Date dateVal;
+
+        /** */
+        @QuerySqlField
+        private Time timeVal;
+
+        /** */
+        @QuerySqlField
+        private Timestamp tsVal;
+
+        /** */
+        @QuerySqlField
+        private URL urlVal;
+
+        /**
+         * @param id ID.
+         */
+        private TestObject(int id) {
+            this.id = id;
+        }
+    }
+}
\ No newline at end of file


Mime
View raw message