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 0055bad84..fcd17b6d6 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java @@ -129,7 +129,7 @@ private String buildSQL() throws SQLException { int p = positions[i] + posOffset; String val = values[i]; if (val == null) { - throw new SQLException("Parameter at position '" + i + "' is not set"); + throw new SQLException("Parameter at position '" + (i + 1) + "' is not set"); } compiledSql.replace(p, p+1, val); posOffset += val.length() - 1; diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcDataTypeTests.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcDataTypeTests.java index 8223e8b6a..50014398a 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcDataTypeTests.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcDataTypeTests.java @@ -33,6 +33,7 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; +import java.sql.Struct; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; @@ -1627,6 +1628,25 @@ public void testNestedTypeNonFlatten() throws SQLException { } } + @Test(groups = {"integration"}) + public void testTupleType() throws Exception { + try (Connection conn = getJdbcConnection()) { + try (PreparedStatement stmt = conn.prepareStatement("SELECT ?::Tuple(String, Int32, Date)")) { + Object[] arr = new Object[]{"test", 123, LocalDate.parse("2026-03-02")}; + Struct tuple = conn.createStruct("Tuple(String, Int32, Date)", arr); + Array tupleArr = conn.createArrayOf("Array(Tuple(String, Int32, Date))", arr); + stmt.setObject(1, tuple); + try (ResultSet rs = stmt.executeQuery()) { + rs.next(); + Array dbTuple = rs.getArray(1); + Assert.assertEquals(dbTuple, tupleArr); + Object tupleObjArr = rs.getObject(1); + Assert.assertEquals(tupleObjArr, arr); + } + } + } + } + @Test(groups = { "integration" }) public void testTupleTypeSimpleStatement() throws SQLException { runQuery("CREATE TABLE test_tuple (order Int8, " diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImplTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImplTest.java index 498188cc9..7e387d76a 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImplTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImplTest.java @@ -130,7 +130,7 @@ public void testGetColumnTypeIntegers() throws Exception { } } - @Test + @Test(groups = { "integration" }) public void testGetColumnTypeMap() throws Exception { try (Connection conn = getJdbcConnection()) { try (Statement stmt = conn.createStatement()) { @@ -142,6 +142,18 @@ public void testGetColumnTypeMap() throws Exception { } } + @Test(groups = { "integration" }) + public void testGetColumnTypeTuple() throws Exception { + try (Connection conn = getJdbcConnection()) { + try (Statement stmt = conn.createStatement()) { + ResultSet rs = stmt.executeQuery("select tuple('a', 1) as t"); + ResultSetMetaData rsmd = rs.getMetaData(); + assertEquals(rsmd.getColumnType(1), Types.OTHER); + assertEquals(rsmd.getColumnClassName(1), Object.class.getName()); + } + } + } + @Test(groups = { "integration" }) public void testGetColumnTypeFloats() throws Exception { try (Connection conn = getJdbcConnection()) {