diff --git a/src/main/java/com/j256/ormlite/db/Db2DatabaseType.java b/src/main/java/com/j256/ormlite/db/Db2DatabaseType.java index 4d5ced0e..f4533850 100644 --- a/src/main/java/com/j256/ormlite/db/Db2DatabaseType.java +++ b/src/main/java/com/j256/ormlite/db/Db2DatabaseType.java @@ -1,8 +1,16 @@ package com.j256.ormlite.db; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; import java.util.List; -import com.j256.ormlite.field.FieldType; +import com.j256.ormlite.field.*; +import com.j256.ormlite.field.types.OffsetDateTimeType; +import com.j256.ormlite.support.DatabaseResults; /** * IBM DB2 database type information used to create the tables, etc.. @@ -74,4 +82,57 @@ public boolean isOffsetSqlSupported() { // there is no easy way to do this in this database type return false; } + + @Override + public FieldConverter getFieldConverter(DataPersister dataType, FieldType fieldType) { + // we are only overriding certain types + switch (dataType.getSqlType()) { + case LOCAL_DATE: // db2 doesn't support JDBC 4.2 + return DataType.LOCAL_DATE_SQL.getDataPersister(); + case LOCAL_TIME: + return DataType.LOCAL_TIME_SQL.getDataPersister(); + case LOCAL_DATE_TIME: + return DataType.LOCAL_DATE_TIME_SQL.getDataPersister(); + // db2 doesn't seem to support TIME/STAMP WITH TIME ZONE + case OFFSET_TIME: + return null; + case OFFSET_DATE_TIME: + return OffsetToLocalDateTimeSqlType.getSingleton(); + default: + return super.getFieldConverter(dataType, fieldType); + } + } + + private static class OffsetToLocalDateTimeSqlType extends OffsetDateTimeType { + private static final OffsetToLocalDateTimeSqlType singleton = isJavaTimeSupported() ? + new OffsetToLocalDateTimeSqlType() : null; + public static OffsetToLocalDateTimeSqlType getSingleton() { return singleton; } + private OffsetToLocalDateTimeSqlType() { super(SqlType.OFFSET_DATE_TIME, new Class[] { OffsetDateTime.class }); } + protected OffsetToLocalDateTimeSqlType(SqlType sqlType, Class[] classes) { super(sqlType, classes); } + + @Override + public Object parseDefaultString(FieldType fieldType, String defaultStr) throws SQLException { + OffsetDateTime offsetDateTime = (OffsetDateTime) super.parseDefaultString(fieldType, defaultStr); + // convert to local timezone + LocalDateTime localDateTime = offsetDateTime.atZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); + return Timestamp.valueOf(localDateTime); + } + + @Override + public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int columnPos) throws SQLException { + return results.getTimestamp(columnPos); + } + + @Override + public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) { + Timestamp value = (Timestamp) sqlArg; + return OffsetDateTime.of(value.toLocalDateTime(), ZoneOffset.of("Z")); + } + + @Override + public Object javaToSqlArg(FieldType fieldType, Object javaObject) { + OffsetDateTime offsetDateTime = (OffsetDateTime) javaObject; + return Timestamp.valueOf(offsetDateTime.atZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime()); + } + } } diff --git a/src/main/java/com/j256/ormlite/db/DerbyEmbeddedDatabaseType.java b/src/main/java/com/j256/ormlite/db/DerbyEmbeddedDatabaseType.java index b9641623..f51ff790 100644 --- a/src/main/java/com/j256/ormlite/db/DerbyEmbeddedDatabaseType.java +++ b/src/main/java/com/j256/ormlite/db/DerbyEmbeddedDatabaseType.java @@ -14,6 +14,7 @@ import com.j256.ormlite.field.FieldConverter; import com.j256.ormlite.field.FieldType; import com.j256.ormlite.field.SqlType; +import com.j256.ormlite.field.DataType; import com.j256.ormlite.misc.IOUtils; import com.j256.ormlite.misc.SqlExceptionUtil; import com.j256.ormlite.support.DatabaseResults; @@ -73,6 +74,15 @@ public FieldConverter getFieldConverter(DataPersister dataType, FieldType fieldT serializableConverter = new SerializableFieldConverter(); } return serializableConverter; + case LOCAL_DATE: // derby doesn't support JDBC 4.2 + return DataType.LOCAL_DATE_SQL.getDataPersister(); + case LOCAL_TIME: + return DataType.LOCAL_TIME_SQL.getDataPersister(); + case LOCAL_DATE_TIME: + return DataType.LOCAL_DATE_TIME_SQL.getDataPersister(); + case OFFSET_TIME: // derby doesn't seem to support TIME/STAMP WITH TIME ZONE + case OFFSET_DATE_TIME: + return null; default: return super.getFieldConverter(dataType, fieldType); } diff --git a/src/main/java/com/j256/ormlite/db/H2DatabaseType.java b/src/main/java/com/j256/ormlite/db/H2DatabaseType.java index d3f6158f..55c8cd11 100644 --- a/src/main/java/com/j256/ormlite/db/H2DatabaseType.java +++ b/src/main/java/com/j256/ormlite/db/H2DatabaseType.java @@ -3,6 +3,10 @@ import java.util.List; import com.j256.ormlite.field.FieldType; +import com.j256.ormlite.field.SqlType; +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.DataPersister; +import com.j256.ormlite.field.FieldConverter; /** * H2 database type information used to create the tables, etc.. @@ -52,6 +56,20 @@ public void appendLimitValue(StringBuilder sb, long limit, Long offset) { sb.append(limit).append(' '); } + @Override + public void appendOffsetTimeType(StringBuilder sb, FieldType fieldType, int fieldWidth) { + sb.append("TIMESTAMP WITH TIME ZONE"); + } + + @Override + public FieldConverter getFieldConverter(DataPersister dataPersister, FieldType fieldType) { + // H2 doesn't support TIME WITH TIME ZONE + if (dataPersister.getSqlType() == SqlType.OFFSET_TIME) + return DataType.OFFSET_TIME_COMPAT.getDataPersister(); + // default is to use the dataPersister itself + return dataPersister; + } + @Override public boolean isOffsetLimitArgument() { return true; diff --git a/src/main/java/com/j256/ormlite/db/NetezzaDatabaseType.java b/src/main/java/com/j256/ormlite/db/NetezzaDatabaseType.java index 0c35d88c..ff0ee87b 100644 --- a/src/main/java/com/j256/ormlite/db/NetezzaDatabaseType.java +++ b/src/main/java/com/j256/ormlite/db/NetezzaDatabaseType.java @@ -2,6 +2,9 @@ import java.util.List; +import com.j256.ormlite.field.DataPersister; +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.FieldConverter; import com.j256.ormlite.field.FieldType; /** @@ -80,4 +83,22 @@ public void appendSelectNextValFromSequence(StringBuilder sb, String sequenceNam // this is word and not entity unfortunately appendEscapedWord(sb, sequenceName); } + + @Override + public FieldConverter getFieldConverter(DataPersister dataType, FieldType fieldType) { + // we are only overriding certain types + switch (dataType.getSqlType()) { + case LOCAL_DATE: // netezza doesn't seem to support JDBC 4.2 + return DataType.LOCAL_DATE_SQL.getDataPersister(); + case LOCAL_TIME: + return DataType.LOCAL_TIME_SQL.getDataPersister(); + case LOCAL_DATE_TIME: + return DataType.LOCAL_DATE_TIME_SQL.getDataPersister(); + case OFFSET_TIME: + case OFFSET_DATE_TIME: + return null; + default: + return super.getFieldConverter(dataType, fieldType); + } + } } diff --git a/src/main/java/com/j256/ormlite/db/PostgresDatabaseType.java b/src/main/java/com/j256/ormlite/db/PostgresDatabaseType.java index 7c870825..501a9d17 100644 --- a/src/main/java/com/j256/ormlite/db/PostgresDatabaseType.java +++ b/src/main/java/com/j256/ormlite/db/PostgresDatabaseType.java @@ -3,6 +3,10 @@ import java.util.List; import com.j256.ormlite.field.FieldType; +import com.j256.ormlite.field.SqlType; +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.DataPersister; +import com.j256.ormlite.field.FieldConverter; /** * Postgres database type information used to create the tables, etc.. @@ -127,4 +131,18 @@ public boolean isCreateIfNotExistsSupported() { return super.isCreateIfNotExistsSupported(); } } + + @Override + public void appendOffsetTimeType(StringBuilder sb, FieldType fieldType, int fieldWidth) { + sb.append("TIMESTAMP WITH TIME ZONE"); + } + + @Override + public FieldConverter getFieldConverter(DataPersister dataPersister, FieldType fieldType) { + // Postgres doesn't support TIME WITH TIME ZONE + if (dataPersister.getSqlType() == SqlType.OFFSET_TIME) + return DataType.OFFSET_TIME_COMPAT.getDataPersister(); + // default is to use the dataPersister itself + return dataPersister; + } } diff --git a/src/main/java/com/j256/ormlite/db/SqliteDatabaseType.java b/src/main/java/com/j256/ormlite/db/SqliteDatabaseType.java index 695ceb9a..8a9b61ba 100644 --- a/src/main/java/com/j256/ormlite/db/SqliteDatabaseType.java +++ b/src/main/java/com/j256/ormlite/db/SqliteDatabaseType.java @@ -1,5 +1,10 @@ package com.j256.ormlite.db; +import com.j256.ormlite.field.DataPersister; +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.FieldConverter; +import com.j256.ormlite.field.FieldType; + /** * Sqlite database type information used to create the tables, etc.. * @@ -52,4 +57,22 @@ public boolean isNestedSavePointsSupported() { public void appendOffsetValue(StringBuilder sb, long offset) { throw new IllegalStateException("Offset is part of the LIMIT in database type " + getClass()); } + + @Override + public FieldConverter getFieldConverter(DataPersister dataType, FieldType fieldType) { + // we are only overriding certain types + switch (dataType.getSqlType()) { + case LOCAL_DATE: // sqlite doesn't support JDBC 4.2 + return DataType.LOCAL_DATE_SQL.getDataPersister(); + case LOCAL_TIME: + return DataType.LOCAL_TIME_SQL.getDataPersister(); + case LOCAL_DATE_TIME: + return DataType.LOCAL_DATE_TIME_SQL.getDataPersister(); + case OFFSET_TIME: // sqlite doesn't seem to support TIME/STAMP WITH TIME ZONE + case OFFSET_DATE_TIME: + return null; + default: + return super.getFieldConverter(dataType, fieldType); + } + } } diff --git a/src/main/java/com/j256/ormlite/jdbc/JdbcDatabaseResults.java b/src/main/java/com/j256/ormlite/jdbc/JdbcDatabaseResults.java index ce2ebef0..5b2f7415 100644 --- a/src/main/java/com/j256/ormlite/jdbc/JdbcDatabaseResults.java +++ b/src/main/java/com/j256/ormlite/jdbc/JdbcDatabaseResults.java @@ -9,6 +9,13 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Timestamp; +import java.sql.Time; +import java.sql.Date; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.LocalDateTime; +import java.time.OffsetTime; +import java.time.OffsetDateTime; import com.j256.ormlite.dao.ObjectCache; import com.j256.ormlite.misc.IOUtils; @@ -175,6 +182,41 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException { return resultSet.getTimestamp(columnIndex + 1); } + @Override + public Date getDate(int columnIndex) throws SQLException { + return resultSet.getDate(columnIndex + 1); + } + + @Override + public Time getTime(int columnIndex) throws SQLException { + return resultSet.getTime(columnIndex + 1); + } + + @Override + public LocalDate getLocalDate(int columnIndex) throws SQLException { + return resultSet.getObject(columnIndex + 1, LocalDate.class); + } + + @Override + public LocalTime getLocalTime(int columnIndex) throws SQLException { + return resultSet.getObject(columnIndex + 1, LocalTime.class); + } + + @Override + public LocalDateTime getLocalDateTime(int columnIndex) throws SQLException { + return resultSet.getObject(columnIndex + 1, LocalDateTime.class); + } + + @Override + public OffsetTime getOffsetTime(int columnIndex) throws SQLException { + return resultSet.getObject(columnIndex + 1, OffsetTime.class); + } + + @Override + public OffsetDateTime getOffsetDateTime(int columnIndex) throws SQLException { + return resultSet.getObject(columnIndex + 1, OffsetDateTime.class); + } + @Override public BigDecimal getBigDecimal(int columnIndex) throws SQLException { return resultSet.getBigDecimal(columnIndex + 1); diff --git a/src/main/java/com/j256/ormlite/jdbc/TypeValMapper.java b/src/main/java/com/j256/ormlite/jdbc/TypeValMapper.java index f1e525da..bde00c00 100644 --- a/src/main/java/com/j256/ormlite/jdbc/TypeValMapper.java +++ b/src/main/java/com/j256/ormlite/jdbc/TypeValMapper.java @@ -27,8 +27,21 @@ public class TypeValMapper { values = new int[] { Types.LONGVARCHAR }; break; case DATE: + case LOCAL_DATE_TIME: values = new int[] { Types.TIMESTAMP }; break; + case LOCAL_DATE: + values = new int[] { Types.DATE }; + break; + case LOCAL_TIME: + values = new int[] { Types.TIME }; + break; + case OFFSET_TIME: + values = new int[] { Types.TIME_WITH_TIMEZONE }; + break; + case OFFSET_DATE_TIME: + values = new int[] { Types.TIMESTAMP_WITH_TIMEZONE }; + break; case BOOLEAN: values = new int[] { Types.BOOLEAN }; break;