From 0d1826db5a29d27e6839af5d540d8dacd9e3b3b6 Mon Sep 17 00:00:00 2001 From: Polyglot AI <293096396+polyglotAI-bot@users.noreply.github.com> Date: Fri, 14 Aug 2026 16:07:24 +0000 Subject: [PATCH 1/2] [jdbc-v1] Make testAsyncInsert deterministic instead of racing the async insert flush The second half of the test asserted that a row inserted with wait_for_async_insert=0 is not queryable yet, which only held while the server had not flushed its async insert buffer. Since 24.2 the adaptive busy timeout is on by default and starts at 50 ms, which is shorter than the client latency before the next SELECT on a loaded runner, so the assertion failed intermittently. Pin the buffer open for the check (adaptive timeout off where supported, busy timeout 30 s) and add the other half of the contract: after SYSTEM FLUSH ASYNC INSERT QUEUE the row must be there. Fixes: https://github.com/ClickHouse/clickhouse-java/issues/3053 --- .../jdbc/ClickHouseStatementTest.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java b/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java index c4ec1ee48..b48eb90dc 100644 --- a/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java +++ b/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java @@ -63,6 +63,8 @@ @Test(groups = { "integration" }) public class ClickHouseStatementTest extends JdbcIntegrationTest { + private static final int ASYNC_INSERT_BUSY_TIMEOUT_MS = 30000; + @BeforeMethod(groups = "integration") public void setV1() { System.setProperty("clickhouse.jdbc.v1","true"); @@ -516,10 +518,12 @@ public void testAsyncInsert() throws SQLException { } Properties props = new Properties(); + boolean adaptiveBusyTimeoutSupported; try (ClickHouseConnection conn = newConnection(props)) { if (conn.getServerVersion().check("(,21.12)")) { return; } + adaptiveBusyTimeoutSupported = !conn.getServerVersion().check("(,24.2)"); } props.setProperty(ClickHouseHttpOption.CUSTOM_PARAMS.getKey(), "async_insert=1,wait_for_async_insert=1"); @@ -536,17 +540,27 @@ public void testAsyncInsert() throws SQLException { Assert.assertFalse(rs.next()); } - //TODO: I'm not sure this is a valid test... if (isCloud()) return; //TODO: testAsyncInsert - Revisit, see: https://github.com/ClickHouse/clickhouse-java/issues/1747 - props.setProperty(ClickHouseHttpOption.CUSTOM_PARAMS.getKey(), "async_insert=1,wait_for_async_insert=0"); + // keep the async insert buffer open for the whole check instead of racing the busy timeout + props.setProperty(ClickHouseHttpOption.CUSTOM_PARAMS.getKey(), + "async_insert=1,wait_for_async_insert=0,async_insert_busy_timeout_ms=" + ASYNC_INSERT_BUSY_TIMEOUT_MS + + (adaptiveBusyTimeoutSupported ? ",async_insert_use_adaptive_busy_timeout=0" : "")); try (ClickHouseConnection conn = newConnection(props); ClickHouseStatement stmt = conn.createStatement();) { stmt.execute("TRUNCATE TABLE test_async_insert; " + "INSERT INTO test_async_insert VALUES(1, 'a'); " + "SELECT * FROM test_async_insert"); ResultSet rs = stmt.getResultSet(); - Assert.assertFalse(rs.next(), - "Server was probably busy at that time, so the row was inserted before your query"); + Assert.assertFalse(rs.next(), "Row must not be queryable while the async insert buffer is still open"); + + stmt.execute("SYSTEM FLUSH ASYNC INSERT QUEUE"); + rs = stmt.executeQuery("SELECT * FROM test_async_insert"); + Assert.assertTrue(rs.next(), "Row must be queryable once the async insert queue is flushed"); + Assert.assertEquals(rs.getInt(1), 1); + Assert.assertEquals(rs.getString(2), "a"); + Assert.assertFalse(rs.next()); + + stmt.execute("DROP TABLE test_async_insert"); } } From 402053c560a9b4aeeb7f3efeb286dffb63b54b45 Mon Sep 17 00:00:00 2001 From: Polyglot AI <293096396+polyglotAI-bot@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:00:22 +0000 Subject: [PATCH 2/2] [jdbc-v1] Gate SYSTEM FLUSH ASYNC INSERT QUEUE on server 23.7+ The command was added in ClickHouse 23.7, but testAsyncInsert only skips servers older than 21.12. On 21.12-23.6 the post-assert flush failed with a syntax error. Gate the flush and the follow-up assertion the same way the adaptive busy timeout setting is gated; older servers keep the "row not queryable yet" check only. --- .../jdbc/ClickHouseStatementTest.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java b/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java index b48eb90dc..697147b79 100644 --- a/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java +++ b/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java @@ -519,11 +519,14 @@ public void testAsyncInsert() throws SQLException { Properties props = new Properties(); boolean adaptiveBusyTimeoutSupported; + boolean flushAsyncInsertQueueSupported; try (ClickHouseConnection conn = newConnection(props)) { if (conn.getServerVersion().check("(,21.12)")) { return; } adaptiveBusyTimeoutSupported = !conn.getServerVersion().check("(,24.2)"); + // SYSTEM FLUSH ASYNC INSERT QUEUE only exists since 23.7 + flushAsyncInsertQueueSupported = !conn.getServerVersion().check("(,23.7)"); } props.setProperty(ClickHouseHttpOption.CUSTOM_PARAMS.getKey(), "async_insert=1,wait_for_async_insert=1"); @@ -553,12 +556,14 @@ public void testAsyncInsert() throws SQLException { ResultSet rs = stmt.getResultSet(); Assert.assertFalse(rs.next(), "Row must not be queryable while the async insert buffer is still open"); - stmt.execute("SYSTEM FLUSH ASYNC INSERT QUEUE"); - rs = stmt.executeQuery("SELECT * FROM test_async_insert"); - Assert.assertTrue(rs.next(), "Row must be queryable once the async insert queue is flushed"); - Assert.assertEquals(rs.getInt(1), 1); - Assert.assertEquals(rs.getString(2), "a"); - Assert.assertFalse(rs.next()); + if (flushAsyncInsertQueueSupported) { + stmt.execute("SYSTEM FLUSH ASYNC INSERT QUEUE"); + rs = stmt.executeQuery("SELECT * FROM test_async_insert"); + Assert.assertTrue(rs.next(), "Row must be queryable once the async insert queue is flushed"); + Assert.assertEquals(rs.getInt(1), 1); + Assert.assertEquals(rs.getString(2), "a"); + Assert.assertFalse(rs.next()); + } stmt.execute("DROP TABLE test_async_insert"); }