From 92b46fc0de1234fc0451eaefa83a1b2392401fbe Mon Sep 17 00:00:00 2001 From: jielongping Date: Mon, 14 Apr 2025 10:00:57 +0800 Subject: [PATCH 1/4] [jdbc-v2] Fixes in the PreparedStatementImpl class, the initial length of the parameters is incorrectly changed in the clearParameters method --- .../main/java/com/clickhouse/jdbc/PreparedStatementImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java index a534b5556..fd364d5e2 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java @@ -211,7 +211,8 @@ public void setBinaryStream(int parameterIndex, InputStream x, int length) throw public void clearParameters() throws SQLException { checkClosed(); if (originalSql.contains("?")) { - this.parameters = new Object[sqlSegments.length]; + int count = originalSql.length() - originalSql.replace("?", "").length(); + this.parameters = new Object[count]; } else { this.parameters = new Object[0]; } From b902094e4e4238d0608409ef5ead6a329cbcae60 Mon Sep 17 00:00:00 2001 From: jielongping Date: Thu, 17 Apr 2025 10:01:57 +0800 Subject: [PATCH 2/4] Resolved code conflicts. --- .../jdbc/PreparedStatementImpl.java | 2 +- .../jdbc/PreparedStatementTest.java | 68 ++++++++++++++++++- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java index fd364d5e2..a4a5cb1a6 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java @@ -84,7 +84,7 @@ public PreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLEx this.defaultCalendar = connection.defaultCalendar; } - private String compileSql(String [] segments) { + String compileSql(String []segments) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < segments.length; i++) { sb.append(segments[i]); diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java index 7f3f61ce5..ef10e68c9 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java @@ -1,15 +1,15 @@ package com.clickhouse.jdbc; import org.apache.commons.lang3.RandomStringUtils; +import org.testng.Assert; import org.testng.annotations.Ignore; import org.testng.annotations.Test; import java.sql.Array; import java.sql.Connection; -import java.sql.JDBCType; import java.sql.PreparedStatement; import java.sql.ResultSet; -import java.sql.ResultSetMetaData; +import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.Arrays; @@ -491,4 +491,68 @@ void testStatementSplit() throws Exception { } } } + + @Test(groups = {"integration"}) + void testClearParameters() throws Exception { + String sql = "insert into `test_issue_2299` (`id`, `name`, `age`) values (?, ?, ?)"; + try (Connection conn = getJdbcConnection(); + PreparedStatementImpl ps = (PreparedStatementImpl) conn.prepareStatement(sql); + TestPreparedStatementImpl ps2 = new TestPreparedStatementImpl((ConnectionImpl) conn, sql)) { + + try (Statement stmt = conn.createStatement()) { + stmt.execute("CREATE TABLE IF NOT EXISTS `test_issue_2299` (`id` Nullable(String), `name` Nullable(String), `age` Int32) ENGINE Memory;"); + } + + Assert.assertEquals(ps.parameters.length, 3); + ps.clearParameters(); + Assert.assertEquals(ps.parameters.length, 3); + + ps.setString(1, "testId"); + ps.setString(2, "testName"); + ps.setInt(3, 18); + String compiledSql1 = ps.compileSql(ps.sqlSegments); + Assert.assertEquals(compiledSql1, "insert into `test_issue_2299` (`id`, `name`, `age`) values ('testId', 'testName', 18)"); + + + Assert.assertEquals(ps2.parameters.length, 3); + ps2.clearParameters(); + Assert.assertEquals(ps2.parameters.length, 4); + + ps2.setString(1, "testId"); + ps2.setString(2, "testName"); + ps2.setInt(3, 18); + + String compiledSql2 = ps2.compileSql(ps2.sqlSegments); + Assert.assertEquals(compiledSql2, "insert into `test_issue_2299` (`id`, `name`, `age`) values ('testId', 'testName', 18)null"); + } + } + + static class TestPreparedStatementImpl extends PreparedStatementImpl { + + public TestPreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLException { + super(connection, sql); + } + + @Override + public void clearParameters() throws SQLException { + checkClosed(); + if (originalSql.contains("?")) { + this.parameters = new Object[sqlSegments.length]; + } else { + this.parameters = new Object[0]; + } + } + + @Override + String compileSql(String[] segments) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < segments.length; i++) { + sb.append(segments[i]); + if (i < parameters.length) { + sb.append(parameters[i]); + } + } + return sb.toString(); + } + } } From 378f96104cd891244b993cef986f6db2d977f9a0 Mon Sep 17 00:00:00 2001 From: jielongping Date: Thu, 17 Apr 2025 10:29:28 +0800 Subject: [PATCH 3/4] Fixed parameters variable being re-assigned in clearParameters method --- .../java/com/clickhouse/jdbc/PreparedStatementImpl.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java index a4a5cb1a6..8388a39ac 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java @@ -1,7 +1,5 @@ package com.clickhouse.jdbc; -import com.clickhouse.client.api.metadata.TableSchema; -import com.clickhouse.data.ClickHouseColumn; import com.clickhouse.data.Tuple; import com.clickhouse.jdbc.internal.ExceptionUtils; import org.slf4j.Logger; @@ -28,7 +26,6 @@ import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLType; import java.sql.SQLXML; -import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; @@ -211,8 +208,7 @@ public void setBinaryStream(int parameterIndex, InputStream x, int length) throw public void clearParameters() throws SQLException { checkClosed(); if (originalSql.contains("?")) { - int count = originalSql.length() - originalSql.replace("?", "").length(); - this.parameters = new Object[count]; + this.parameters = new Object[sqlSegments.length - 1]; } else { this.parameters = new Object[0]; } From cfa48eb63e93de2835dd1d3259a1ba2cdb15c2e2 Mon Sep 17 00:00:00 2001 From: jielongping Date: Thu, 17 Apr 2025 14:13:52 +0800 Subject: [PATCH 4/4] Update test case. --- .../jdbc/PreparedStatementImpl.java | 2 +- .../jdbc/PreparedStatementTest.java | 54 +++---------------- 2 files changed, 9 insertions(+), 47 deletions(-) diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java index 8388a39ac..1506eebfe 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java @@ -81,7 +81,7 @@ public PreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLEx this.defaultCalendar = connection.defaultCalendar; } - String compileSql(String []segments) { + private String compileSql(String []segments) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < segments.length; i++) { sb.append(segments[i]); diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java index ef10e68c9..1b89998e2 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java @@ -9,7 +9,6 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.Arrays; @@ -496,63 +495,26 @@ void testStatementSplit() throws Exception { void testClearParameters() throws Exception { String sql = "insert into `test_issue_2299` (`id`, `name`, `age`) values (?, ?, ?)"; try (Connection conn = getJdbcConnection(); - PreparedStatementImpl ps = (PreparedStatementImpl) conn.prepareStatement(sql); - TestPreparedStatementImpl ps2 = new TestPreparedStatementImpl((ConnectionImpl) conn, sql)) { + PreparedStatementImpl ps = (PreparedStatementImpl) conn.prepareStatement(sql)) { try (Statement stmt = conn.createStatement()) { stmt.execute("CREATE TABLE IF NOT EXISTS `test_issue_2299` (`id` Nullable(String), `name` Nullable(String), `age` Int32) ENGINE Memory;"); } - Assert.assertEquals(ps.parameters.length, 3); - ps.clearParameters(); Assert.assertEquals(ps.parameters.length, 3); ps.setString(1, "testId"); ps.setString(2, "testName"); ps.setInt(3, 18); - String compiledSql1 = ps.compileSql(ps.sqlSegments); - Assert.assertEquals(compiledSql1, "insert into `test_issue_2299` (`id`, `name`, `age`) values ('testId', 'testName', 18)"); - - - Assert.assertEquals(ps2.parameters.length, 3); - ps2.clearParameters(); - Assert.assertEquals(ps2.parameters.length, 4); - - ps2.setString(1, "testId"); - ps2.setString(2, "testName"); - ps2.setInt(3, 18); - - String compiledSql2 = ps2.compileSql(ps2.sqlSegments); - Assert.assertEquals(compiledSql2, "insert into `test_issue_2299` (`id`, `name`, `age`) values ('testId', 'testName', 18)null"); - } - } - - static class TestPreparedStatementImpl extends PreparedStatementImpl { + ps.execute(); - public TestPreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLException { - super(connection, sql); - } - - @Override - public void clearParameters() throws SQLException { - checkClosed(); - if (originalSql.contains("?")) { - this.parameters = new Object[sqlSegments.length]; - } else { - this.parameters = new Object[0]; - } - } + ps.clearParameters(); + Assert.assertEquals(ps.parameters.length, 3); - @Override - String compileSql(String[] segments) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < segments.length; i++) { - sb.append(segments[i]); - if (i < parameters.length) { - sb.append(parameters[i]); - } - } - return sb.toString(); + ps.setString(1, "testId2"); + ps.setString(2, "testName2"); + ps.setInt(3, 19); + ps.execute(); } } }