You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2019/12/20 09:15:54 UTC

[ignite] branch master updated: IGNITE-12462: JDBC thin: Add JDBC URL properties support for query timeout and for connection timeout. This closes #7156.

This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 9f19e01  IGNITE-12462: JDBC thin: Add JDBC URL properties support for query timeout and for connection timeout. This closes #7156.
9f19e01 is described below

commit 9f19e0160b1ca43a27908849ad46c65ebd8689f1
Author: amashenkov <an...@gmail.com>
AuthorDate: Wed Jul 31 20:00:40 2019 +0300

    IGNITE-12462: JDBC thin: Add JDBC URL properties support for query timeout and for connection timeout. This closes #7156.
    
    Signed-off-by: Andrey V. Mashenkov <an...@gmail.com>
---
 .../thin/JdbcThinConnectionTimeoutSelfTest.java    | 96 +++++++++++++++++++---
 .../thin/JdbcThinStatementTimeoutSelfTest.java     | 62 +++++++++++++-
 .../internal/jdbc/thin/ConnectionProperties.java   | 28 +++++++
 .../jdbc/thin/ConnectionPropertiesImpl.java        | 38 ++++++++-
 .../internal/jdbc/thin/JdbcThinConnection.java     |  7 ++
 5 files changed, 215 insertions(+), 16 deletions(-)

diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionTimeoutSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionTimeoutSelfTest.java
index 0d77b73..c739afa 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionTimeoutSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionTimeoutSelfTest.java
@@ -144,7 +144,6 @@ public class JdbcThinConnectionTimeoutSelfTest extends JdbcThinAbstractSelfTest
      */
     @Test
     public void testSettingNegativeConnectionTimeout() {
-
         GridTestUtils.assertThrows(log,
             () -> {
                 conn.setNetworkTimeout(EXECUTOR_STUB, -1);
@@ -154,12 +153,31 @@ public class JdbcThinConnectionTimeoutSelfTest extends JdbcThinAbstractSelfTest
     }
 
     /**
+     *
+     */
+    @Test
+    public void testNegativeConnectionTimeout() {
+        GridTestUtils.assertThrows(log,
+            () -> {
+                try(final Connection conn = DriverManager.getConnection(URL+"?connectionTimeout=-1")) {
+                    return null;
+                }
+            },
+            SQLException.class, "Property cannot be lower than 0 [name=connectionTimeout, value=-1]");
+    }
+
+    /**
      * @throws Exception If failed.
      */
     @Test
     public void testConnectionTimeoutRetrieval() throws Exception {
-        conn.setNetworkTimeout(EXECUTOR_STUB, 2000);
-        assertEquals(2000, conn.getNetworkTimeout());
+        try (final Connection conn = DriverManager.getConnection(URL + "?connectionTimeout=1000")) {
+            assertEquals(1000, conn.getNetworkTimeout());
+
+            conn.setNetworkTimeout(EXECUTOR_STUB, 2000);
+
+            assertEquals(2000, conn.getNetworkTimeout());
+        }
     }
 
     /**
@@ -167,7 +185,6 @@ public class JdbcThinConnectionTimeoutSelfTest extends JdbcThinAbstractSelfTest
      */
     @Test
     public void testConnectionTimeout() throws Exception {
-
         conn.setNetworkTimeout(EXECUTOR_STUB, 1000);
 
         GridTestUtils.assertThrows(log,
@@ -189,13 +206,41 @@ public class JdbcThinConnectionTimeoutSelfTest extends JdbcThinAbstractSelfTest
      * @throws Exception If failed.
      */
     @Test
+    public void testUrlConnectionTimeoutProperty() throws Exception {
+        try (final Connection conn = DriverManager.getConnection(URL + "?connectionTimeout=1000")) {
+            conn.setSchema('"' + DEFAULT_CACHE_NAME + '"');
+
+            try (final Statement stmt = conn.createStatement()) {
+                GridTestUtils.assertThrows(log,
+                    () -> {
+                        stmt.execute("select sleep_func(2000)");
+
+                        return null;
+                    },
+                    SQLException.class, "Connection timed out.");
+
+                GridTestUtils.assertThrows(log,
+                    () -> {
+                        stmt.execute("select 1");
+
+                        return null;
+                    },
+                    SQLException.class, "Statement is closed.");
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
     public void testQueryTimeoutOccursBeforeConnectionTimeout() throws Exception {
         conn.setNetworkTimeout(EXECUTOR_STUB, 10_000);
 
         stmt.setQueryTimeout(1);
 
         GridTestUtils.assertThrows(log, () -> {
-            stmt.executeQuery("select sleep_func(10) from Integer;");
+            stmt.executeQuery("select sleep_func(3) from Integer;");
 
             return null;
         }, SQLTimeoutException.class, "The query was cancelled while executing.");
@@ -207,17 +252,43 @@ public class JdbcThinConnectionTimeoutSelfTest extends JdbcThinAbstractSelfTest
      * @throws Exception If failed.
      */
     @Test
-    public void testConnectionTimeoutUpdate() throws Exception {
-        conn.setNetworkTimeout(EXECUTOR_STUB, 5000);
+    public void testUrlQueryTimeoutProperty() throws Exception {
+        try (final Connection conn = DriverManager.getConnection(URL + "?connectionTimeout=10000&queryTimeout=1")) {
+            conn.setSchema('"' + DEFAULT_CACHE_NAME + '"');
 
-        stmt.execute("select sleep_func(1000)");
+            final Statement stmt = conn.createStatement();
 
-        conn.setNetworkTimeout(EXECUTOR_STUB, 500);
+            GridTestUtils.assertThrows(log, () -> {
+                stmt.executeQuery("select sleep_func(3) from Integer;");
+
+                return null;
+            }, SQLTimeoutException.class, "The query was cancelled while executing.");
+
+            stmt.execute("select 1");
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionTimeoutUpdate() throws Exception {
+        try (final Connection conn = DriverManager.getConnection(URL +
+            "?connectionTimeout=5000")) {
+            conn.setSchema('"' + DEFAULT_CACHE_NAME + '"');
+
+            final Statement stmt = conn.createStatement();
 
-        GridTestUtils.assertThrows(log, () -> {
             stmt.execute("select sleep_func(1000)");
-            return null;
-        }, SQLException.class, "Connection timed out.");
+
+            conn.setNetworkTimeout(EXECUTOR_STUB, 500);
+
+            GridTestUtils.assertThrows(log, () -> {
+                stmt.execute("select sleep_func(1000)");
+
+                return null;
+            }, SQLException.class, "Connection timed out.");
+        }
     }
 
     /**
@@ -235,6 +306,7 @@ public class JdbcThinConnectionTimeoutSelfTest extends JdbcThinAbstractSelfTest
                     GridTestUtils.assertThrows(log,
                         () -> {
                             stmt.cancel();
+
                             return null;
                         },
                         SQLException.class, "Statement is closed.");
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementTimeoutSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementTimeoutSelfTest.java
index 9d6b742..a7c26cf 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementTimeoutSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementTimeoutSelfTest.java
@@ -147,6 +147,21 @@ public class JdbcThinStatementTimeoutSelfTest extends JdbcThinAbstractSelfTest {
     }
 
     /**
+     * Trying to set negative timeout. <code>SQLException</> with message "Invalid timeout value." is expected.
+     * @throws SQLException If failed.
+     */
+    @Test
+    public void testNegativeQueryTimeout() throws SQLException {
+        GridTestUtils.assertThrows(log, () -> {
+            try (final Connection conn = DriverManager.getConnection(URL + "?queryTimeout=-1")) {
+                try (final Statement stmt = conn.createStatement()) {
+                    return null;
+                }
+            }
+        }, SQLException.class, "Property cannot be lower than 0 [name=queryTimeout, value=-1]");
+    }
+
+    /**
      * Trying to set zero timeout. Zero timeout means no timeout, so no exception is expected.
      *
      * @throws Exception If failed.
@@ -159,6 +174,22 @@ public class JdbcThinStatementTimeoutSelfTest extends JdbcThinAbstractSelfTest {
     }
 
     /**
+     * Trying to set zero timeout. Zero timeout means no timeout, so no exception is expected.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testZeroQueryTimeout() throws Exception {
+        try(final Connection conn = DriverManager.getConnection(URL+"?queryTimeout=0")) {
+            conn.setSchema('"' + DEFAULT_CACHE_NAME + '"');
+
+            try (final Statement stmt = conn.createStatement()) {
+                stmt.executeQuery("select sleep_func(1000);");
+            }
+        }
+    }
+
+    /**
      * Setting timeout that is greater than query execution time. <code>SQLTimeoutException</code> is expected.
      *
      * @throws Exception If failed.
@@ -175,6 +206,31 @@ public class JdbcThinStatementTimeoutSelfTest extends JdbcThinAbstractSelfTest {
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testQueryTimeoutRetrival() throws Exception {
+        try(final Connection conn = DriverManager.getConnection(URL+"?queryTimeout=5")) {
+            conn.setSchema('"' + DEFAULT_CACHE_NAME + '"');
+
+            try (final Statement stmt = conn.createStatement()) {
+                stmt.executeQuery("select sleep_func(2);");
+            }
+
+            try (final Statement stmt = conn.createStatement()) {
+                stmt.setQueryTimeout(1);
+
+                GridTestUtils.assertThrows(log, () -> {
+                    // This takes 10_000 ms.
+                    stmt.executeQuery("select sleep_func(2) from Integer;");
+
+                    return null;
+                }, SQLTimeoutException.class, "The query was cancelled while executing.");
+            }
+        }
+    }
+
+    /**
      * Setting timeout that is greater than query execution time. Running same query multiple times.
      * <code>SQLTimeoutException</code> is expected in all cases.
      *
@@ -186,16 +242,18 @@ public class JdbcThinStatementTimeoutSelfTest extends JdbcThinAbstractSelfTest {
         stmt.setQueryTimeout(2);
 
         GridTestUtils.assertThrows(log, () -> {
-            stmt.executeQuery("select sleep_func(10) from Integer;");
+            stmt.executeQuery("select sleep_func(5) from Integer;");
 
             return null;
         }, SQLTimeoutException.class, "The query was cancelled while executing.");
 
         GridTestUtils.assertThrows(log, () -> {
-            stmt.executeQuery("select sleep_func(10) from Integer;");
+            stmt.executeQuery("select sleep_func(5) from Integer;");
 
             return null;
         }, SQLTimeoutException.class, "The query was cancelled while executing.");
+
+        stmt.executeQuery("select sleep_func(50)");
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
index 90b21e7..f728d12 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
@@ -459,4 +459,32 @@ public interface ConnectionProperties {
      */
     public void setAffinityAwarenessPartitionDistributionsCacheSize(
         int affinityAwarenessPartDistributionsCacheSize) throws SQLException;
+
+    /**
+     * Note: zero value means there is no limits.
+     *
+     * @return Query timeout in seconds.
+     */
+    @Nullable public Integer getQueryTimeout();
+
+    /**
+     * Note: zero value means there is no limits.
+     *
+     * @param qryTimeout Query timeout in seconds.
+     */
+    public void setQueryTimeout(@Nullable Integer qryTimeout) throws SQLException;
+
+    /**
+     * Note: zero value means there is no limits.
+     *
+     * @return Connection timeout in milliseconds.
+     */
+    @Nullable public int getConnectionTimeout();
+
+    /**
+     * Note: zero value means there is no limits.
+     *
+     * @param connTimeout Connection timeout in milliseconds.
+     */
+    public void setConnectionTimeout(@Nullable Integer connTimeout) throws SQLException;
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
index 0237941..30af93f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
@@ -212,6 +212,18 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
         "The size of partition distributions cache that is used within affinity awareness optimization.",
         1_000, false, 1, Integer.MAX_VALUE);
 
+    /** Query timeout. */
+    private IntegerProperty qryTimeout = new IntegerProperty("queryTimeout",
+        "Sets the number of seconds the driver will wait for a <code>Statement</code> object to execute." +
+            " Zero means there is no limits.",
+        0, false, 0, Integer.MAX_VALUE);
+
+    /** JDBC connection timeout. */
+    private IntegerProperty connTimeout = new IntegerProperty("connectionTimeout",
+        "Sets the number of milliseconds JDBC client will waits for server to response." +
+            " Zero means there is no limits.",
+        0, false, 0, Integer.MAX_VALUE);
+
     /** Properties array. */
     private final ConnectionProperty [] propsArray = {
         distributedJoins, enforceJoinOrder, collocated, replicatedOnly, autoCloseServerCursor,
@@ -225,7 +237,9 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
         affinityAwareness,
         updateBatchSize,
         affinityAwarenessSQLCacheSize,
-        affinityAwarenessPartDistributionsCacheSize
+        affinityAwarenessPartDistributionsCacheSize,
+        qryTimeout,
+        connTimeout
     };
 
     /** {@inheritDoc} */
@@ -574,6 +588,26 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
             affinityAwarenessPartDistributionsCacheSize);
     }
 
+    /** {@inheritDoc} */
+    @Override public Integer getQueryTimeout() {
+        return qryTimeout.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setQueryTimeout(@Nullable Integer timeout) throws SQLException {
+        qryTimeout.setValue(timeout);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getConnectionTimeout() {
+        return connTimeout.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setConnectionTimeout(@Nullable Integer timeout) throws SQLException {
+        connTimeout.setValue(timeout);
+    }
+
     /**
      * @param url URL connection.
      * @param props Environment properties.
@@ -1082,7 +1116,7 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
         /** {@inheritDoc} */
         @Override void init(String str) throws SQLException {
             if (str == null)
-                val = dfltVal != null ? (int)dfltVal : null;
+                val = dfltVal != null ? (Number)dfltVal : null;
             else {
                 try {
                     setValue(parse(str));
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
index 3dddb83..60fc1c4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -203,6 +203,9 @@ public class JdbcThinConnection implements Connection {
     /** Network timeout. */
     private int netTimeout;
 
+    /** Query timeout. */
+    private int qryTimeout;
+
     /** Background periodical maintenance: query timeouts and reconnection handler. */
     private final ScheduledExecutorService maintenanceExecutor = Executors.newScheduledThreadPool(2);
 
@@ -227,6 +230,8 @@ public class JdbcThinConnection implements Connection {
         holdability = HOLD_CURSORS_OVER_COMMIT;
         autoCommit = true;
         txIsolation = Connection.TRANSACTION_NONE;
+        netTimeout = connProps.getConnectionTimeout();
+        qryTimeout = connProps.getQueryTimeout();
 
         schema = JdbcUtils.normalizeSchema(connProps.getSchema());
 
@@ -344,6 +349,8 @@ public class JdbcThinConnection implements Connection {
 
         JdbcThinStatement stmt = new JdbcThinStatement(this, resSetHoldability, schema);
 
+        stmt.setQueryTimeout(qryTimeout);
+
         synchronized (stmtsMux) {
             stmts.add(stmt);
         }