From bcf40b1b8c8043707a775b65905c7ae494bae5fa Mon Sep 17 00:00:00 2001 From: Alex Castillo Date: Sat, 7 Nov 2026 01:32:57 -0400 Subject: [PATCH] fix(jdbc-v2): read Date/DateTime/Time array elements as java.time types via getObject(i, Class) Fixes #3284 --- .../internal/ValueConverters.java | 21 ++++++++++++++++--- history/latest/3284.md | 5 +++++ .../jdbc/types/ArrayResultSetTest.java | 21 +++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 history/latest/3284.md diff --git a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/ValueConverters.java b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/ValueConverters.java index adf2246ba3..e4a3646509 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/ValueConverters.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/ValueConverters.java @@ -108,11 +108,14 @@ public ValueConverters() { mapBuilder.put(String.class, stringMapBuilder.build()); mapBuilder.put(java.sql.Date.class, ImmutableMap.of(java.sql.Date.class, this::convertSqlDateToSqlDate, - String.class, this::convertDateToString)); + String.class, this::convertDateToString, + java.time.LocalDate.class, this::convertSqlDateToLocalDate)); mapBuilder.put(Time.class, ImmutableMap.of(Time.class, this::convertSqlTimeToSqlTime, - String.class, this::convertTimeToString)); + String.class, this::convertTimeToString, + java.time.LocalTime.class, this::convertSqlTimeToLocalTime)); mapBuilder.put(Timestamp.class, ImmutableMap.of(Timestamp.class, this::convertSqlTimestampToSqlTimestamp, - String.class, this::convertTimestampToString)); + String.class, this::convertTimestampToString, + java.time.LocalDateTime.class, this::convertSqlTimestampToLocalDateTime)); classConverters = mapBuilder.build(); } @@ -232,6 +235,18 @@ public Timestamp convertSqlTimestampToSqlTimestamp(Object value) { return (Timestamp) value; } + public java.time.LocalDate convertSqlDateToLocalDate(Object value) { + return ((java.sql.Date) value).toLocalDate(); + } + + public java.time.LocalTime convertSqlTimeToLocalTime(Object value) { + return ((Time) value).toLocalTime(); + } + + public java.time.LocalDateTime convertSqlTimestampToLocalDateTime(Object value) { + return ((Timestamp) value).toLocalDateTime(); + } + public String convertDateToString(Object value) { return value.toString(); } diff --git a/history/latest/3284.md b/history/latest/3284.md new file mode 100644 index 0000000000..691bd0b7d8 --- /dev/null +++ b/history/latest/3284.md @@ -0,0 +1,5 @@ +- **[jdbc-v2]** Fixed `ResultSet#getObject(int, Class)` on the result set returned by `java.sql.Array#getResultSet()` + failing with `Value of class java.sql.Date cannot be converted to class java.time.LocalDate` for arrays of + `Date`/`Date32`, `DateTime`/`DateTime64` and `Time`/`Time64`. These elements can now also be read as + `java.time.LocalDate`, `java.time.LocalDateTime` and `java.time.LocalTime`, the same as for non-array columns. + (https://github.com/ClickHouse/clickhouse-java/issues/3284) diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/types/ArrayResultSetTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/types/ArrayResultSetTest.java index 87b7e14d1f..0cde2a5fbd 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/types/ArrayResultSetTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/types/ArrayResultSetTest.java @@ -629,4 +629,25 @@ void testArrayOfObjects() throws Exception { assertEquals(rs.getObject(valueColumn, String.class), "2"); assertEquals(rs.getString(valueColumn), rs.getObject(valueColumn, String.class)); } + + @Test + void testJavaTimeConversions() throws Exception { + Date[] dates = {Date.valueOf("2020-01-01"), null}; + ArrayResultSet rs = new ArrayResultSet(dates, ClickHouseColumn.parse("v Array(Date32)").get(0)); + rs.next(); + assertEquals(rs.getObject(2, java.time.LocalDate.class), java.time.LocalDate.of(2020, 1, 1)); + rs.next(); + assertEquals(rs.getObject(2, java.time.LocalDate.class), null); + + Timestamp[] timestamps = {Timestamp.valueOf("2020-01-01 12:34:56.789123"), null}; + rs = new ArrayResultSet(timestamps, ClickHouseColumn.parse("v Array(DateTime64(6))").get(0)); + rs.next(); + assertEquals(rs.getObject(2, java.time.LocalDateTime.class), + java.time.LocalDateTime.of(2020, 1, 1, 12, 34, 56, 789123000)); + + Time[] times = {Time.valueOf("12:34:56"), null}; + rs = new ArrayResultSet(times, ClickHouseColumn.parse("v Array(Time)").get(0)); + rs.next(); + assertEquals(rs.getObject(2, java.time.LocalTime.class), java.time.LocalTime.of(12, 34, 56)); + } }