Mercurial > hg > monetdb-java
changeset 820:4c35009cd59c
In ResultSet.getObject() method added support for retrieving
TIMESTAMP WITH TIME ZONE data as java.time.OffsetDateTime object and
TIME WITH TIME ZONE as java.time.OffsetTime object.
Also methods ResultSetMetaData.getColumnClassName() and ParameterMetaData.getParameterClassName() now return
java.time.OffsetDateTime.class for columns of type TIMESTAMP WITH TIME ZONE and
java.time.OffsetTime.class for columns of type TIME WITH TIME ZONE.
author | Martin van Dinther <martin.van.dinther@monetdbsolutions.com> |
---|---|
date | Thu, 14 Dec 2023 14:58:21 +0100 (16 months ago) |
parents | 726a1d7b168c |
children | 8053a633f548 |
files | ChangeLog SQLSTATEs src/main/java/org/monetdb/jdbc/MonetDriver.java src/main/java/org/monetdb/jdbc/MonetResultSet.java tests/JDBC_API_Tester.java |
diffstat | 5 files changed, 144 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,15 @@ # ChangeLog file for monetdb-java # This file is updated with Maddlog +* Thu Dec 14 2023 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- In ResultSet.getObject() method added support for retrieving + TIMESTAMP WITH TIME ZONE data as java.time.OffsetDateTime object + and TIME WITH TIME ZONE as java.time.OffsetTime object. + Also methods ResultSetMetaData.getColumnClassName() and + ParameterMetaData.getParameterClassName() now return + java.time.OffsetDateTime.class for columns of type TIMESTAMP WITH TIME ZONE + and java.time.OffsetTime.class for columns of type TIME WITH TIME ZONE. + * Thu Oct 12 2023 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> - Improved DatabaseMetaData.getSystemFunctions(). It now also returns functions: current_sessionid, greatest, ifnull, least, sql_max, sql_min.
--- a/SQLSTATEs +++ b/SQLSTATEs @@ -27,6 +27,11 @@ 22M29 invalid inet format 22M30 invalid URL format 22M31 invalid UUID format 22M32 invalid JSON format +22M33 invalid Date format +22M34 invalid Time format +22M35 invalid Timestamp format +22M36 invalid Time with time zone format +22M37 invalid Timestamp with time zone format 2BM37 dependent objects still exist 2DM30 autocommit mode active
--- a/src/main/java/org/monetdb/jdbc/MonetDriver.java +++ b/src/main/java/org/monetdb/jdbc/MonetDriver.java @@ -433,11 +433,13 @@ public final class MonetDriver implement case Types.DATE: return java.sql.Date.class; case Types.TIME: + return java.sql.Time.class; case Types.TIME_WITH_TIMEZONE: - return java.sql.Time.class; + return java.time.OffsetTime.class; case Types.TIMESTAMP: + return java.sql.Timestamp.class; case Types.TIMESTAMP_WITH_TIMEZONE: - return java.sql.Timestamp.class; + return java.time.OffsetDateTime.class; case Types.CLOB: return java.sql.Clob.class; case Types.BLOB:
--- a/src/main/java/org/monetdb/jdbc/MonetResultSet.java +++ b/src/main/java/org/monetdb/jdbc/MonetResultSet.java @@ -38,6 +38,8 @@ import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.text.SimpleDateFormat; +import java.time.OffsetDateTime; +import java.time.OffsetTime; import java.util.Calendar; import java.util.Map; import java.util.TimeZone; @@ -1426,11 +1428,13 @@ public class MonetResultSet case Types.DATE: return getDate(columnIndex, null); case Types.TIME: + return getTime(columnIndex, null); case Types.TIME_WITH_TIMEZONE: - return getTime(columnIndex, null); + return getOffsetTime(columnIndex); case Types.TIMESTAMP: + return getTimestamp(columnIndex, null); case Types.TIMESTAMP_WITH_TIMEZONE: - return getTimestamp(columnIndex, null); + return getOffsetDateTime(columnIndex); case Types.BINARY: case Types.VARBINARY: /* case Types.LONGVARBINARY: // MonetDB doesn't use type LONGVARBINARY */ @@ -1511,33 +1515,53 @@ public class MonetResultSet if (type == null || type == String.class) { return val; - } else if (type == BigDecimal.class) { + } + if (type == BigDecimal.class) { return getBigDecimal(columnIndex); - } else if (type == Boolean.class) { + } + if (type == Boolean.class) { return Boolean.valueOf(getBoolean(columnIndex)); - } else if (type == Short.class) { + } + if (type == Integer.class) { + return Integer.valueOf(getInt(columnIndex)); + } + if (type == Long.class) { + return Long.valueOf(getLong(columnIndex)); + } + if (type == Short.class) { return Short.valueOf(getShort(columnIndex)); - } else if (type == Integer.class) { - return Integer.valueOf(getInt(columnIndex)); - } else if (type == Long.class) { - return Long.valueOf(getLong(columnIndex)); - } else if (type == Float.class) { - return Float.valueOf(getFloat(columnIndex)); - } else if (type == Double.class) { + } + if (type == Double.class) { return Double.valueOf(getDouble(columnIndex)); - } else if (type == byte[].class) { - return getBytes(columnIndex); - } else if (type == Date.class) { + } + if (type == Float.class) { + return Float.valueOf(getFloat(columnIndex)); + } + if (type == Date.class) { return getDate(columnIndex, null); - } else if (type == Time.class) { + } + if (type == Time.class) { return getTime(columnIndex, null); - } else if (type == Timestamp.class) { + } + if (type == Timestamp.class) { return getTimestamp(columnIndex, null); - } else if (type == Clob.class) { + } + if (type == OffsetTime.class) { + return getOffsetTime(columnIndex); + } + if (type == OffsetDateTime.class) { + return getOffsetDateTime(columnIndex); + } + if (type == Clob.class) { return getClob(columnIndex); - } else if (type == Blob.class) { + } + if (type == Blob.class) { return getBlob(columnIndex); - } else if (classImplementsSQLData(type)) { + } + if (type == byte[].class) { + return getBytes(columnIndex); + } + if (classImplementsSQLData(type)) { final SQLData x; try { final java.lang.reflect.Constructor<? extends SQLData> ctor = @@ -1694,9 +1718,8 @@ public class MonetResultSet }; x.readSQL(input, MonetDBtype); return x; - } else { - return val; } + return val; } /** @@ -3254,6 +3277,12 @@ public class MonetResultSet if (type == Timestamp.class) { return type.cast(getTimestamp(columnIndex, null)); } + if (type == OffsetTime.class) { + return type.cast(getOffsetTime(columnIndex)); + } + if (type == OffsetDateTime.class) { + return type.cast(getOffsetDateTime(columnIndex)); + } if (type == java.util.Date.class) { final Timestamp timestamp = getTimestamp(columnIndex, null); return type.cast(new java.util.Date(timestamp.getTime())); @@ -3362,6 +3391,67 @@ 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, java.time.format.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"); + } + } + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object and will convert to OffsetDateTime. + * If the conversion is not supported a SQLException is thrown. + * + * @param columnIndex the first column is 1, the second is 2, ... + * @return OffsetDateTime object or null + * @throws SQLException if conversion is not supported + */ + private OffsetDateTime getOffsetDateTime(final int columnIndex) throws SQLException { + final String val; + try { + val = tlp.values[columnIndex - 1]; + if (val == null) { + lastReadWasNull = true; + return null; + } + lastReadWasNull = false; + + // ISO_OFFSET_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("getOffsetDateTime() changed " + val + " into " + val_new); + return OffsetDateTime.parse(val_new, java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } catch (IndexOutOfBoundsException e) { + throw newSQLInvalidColumnIndexException(columnIndex); + } catch (java.time.format.DateTimeParseException e) { + throw new SQLException("Failed to convert to OffsetDateTime: " + e.getMessage(), "22M37"); + } + } + + /** * 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.
--- a/tests/JDBC_API_Tester.java +++ b/tests/JDBC_API_Tester.java @@ -3071,6 +3071,12 @@ final public class JDBC_API_Tester { .append(rs.getTime("t", c)).append(" | ") .append(rs.getTime("tz", c)).append("\n"); + sb.append("getObject:\n") + .append(rs.getObject("ts")).append(" | ") + .append(rs.getObject("tsz")).append(" | ") + .append(rs.getObject("t")).append(" | ") + .append(rs.getObject("tz")).append("\n"); + SQLWarning w = rs.getWarnings(); while (w != null) { sb.append(w.getMessage()).append("\n"); @@ -3109,6 +3115,8 @@ final public class JDBC_API_Tester { "1970-01-01 08:00:00.0 | 1970-01-01 00:00:00.0 | 08:00:00 | 00:00:00\n" + "Africa/Windhoek:\n" + "1969-12-31 22:00:00.0 | 1970-01-01 00:00:00.0 | 22:00:00 | 00:00:00\n" + + "getObject:\n" + + "1970-01-01 00:00:00.0 | 1970-01-01T01:00+01:00 | 00:00:00 | 01:00+01:00\n" + "retrieved row (String):\n" + // old output "1970-01-01 00:00:00.000000 | 1970-01-01 01:00:00.000000+01:00 | 00:00:00 | 01:00:00+01:00\n" + "1970-01-01 00:00:00.000000 | 00:00:00 | \n" + @@ -3118,6 +3126,8 @@ final public class JDBC_API_Tester { "1970-01-01 08:00:00.0 | 1970-01-01 00:00:00.0 | 08:00:00 | 00:00:00\n" + "Africa/Windhoek:\n" + "1969-12-31 22:00:00.0 | 1970-01-01 00:00:00.0 | 22:00:00 | 00:00:00\n" + + "getObject:\n" + + "1970-01-01 00:00:00.0 | 1970-01-01T01:00+01:00 | 00:00:00 | 01:00+01:00\n" + "retrieved row (String):\n" + // old output "1969-12-31 16:00:00.000000 | 1970-01-01 01:00:00.000000+01:00 | 16:00:00 | 01:00:00+01:00\n" + "1969-12-31 16:00:00.000000 | 16:00:00 | \n" + @@ -3127,6 +3137,8 @@ final public class JDBC_API_Tester { "1970-01-01 00:00:00.0 | 1970-01-01 00:00:00.0 | 00:00:00 | 00:00:00\n" + "Africa/Windhoek:\n" + "1969-12-31 14:00:00.0 | 1970-01-01 00:00:00.0 | 14:00:00 | 00:00:00\n" + + "getObject:\n" + + "1969-12-31 16:00:00.0 | 1970-01-01T01:00+01:00 | 16:00:00 | 01:00+01:00\n" + "retrieved row (String):\n" + // old output "1970-01-01 00:00:00.000000 | 1970-01-01 01:00:00.000000+01:00 | 00:00:00 | 01:00:00+01:00\n" + "1970-01-01 00:00:00.000000 | 00:00:00 | \n" + @@ -3136,6 +3148,8 @@ final public class JDBC_API_Tester { "1970-01-01 08:00:00.0 | 1970-01-01 00:00:00.0 | 08:00:00 | 00:00:00\n" + "Africa/Windhoek:\n" + "1969-12-31 22:00:00.0 | 1970-01-01 00:00:00.0 | 22:00:00 | 00:00:00\n" + + "getObject:\n" + + "1970-01-01 00:00:00.0 | 1970-01-01T01:00+01:00 | 00:00:00 | 01:00+01:00\n" + "0. true true\n"); }