-
Notifications
You must be signed in to change notification settings - Fork 618
[client-v2,jdbc-v2] Fix reading Date/Time values #2727
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…be stored as Integer
…is reduces number of conversions and makes logic simple
… dates are used for simpler reference
Client V2 CoverageCoverage Report
Class Coverage
|
JDBC V2 CoverageCoverage Report
Class Coverage
|
JDBC V1 CoverageCoverage Report
Class Coverage
|
Client V1 CoverageCoverage Report
Class Coverage
|
...rc/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java
Outdated
Show resolved
Hide resolved
client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java
Outdated
Show resolved
Hide resolved
...rc/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java
Outdated
Show resolved
Hide resolved
...rc/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java
Outdated
Show resolved
Hide resolved
...rc/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java
Show resolved
Hide resolved
…ime value and actual time from it
| return getString(schema.columnIndexToName(index)); | ||
| ClickHouseColumn column = schema.getColumnByIndex(index); | ||
| Object value; | ||
| switch (column.getEffectiveDataType()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
each type better represented by different type
| if (converter != null) { | ||
| Object value = readValue(colName); | ||
| if (value == null) { | ||
| if (targetType == NumberConverter.NumberType.BigInteger || targetType == NumberConverter.NumberType.BigDecimal) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BigInteger and BigDecimal are object type so they fine with null.
in the next steps we will move it to converter so this check also go away.
| default: | ||
| throw new ClientException("Column of type " + column.getDataType() + " cannot be converted to Instant"); | ||
| } | ||
| return getInstant(getSchema().nameToColumnIndex(colName)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getting columns by index is more common and values also stored in simple array
| public ZonedDateTime getZonedDateTime(int index) { | ||
| return readValue(index); | ||
| ClickHouseColumn column = schema.getColumnByIndex(index); | ||
| switch (column.getEffectiveDataType()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
previously anything we store as ZonedDateTime will work. But effectively it was only Date values.
Returning Date as ZonedDateTime is completely incorrect because date values do not have time part and timezone.
| @Override | ||
| public LocalDate getLocalDate(int index) { | ||
| ClickHouseColumn column = schema.getColumnByIndex(index); | ||
| switch(column.getEffectiveDataType()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only Date and DateTime values were stored as ZonedDateTime - so nothing changed but Date value conversion to LocalDate is not needed.
| @Override | ||
| public LocalDate getLocalDate(int index) { | ||
| return getLocalDate(schema.columnIndexToName(index)); | ||
| public LocalTime getLocalTime(int index) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New method in the interface.
Only types with time component are converted.
| } | ||
| } else { | ||
| /// shortcut | ||
| if (type == Timestamp.class) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we taking a shortcut here. Next we need to refactor conversion code to make it less complex and more context aware.
client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java
Show resolved
Hide resolved
client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java
Show resolved
Hide resolved
...rc/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java
Outdated
Show resolved
Hide resolved
...rc/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
| ZonedDateTime dateTime = (ZonedDateTime) value; | ||
| return dateTime.toInstant(); | ||
| } | ||
| return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing LocalDate handling in objectToInstant causes inconsistency
Medium Severity
The objectToInstant() helper method handles LocalDateTime and ZonedDateTime but not LocalDate. This creates an inconsistency: calling getInstant() on a regular Date/Date32 column works (lines 672-675 convert via date.atStartOfDay()), but calling getInstant() on a Dynamic/Variant column containing a Date value throws an exception because objectToInstant() returns null for LocalDate. The helper is missing a LocalDate branch that mirrors the regular column handling.
|






Summary
Closes
Checklist
Delete items not relevant to your PR:
Note
Medium Risk
Medium risk because it changes the runtime types returned for
Date/Timecolumns (and their string/JDBC conversions), including a behavior change whereDateis no longer exposed asZonedDateTime, which can break downstream code relying on prior conversions.Overview
Client-v2 now decodes
Date/Date32asLocalDate(timezone-free) andTime/Time64as UTC-backedLocalDateTime, with newgetLocalTime()accessors and updatedgetString()/temporal getters to route through the appropriate typed value (includingDynamic/Variantcoercions).Adds
ClickHouseColumn.getEffectiveDataType()to consistently unwrapSimpleAggregateFunctioncolumns for conversion logic, improves null-handling for several getters (arrays, geo, inet, duration, enums), and updates the binary reader to emit the new date/time representations.JDBC v2 updates
ResultSetdate/time conversions to useLocalDateforDateandLocalDateTimeforTime, adds agetObject()shortcut forDate/Time/Timestamp, and extendsJdbcUtilsconversions (includingDurationfrom time values).Integration tests were added/updated to validate
Date/Timebehavior across time zones and support reading date/time values fromDynamic/Variant(plus refactoring/renaming of some JDBC tests).Written by Cursor Bugbot for commit b23d218. This will update automatically on new commits. Configure here.