From 3677ea75ce9388c47d7d449fbaf782eae286c510 Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Mon, 20 Oct 2025 11:17:56 -0700 Subject: [PATCH 1/3] fixes problem with duplicate column names by leaving last one index in the column index lookup by name map --- .../client/api/metadata/TableSchema.java | 4 +-- .../clickhouse/client/query/QueryTests.java | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java b/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java index ef41832de..023571dbd 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java @@ -32,13 +32,13 @@ public TableSchema(String tableName, String query, String databaseName, Collecti this.columns = ImmutableList.copyOf(columns); ImmutableMap.Builder colIndexMapBuilder = ImmutableMap.builder(); for (int i = 0; i < this.columns.size(); i++) { - ClickHouseColumn column= this.columns.get(i); + ClickHouseColumn column = this.columns.get(i); if (column.hasDefault()) { this.hasDefaults = true; } colIndexMapBuilder.put(this.columns.get(i).getColumnName(), i); } - this.colIndex = colIndexMapBuilder.build(); + this.colIndex = colIndexMapBuilder.buildKeepingLast(); } /** diff --git a/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java b/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java index d3dd90eae..d813d4365 100644 --- a/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java +++ b/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java @@ -2215,4 +2215,32 @@ public void testSettingsNotChanged() throws Exception{ Assert.assertEquals(response.getFormat(), ClickHouseFormat.JSONEachRow); } } + + @Test + public void testDuplicateColumnNames() throws Exception { + { + // simple scenario + List records = client.queryAll("SELECT 'a', 'a'"); + GenericRecord record = records.get(0); + Assert.assertEquals(record.getString("'a'"), "a"); + Assert.assertEquals(record.getString(1), "a"); + Assert.assertEquals(record.getString(2), "a"); + } + + { + client.execute("DROP TABLE IF EXISTS test_duplicate_column_names_1").get().close(); + client.execute("DROP TABLE IF EXISTS test_duplicate_column_names_2").get().close(); + client.execute("CREATE TABLE test_duplicate_column_names1 (name String ) ENGINE = MergeTree ORDER BY ()").get().close(); + client.execute("INSERT INTO test_duplicate_column_names1 VALUES ('some name')").get().close(); + client.execute("CREATE TABLE test_duplicate_column_names2 (name String ) ENGINE = MergeTree ORDER BY ()").get().close(); + client.execute("INSERT INTO test_duplicate_column_names2 VALUES ('another name')").get().close(); + + List records = client.queryAll("SELECT * FROM test_duplicate_column_names1, test_duplicate_column_names2"); + GenericRecord record = records.get(0); + Assert.assertEquals(record.getString("name"), "some name"); + Assert.assertEquals(record.getString("test_duplicate_column_names2.name"), "another name"); + Assert.assertEquals(record.getString(1), "some name"); + Assert.assertEquals(record.getString(2), "another name"); + } + } } From 95469dad278ea5bfea3977c90178ad93e132db10 Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Fri, 24 Oct 2025 22:11:28 -0700 Subject: [PATCH 2/3] added test for JDBC --- .../com/clickhouse/jdbc/StatementTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) 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 46ec48405..537e26b06 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java @@ -15,6 +15,7 @@ import java.sql.Connection; import java.sql.Date; import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.time.LocalDate; @@ -1189,6 +1190,43 @@ public void testSetFetchSize() throws Exception { } } + @Test(groups = {"integration"}) + public void testResponseWithDuplicateColumns() throws Exception { + try (Connection conn = getJdbcConnection(); Statement stmt = conn.createStatement()) { + + + try (ResultSet rs = stmt.executeQuery("SELECT 'a', 'a'")) { + ResultSetMetaData metaData = rs.getMetaData(); + Assert.assertEquals(metaData.getColumnCount(), 2); + Assert.assertEquals(metaData.getColumnName(1), "'a'"); + Assert.assertEquals(metaData.getColumnName(2), "'a'"); + } + + { + stmt.execute("DROP TABLE IF EXISTS test_jdbc_duplicate_column_names_1"); + stmt.execute("DROP TABLE IF EXISTS test_jdbc_duplicate_column_names_2"); + stmt.execute("CREATE TABLE test_jdbc_duplicate_column_names1 (name String ) ENGINE = MergeTree ORDER BY ()"); + stmt.execute("INSERT INTO test_jdbc_duplicate_column_names1 VALUES ('some name')"); + stmt.execute("CREATE TABLE test_jdbc_duplicate_column_names2 (name String ) ENGINE = MergeTree ORDER BY ()"); + stmt.execute("INSERT INTO test_jdbc_duplicate_column_names2 VALUES ('another name')"); + + try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_jdbc_duplicate_column_names1, test_jdbc_duplicate_column_names2")) { + ResultSetMetaData metaData = rs.getMetaData(); + Assert.assertEquals(metaData.getColumnCount(), 2); + Assert.assertEquals(metaData.getColumnName(1), "name"); + Assert.assertEquals(metaData.getColumnName(2), "test_jdbc_duplicate_column_names2.name"); + + rs.next(); + Assert.assertEquals(rs.getString("name"), "some name"); + Assert.assertEquals(rs.getString("test_jdbc_duplicate_column_names2.name"), "another name"); + Assert.assertEquals(rs.getString(1), "some name"); + Assert.assertEquals(rs.getString(2), "another name"); + + } + } + } + } + private static String getDBName(Statement stmt) throws SQLException { try (ResultSet rs = stmt.executeQuery("SELECT database()")) { rs.next(); From f08a1863880a1df28f253b12d1510419a1e6d7dc Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Mon, 27 Oct 2025 08:11:39 -0700 Subject: [PATCH 3/3] fixed test to clean tables --- .../src/test/java/com/clickhouse/client/query/QueryTests.java | 4 ++-- jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java b/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java index d813d4365..3cd71b2bf 100644 --- a/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java +++ b/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java @@ -2228,8 +2228,8 @@ public void testDuplicateColumnNames() throws Exception { } { - client.execute("DROP TABLE IF EXISTS test_duplicate_column_names_1").get().close(); - client.execute("DROP TABLE IF EXISTS test_duplicate_column_names_2").get().close(); + client.execute("DROP TABLE IF EXISTS test_duplicate_column_names1").get().close(); + client.execute("DROP TABLE IF EXISTS test_duplicate_column_names2").get().close(); client.execute("CREATE TABLE test_duplicate_column_names1 (name String ) ENGINE = MergeTree ORDER BY ()").get().close(); client.execute("INSERT INTO test_duplicate_column_names1 VALUES ('some name')").get().close(); client.execute("CREATE TABLE test_duplicate_column_names2 (name String ) ENGINE = MergeTree ORDER BY ()").get().close(); 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 537e26b06..edb2559d3 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java @@ -1203,8 +1203,8 @@ public void testResponseWithDuplicateColumns() throws Exception { } { - stmt.execute("DROP TABLE IF EXISTS test_jdbc_duplicate_column_names_1"); - stmt.execute("DROP TABLE IF EXISTS test_jdbc_duplicate_column_names_2"); + stmt.execute("DROP TABLE IF EXISTS test_jdbc_duplicate_column_names1"); + stmt.execute("DROP TABLE IF EXISTS test_jdbc_duplicate_column_names2"); stmt.execute("CREATE TABLE test_jdbc_duplicate_column_names1 (name String ) ENGINE = MergeTree ORDER BY ()"); stmt.execute("INSERT INTO test_jdbc_duplicate_column_names1 VALUES ('some name')"); stmt.execute("CREATE TABLE test_jdbc_duplicate_column_names2 (name String ) ENGINE = MergeTree ORDER BY ()");