diff 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
line wrap: on
line diff
--- 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.