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 <[email protected]> Authored: Fri Jun 2 14:33:33 2017 +0300 Committer: devozerov <[email protected]> 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
