From df7ebaefe4b6a8529b1dfefecbf07ae164533436 Mon Sep 17 00:00:00 2001 From: Polyglot AI <293096396+polyglotAI-bot@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:02:45 +0000 Subject: [PATCH] [jdbc-v2] Add end-to-end test for backtick-quoted INSERT columns via RowBinary writer Issue #2978 reports that an INSERT with backtick-quoted column names throws NoSuchColumnException under the beta RowBinary writer (WriterStatementImpl). The functional fix already landed in #2899 (SqlParserFacade.enterInsertStmt unescapes each identifier component before the by-name schema lookup); this adds the end-to-end regression coverage for the WriterStatementImpl path that #2978 flagged as uncovered. Verified the test fails with "NoSuchColumnException: Result has no column with name '`field1`'" when the #2899 unescape is reverted, and passes with it. Closes: https://github.com/ClickHouse/clickhouse-java/issues/2978 --- .../jdbc/WriterStatementImplTest.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/WriterStatementImplTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/WriterStatementImplTest.java index 2762c76c6..458df7a98 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/WriterStatementImplTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/WriterStatementImplTest.java @@ -1,12 +1,16 @@ package com.clickhouse.jdbc; +import com.clickhouse.client.api.internal.ServerSettings; import org.testng.Assert; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.sql.Connection; import java.sql.JDBCType; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.util.Properties; @Test(groups = {"integration"}) @@ -28,4 +32,50 @@ public void testTargetTypeMethodThrowException() throws SQLException { Assert.expectThrows(SQLException.class, () -> stmt.setObject(1, "", JDBCType.DECIMAL, 3)); } } + + @DataProvider(name = "insertColumnListForms") + Object[][] insertColumnListForms() { + return new Object[][]{ + {"INSERT INTO %s (`field1`, `field2`, `field3`) VALUES (?, ?, ?)"}, + {"INSERT INTO %s (field1, field2, field3) VALUES (?, ?, ?)"}, + }; + } + + @Test(groups = {"integration"}, dataProvider = "insertColumnListForms") + public void testInsertWithQuotedColumnNames(String sqlTemplate) throws SQLException { + String table = "bt_writer_cols"; + Properties properties = new Properties(); + properties.setProperty(DriverProperties.BETA_ROW_BINARY_WRITER.getKey(), "true"); + // ANTLR4 backend extracts the explicit column list (default JAVACC does not). + properties.setProperty(DriverProperties.SQL_PARSER.getKey(), "ANTLR4"); + properties.setProperty(ASYNC_INSERT_SETTING_KEY, ServerSettings.OFF); + try (Connection connection = getJdbcConnection(properties)) { + try (Statement stmt = connection.createStatement()) { + stmt.execute("DROP TABLE IF EXISTS " + table); + stmt.execute("CREATE TABLE " + table + + " (field1 String, field2 Int32, field3 String) Engine MergeTree ORDER BY ()"); + } + + try (PreparedStatement ps = connection.prepareStatement(String.format(sqlTemplate, table))) { + Assert.assertTrue(ps instanceof WriterStatementImpl); + ps.setString(1, "alpha"); + ps.setInt(2, 42); + ps.setString(3, "gamma"); + Assert.assertEquals(ps.executeUpdate(), 1); + } + + try (Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT field1, field2, field3 FROM " + table)) { + Assert.assertTrue(rs.next()); + Assert.assertEquals(rs.getString(1), "alpha"); + Assert.assertEquals(rs.getInt(2), 42); + Assert.assertEquals(rs.getString(3), "gamma"); + Assert.assertFalse(rs.next()); + } finally { + try (Statement stmt = connection.createStatement()) { + stmt.execute("DROP TABLE IF EXISTS " + table); + } + } + } + } }