comparison src/main/java/org/monetdb/jdbc/MonetResultSet.java @ 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 e029af7551b7
children 7eb05cbf67dc
comparison
equal deleted inserted replaced
819:726a1d7b168c 820:4c35009cd59c
36 import java.sql.Statement; 36 import java.sql.Statement;
37 import java.sql.Time; 37 import java.sql.Time;
38 import java.sql.Timestamp; 38 import java.sql.Timestamp;
39 import java.sql.Types; 39 import java.sql.Types;
40 import java.text.SimpleDateFormat; 40 import java.text.SimpleDateFormat;
41 import java.time.OffsetDateTime;
42 import java.time.OffsetTime;
41 import java.util.Calendar; 43 import java.util.Calendar;
42 import java.util.Map; 44 import java.util.Map;
43 import java.util.TimeZone; 45 import java.util.TimeZone;
44 46
45 /** 47 /**
1424 case Types.BLOB: 1426 case Types.BLOB:
1425 return new MonetBlob(val); 1427 return new MonetBlob(val);
1426 case Types.DATE: 1428 case Types.DATE:
1427 return getDate(columnIndex, null); 1429 return getDate(columnIndex, null);
1428 case Types.TIME: 1430 case Types.TIME:
1431 return getTime(columnIndex, null);
1429 case Types.TIME_WITH_TIMEZONE: 1432 case Types.TIME_WITH_TIMEZONE:
1430 return getTime(columnIndex, null); 1433 return getOffsetTime(columnIndex);
1431 case Types.TIMESTAMP: 1434 case Types.TIMESTAMP:
1435 return getTimestamp(columnIndex, null);
1432 case Types.TIMESTAMP_WITH_TIMEZONE: 1436 case Types.TIMESTAMP_WITH_TIMEZONE:
1433 return getTimestamp(columnIndex, null); 1437 return getOffsetDateTime(columnIndex);
1434 case Types.BINARY: 1438 case Types.BINARY:
1435 case Types.VARBINARY: 1439 case Types.VARBINARY:
1436 /* case Types.LONGVARBINARY: // MonetDB doesn't use type LONGVARBINARY */ 1440 /* case Types.LONGVARBINARY: // MonetDB doesn't use type LONGVARBINARY */
1437 return getBytes(columnIndex); 1441 return getBytes(columnIndex);
1438 case Types.OTHER: 1442 case Types.OTHER:
1509 type = MonetDriver.getClassForType(JdbcSQLTypes[columnIndex - 1]); 1513 type = MonetDriver.getClassForType(JdbcSQLTypes[columnIndex - 1]);
1510 } 1514 }
1511 1515
1512 if (type == null || type == String.class) { 1516 if (type == null || type == String.class) {
1513 return val; 1517 return val;
1514 } else if (type == BigDecimal.class) { 1518 }
1519 if (type == BigDecimal.class) {
1515 return getBigDecimal(columnIndex); 1520 return getBigDecimal(columnIndex);
1516 } else if (type == Boolean.class) { 1521 }
1522 if (type == Boolean.class) {
1517 return Boolean.valueOf(getBoolean(columnIndex)); 1523 return Boolean.valueOf(getBoolean(columnIndex));
1518 } else if (type == Short.class) { 1524 }
1525 if (type == Integer.class) {
1526 return Integer.valueOf(getInt(columnIndex));
1527 }
1528 if (type == Long.class) {
1529 return Long.valueOf(getLong(columnIndex));
1530 }
1531 if (type == Short.class) {
1519 return Short.valueOf(getShort(columnIndex)); 1532 return Short.valueOf(getShort(columnIndex));
1520 } else if (type == Integer.class) { 1533 }
1521 return Integer.valueOf(getInt(columnIndex)); 1534 if (type == Double.class) {
1522 } else if (type == Long.class) { 1535 return Double.valueOf(getDouble(columnIndex));
1523 return Long.valueOf(getLong(columnIndex)); 1536 }
1524 } else if (type == Float.class) { 1537 if (type == Float.class) {
1525 return Float.valueOf(getFloat(columnIndex)); 1538 return Float.valueOf(getFloat(columnIndex));
1526 } else if (type == Double.class) { 1539 }
1527 return Double.valueOf(getDouble(columnIndex)); 1540 if (type == Date.class) {
1528 } else if (type == byte[].class) { 1541 return getDate(columnIndex, null);
1542 }
1543 if (type == Time.class) {
1544 return getTime(columnIndex, null);
1545 }
1546 if (type == Timestamp.class) {
1547 return getTimestamp(columnIndex, null);
1548 }
1549 if (type == OffsetTime.class) {
1550 return getOffsetTime(columnIndex);
1551 }
1552 if (type == OffsetDateTime.class) {
1553 return getOffsetDateTime(columnIndex);
1554 }
1555 if (type == Clob.class) {
1556 return getClob(columnIndex);
1557 }
1558 if (type == Blob.class) {
1559 return getBlob(columnIndex);
1560 }
1561 if (type == byte[].class) {
1529 return getBytes(columnIndex); 1562 return getBytes(columnIndex);
1530 } else if (type == Date.class) { 1563 }
1531 return getDate(columnIndex, null); 1564 if (classImplementsSQLData(type)) {
1532 } else if (type == Time.class) {
1533 return getTime(columnIndex, null);
1534 } else if (type == Timestamp.class) {
1535 return getTimestamp(columnIndex, null);
1536 } else if (type == Clob.class) {
1537 return getClob(columnIndex);
1538 } else if (type == Blob.class) {
1539 return getBlob(columnIndex);
1540 } else if (classImplementsSQLData(type)) {
1541 final SQLData x; 1565 final SQLData x;
1542 try { 1566 try {
1543 final java.lang.reflect.Constructor<? extends SQLData> ctor = 1567 final java.lang.reflect.Constructor<? extends SQLData> ctor =
1544 ((Class)type).getConstructor(); 1568 ((Class)type).getConstructor();
1545 x = ctor.newInstance(); 1569 x = ctor.newInstance();
1692 return getRowId(colnum); 1716 return getRowId(colnum);
1693 } 1717 }
1694 }; 1718 };
1695 x.readSQL(input, MonetDBtype); 1719 x.readSQL(input, MonetDBtype);
1696 return x; 1720 return x;
1697 } else { 1721 }
1698 return val; 1722 return val;
1699 }
1700 } 1723 }
1701 1724
1702 /** 1725 /**
1703 * Gets the value of the designated column in the current row of this 1726 * Gets the value of the designated column in the current row of this
1704 * ResultSet object as an Object in the Java programming language. 1727 * ResultSet object as an Object in the Java programming language.
3252 return type.cast(getTime(columnIndex, null)); 3275 return type.cast(getTime(columnIndex, null));
3253 } 3276 }
3254 if (type == Timestamp.class) { 3277 if (type == Timestamp.class) {
3255 return type.cast(getTimestamp(columnIndex, null)); 3278 return type.cast(getTimestamp(columnIndex, null));
3256 } 3279 }
3280 if (type == OffsetTime.class) {
3281 return type.cast(getOffsetTime(columnIndex));
3282 }
3283 if (type == OffsetDateTime.class) {
3284 return type.cast(getOffsetDateTime(columnIndex));
3285 }
3257 if (type == java.util.Date.class) { 3286 if (type == java.util.Date.class) {
3258 final Timestamp timestamp = getTimestamp(columnIndex, null); 3287 final Timestamp timestamp = getTimestamp(columnIndex, null);
3259 return type.cast(new java.util.Date(timestamp.getTime())); 3288 return type.cast(new java.util.Date(timestamp.getTime()));
3260 } 3289 }
3261 if (type == Calendar.class) { 3290 if (type == Calendar.class) {
3360 if (isClosed()) 3389 if (isClosed())
3361 throw new SQLException("ResultSet is closed", "M1M20"); 3390 throw new SQLException("ResultSet is closed", "M1M20");
3362 } 3391 }
3363 3392
3364 /** 3393 /**
3394 * Retrieves the value of the designated column in the current row
3395 * of this ResultSet object and will convert to OffsetTime.
3396 * If the conversion is not supported a SQLException is thrown.
3397 *
3398 * @param columnIndex the first column is 1, the second is 2, ...
3399 * @return OffsetTime object or null
3400 * @throws SQLException if conversion is not supported
3401 */
3402 private OffsetTime getOffsetTime(final int columnIndex) throws SQLException {
3403 final String val;
3404 try {
3405 val = tlp.values[columnIndex - 1];
3406 if (val == null) {
3407 lastReadWasNull = true;
3408 return null;
3409 }
3410 lastReadWasNull = false;
3411 return OffsetTime.parse(val, java.time.format.DateTimeFormatter.ISO_TIME);
3412 } catch (IndexOutOfBoundsException e) {
3413 throw newSQLInvalidColumnIndexException(columnIndex);
3414 } catch (java.time.format.DateTimeParseException e) {
3415 throw new SQLException("Failed to convert to OffsetTime: " + e.getMessage(), "22M36");
3416 }
3417 }
3418
3419 /**
3420 * Retrieves the value of the designated column in the current row
3421 * of this ResultSet object and will convert to OffsetDateTime.
3422 * If the conversion is not supported a SQLException is thrown.
3423 *
3424 * @param columnIndex the first column is 1, the second is 2, ...
3425 * @return OffsetDateTime object or null
3426 * @throws SQLException if conversion is not supported
3427 */
3428 private OffsetDateTime getOffsetDateTime(final int columnIndex) throws SQLException {
3429 final String val;
3430 try {
3431 val = tlp.values[columnIndex - 1];
3432 if (val == null) {
3433 lastReadWasNull = true;
3434 return null;
3435 }
3436 lastReadWasNull = false;
3437
3438 // ISO_OFFSET_DATE_TIME format expects a 'T' instead of a space between date and time parts
3439 // replace the space between date and time parts with 'T'
3440 String val_new = val;
3441 final int space = val.indexOf(' ', 4);
3442 if (space > 4 && space < 16) {
3443 val_new = val.substring(0, space) + "T" + val.substring(space + 1);
3444 }
3445 // System.out.println("getOffsetDateTime() changed " + val + " into " + val_new);
3446 return OffsetDateTime.parse(val_new, java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME);
3447 } catch (IndexOutOfBoundsException e) {
3448 throw newSQLInvalidColumnIndexException(columnIndex);
3449 } catch (java.time.format.DateTimeParseException e) {
3450 throw new SQLException("Failed to convert to OffsetDateTime: " + e.getMessage(), "22M37");
3451 }
3452 }
3453
3454 /**
3365 * Small helper method that formats the "Invalid Column Index number ..." message 3455 * Small helper method that formats the "Invalid Column Index number ..." message
3366 * and creates a new SQLDataException object whose SQLState is set 3456 * and creates a new SQLDataException object whose SQLState is set
3367 * to "22010": invalid indicator parameter value. 3457 * to "22010": invalid indicator parameter value.
3368 * 3458 *
3369 * @param colIdx the column index number 3459 * @param colIdx the column index number