| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.ignite.jdbc.thin; |
| |
| import java.net.InetSocketAddress; |
| import java.sql.Connection; |
| import java.sql.DatabaseMetaData; |
| import java.sql.DriverManager; |
| import java.sql.PreparedStatement; |
| import java.sql.ResultSet; |
| import java.sql.SQLClientInfoException; |
| import java.sql.SQLException; |
| import java.sql.SQLFeatureNotSupportedException; |
| import java.sql.SQLWarning; |
| import java.sql.Savepoint; |
| import java.sql.Statement; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.UUID; |
| import java.util.concurrent.Callable; |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.atomic.AtomicInteger; |
| import org.apache.ignite.IgniteCheckedException; |
| import org.apache.ignite.configuration.CacheConfiguration; |
| import org.apache.ignite.configuration.IgniteConfiguration; |
| import org.apache.ignite.internal.IgniteInternalFuture; |
| import org.apache.ignite.internal.binary.BinaryContext; |
| import org.apache.ignite.internal.binary.BinaryMarshaller; |
| import org.apache.ignite.internal.binary.BinaryNoopMetadataHandler; |
| import org.apache.ignite.internal.jdbc.thin.ConnectionProperties; |
| import org.apache.ignite.internal.jdbc.thin.ConnectionPropertiesImpl; |
| import org.apache.ignite.internal.jdbc.thin.JdbcThinConnection; |
| import org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo; |
| import org.apache.ignite.internal.util.HostAndPortRange; |
| import org.apache.ignite.internal.util.lang.RunnableX; |
| import org.apache.ignite.internal.util.typedef.internal.U; |
| import org.apache.ignite.lang.IgnitePredicate; |
| import org.apache.ignite.logger.NullLogger; |
| import org.apache.ignite.marshaller.MarshallerContext; |
| import org.apache.ignite.marshaller.jdk.JdkMarshaller; |
| import org.apache.ignite.testframework.GridStringLogger; |
| import org.jetbrains.annotations.NotNull; |
| import org.junit.Test; |
| |
| import static java.sql.Connection.TRANSACTION_NONE; |
| import static java.sql.Connection.TRANSACTION_READ_COMMITTED; |
| import static java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; |
| import static java.sql.Connection.TRANSACTION_REPEATABLE_READ; |
| import static java.sql.Connection.TRANSACTION_SERIALIZABLE; |
| import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT; |
| import static java.sql.ResultSet.CONCUR_READ_ONLY; |
| import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; |
| import static java.sql.ResultSet.TYPE_FORWARD_ONLY; |
| import static java.sql.Statement.NO_GENERATED_KEYS; |
| import static java.sql.Statement.RETURN_GENERATED_KEYS; |
| import static org.apache.ignite.configuration.ClientConnectorConfiguration.DFLT_PORT; |
| import static org.apache.ignite.internal.processors.odbc.SqlStateCode.TRANSACTION_STATE_EXCEPTION; |
| import static org.apache.ignite.testframework.GridTestUtils.assertThrows; |
| import static org.apache.ignite.testframework.GridTestUtils.assertThrowsAnyCause; |
| import static org.apache.ignite.testframework.GridTestUtils.getFieldValue; |
| import static org.apache.ignite.testframework.GridTestUtils.runMultiThreadedAsync; |
| |
| /** |
| * Connection test. |
| */ |
| @SuppressWarnings("ThrowableNotThrown") |
| public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest { |
| /** Client key store path. */ |
| private static final String CLI_KEY_STORE_PATH = U.getIgniteHome() + |
| "/modules/clients/src/test/keystore/client.jks"; |
| |
| /** Server key store path. */ |
| private static final String SRV_KEY_STORE_PATH = U.getIgniteHome() + |
| "/modules/clients/src/test/keystore/server.jks"; |
| |
| /** Localhost. */ |
| private static final String LOCALHOST = "127.0.0.1"; |
| |
| /** URL. */ |
| private String url = partitionAwareness ? |
| "jdbc:ignite:thin://127.0.0.1:10800..10802" : |
| "jdbc:ignite:thin://127.0.0.1"; |
| |
| /** URL with partition awareness property. */ |
| private String urlWithPartitionAwarenessProp = url + "?partitionAwareness=" + partitionAwareness; |
| |
| /** URL with partition awareness property and semicolon as delimiter. */ |
| private String urlWithPartitionAwarenessPropSemicolon = url + ";partitionAwareness=" + partitionAwareness; |
| |
| /** Nodes count. */ |
| private int nodesCnt = partitionAwareness ? 4 : 2; |
| |
| /** {@inheritDoc} */ |
| @SuppressWarnings("deprecation") |
| @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { |
| IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); |
| |
| cfg.setCacheConfiguration(cacheConfiguration(DEFAULT_CACHE_NAME)); |
| |
| cfg.setMarshaller(new BinaryMarshaller()); |
| |
| cfg.setGridLogger(new GridStringLogger()); |
| |
| 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(nodesCnt); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @SuppressWarnings({"EmptyTryBlock", "unused"}) |
| @Test |
| public void testDefaults() throws Exception { |
| try (Connection conn = DriverManager.getConnection(url)) { |
| // No-op. |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "/")) { |
| // No-op. |
| } |
| } |
| |
| /** |
| * Test invalid endpoint. |
| */ |
| @Test |
| public void testInvalidEndpoint() { |
| assertInvalid("jdbc:ignite:thin://", "Address is empty"); |
| assertInvalid("jdbc:ignite:thin://:10000", "Host name is empty"); |
| assertInvalid("jdbc:ignite:thin:// :10000", "Host name is empty"); |
| |
| assertInvalid("jdbc:ignite:thin://127.0.0.1:-1", "port range contains invalid port -1"); |
| assertInvalid("jdbc:ignite:thin://127.0.0.1:0", "port range contains invalid port 0"); |
| assertInvalid("jdbc:ignite:thin://127.0.0.1:100000", |
| "port range contains invalid port 100000"); |
| } |
| |
| /** |
| * Test invalid socket buffer sizes. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testSocketBuffers() throws Exception { |
| final int dfltDufSize = 64 * 1024; |
| |
| assertInvalid(urlWithPartitionAwarenessProp + "&socketSendBuffer=-1", |
| "Property cannot be lower than 0 [name=socketSendBuffer, value=-1]"); |
| |
| assertInvalid(urlWithPartitionAwarenessProp + "&socketReceiveBuffer=-1", |
| "Property cannot be lower than 0 [name=socketReceiveBuffer, value=-1]"); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| for (JdbcThinTcpIo io: ios(conn)) { |
| assertEquals(dfltDufSize, io.connectionProperties().getSocketSendBuffer()); |
| assertEquals(dfltDufSize, io.connectionProperties().getSocketReceiveBuffer()); |
| } |
| } |
| |
| // Note that SO_* options are hints, so we check that value is equals to either what we set or to default. |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&socketSendBuffer=1024")) { |
| for (JdbcThinTcpIo io: ios(conn)) { |
| assertEquals(1024, io.connectionProperties().getSocketSendBuffer()); |
| assertEquals(dfltDufSize, io.connectionProperties().getSocketReceiveBuffer()); |
| } |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&socketReceiveBuffer=1024")) { |
| for (JdbcThinTcpIo io: ios(conn)) { |
| assertEquals(dfltDufSize, io.connectionProperties().getSocketSendBuffer()); |
| assertEquals(1024, io.connectionProperties().getSocketReceiveBuffer()); |
| } |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&" + |
| "socketSendBuffer=1024&socketReceiveBuffer=2048")) { |
| for (JdbcThinTcpIo io: ios(conn)) { |
| assertEquals(1024, io.connectionProperties().getSocketSendBuffer()); |
| assertEquals(2048, io.connectionProperties().getSocketReceiveBuffer()); |
| } |
| } |
| } |
| |
| /** |
| * Test invalid socket buffer sizes with semicolon. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testSocketBuffersSemicolon() throws Exception { |
| final int dfltDufSize = 64 * 1024; |
| |
| assertInvalid(urlWithPartitionAwarenessPropSemicolon + ";socketSendBuffer=-1", |
| "Property cannot be lower than 0 [name=socketSendBuffer, value=-1]"); |
| |
| assertInvalid(urlWithPartitionAwarenessPropSemicolon + ";socketReceiveBuffer=-1", |
| "Property cannot be lower than 0 [name=socketReceiveBuffer, value=-1]"); |
| |
| // Note that SO_* options are hints, so we check that value is equals to either what we set or to default. |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";socketSendBuffer=1024")) { |
| for (JdbcThinTcpIo io: ios(conn)) { |
| assertEquals(1024, io.connectionProperties().getSocketSendBuffer()); |
| assertEquals(dfltDufSize, io.connectionProperties().getSocketReceiveBuffer()); |
| } |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";socketReceiveBuffer=1024")) { |
| for (JdbcThinTcpIo io: ios(conn)) { |
| assertEquals(dfltDufSize, io.connectionProperties().getSocketSendBuffer()); |
| assertEquals(1024, io.connectionProperties().getSocketReceiveBuffer()); |
| } |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";" + |
| "socketSendBuffer=1024;socketReceiveBuffer=2048")) { |
| for (JdbcThinTcpIo io: ios(conn)) { |
| assertEquals(1024, io.connectionProperties().getSocketSendBuffer()); |
| assertEquals(2048, io.connectionProperties().getSocketReceiveBuffer()); |
| } |
| } |
| } |
| |
| /** |
| * Test update batch size property. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testUpdateBatchSize() throws Exception { |
| assertInvalid(urlWithPartitionAwarenessPropSemicolon + ";updateBatchSize=-1", |
| "Property cannot be lower than 1 [name=updateBatchSize, value=-1]"); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon)) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertNull(io.connectionProperties().getUpdateBatchSize()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon |
| + ";updateBatchSize=1024")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertEquals(1024, (int)io.connectionProperties().getUpdateBatchSize()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + |
| "&updateBatchSize=1024")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertEquals(1024, (int)io.connectionProperties().getUpdateBatchSize()); |
| } |
| } |
| |
| /** |
| * Test partition awareness Sql cache size property. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPartitionAwarenessSqlCacheSizeProperty() throws Exception { |
| assertInvalid(urlWithPartitionAwarenessProp + "&partitionAwarenessSQLCacheSize=0", |
| "Property cannot be lower than 1 [name=partitionAwarenessSQLCacheSize, value=0]"); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| for (JdbcThinTcpIo io : ios(conn)) |
| assertEquals(1_000, io.connectionProperties().getPartitionAwarenessSqlCacheSize()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + |
| "&partitionAwarenessSQLCacheSize=100")) { |
| for (JdbcThinTcpIo io : ios(conn)) |
| assertEquals(100, io.connectionProperties().getPartitionAwarenessSqlCacheSize()); |
| } |
| } |
| |
| /** |
| * Test partition awareness Sql cache size property with semicolon. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPartitionAwarenessSqlCacheSizePropertySemicolon() throws Exception { |
| assertInvalid(urlWithPartitionAwarenessPropSemicolon + ";partitionAwarenessSQLCacheSize=0", |
| "Property cannot be lower than 1 [name=partitionAwarenessSQLCacheSize, value=0]"); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon)) { |
| for (JdbcThinTcpIo io : ios(conn)) |
| assertEquals(1_000, io.connectionProperties().getPartitionAwarenessSqlCacheSize()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + |
| ";partitionAwarenessSQLCacheSize=100")) { |
| for (JdbcThinTcpIo io : ios(conn)) |
| assertEquals(100, io.connectionProperties().getPartitionAwarenessSqlCacheSize()); |
| } |
| } |
| |
| /** |
| * Test partition awareness partition distributions cache size property. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPartitionAwarenessPartitionDistributionsCacheSizeProperty() throws Exception { |
| assertInvalid(urlWithPartitionAwarenessProp + "&partitionAwarenessPartitionDistributionsCacheSize=0", |
| "Property cannot be lower than 1 [name=partitionAwarenessPartitionDistributionsCacheSize, value=0]"); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| for (JdbcThinTcpIo io : ios(conn)) { |
| assertEquals(1_000, |
| io.connectionProperties().getPartitionAwarenessPartitionDistributionsCacheSize()); |
| } |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + |
| "&partitionAwarenessPartitionDistributionsCacheSize=100")) { |
| for (JdbcThinTcpIo io : ios(conn)) |
| assertEquals(100, io.connectionProperties().getPartitionAwarenessPartitionDistributionsCacheSize()); |
| } |
| } |
| |
| /** |
| * Test partition awareness partition distributions cache size property with semicolon. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPartitionAwarenessPartitionDistributionsCacheSizePropertySemicolon() throws Exception { |
| assertInvalid(urlWithPartitionAwarenessPropSemicolon + ";partitionAwarenessPartitionDistributionsCacheSize=0", |
| "Property cannot be lower than 1 [name=partitionAwarenessPartitionDistributionsCacheSize, value=0]"); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon)) { |
| for (JdbcThinTcpIo io : ios(conn)) { |
| assertEquals(1_000, |
| io.connectionProperties().getPartitionAwarenessPartitionDistributionsCacheSize()); |
| } |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + |
| ";partitionAwarenessPartitionDistributionsCacheSize=100")) { |
| for (JdbcThinTcpIo io : ios(conn)) |
| assertEquals(100, io.connectionProperties().getPartitionAwarenessPartitionDistributionsCacheSize()); |
| } |
| } |
| |
| /** |
| * Test SQL hints. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testSqlHints() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| assertHints(conn, false, false, false, false, false, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&distributedJoins=true")) { |
| assertHints(conn, true, false, false, false, false, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&enforceJoinOrder=true")) { |
| assertHints(conn, false, true, false, false, false, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&collocated=true")) { |
| assertHints(conn, false, false, true, false, false, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&replicatedOnly=true")) { |
| assertHints(conn, false, false, false, true, false, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&lazy=true")) { |
| assertHints(conn, false, false, false, false, true, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&skipReducerOnUpdate=true")) { |
| assertHints(conn, false, false, false, false, false, |
| true, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&distributedJoins=true&" + |
| "enforceJoinOrder=true&collocated=true&replicatedOnly=true&lazy=true&skipReducerOnUpdate=true")) { |
| assertHints(conn, true, true, true, true, true, |
| true, partitionAwareness); |
| } |
| } |
| |
| /** |
| * Test SQL hints with semicolon. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testSqlHintsSemicolon() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";distributedJoins=true")) { |
| assertHints(conn, true, false, false, false, false, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";enforceJoinOrder=true")) { |
| assertHints(conn, false, true, false, false, false, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";collocated=true")) { |
| assertHints(conn, false, false, true, false, false, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";replicatedOnly=true")) { |
| assertHints(conn, false, false, false, true, false, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";lazy=true")) { |
| assertHints(conn, false, false, false, false, true, |
| false, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";skipReducerOnUpdate=true")) { |
| assertHints(conn, false, false, false, false, false, |
| true, partitionAwareness); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";distributedJoins=true;" + |
| "enforceJoinOrder=true;collocated=true;replicatedOnly=true;lazy=true;skipReducerOnUpdate=true")) { |
| assertHints(conn, true, true, true, true, true, |
| true, partitionAwareness); |
| } |
| } |
| |
| /** |
| * Assert hints. |
| * |
| * @param conn Connection. |
| * @param distributedJoins Distributed joins. |
| * @param enforceJoinOrder Enforce join order. |
| * @param collocated Co-located. |
| * @param replicatedOnly Replicated only. |
| * @param lazy Lazy. |
| * @param skipReducerOnUpdate Skip reducer on update. |
| * @throws Exception If failed. |
| */ |
| private void assertHints(Connection conn, boolean distributedJoins, boolean enforceJoinOrder, boolean collocated, |
| boolean replicatedOnly, boolean lazy, boolean skipReducerOnUpdate, boolean partitionAwarenessEnabled)throws Exception { |
| for (JdbcThinTcpIo io: ios(conn)) { |
| assertEquals(distributedJoins, io.connectionProperties().isDistributedJoins()); |
| assertEquals(enforceJoinOrder, io.connectionProperties().isEnforceJoinOrder()); |
| assertEquals(collocated, io.connectionProperties().isCollocated()); |
| assertEquals(replicatedOnly, io.connectionProperties().isReplicatedOnly()); |
| assertEquals(lazy, io.connectionProperties().isLazy()); |
| assertEquals(skipReducerOnUpdate, io.connectionProperties().isSkipReducerOnUpdate()); |
| assertEquals(partitionAwarenessEnabled, io.connectionProperties().isPartitionAwareness()); |
| } |
| } |
| |
| /** |
| * Test TCP no delay property handling. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testTcpNoDelay() throws Exception { |
| assertInvalid(urlWithPartitionAwarenessProp + "&tcpNoDelay=0", |
| "Invalid property value. [name=tcpNoDelay, val=0, choices=[true, false]]"); |
| |
| assertInvalid(urlWithPartitionAwarenessProp + "&tcpNoDelay=1", |
| "Invalid property value. [name=tcpNoDelay, val=1, choices=[true, false]]"); |
| |
| assertInvalid(urlWithPartitionAwarenessProp + "&tcpNoDelay=false1", |
| "Invalid property value. [name=tcpNoDelay, val=false1, choices=[true, false]]"); |
| |
| assertInvalid(urlWithPartitionAwarenessProp + "&tcpNoDelay=true1", |
| "Invalid property value. [name=tcpNoDelay, val=true1, choices=[true, false]]"); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertTrue(io.connectionProperties().isTcpNoDelay()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&tcpNoDelay=true")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertTrue(io.connectionProperties().isTcpNoDelay()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&tcpNoDelay=True")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertTrue(io.connectionProperties().isTcpNoDelay()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&tcpNoDelay=false")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertFalse(io.connectionProperties().isTcpNoDelay()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp + "&tcpNoDelay=False")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertFalse(io.connectionProperties().isTcpNoDelay()); |
| } |
| } |
| |
| /** |
| * Test TCP no delay property handling with semicolon. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testTcpNoDelaySemicolon() throws Exception { |
| assertInvalid(urlWithPartitionAwarenessPropSemicolon + ";tcpNoDelay=0", |
| "Invalid property value. [name=tcpNoDelay, val=0, choices=[true, false]]"); |
| |
| assertInvalid(urlWithPartitionAwarenessPropSemicolon + ";tcpNoDelay=1", |
| "Invalid property value. [name=tcpNoDelay, val=1, choices=[true, false]]"); |
| |
| assertInvalid(urlWithPartitionAwarenessPropSemicolon + ";tcpNoDelay=false1", |
| "Invalid property value. [name=tcpNoDelay, val=false1, choices=[true, false]]"); |
| |
| assertInvalid(urlWithPartitionAwarenessPropSemicolon + ";tcpNoDelay=true1", |
| "Invalid property value. [name=tcpNoDelay, val=true1, choices=[true, false]]"); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";tcpNoDelay=true")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertTrue(io.connectionProperties().isTcpNoDelay()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";tcpNoDelay=True")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertTrue(io.connectionProperties().isTcpNoDelay()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";tcpNoDelay=false")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertFalse(io.connectionProperties().isTcpNoDelay()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";tcpNoDelay=False")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertFalse(io.connectionProperties().isTcpNoDelay()); |
| } |
| } |
| |
| /** |
| * Test autoCloseServerCursor property handling. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testAutoCloseServerCursorProperty() throws Exception { |
| String url = urlWithPartitionAwarenessProp + "&autoCloseServerCursor"; |
| |
| String err = "Invalid property value. [name=autoCloseServerCursor"; |
| |
| assertInvalid(url + "=0", err); |
| assertInvalid(url + "=1", err); |
| assertInvalid(url + "=false1", err); |
| assertInvalid(url + "=true1", err); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertFalse(io.connectionProperties().isAutoCloseServerCursor()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "=true")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertTrue(io.connectionProperties().isAutoCloseServerCursor()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "=True")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertTrue(io.connectionProperties().isAutoCloseServerCursor()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "=false")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertFalse(io.connectionProperties().isAutoCloseServerCursor()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "=False")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertFalse(io.connectionProperties().isAutoCloseServerCursor()); |
| } |
| } |
| |
| /** |
| * Test autoCloseServerCursor property handling with semicolon. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testAutoCloseServerCursorPropertySemicolon() throws Exception { |
| String url = urlWithPartitionAwarenessPropSemicolon + ";autoCloseServerCursor"; |
| |
| String err = "Invalid property value. [name=autoCloseServerCursor"; |
| |
| assertInvalid(url + "=0", err); |
| assertInvalid(url + "=1", err); |
| assertInvalid(url + "=false1", err); |
| assertInvalid(url + "=true1", err); |
| |
| try (Connection conn = DriverManager.getConnection(url + "=true")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertTrue(io.connectionProperties().isAutoCloseServerCursor()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "=True")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertTrue(io.connectionProperties().isAutoCloseServerCursor()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "=false")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertFalse(io.connectionProperties().isAutoCloseServerCursor()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "=False")) { |
| for (JdbcThinTcpIo io: ios(conn)) |
| assertFalse(io.connectionProperties().isAutoCloseServerCursor()); |
| } |
| } |
| |
| /** |
| * Test schema property in URL. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testSchema() throws Exception { |
| assertInvalid(url + "/qwe/qwe", |
| "Invalid URL format (only schema name is allowed in URL path parameter 'host:port[/schemaName]')" ); |
| |
| try (Connection conn = DriverManager.getConnection(url + "/public")) { |
| assertEquals("Invalid schema", "PUBLIC", conn.getSchema()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "/\"" + DEFAULT_CACHE_NAME + '"')) { |
| assertEquals("Invalid schema", DEFAULT_CACHE_NAME, conn.getSchema()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(url + "/_not_exist_schema_")) { |
| assertEquals("Invalid schema", "_NOT_EXIST_SCHEMA_", conn.getSchema()); |
| } |
| } |
| |
| /** |
| * Test schema property in URL with semicolon. |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testSchemaSemicolon() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";schema=public")) { |
| assertEquals("Invalid schema", "PUBLIC", conn.getSchema()); |
| } |
| |
| try (Connection conn = |
| DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";schema=\"" + DEFAULT_CACHE_NAME + '"')) { |
| assertEquals("Invalid schema", DEFAULT_CACHE_NAME, conn.getSchema()); |
| } |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessPropSemicolon + ";schema=_not_exist_schema_")) { |
| assertEquals("Invalid schema", "_NOT_EXIST_SCHEMA_", conn.getSchema()); |
| } |
| } |
| |
| /** |
| * Get client endpoints for connection. |
| * |
| * @param conn Connection. |
| * @return Collection of endpoints. |
| * @throws Exception If failed. |
| */ |
| private static Collection<JdbcThinTcpIo> ios(Connection conn) throws Exception { |
| JdbcThinConnection conn0 = conn.unwrap(JdbcThinConnection.class); |
| |
| Collection<JdbcThinTcpIo> ios = partitionAwareness ? ((Map<UUID, JdbcThinTcpIo>) |
| getFieldValue(conn0, JdbcThinConnection.class, "ios")).values() : |
| Collections.singleton(getFieldValue(conn0, JdbcThinConnection.class, "singleIo")); |
| |
| assert !ios.isEmpty(); |
| |
| return ios; |
| } |
| |
| /** |
| * Assert that provided URL is invalid. |
| * |
| * @param url URL. |
| * @param errMsg Error message. |
| */ |
| @SuppressWarnings("ThrowableNotThrown") |
| private void assertInvalid(final String url, String errMsg) { |
| assertThrowsAnyCause(log, new Callable<Void>() { |
| @Override public Void call() throws Exception { |
| DriverManager.getConnection(url); |
| |
| return null; |
| } |
| }, SQLException.class, errMsg); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @SuppressWarnings("ThrowableNotThrown") |
| @Test |
| public void testClose() throws Exception { |
| final Connection conn; |
| |
| try (Connection conn0 = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| conn = conn0; |
| |
| assert conn != null; |
| assert !conn.isClosed(); |
| } |
| |
| assert conn.isClosed(); |
| |
| assert !conn.isValid(2) : "Connection must be closed"; |
| |
| assertThrows(log, new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.isValid(-2); |
| |
| return null; |
| } |
| }, SQLException.class, "Invalid timeout"); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCreateStatement() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| try (Statement stmt = conn.createStatement()) { |
| assertNotNull(stmt); |
| |
| stmt.close(); |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.createStatement(); |
| } |
| }); |
| } |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCreateStatement2() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| int[] rsTypes = new int[] |
| {TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE}; |
| |
| int[] rsConcurs = new int[] |
| {CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE}; |
| |
| DatabaseMetaData meta = conn.getMetaData(); |
| |
| for (final int type : rsTypes) { |
| for (final int concur : rsConcurs) { |
| if (meta.supportsResultSetConcurrency(type, concur)) { |
| assert type == TYPE_FORWARD_ONLY; |
| assert concur == CONCUR_READ_ONLY; |
| |
| try (Statement stmt = conn.createStatement(type, concur)) { |
| assertNotNull(stmt); |
| |
| assertEquals(type, stmt.getResultSetType()); |
| assertEquals(concur, stmt.getResultSetConcurrency()); |
| } |
| |
| continue; |
| } |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createStatement(type, concur); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| null |
| ); |
| } |
| } |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.createStatement(TYPE_FORWARD_ONLY, |
| CONCUR_READ_ONLY); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCreateStatement3() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| int[] rsTypes = new int[] |
| {TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE}; |
| |
| int[] rsConcurs = new int[] |
| {CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE}; |
| |
| int[] rsHoldabilities = new int[] |
| {HOLD_CURSORS_OVER_COMMIT, CLOSE_CURSORS_AT_COMMIT}; |
| |
| DatabaseMetaData meta = conn.getMetaData(); |
| |
| for (final int type : rsTypes) { |
| for (final int concur : rsConcurs) { |
| for (final int holdabililty : rsHoldabilities) { |
| if (meta.supportsResultSetConcurrency(type, concur)) { |
| assert type == TYPE_FORWARD_ONLY; |
| assert concur == CONCUR_READ_ONLY; |
| |
| try (Statement stmt = conn.createStatement(type, concur, holdabililty)) { |
| assertNotNull(stmt); |
| |
| assertEquals(type, stmt.getResultSetType()); |
| assertEquals(concur, stmt.getResultSetConcurrency()); |
| assertEquals(holdabililty, stmt.getResultSetHoldability()); |
| } |
| |
| continue; |
| } |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createStatement(type, concur, holdabililty); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| null |
| ); |
| } |
| } |
| } |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.createStatement(TYPE_FORWARD_ONLY, |
| CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPrepareStatement() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // null query text |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareStatement(null); |
| } |
| }, |
| SQLException.class, |
| "SQL string cannot be null" |
| ); |
| |
| final String sqlText = "select * from test where param = ?"; |
| |
| try (PreparedStatement prepared = conn.prepareStatement(sqlText)) { |
| assertNotNull(prepared); |
| } |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.prepareStatement(sqlText); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPrepareStatement3() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| final String sqlText = "select * from test where param = ?"; |
| |
| int[] rsTypes = new int[] |
| {TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE}; |
| |
| int[] rsConcurs = new int[] |
| {CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE}; |
| |
| DatabaseMetaData meta = conn.getMetaData(); |
| |
| for (final int type : rsTypes) { |
| for (final int concur : rsConcurs) { |
| if (meta.supportsResultSetConcurrency(type, concur)) { |
| assert type == TYPE_FORWARD_ONLY; |
| assert concur == CONCUR_READ_ONLY; |
| |
| // null query text |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareStatement(null, type, concur); |
| } |
| }, |
| SQLException.class, |
| "SQL string cannot be null" |
| ); |
| |
| continue; |
| } |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareStatement(sqlText, type, concur); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| null |
| ); |
| } |
| } |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.prepareStatement(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY); |
| } |
| }); |
| |
| conn.close(); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPrepareStatement4() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| final String sqlText = "select * from test where param = ?"; |
| |
| int[] rsTypes = new int[] |
| {TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE}; |
| |
| int[] rsConcurs = new int[] |
| {CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE}; |
| |
| int[] rsHoldabilities = new int[] |
| {HOLD_CURSORS_OVER_COMMIT, CLOSE_CURSORS_AT_COMMIT}; |
| |
| DatabaseMetaData meta = conn.getMetaData(); |
| |
| for (final int type : rsTypes) { |
| for (final int concur : rsConcurs) { |
| for (final int holdabililty : rsHoldabilities) { |
| if (meta.supportsResultSetConcurrency(type, concur)) { |
| assert type == TYPE_FORWARD_ONLY; |
| assert concur == CONCUR_READ_ONLY; |
| |
| // null query text |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareStatement(null, type, concur, holdabililty); |
| } |
| }, |
| SQLException.class, |
| "SQL string cannot be null" |
| ); |
| |
| continue; |
| } |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareStatement(sqlText, type, concur, holdabililty); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| null |
| ); |
| } |
| } |
| } |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.prepareStatement(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT); |
| } |
| }); |
| |
| conn.close(); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPrepareStatementAutoGeneratedKeysUnsupported() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| final String sqlText = "insert into test (val) values (?)"; |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareStatement(sqlText, RETURN_GENERATED_KEYS); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "Auto generated keys are not supported." |
| ); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareStatement(sqlText, NO_GENERATED_KEYS); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "Auto generated keys are not supported." |
| ); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareStatement(sqlText, new int[] {1}); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "Auto generated keys are not supported." |
| ); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareStatement(sqlText, new String[] {"ID"}); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "Auto generated keys are not supported." |
| ); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPrepareCallUnsupported() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| final String sqlText = "exec test()"; |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareCall(sqlText); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "Callable functions are not supported." |
| ); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareCall(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "Callable functions are not supported." |
| ); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.prepareCall(sqlText, TYPE_FORWARD_ONLY, |
| CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "Callable functions are not supported." |
| ); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testNativeSql() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // null query text |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.nativeSQL(null); |
| } |
| }, |
| SQLException.class, |
| "SQL string cannot be null" |
| ); |
| |
| final String sqlText = "select * from test"; |
| |
| assertEquals(sqlText, conn.nativeSQL(sqlText)); |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.nativeSQL(sqlText); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetAutoCommit() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| boolean ac0 = conn.getAutoCommit(); |
| |
| conn.setAutoCommit(!ac0); |
| // assert no exception |
| |
| conn.setAutoCommit(ac0); |
| // assert no exception |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.setAutoCommit(ac0); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCommit() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // Should not be called in auto-commit mode |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.commit(); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Transaction cannot be committed explicitly in auto-commit mode" |
| ); |
| |
| assertTrue(conn.getAutoCommit()); |
| |
| // Should not be called in auto-commit mode |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.commit(); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Transaction cannot be committed explicitly in auto-commit mode." |
| ); |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.commit(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testRollback() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // Should not be called in auto-commit mode |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.rollback(); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Transaction cannot be rolled back explicitly in auto-commit mode." |
| ); |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.rollback(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception if failed. |
| */ |
| @Test |
| public void testBeginFailsWhenMvccIsDisabled() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| conn.createStatement().execute("BEGIN"); |
| |
| fail("Exception is expected"); |
| } |
| catch (SQLException e) { |
| assertEquals(TRANSACTION_STATE_EXCEPTION, e.getSQLState()); |
| } |
| } |
| |
| /** |
| * @throws Exception if failed. |
| */ |
| @Test |
| public void testCommitIgnoredWhenMvccIsDisabled() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| conn.setAutoCommit(false); |
| conn.createStatement().execute("COMMIT"); |
| |
| conn.commit(); |
| } |
| // assert no exception |
| } |
| |
| /** |
| * @throws Exception if failed. |
| */ |
| @Test |
| public void testRollbackIgnoredWhenMvccIsDisabled() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| conn.setAutoCommit(false); |
| |
| conn.createStatement().execute("ROLLBACK"); |
| |
| conn.rollback(); |
| } |
| // assert no exception |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetMetaData() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| DatabaseMetaData meta = conn.getMetaData(); |
| |
| assertNotNull(meta); |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.getMetaData(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetReadOnly() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.setReadOnly(true); |
| } |
| }); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.isReadOnly(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetCatalog() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| assert !conn.getMetaData().supportsCatalogsInDataManipulation(); |
| |
| assertNull(conn.getCatalog()); |
| |
| conn.setCatalog("catalog"); |
| |
| assertEquals(null, conn.getCatalog()); |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.setCatalog(""); |
| } |
| }); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.getCatalog(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetTransactionIsolation() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // Invalid parameter value |
| assertThrows(log, |
| new Callable<Object>() { |
| @SuppressWarnings("MagicConstant") |
| @Override public Object call() throws Exception { |
| conn.setTransactionIsolation(-1); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Invalid transaction isolation level" |
| ); |
| |
| // default level |
| assertEquals(TRANSACTION_NONE, conn.getTransactionIsolation()); |
| |
| int[] levels = { |
| TRANSACTION_READ_UNCOMMITTED, TRANSACTION_READ_COMMITTED, |
| TRANSACTION_REPEATABLE_READ, TRANSACTION_SERIALIZABLE}; |
| |
| for (int level : levels) { |
| conn.setTransactionIsolation(level); |
| assertEquals(level, conn.getTransactionIsolation()); |
| } |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.getTransactionIsolation(); |
| } |
| }); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.setTransactionIsolation(TRANSACTION_SERIALIZABLE); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testClearGetWarnings() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| SQLWarning warn = conn.getWarnings(); |
| |
| assertNull(warn); |
| |
| conn.clearWarnings(); |
| |
| warn = conn.getWarnings(); |
| |
| assertNull(warn); |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.getWarnings(); |
| } |
| }); |
| |
| // Exception when called on closed connection |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.clearWarnings(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetTypeMap() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.getTypeMap(); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "Types mapping is not supported" |
| ); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setTypeMap(new HashMap<String, Class<?>>()); |
| |
| return null; |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "Types mapping is not supported" |
| ); |
| |
| conn.close(); |
| |
| // Exception when called on closed connection |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.getTypeMap(); |
| } |
| }, |
| SQLException.class, |
| "Connection is closed" |
| ); |
| |
| // Exception when called on closed connection |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setTypeMap(new HashMap<String, Class<?>>()); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Connection is closed" |
| ); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetHoldability() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // default value |
| assertEquals(conn.getMetaData().getResultSetHoldability(), conn.getHoldability()); |
| |
| assertEquals(HOLD_CURSORS_OVER_COMMIT, conn.getHoldability()); |
| |
| conn.setHoldability(CLOSE_CURSORS_AT_COMMIT); |
| |
| assertEquals(CLOSE_CURSORS_AT_COMMIT, conn.getHoldability()); |
| |
| // Invalid constant |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setHoldability(-1); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Invalid result set holdability value" |
| ); |
| |
| conn.close(); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.getHoldability(); |
| } |
| }, |
| SQLException.class, |
| "Connection is closed" |
| ); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setHoldability(HOLD_CURSORS_OVER_COMMIT); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Connection is closed" |
| ); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testSetSavepoint() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| assert !conn.getMetaData().supportsSavepoints(); |
| |
| // Disallowed in auto-commit mode |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setSavepoint(); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Savepoint cannot be set in auto-commit mode" |
| ); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.setSavepoint(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testSetSavepointName() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| assert !conn.getMetaData().supportsSavepoints(); |
| |
| // Invalid arg |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setSavepoint(null); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Savepoint name cannot be null" |
| ); |
| |
| final String name = "savepoint"; |
| |
| // Disallowed in auto-commit mode |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setSavepoint(name); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Savepoint cannot be set in auto-commit mode" |
| ); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.setSavepoint(name); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testRollbackSavePoint() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| assert !conn.getMetaData().supportsSavepoints(); |
| |
| // Invalid arg |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.rollback(null); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Invalid savepoint" |
| ); |
| |
| final Savepoint savepoint = getFakeSavepoint(); |
| |
| // Disallowed in auto-commit mode |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.rollback(savepoint); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Auto-commit mode" |
| ); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.rollback(savepoint); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDisabledFeatures() throws Exception { |
| assertInvalid(url + "?disabledFeatures=unknownFeature", |
| "Unknown feature: unknownFeature"); |
| |
| try (Connection conn = DriverManager.getConnection(url + "?disabledFeatures=reserved")) { |
| // No-op. |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testReleaseSavepoint() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| assert !conn.getMetaData().supportsSavepoints(); |
| |
| // Invalid arg |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.releaseSavepoint(null); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Savepoint cannot be null" |
| ); |
| |
| final Savepoint savepoint = getFakeSavepoint(); |
| |
| checkNotSupported(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.releaseSavepoint(savepoint); |
| } |
| }); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.releaseSavepoint(savepoint); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCreateClob() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // Unsupported |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createClob(); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "SQL-specific types are not supported" |
| ); |
| |
| conn.close(); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createClob(); |
| } |
| }, |
| SQLException.class, |
| "Connection is closed" |
| ); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCreateBlob() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // Unsupported |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createBlob(); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "SQL-specific types are not supported" |
| ); |
| |
| conn.close(); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createBlob(); |
| } |
| }, |
| SQLException.class, |
| "Connection is closed" |
| ); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCreateNClob() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // Unsupported |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createNClob(); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "SQL-specific types are not supported" |
| ); |
| |
| conn.close(); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createNClob(); |
| } |
| }, |
| SQLException.class, |
| "Connection is closed" |
| ); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCreateSQLXML() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // Unsupported |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createSQLXML(); |
| } |
| }, |
| SQLFeatureNotSupportedException.class, |
| "SQL-specific types are not supported" |
| ); |
| |
| conn.close(); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createSQLXML(); |
| } |
| }, |
| SQLException.class, |
| "Connection is closed" |
| ); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetClientInfoPair() throws Exception { |
| // fail("https://issues.apache.org/jira/browse/IGNITE-5425"); |
| |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| final String name = "ApplicationName"; |
| final String val = "SelfTest"; |
| |
| assertNull(conn.getWarnings()); |
| |
| conn.setClientInfo(name, val); |
| |
| assertNull(conn.getClientInfo(val)); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.getClientInfo(name); |
| } |
| }); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setClientInfo(name, val); |
| |
| return null; |
| } |
| }, SQLClientInfoException.class, "Connection is closed"); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetClientInfoProperties() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| final String name = "ApplicationName"; |
| final String val = "SelfTest"; |
| |
| final Properties props = new Properties(); |
| props.setProperty(name, val); |
| |
| conn.setClientInfo(props); |
| |
| Properties propsResult = conn.getClientInfo(); |
| |
| assertNotNull(propsResult); |
| |
| assertTrue(propsResult.isEmpty()); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.getClientInfo(); |
| } |
| }); |
| |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setClientInfo(props); |
| |
| return null; |
| } |
| }, SQLClientInfoException.class, "Connection is closed"); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCreateArrayOf() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| final String typeName = "varchar"; |
| |
| final String[] elements = new String[] {"apple", "pear"}; |
| |
| // Invalid typename |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.createArrayOf(null, null); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Type name cannot be null" |
| ); |
| |
| // Unsupported |
| |
| checkNotSupported(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.createArrayOf(typeName, elements); |
| } |
| }); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.createArrayOf(typeName, elements); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCreateStruct() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // Invalid typename |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return conn.createStruct(null, null); |
| } |
| }, |
| SQLException.class, |
| "Type name cannot be null" |
| ); |
| |
| final String typeName = "employee"; |
| |
| final Object[] attrs = new Object[] {100, "Tom"}; |
| |
| checkNotSupported(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.createStruct(typeName, attrs); |
| } |
| }); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.createStruct(typeName, attrs); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetSchema() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| assertEquals("PUBLIC", conn.getSchema()); |
| |
| final String schema = "test"; |
| |
| conn.setSchema(schema); |
| |
| assertEquals(schema.toUpperCase(), conn.getSchema()); |
| |
| conn.setSchema('"' + schema + '"'); |
| |
| assertEquals(schema, conn.getSchema()); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.setSchema(schema); |
| } |
| }); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.getSchema(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testAbort() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| //Invalid executor |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.abort(null); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Executor cannot be null" |
| ); |
| |
| final Executor executor = Executors.newFixedThreadPool(1); |
| |
| conn.abort(executor); |
| |
| assertTrue(conn.isClosed()); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testGetSetNetworkTimeout() throws Exception { |
| try (Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| // default |
| assertEquals(0, conn.getNetworkTimeout()); |
| |
| final Executor executor = Executors.newFixedThreadPool(1); |
| |
| final int timeout = 1000; |
| |
| //Invalid timeout |
| assertThrows(log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| conn.setNetworkTimeout(executor, -1); |
| |
| return null; |
| } |
| }, |
| SQLException.class, |
| "Network timeout cannot be negative" |
| ); |
| |
| conn.setNetworkTimeout(executor, timeout); |
| |
| assertEquals(timeout, conn.getNetworkTimeout()); |
| |
| conn.close(); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.getNetworkTimeout(); |
| } |
| }); |
| |
| checkConnectionClosed(new RunnableX() { |
| @Override public void runx() throws Exception { |
| conn.setNetworkTimeout(executor, timeout); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * Test that attempting to supply invalid nested TX mode to driver fails on the client. |
| */ |
| @Test |
| public void testInvalidNestedTxMode() { |
| assertThrows(null, new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| DriverManager.getConnection(urlWithPartitionAwarenessProp + "&nestedTransactionsMode=invalid"); |
| |
| return null; |
| } |
| }, SQLException.class, "Invalid nested transactions handling mode"); |
| } |
| |
| /** |
| * Test that attempting to send unexpected name of nested TX mode to server on handshake yields an error. |
| * We have to do this without explicit {@link Connection} as long as there's no other way to bypass validation and |
| * supply a malformed {@link ConnectionProperties} to {@link JdbcThinTcpIo}. |
| */ |
| @Test |
| public void testInvalidNestedTxModeOnServerSide() { |
| ConnectionPropertiesImpl connProps = new ConnectionPropertiesImpl(); |
| |
| connProps.setAddresses(new HostAndPortRange[] {new HostAndPortRange(LOCALHOST, DFLT_PORT, DFLT_PORT)}); |
| |
| connProps.nestedTxMode("invalid"); |
| |
| connProps.setPartitionAwareness(partitionAwareness); |
| |
| assertThrows(null, new Callable<Object>() { |
| @SuppressWarnings("ResultOfObjectAllocationIgnored") |
| @Override public Object call() throws Exception { |
| new JdbcThinTcpIo(connProps, new InetSocketAddress(LOCALHOST, DFLT_PORT), getBinaryContext(), 0); |
| |
| return null; |
| } |
| }, SQLException.class, "err=Invalid nested transactions handling mode: invalid"); |
| } |
| |
| /** |
| */ |
| @Test |
| public void testSslClientAndPlainServer() { |
| Throwable e = assertThrows(log, new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| DriverManager.getConnection(urlWithPartitionAwarenessProp + "&sslMode=require" + |
| "&sslClientCertificateKeyStoreUrl=" + CLI_KEY_STORE_PATH + |
| "&sslClientCertificateKeyStorePassword=123456" + |
| "&sslTrustCertificateKeyStoreUrl=" + SRV_KEY_STORE_PATH + |
| "&sslTrustCertificateKeyStorePassword=123456"); |
| |
| return null; |
| } |
| }, SQLException.class, partitionAwareness ? "Failed to connect to server" : "Failed to SSL connect to server"); |
| |
| if (partitionAwareness) { |
| for (Throwable t: e.getSuppressed()) { |
| assertEquals(SQLException.class, t.getClass()); |
| assertTrue(t.getMessage().contains("Failed to SSL connect to server")); |
| } |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testMultithreadingException() throws Exception { |
| int threadCnt = 10; |
| |
| final boolean end[] = new boolean[] {false}; |
| |
| final SQLException exs[] = new SQLException[threadCnt]; |
| |
| final AtomicInteger exCnt = new AtomicInteger(0); |
| |
| try (final Connection conn = DriverManager.getConnection(urlWithPartitionAwarenessProp)) { |
| final IgniteInternalFuture f = runMultiThreadedAsync(new Runnable() { |
| @Override public void run() { |
| try { |
| conn.createStatement(); |
| |
| while (!end[0]) |
| conn.createStatement().execute("SELECT 1"); |
| |
| conn.createStatement().execute("SELECT 1"); |
| } |
| catch (SQLException e) { |
| end[0] = true; |
| exs[exCnt.getAndIncrement()] = e; |
| } |
| catch (Exception e) { |
| e.printStackTrace(System.err); |
| |
| fail("Unexpected exception (see details above): " + e.getMessage()); |
| } |
| } |
| }, threadCnt, "run-query"); |
| |
| f.get(); |
| |
| boolean exceptionFound = false; |
| |
| for (SQLException e : exs) { |
| if (e != null && e.getMessage().contains("Concurrent access to JDBC connection is not allowed")) |
| exceptionFound = true; |
| } |
| |
| assertTrue("Concurrent access to JDBC connection is not allowed", exceptionFound); |
| } |
| } |
| |
| /** |
| * @return Savepoint. |
| */ |
| private Savepoint getFakeSavepoint() { |
| return new Savepoint() { |
| @Override public int getSavepointId() throws SQLException { |
| return 100; |
| } |
| |
| @Override public String getSavepointName() { |
| return "savepoint"; |
| } |
| }; |
| } |
| |
| /** |
| * Returns stub for marshaller context. |
| * |
| * @return Marshaller context. |
| */ |
| private MarshallerContext getFakeMarshallerCtx() { |
| return new MarshallerContext() { |
| @Override public boolean registerClassName(byte platformId, int typeId, |
| String clsName) throws IgniteCheckedException { |
| return false; |
| } |
| |
| @Override public boolean registerClassNameLocally(byte platformId, int typeId, |
| String clsName) throws IgniteCheckedException { |
| return false; |
| } |
| |
| @Override public Class getClass(int typeId, ClassLoader ldr) throws ClassNotFoundException, IgniteCheckedException { |
| return null; |
| } |
| |
| @Override public String getClassName(byte platformId, |
| int typeId) throws ClassNotFoundException, IgniteCheckedException { |
| return null; |
| } |
| |
| @Override public boolean isSystemType(String typeName) { |
| return false; |
| } |
| |
| @Override public IgnitePredicate<String> classNameFilter() { |
| return null; |
| } |
| |
| @Override public JdkMarshaller jdkMarshaller() { |
| return null; |
| } |
| }; |
| } |
| |
| /** |
| * Returns new binary context. |
| * |
| * @return New binary context. |
| */ |
| private BinaryContext getBinaryContext() { |
| BinaryMarshaller marsh = new BinaryMarshaller(); |
| |
| marsh.setContext(getFakeMarshallerCtx()); |
| |
| BinaryContext ctx = new BinaryContext(BinaryNoopMetadataHandler.instance(), |
| new IgniteConfiguration(), new NullLogger()); |
| |
| ctx.configure(marsh); |
| ctx.registerUserTypesSchema(); |
| |
| return ctx; |
| } |
| } |