From 23bedd469bf87be1b9ed46dd9ec6f7b522f67a45 Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Tue, 21 Apr 2026 11:32:51 -0700 Subject: [PATCH 1/4] Added clearSession method to settings. done proper test to verify that query is really canceled --- .../client/api/ServerException.java | 2 + .../client/api/command/CommandSettings.java | 5 +++ .../client/api/insert/InsertSettings.java | 5 +++ .../client/api/internal/CommonSettings.java | 31 ++++++++----- .../client/api/internal/ServerSettings.java | 8 ++++ .../client/api/query/QuerySettings.java | 12 ++++- .../com/clickhouse/jdbc/StatementImpl.java | 11 +++-- .../com/clickhouse/jdbc/StatementTest.java | 44 +++++++++++++++++++ 8 files changed, 102 insertions(+), 16 deletions(-) diff --git a/client-v2/src/main/java/com/clickhouse/client/api/ServerException.java b/client-v2/src/main/java/com/clickhouse/client/api/ServerException.java index bd2361bfa..7cd6137fc 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/ServerException.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/ServerException.java @@ -8,6 +8,8 @@ public class ServerException extends ClickHouseException { public static final int UNKNOWN_SETTING = 115; + public static final int QUERY_CANCELLED = 394; + private final int code; private final int transportProtocolCode; diff --git a/client-v2/src/main/java/com/clickhouse/client/api/command/CommandSettings.java b/client-v2/src/main/java/com/clickhouse/client/api/command/CommandSettings.java index 399a50f26..fd860b2dd 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/command/CommandSettings.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/command/CommandSettings.java @@ -28,6 +28,11 @@ public CommandSettings setSessionTimezone(String timezone) { return this; } + public CommandSettings clearSession() { + super.clearSession(); + return this; + } + @Override public CommandSettings use(Session session) { super.use(session); diff --git a/client-v2/src/main/java/com/clickhouse/client/api/insert/InsertSettings.java b/client-v2/src/main/java/com/clickhouse/client/api/insert/InsertSettings.java index 840e33889..18e187774 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/insert/InsertSettings.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/insert/InsertSettings.java @@ -140,6 +140,11 @@ public String getSessionTimezone() { return settings.getSessionTimezone(); } + public InsertSettings clearSession() { + settings.clearSession(); + return this; + } + public InsertSettings use(Session session) { settings.use(session); return this; diff --git a/client-v2/src/main/java/com/clickhouse/client/api/internal/CommonSettings.java b/client-v2/src/main/java/com/clickhouse/client/api/internal/CommonSettings.java index aa2403c73..7ec626fb9 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/internal/CommonSettings.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/internal/CommonSettings.java @@ -3,7 +3,6 @@ import com.clickhouse.client.api.Client; import com.clickhouse.client.api.ClientConfigProperties; import com.clickhouse.client.api.Session; -import com.clickhouse.client.api.http.ClickHouseHttpProto; import java.time.Duration; import java.time.temporal.ChronoUnit; @@ -18,6 +17,8 @@ */ public class CommonSettings { + public static final String SESSION_ID_NONE = null; + private String operationId; private String logComment; protected Map settings; @@ -93,44 +94,50 @@ public CommonSettings setQueryId(String queryId) { } public CommonSettings setSessionId(String sessionId) { - ValidationUtils.checkNonBlank(sessionId, ClickHouseHttpProto.QPARAM_SESSION_ID); - serverSetting(ClickHouseHttpProto.QPARAM_SESSION_ID, sessionId); + ValidationUtils.checkNonBlank(sessionId, ServerSettings.SESSION_ID); + serverSetting(ServerSettings.SESSION_ID, sessionId); return this; } public String getSessionId() { - return (String) settings.get(ClientConfigProperties.serverSetting(ClickHouseHttpProto.QPARAM_SESSION_ID)); + return (String) settings.get(ClientConfigProperties.serverSetting(ServerSettings.SESSION_ID)); } public CommonSettings setSessionCheck(boolean sessionCheck) { - serverSetting(ClickHouseHttpProto.QPARAM_SESSION_CHECK, sessionCheck ? "1" : "0"); + serverSetting(ServerSettings.SESSION_CHECK, sessionCheck ? "1" : "0"); return this; } public Boolean getSessionCheck() { - String value = (String) settings.get(ClientConfigProperties.serverSetting(ClickHouseHttpProto.QPARAM_SESSION_CHECK)); + String value = (String) settings.get(ClientConfigProperties.serverSetting(ServerSettings.SESSION_CHECK)); return value == null ? null : ("1".equals(value) || Boolean.parseBoolean(value)); } public CommonSettings setSessionTimeout(int timeoutInSeconds) { - ValidationUtils.checkPositive(timeoutInSeconds, ClickHouseHttpProto.QPARAM_SESSION_TIMEOUT); - serverSetting(ClickHouseHttpProto.QPARAM_SESSION_TIMEOUT, String.valueOf(timeoutInSeconds)); + ValidationUtils.checkPositive(timeoutInSeconds, ServerSettings.SESSION_TIMEOUT); + serverSetting(ServerSettings.SESSION_TIMEOUT, String.valueOf(timeoutInSeconds)); return this; } public Integer getSessionTimeout() { - String value = (String) settings.get(ClientConfigProperties.serverSetting(ClickHouseHttpProto.QPARAM_SESSION_TIMEOUT)); + String value = (String) settings.get(ClientConfigProperties.serverSetting(ServerSettings.SESSION_TIMEOUT)); return value == null ? null : Integer.valueOf(value); } public CommonSettings setSessionTimezone(String timezone) { - ValidationUtils.checkNonBlank(timezone, ClickHouseHttpProto.QPARAM_SESSION_TIMEZONE); - serverSetting(ClickHouseHttpProto.QPARAM_SESSION_TIMEZONE, timezone); + ValidationUtils.checkNonBlank(timezone, ServerSettings.SESSION_TIMEZONE); + serverSetting(ServerSettings.SESSION_TIMEZONE, timezone); return this; } public String getSessionTimezone() { - return (String) settings.get(ClientConfigProperties.serverSetting(ClickHouseHttpProto.QPARAM_SESSION_TIMEZONE)); + return (String) settings.get(ClientConfigProperties.serverSetting(ServerSettings.SESSION_TIMEZONE)); + } + + public CommonSettings clearSession() { + serverSetting(ServerSettings.SESSION_ID, (String) null); + serverSetting(ServerSettings.SESSION_CHECK, "0"); + return this; } public CommonSettings use(Session session) { diff --git a/client-v2/src/main/java/com/clickhouse/client/api/internal/ServerSettings.java b/client-v2/src/main/java/com/clickhouse/client/api/internal/ServerSettings.java index 24210866f..b58f776f3 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/internal/ServerSettings.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/internal/ServerSettings.java @@ -46,4 +46,12 @@ public final class ServerSettings { public static final String ASYNC_INSERT = "async_insert"; public static final String WAIT_ASYNC_INSERT = "wait_for_async_insert"; + + public static final String SESSION_ID = "session_id"; + + public static final String SESSION_CHECK = "session_check"; + + public static final String SESSION_TIMEOUT = "session_timeout"; + + public static final String SESSION_TIMEZONE = "session_timezone"; } diff --git a/client-v2/src/main/java/com/clickhouse/client/api/query/QuerySettings.java b/client-v2/src/main/java/com/clickhouse/client/api/query/QuerySettings.java index 95babb1ea..9570de497 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/query/QuerySettings.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/query/QuerySettings.java @@ -11,6 +11,7 @@ import java.time.temporal.ChronoUnit; import java.util.Collection; +import java.util.Collections; import java.util.Map; import java.util.TimeZone; @@ -24,7 +25,7 @@ public class QuerySettings { private final CommonSettings settings; public QuerySettings(Map settings) { - this.settings = new CommonSettings(); + this(); for (Map.Entry entry : settings.entrySet()) { this.settings.setOption(entry.getKey(), entry.getValue()); } @@ -34,6 +35,10 @@ public QuerySettings() { this.settings = new CommonSettings(); } + public QuerySettings(QuerySettings settings) { + this(settings == null ? Collections.emptyMap() : settings.getAllSettings()); + } + private QuerySettings(CommonSettings settings) { this.settings = settings; } @@ -139,6 +144,11 @@ public QuerySettings use(Session session) { return this; } + public QuerySettings clearSession() { + settings.clearSession(); + return this; + } + /** * Read buffer is used for reading data from a server. Size is in bytes. * Minimal value is {@value MINIMAL_READ_BUFFER_SIZE} bytes. diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java index f50546393..247c69ea5 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java @@ -333,9 +333,14 @@ public void cancel() throws SQLException { return; } - try (QueryResponse response = connection.getClient().query(String.format("KILL QUERY%sWHERE query_id = '%s'", - connection.onCluster ? " ON CLUSTER " + connection.cluster + " " : " ", - lastQueryId), connection.getDefaultQuerySettings()).get()){ + final String sql = "KILL QUERY " + + (connection.onCluster ? "ON CLUSTER " + connection.cluster + " " : "") + + "WHERE query_id = '" + lastQueryId + "'"; + + String queryId = queryIdGenerator == null ? UUID.randomUUID().toString() : queryIdGenerator.get(); + // Clear session settings to prevent KILL QUERY from using the locked session + try (QueryResponse response = connection.getClient().query(sql, + new QuerySettings(connection.getDefaultQuerySettings()).setQueryId(queryId).clearSession()).get()){ LOG.debug("Query {} was killed by {}", lastQueryId, response.getQueryId()); } catch (Exception e) { throw new SQLException(e); diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java index 575dde388..05945e8f4 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java @@ -1,6 +1,7 @@ package com.clickhouse.jdbc; import com.clickhouse.client.api.ClientConfigProperties; +import com.clickhouse.client.api.ServerException; import com.clickhouse.client.api.internal.ServerSettings; import com.clickhouse.client.api.query.GenericRecord; import com.clickhouse.data.ClickHouseVersion; @@ -26,7 +27,9 @@ import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -611,6 +614,47 @@ public void testConcurrentCancel() throws Exception { } } + @Test(groups = {"integration"}) + public void testCancelWithSessionId() throws Exception { + // Test for issue #2690 - Cancel statement should work with active session + String sessionId = java.util.UUID.randomUUID().toString(); + Properties props = new Properties(); + props.put(DriverProperties.serverSetting(ServerSettings.SESSION_ID), sessionId); + + try (Connection conn = getJdbcConnection(props); + StatementImpl stmt = (StatementImpl) conn.createStatement()) { + // There is no way to check current session_id + + final CompletableFuture queryComplete = new CompletableFuture<>(); + final CountDownLatch startLatch = new CountDownLatch(1); + Thread queryThread = new Thread(() -> { + try { + startLatch.countDown(); + stmt.executeQuery("SELECT sum(reinterpretAsUInt64(MD5(toString(number)))) FROM system.numbers LIMIT 1000000"); + queryComplete.complete(true); + } catch (SQLException e) { + queryComplete.completeExceptionally(e); + } + }); + queryThread.start(); + startLatch.await(); + Thread.sleep(500); + stmt.cancel(); + + try { + queryComplete.get(); + } catch (ExecutionException e) { + assertEquals(((ServerException)e.getCause().getCause()).getCode(), ServerException.QUERY_CANCELLED); + } + + // Verify statement is still usable after cancel + try (ResultSet rs = stmt.executeQuery("SELECT 1")) { + assertTrue(rs.next()); + assertEquals(rs.getInt(1), 1); + } + } + } + @Test(groups = {"integration"}) public void testTextFormatInResponse() throws Exception { try (Connection conn = getJdbcConnection(); From 3adaa91e20ca5c7774df95692b77376102bd59ab Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Tue, 21 Apr 2026 13:47:10 -0700 Subject: [PATCH 2/4] Added tests and missing changelog records --- CHANGELOG.md | 29 +++++++++++++++ .../api/command/CommandSettingsTest.java | 21 +++++++++++ .../client/api/insert/InsertSettingsTest.java | 21 +++++++++++ .../api/internal/CommonSettingsTest.java | 21 +++++++++++ .../client/api/query/QuerySettingsTest.java | 35 +++++++++++++++++++ 5 files changed, 127 insertions(+) create mode 100644 client-v2/src/test/java/com/clickhouse/client/api/command/CommandSettingsTest.java create mode 100644 client-v2/src/test/java/com/clickhouse/client/api/insert/InsertSettingsTest.java create mode 100644 client-v2/src/test/java/com/clickhouse/client/api/internal/CommonSettingsTest.java create mode 100644 client-v2/src/test/java/com/clickhouse/client/api/query/QuerySettingsTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index f836a5c89..9036de33b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,32 @@ +## 0.9.9 + +### New Features + +- **[client-v2]** Added ClickHouse session APIs to `Client.Builder`, `QuerySettings`, `InsertSettings`, and `CommandSettings`: `setSessionId()`, `setSessionCheck()`, `setSessionTimeout()`, `setSessionTimezone()`, and `use(Session)`, plus `getSessionId()`, `getSessionCheck()`, `getSessionTimeout()`, `getSessionTimezone()`, and `clearSession()` on operation settings. `clearSession()` clears session-related request settings. (https://github.com/ClickHouse/clickhouse-java/pull/2810, https://github.com/ClickHouse/clickhouse-java/pull/2836) + +### Improvements + +- **[client-v2]** Improved HTTP transport error handling: unwrap compressed error responses, read server error bodies reliably, handle common HTTP status +failures (for example 401, 403, 404), and include more context when an `IOException` occurs while reading result data. (https://github.com/ClickHouse/ +clickhouse-java/pull/2804) + +- **[client-v2]** Refined `HttpEndpoint` construction and validation so hostnames containing underscores are handled consistently with JVM name resolution +behavior. (https://github.com/ClickHouse/clickhouse-java/issues/2792, https://github.com/ClickHouse/clickhouse-java/issues/2753) + +- **[jdbc-v2]** Extended the JavaCC SQL utilities keyword list with CENTURY, DECADE, DOW, DOY, EPOCH, ISODOW, ISOYEAR, MILLENNIUM, NATURAL, SOME, ZONE. (https://github.com/ClickHouse/clickhouse-java/pull/2818) + +### Bug Fixes + +- **[client-v2, jdbc-v2]** Fixed `Statement#cancel()` when the connection uses a ClickHouse server session (`session_id`): the internal `KILL QUERY` is executed with settings copied from the connection defaults but **without** the session id, so the cancel request is not blocked by the same session. (https://github.com/ClickHouse/clickhouse-java/issues/2690) + +- **[client-v2]** Fixed decoding of SQL `NULL` values inside `Variant` and `Dynamic` columns in the binary row protocol reader. (https://github.com/ClickHouse/clickhouse-java/issues/2789, https://github.com/ClickHouse/clickhouse-java/issues/2791) + +- **[client-v2, jdbc-v2]** Fixed decimal-related conversion and rounding when values pass through `ValueConverters` / serialization helpers (including +integer-to-decimal paths and floating-point edge cases), with expanded regression tests. (https://github.com/ClickHouse/clickhouse-java/issues/2748) + +- **[client-v2]** Fixed Basic authentication when no password is configured: the literal `"null"` string is no longer sent as the password value. (https:// +github.com/ClickHouse/clickhouse-java/pull/2809) + ## 0.9.8 ### Improvements diff --git a/client-v2/src/test/java/com/clickhouse/client/api/command/CommandSettingsTest.java b/client-v2/src/test/java/com/clickhouse/client/api/command/CommandSettingsTest.java new file mode 100644 index 000000000..9397c7a55 --- /dev/null +++ b/client-v2/src/test/java/com/clickhouse/client/api/command/CommandSettingsTest.java @@ -0,0 +1,21 @@ +package com.clickhouse.client.api.command; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class CommandSettingsTest { + @Test + public void testClearSession() { + CommandSettings settings = new CommandSettings(); + settings.setSessionId("test-session"); + settings.setSessionCheck(true); + + Assert.assertEquals(settings.getSessionId(), "test-session"); + Assert.assertEquals(settings.getSessionCheck(), Boolean.TRUE); + + settings.clearSession(); + + Assert.assertNull(settings.getSessionId()); + Assert.assertEquals(settings.getSessionCheck(), Boolean.FALSE); + } +} diff --git a/client-v2/src/test/java/com/clickhouse/client/api/insert/InsertSettingsTest.java b/client-v2/src/test/java/com/clickhouse/client/api/insert/InsertSettingsTest.java new file mode 100644 index 000000000..0b7c9c616 --- /dev/null +++ b/client-v2/src/test/java/com/clickhouse/client/api/insert/InsertSettingsTest.java @@ -0,0 +1,21 @@ +package com.clickhouse.client.api.insert; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class InsertSettingsTest { + @Test + public void testClearSession() { + InsertSettings settings = new InsertSettings(); + settings.setSessionId("test-session"); + settings.setSessionCheck(true); + + Assert.assertEquals(settings.getSessionId(), "test-session"); + Assert.assertEquals(settings.getSessionCheck(), Boolean.TRUE); + + settings.clearSession(); + + Assert.assertNull(settings.getSessionId()); + Assert.assertEquals(settings.getSessionCheck(), Boolean.FALSE); + } +} diff --git a/client-v2/src/test/java/com/clickhouse/client/api/internal/CommonSettingsTest.java b/client-v2/src/test/java/com/clickhouse/client/api/internal/CommonSettingsTest.java new file mode 100644 index 000000000..a97c0a769 --- /dev/null +++ b/client-v2/src/test/java/com/clickhouse/client/api/internal/CommonSettingsTest.java @@ -0,0 +1,21 @@ +package com.clickhouse.client.api.internal; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class CommonSettingsTest { + @Test + public void testClearSession() { + CommonSettings settings = new CommonSettings(); + settings.setSessionId("test-session"); + settings.setSessionCheck(true); + + Assert.assertEquals(settings.getSessionId(), "test-session"); + Assert.assertEquals(settings.getSessionCheck(), Boolean.TRUE); + + settings.clearSession(); + + Assert.assertNull(settings.getSessionId()); + Assert.assertEquals(settings.getSessionCheck(), Boolean.FALSE); + } +} diff --git a/client-v2/src/test/java/com/clickhouse/client/api/query/QuerySettingsTest.java b/client-v2/src/test/java/com/clickhouse/client/api/query/QuerySettingsTest.java new file mode 100644 index 000000000..45ccbaf83 --- /dev/null +++ b/client-v2/src/test/java/com/clickhouse/client/api/query/QuerySettingsTest.java @@ -0,0 +1,35 @@ +package com.clickhouse.client.api.query; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class QuerySettingsTest { + @Test + public void testClearSession() { + QuerySettings settings = new QuerySettings(); + settings.setSessionId("test-session"); + settings.setSessionCheck(true); + + Assert.assertEquals(settings.getSessionId(), "test-session"); + Assert.assertEquals(settings.getSessionCheck(), Boolean.TRUE); + + settings.clearSession(); + + Assert.assertNull(settings.getSessionId()); + Assert.assertEquals(settings.getSessionCheck(), Boolean.FALSE); + } + + @Test + public void testCopyConstructor() { + QuerySettings settings = new QuerySettings(); + settings.setSessionId("test-session"); + settings.setSessionCheck(true); + + QuerySettings copy = new QuerySettings(settings); + Assert.assertEquals(copy.getSessionId(), "test-session"); + Assert.assertEquals(copy.getSessionCheck(), Boolean.TRUE); + + QuerySettings nullCopy = new QuerySettings((QuerySettings) null); + Assert.assertNull(nullCopy.getSessionId()); + } +} From dd52f23ccd483ada42f2621c14221f90536dcb0e Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Tue, 21 Apr 2026 18:07:11 -0700 Subject: [PATCH 3/4] Made test part of integration tests --- .../clickhouse/client/api/internal/CommonSettingsTest.java | 2 +- .../com/clickhouse/client/api/query/QuerySettingsTest.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client-v2/src/test/java/com/clickhouse/client/api/internal/CommonSettingsTest.java b/client-v2/src/test/java/com/clickhouse/client/api/internal/CommonSettingsTest.java index a97c0a769..6fb35a3c6 100644 --- a/client-v2/src/test/java/com/clickhouse/client/api/internal/CommonSettingsTest.java +++ b/client-v2/src/test/java/com/clickhouse/client/api/internal/CommonSettingsTest.java @@ -4,7 +4,7 @@ import org.testng.annotations.Test; public class CommonSettingsTest { - @Test + @Test(groups = {"integration"}) public void testClearSession() { CommonSettings settings = new CommonSettings(); settings.setSessionId("test-session"); diff --git a/client-v2/src/test/java/com/clickhouse/client/api/query/QuerySettingsTest.java b/client-v2/src/test/java/com/clickhouse/client/api/query/QuerySettingsTest.java index 45ccbaf83..080d1441c 100644 --- a/client-v2/src/test/java/com/clickhouse/client/api/query/QuerySettingsTest.java +++ b/client-v2/src/test/java/com/clickhouse/client/api/query/QuerySettingsTest.java @@ -4,7 +4,7 @@ import org.testng.annotations.Test; public class QuerySettingsTest { - @Test + @Test(groups = {"integration"}) public void testClearSession() { QuerySettings settings = new QuerySettings(); settings.setSessionId("test-session"); @@ -18,8 +18,8 @@ public void testClearSession() { Assert.assertNull(settings.getSessionId()); Assert.assertEquals(settings.getSessionCheck(), Boolean.FALSE); } - - @Test + + @Test(groups = {"integration"}) public void testCopyConstructor() { QuerySettings settings = new QuerySettings(); settings.setSessionId("test-session"); From 901da760f1ecfc17fd71c04c8f13c3ed473d2e0e Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Tue, 21 Apr 2026 19:24:05 -0700 Subject: [PATCH 4/4] Added more tests for coverage --- .../client/api/insert/InsertSettingsTest.java | 2 +- .../com/clickhouse/jdbc/StatementTest.java | 51 +++++-------------- 2 files changed, 15 insertions(+), 38 deletions(-) diff --git a/client-v2/src/test/java/com/clickhouse/client/api/insert/InsertSettingsTest.java b/client-v2/src/test/java/com/clickhouse/client/api/insert/InsertSettingsTest.java index 0b7c9c616..32a2e395b 100644 --- a/client-v2/src/test/java/com/clickhouse/client/api/insert/InsertSettingsTest.java +++ b/client-v2/src/test/java/com/clickhouse/client/api/insert/InsertSettingsTest.java @@ -4,7 +4,7 @@ import org.testng.annotations.Test; public class InsertSettingsTest { - @Test + @Test(groups = {"integration"}) public void testClearSession() { InsertSettings settings = new InsertSettings(); settings.setSessionId("test-session"); diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java index 05945e8f4..3aa221225 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java @@ -27,9 +27,11 @@ import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; +import java.util.function.Supplier; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -582,44 +584,11 @@ public void testConnectionExhaustion() throws Exception { } } - @Test(groups = {"integration"}) - public void testConcurrentCancel() throws Exception { - int maxNumConnections = 3; - Properties p = new Properties(); - p.put(ClientConfigProperties.HTTP_MAX_OPEN_CONNECTIONS.getKey(), String.valueOf(maxNumConnections)); - try (Connection conn = getJdbcConnection()) { - try (StatementImpl stmt = (StatementImpl) conn.createStatement()) { - stmt.executeQuery("SELECT number FROM system.numbers LIMIT 1000000"); - stmt.cancel(); - } - for (int i = 0; i < maxNumConnections; i++) { - try (StatementImpl stmt = (StatementImpl) conn.createStatement()) { - final int threadNum = i; - log.info("Starting thread {}", threadNum); - final CountDownLatch latch = new CountDownLatch(1); - Thread t = new Thread(() -> { - try { - latch.countDown(); - ResultSet rs = stmt.executeQuery("SELECT number FROM system.numbers LIMIT 10000000"); - } catch (SQLException e) { - log.error("Error in thread {}", threadNum, e); - } - }); - t.start(); - - latch.await(); - stmt.cancel(); - } - } - } - } - - @Test(groups = {"integration"}) - public void testCancelWithSessionId() throws Exception { - // Test for issue #2690 - Cancel statement should work with active session - String sessionId = java.util.UUID.randomUUID().toString(); + @Test(groups = {"integration"}, dataProvider = "testCancel_DP") + public void testCancel(String configName, Map additionalConfig) throws Exception { + log.debug("config name: {}", configName); Properties props = new Properties(); - props.put(DriverProperties.serverSetting(ServerSettings.SESSION_ID), sessionId); + props.putAll(additionalConfig); try (Connection conn = getJdbcConnection(props); StatementImpl stmt = (StatementImpl) conn.createStatement()) { @@ -655,6 +624,14 @@ public void testCancelWithSessionId() throws Exception { } } + @DataProvider(name = "testCancel_DP") + public static Object[][] testCancel_DP() { + return new Object[][] { + {"withSession", Map.of(DriverProperties.serverSetting(ServerSettings.SESSION_ID), java.util.UUID.randomUUID().toString())}, + {"withQueryGenerator", Map.of(DriverProperties.QUERY_ID_GENERATOR.getKey(), (Supplier)() -> String.valueOf(new Random().nextInt()))} + }; + } + @Test(groups = {"integration"}) public void testTextFormatInResponse() throws Exception { try (Connection conn = getJdbcConnection();