Changeset: 7eb05cbf67dc for monetdb-java URL: https://dev.monetdb.org/hg/monetdb-java/rev/7eb05cbf67dc Modified Files: ChangeLog src/main/java/org/monetdb/jdbc/MonetResultSet.java tests/JDBC_API_Tester.java Branch: default Log Message:
In ResultSet.getObject(column, Class<T> type) and ResultSet.getObject(column, Map<String,Class<?>>) methods added support to return objects for classes: java.time.LocalDate, java.time.LocalDateTime. diffs (truncated from 329 to 300 lines): diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ # ChangeLog file for monetdb-java # This file is updated with Maddlog +* Thu Dec 28 2023 Martin van Dinther <martin.van.dint...@monetdbsolutions.com> +- In ResultSet.getObject(column, Class<T> type) and + ResultSet.getObject(column, Map<String,Class<?>>) methods added support + to return objects for classes: java.time.LocalDate, java.time.LocalDateTime + and java.time.LocalTime. + * Wed Dec 20 2023 Martin van Dinther <martin.van.dint...@monetdbsolutions.com> - Enhanced DatabaseMetaData.getTables() method by adding support for SQL table type names: 'BASE TABLE', 'GLOBAL TEMPORARY' and 'LOCAL TEMPORARY' diff --git a/src/main/java/org/monetdb/jdbc/MonetResultSet.java b/src/main/java/org/monetdb/jdbc/MonetResultSet.java --- a/src/main/java/org/monetdb/jdbc/MonetResultSet.java +++ b/src/main/java/org/monetdb/jdbc/MonetResultSet.java @@ -38,8 +38,12 @@ import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.OffsetDateTime; import java.time.OffsetTime; +import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Map; import java.util.TimeZone; @@ -1546,12 +1550,21 @@ public class MonetResultSet if (type == Timestamp.class) { return getTimestamp(columnIndex, null); } - if (type == OffsetTime.class) { - return getOffsetTime(columnIndex); + if (type == LocalDate.class) { + return getLocalDate(columnIndex); + } + if (type == LocalDateTime.class) { + return getLocalDateTime(columnIndex); + } + if (type == LocalTime.class) { + return getLocalTime(columnIndex); } if (type == OffsetDateTime.class) { return getOffsetDateTime(columnIndex); } + if (type == OffsetTime.class) { + return getOffsetTime(columnIndex); + } if (type == Clob.class) { return getClob(columnIndex); } @@ -3277,12 +3290,21 @@ public class MonetResultSet if (type == Timestamp.class) { return type.cast(getTimestamp(columnIndex, null)); } - if (type == OffsetTime.class) { - return type.cast(getOffsetTime(columnIndex)); + if (type == LocalDate.class) { + return type.cast(getLocalDate(columnIndex)); + } + if (type == LocalDateTime.class) { + return type.cast(getLocalDateTime(columnIndex)); + } + if (type == LocalTime.class) { + return type.cast(getLocalTime(columnIndex)); } if (type == OffsetDateTime.class) { return type.cast(getOffsetDateTime(columnIndex)); } + if (type == OffsetTime.class) { + return type.cast(getOffsetTime(columnIndex)); + } if (type == java.util.Date.class) { final Timestamp timestamp = getTimestamp(columnIndex, null); return type.cast(new java.util.Date(timestamp.getTime())); @@ -3392,14 +3414,14 @@ public class MonetResultSet /** * Retrieves the value of the designated column in the current row - * of this ResultSet object and will convert to OffsetTime. + * of this ResultSet object and will convert to LocalDate. * If the conversion is not supported a SQLException is thrown. * * @param columnIndex the first column is 1, the second is 2, ... - * @return OffsetTime object or null + * @return LocalDate object or null * @throws SQLException if conversion is not supported */ - private OffsetTime getOffsetTime(final int columnIndex) throws SQLException { + private LocalDate getLocalDate(final int columnIndex) throws SQLException { final String val; try { val = tlp.values[columnIndex - 1]; @@ -3408,11 +3430,78 @@ public class MonetResultSet return null; } lastReadWasNull = false; - return OffsetTime.parse(val, java.time.format.DateTimeFormatter.ISO_TIME); + + // Note: ISO_LOCAL_DATE format requires the year to have 4 (or more) digits else parse will fail + // This means years -999 to 999 will fail to parse. They should have been zero padded, so -0999 to 0999. + return LocalDate.parse(val, DateTimeFormatter.ISO_LOCAL_DATE); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } catch (java.time.format.DateTimeParseException e) { - throw new SQLException("Failed to convert to OffsetTime: " + e.getMessage(), "22M36"); + throw new SQLException("Failed to convert to LocalDate: " + e.getMessage(), "22M33"); + } + } + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object and will convert to LocalDateTime. + * If the conversion is not supported a SQLException is thrown. + * + * @param columnIndex the first column is 1, the second is 2, ... + * @return LocalDateTime object or null + * @throws SQLException if conversion is not supported + */ + private LocalDateTime getLocalDateTime(final int columnIndex) throws SQLException { + final String val; + try { + val = tlp.values[columnIndex - 1]; + if (val == null) { + lastReadWasNull = true; + return null; + } + lastReadWasNull = false; + + // ISO_LOCAL_DATE_TIME format expects a 'T' instead of a space between date and time parts + // replace the space between date and time parts with 'T' + String val_new = val; + final int space = val.indexOf(' ', 4); + if (space > 4 && space < 16) { + val_new = val.substring(0, space) + "T" + val.substring(space + 1); + // System.out.println("getLocalDateTime() changed " + val + " into " + val_new); + } + + // Note: ISO_LOCAL_DATE_TIME format requires the year to have 4 (or more) digits else parse will fail + // This means years -999 to 999 will fail to parse. They should have been zero padded, so -0999 to 0999. + return LocalDateTime.parse(val_new, DateTimeFormatter.ISO_LOCAL_DATE_TIME); + } catch (IndexOutOfBoundsException e) { + throw newSQLInvalidColumnIndexException(columnIndex); + } catch (java.time.format.DateTimeParseException e) { + throw new SQLException("Failed to convert to LocalDateTime: " + e.getMessage(), "22M35"); + } + } + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object and will convert to LocalTime. + * If the conversion is not supported a SQLException is thrown. + * + * @param columnIndex the first column is 1, the second is 2, ... + * @return LocalTime object or null + * @throws SQLException if conversion is not supported + */ + private LocalTime getLocalTime(final int columnIndex) throws SQLException { + final String val; + try { + val = tlp.values[columnIndex - 1]; + if (val == null) { + lastReadWasNull = true; + return null; + } + lastReadWasNull = false; + return LocalTime.parse(val, DateTimeFormatter.ISO_LOCAL_TIME); + } catch (IndexOutOfBoundsException e) { + throw newSQLInvalidColumnIndexException(columnIndex); + } catch (java.time.format.DateTimeParseException e) { + throw new SQLException("Failed to convert to LocalTime: " + e.getMessage(), "22M34"); } } @@ -3441,9 +3530,12 @@ public class MonetResultSet final int space = val.indexOf(' ', 4); if (space > 4 && space < 16) { val_new = val.substring(0, space) + "T" + val.substring(space + 1); + // System.out.println("getOffsetDateTime() changed " + val + " into " + val_new); } - // System.out.println("getOffsetDateTime() changed " + val + " into " + val_new); - return OffsetDateTime.parse(val_new, java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME); + + // Note: ISO_OFFSET_DATE_TIME format requires the year to have 4 (or more) digits else parse will fail + // This means years -999 to 999 will fail to parse. They should have been zero padded, so -0999 to 0999. + return OffsetDateTime.parse(val_new, DateTimeFormatter.ISO_OFFSET_DATE_TIME); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } catch (java.time.format.DateTimeParseException e) { @@ -3452,6 +3544,32 @@ public class MonetResultSet } /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object and will convert to OffsetTime. + * If the conversion is not supported a SQLException is thrown. + * + * @param columnIndex the first column is 1, the second is 2, ... + * @return OffsetTime object or null + * @throws SQLException if conversion is not supported + */ + private OffsetTime getOffsetTime(final int columnIndex) throws SQLException { + final String val; + try { + val = tlp.values[columnIndex - 1]; + if (val == null) { + lastReadWasNull = true; + return null; + } + lastReadWasNull = false; + return OffsetTime.parse(val, DateTimeFormatter.ISO_TIME); + } catch (IndexOutOfBoundsException e) { + throw newSQLInvalidColumnIndexException(columnIndex); + } catch (java.time.format.DateTimeParseException e) { + throw new SQLException("Failed to convert to OffsetTime: " + e.getMessage(), "22M36"); + } + } + + /** * Small helper method that formats the "Invalid Column Index number ..." message * and creates a new SQLDataException object whose SQLState is set * to "22010": invalid indicator parameter value. diff --git a/tests/JDBC_API_Tester.java b/tests/JDBC_API_Tester.java --- a/tests/JDBC_API_Tester.java +++ b/tests/JDBC_API_Tester.java @@ -39,7 +39,7 @@ import org.monetdb.jdbc.types.URL; */ final public class JDBC_API_Tester { StringBuilder sb; // buffer to collect the test output - final static int sbInitLen = 3712; + final static int sbInitLen = 5224; Connection con; // main connection shared by all tests int dbmsMajorVersion; int dbmsMinorVersion; @@ -4296,12 +4296,15 @@ final public class JDBC_API_Tester { "1. ts 2004-04-24 11:43:53.123000 to ts: 2004-04-24 11:43:53.123\n" + "1. ts 2004-04-24 11:43:53.123000 to tm: 11:43:53\n" + "1. ts 2004-04-24 11:43:53.123000 to dt: 2004-04-24\n" + + "1. ts 2004-04-24 11:43:53.123000 to LocalDateTime: 2004-04-24T11:43:53.123\n" + "2. t 11:43:53 to ts: 1970-01-01 11:43:53.0\n" + "2. t 11:43:53 to tm: 11:43:53\n" + "2. t 11:43:53 to dt: 1970-01-01\n" + + "2. t 11:43:53 to LocalTime: 11:43:53\n" + "3. d 2004-04-24 to ts: 2004-04-24 00:00:00.0\n" + "3. d 2004-04-24 to tm: 00:00:00\n" + "3. d 2004-04-24 to dt: 2004-04-24\n" + + "3. d 2004-04-24 to LocalDate: 2004-04-24\n" + "4. vc 2004-04-24 11:43:53.654321 to ts: 2004-04-24 11:43:53.654321\n" + "4. vc 2004-04-24 11:43:53.654321 to tm: rs.getTime(colnm) failed with error: parsing failed at pos 5 found: '-' in '2004-04-24 11:43:53.654321'\n" + "4. vc 2004-04-24 11:43:53.654321 to dt: 2004-04-24\n" + @@ -4314,21 +4317,27 @@ final public class JDBC_API_Tester { "11. ts 904-04-24 11:43:53.567000 to ts: 0904-04-24 11:43:53.567\n" + "11. ts 904-04-24 11:43:53.567000 to tm: 11:43:53\n" + "11. ts 904-04-24 11:43:53.567000 to dt: 0904-04-24\n" + + "11. ts 904-04-24 11:43:53.567000 to LocalDateTime: rs.getObject(colnm, class<T>): Failed to convert to LocalDateTime: Text '904-04-24T11:43:53.567000' could not be parsed at index 0\n" + "12. ts 74-04-24 11:43:53.567000 to ts: 0074-04-24 11:43:53.567\n" + "12. ts 74-04-24 11:43:53.567000 to tm: 11:43:53\n" + "12. ts 74-04-24 11:43:53.567000 to dt: 0074-04-24\n" + + "12. ts 74-04-24 11:43:53.567000 to LocalDateTime: rs.getObject(colnm, class<T>): Failed to convert to LocalDateTime: Text '74-04-24T11:43:53.567000' could not be parsed at index 0\n" + "13. ts 4-04-24 11:43:53.567000 to ts: 0004-04-24 11:43:53.567\n" + "13. ts 4-04-24 11:43:53.567000 to tm: 11:43:53\n" + "13. ts 4-04-24 11:43:53.567000 to dt: 0004-04-24\n" + + "13. ts 4-04-24 11:43:53.567000 to LocalDateTime: rs.getObject(colnm, class<T>): Failed to convert to LocalDateTime: Text '4-04-24T11:43:53.567000' could not be parsed at index 0\n" + "14. d 904-04-24 to ts: 0904-04-24 00:00:00.0\n" + "14. d 904-04-24 to tm: 00:00:00\n" + "14. d 904-04-24 to dt: 0904-04-24\n" + + "14. d 904-04-24 to LocalDate: rs.getObject(colnm, class<T>): Failed to convert to LocalDate: Text '904-04-24' could not be parsed at index 0\n" + "15. d 74-04-24 to ts: 0074-04-24 00:00:00.0\n" + "15. d 74-04-24 to tm: 00:00:00\n" + "15. d 74-04-24 to dt: 0074-04-24\n" + + "15. d 74-04-24 to LocalDate: rs.getObject(colnm, class<T>): Failed to convert to LocalDate: Text '74-04-24' could not be parsed at index 0\n" + "16. d 4-04-24 to ts: 0004-04-24 00:00:00.0\n" + "16. d 4-04-24 to tm: 00:00:00\n" + "16. d 4-04-24 to dt: 0004-04-24\n" + + "16. d 4-04-24 to LocalDate: rs.getObject(colnm, class<T>): Failed to convert to LocalDate: Text '4-04-24' could not be parsed at index 0\n" + "17. vc 904-04-24 11:43:53.567 to ts: 0904-04-24 11:43:53.567\n" + "17. vc 904-04-24 11:43:53.567 to tm: rs.getTime(colnm) failed with error: parsing failed at pos 4 found: '-' in '904-04-24 11:43:53.567'\n" + "17. vc 904-04-24 11:43:53.567 to dt: 0904-04-24\n" + @@ -4341,15 +4350,19 @@ final public class JDBC_API_Tester { "21. ts -4-04-24 11:43:53.567000 to ts: 0004-04-24 11:43:53.567\n" + "21. ts -4-04-24 11:43:53.567000 to tm: 11:43:53\n" + "21. ts -4-04-24 11:43:53.567000 to dt: 0004-04-24\n" + + "21. ts -4-04-24 11:43:53.567000 to LocalDateTime: rs.getObject(colnm, class<T>): Failed to convert to LocalDateTime: Text '-4-04-24T11:43:53.567000' could not be parsed at index 1\n" + "22. ts -2004-04-24 11:43:53.567000 to ts: 2004-04-24 11:43:53.567\n" + "22. ts -2004-04-24 11:43:53.567000 to tm: 11:43:53\n" + "22. ts -2004-04-24 11:43:53.567000 to dt: 2004-04-24\n" + + "22. ts -2004-04-24 11:43:53.567000 to LocalDateTime: -2004-04-24T11:43:53.567\n" + "23. d -4-04-24 to ts: 0004-04-24 00:00:00.0\n" + "23. d -4-04-24 to tm: 00:00:00\n" + "23. d -4-04-24 to dt: 0004-04-24\n" + + "23. d -4-04-24 to LocalDate: rs.getObject(colnm, class<T>): Failed to convert to LocalDate: Text '-4-04-24' could not be parsed at index 1\n" + "24. d -3004-04-24 to ts: 3004-04-24 00:00:00.0\n" + "24. d -3004-04-24 to tm: 00:00:00\n" + "24. d -3004-04-24 to dt: 3004-04-24\n" + + "24. d -3004-04-24 to LocalDate: -3004-04-24\n" + _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org