Skip to content

Commit e207750

Browse files
committed
Allow to get timestamps from DATE column (1.4)
This is a backport of the PR duckdb#539 to `v1.4-andium` stable branch. This change fixes the NPE when a timestamp is being requested from the `DATE` result column. With it both `rs.getTimestamp(idx)` and `rs.getObject(idx, LocalDateTime.class)` should work. Testing: new tests added to cover `java.sql.Timestamp` and `java.time.LocalDateTime` Fixes: duckdb#537
1 parent 039c537 commit e207750

3 files changed

Lines changed: 53 additions & 3 deletions

File tree

src/main/java/org/duckdb/DuckDBResultSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1356,7 +1356,7 @@ public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
13561356
", SQL type: " + sqlType);
13571357
}
13581358
} else if (type == LocalDateTime.class) {
1359-
if (isTimestamp(sqlType)) {
1359+
if (isTimestamp(sqlType) || sqlType == DuckDBColumnType.DATE) {
13601360
return type.cast(getLocalDateTime(columnIndex));
13611361
} else {
13621362
throw new SQLException("Can't convert value to LocalDateTime, Java type: " + type +

src/main/java/org/duckdb/DuckDBVector.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -632,11 +632,24 @@ private boolean isType(DuckDBColumnType columnType) {
632632
return duckdb_type == columnType;
633633
}
634634

635+
private LocalDateTime getLocalDateTimeFromDate(int idx) throws SQLException {
636+
LocalDate ld = getLocalDate(idx);
637+
if (ld == null) {
638+
return null;
639+
}
640+
return ld.atStartOfDay();
641+
}
642+
635643
Timestamp getTimestamp(int idx, Calendar calNullable) throws SQLException {
636644
if (check_and_null(idx)) {
637645
return null;
638646
}
639-
LocalDateTime ldt = getLocalDateTimeFromTimestamp(idx, calNullable);
647+
final LocalDateTime ldt;
648+
if (duckdb_type == DuckDBColumnType.DATE) {
649+
ldt = getLocalDateTimeFromDate(idx);
650+
} else {
651+
ldt = getLocalDateTimeFromTimestamp(idx, calNullable);
652+
}
640653
if (ldt != null) {
641654
return Timestamp.valueOf(ldt);
642655
}
@@ -648,7 +661,12 @@ Timestamp getTimestamp(int idx, Calendar calNullable) throws SQLException {
648661
}
649662

650663
LocalDateTime getLocalDateTime(int idx) throws SQLException {
651-
LocalDateTime ldt = getLocalDateTimeFromTimestamp(idx, null);
664+
final LocalDateTime ldt;
665+
if (duckdb_type == DuckDBColumnType.DATE) {
666+
ldt = getLocalDateTimeFromDate(idx);
667+
} else {
668+
ldt = getLocalDateTimeFromTimestamp(idx, null);
669+
}
652670
if (ldt != null) {
653671
return ldt;
654672
}

src/test/java/org/duckdb/TestTimestamp.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,4 +581,36 @@ public static void test_timestamp_before_epoch() throws Exception {
581581
TimeZone.setDefault(defaultTimeZone);
582582
}
583583
}
584+
585+
public static void test_timestamp_read_ts_from_date() throws Exception {
586+
try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement();
587+
ResultSet rs = stmt.executeQuery("SELECT '2020-01-02'::DATE")) {
588+
assertTrue(rs.next());
589+
assertEquals(rs.getTimestamp(1).toLocalDateTime().toLocalDate(), LocalDate.of(2020, 1, 2));
590+
assertFalse(rs.next());
591+
}
592+
try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement();
593+
ResultSet rs = stmt.executeQuery("SELECT NULL::DATE")) {
594+
assertTrue(rs.next());
595+
assertNull(rs.getTimestamp(1));
596+
assertTrue(rs.wasNull());
597+
assertFalse(rs.next());
598+
}
599+
}
600+
601+
public static void test_timestamp_read_ldt_from_date() throws Exception {
602+
try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement();
603+
ResultSet rs = stmt.executeQuery("SELECT '2020-01-02'::DATE")) {
604+
assertTrue(rs.next());
605+
assertEquals(rs.getObject(1, LocalDateTime.class).toLocalDate(), LocalDate.of(2020, 1, 2));
606+
assertFalse(rs.next());
607+
}
608+
try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement();
609+
ResultSet rs = stmt.executeQuery("SELECT NULL::DATE")) {
610+
assertTrue(rs.next());
611+
assertNull(rs.getObject(1, LocalDateTime.class));
612+
assertTrue(rs.wasNull());
613+
assertFalse(rs.next());
614+
}
615+
}
584616
}

0 commit comments

Comments
 (0)