diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/Database.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/Database.java index 2ce2ee0..c941ae9 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/Database.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/Database.java @@ -1,7 +1,7 @@ package org.xbib.jdbc.query; import java.sql.Connection; -import java.util.Date; +import java.time.LocalDateTime; import java.util.function.Supplier; /** @@ -90,7 +90,7 @@ public interface Database extends Supplier { /** * Get the value that would be used if you specify an argNowPerApp() parameter. */ - Date nowPerApp(); + LocalDateTime nowPerApp(); /** * Cause the underlying connection to commit its transaction immediately. This diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/DatabaseImpl.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/DatabaseImpl.java index 705b0b2..f1d5e47 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/DatabaseImpl.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/DatabaseImpl.java @@ -5,8 +5,9 @@ import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; +import java.time.Duration; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.Date; import java.util.logging.Logger; /** @@ -90,7 +91,7 @@ public class DatabaseImpl implements Database { } @Override - public Date nowPerApp() { + public LocalDateTime nowPerApp() { return options.currentDate(); } @@ -249,25 +250,26 @@ public class DatabaseImpl implements Database { public void assertTimeSynchronized(long millisToWarn, long millisToError) { toSelect("select ?" + flavor().fromAny()) .argDateNowPerDb().queryFirstOrNull(r -> { - Date appDate = nowPerApp(); - Date dbDate = r.getDateOrNull(); + LocalDateTime appDate = nowPerApp(); + LocalDateTime dbDate = r.getLocalDateTimeOrNull(); if (dbDate == null) { throw new DatabaseException("Expecting a date in the result"); } - if (Math.abs(appDate.getTime() - dbDate.getTime()) > 3600000) { + Duration duration = Duration.between(appDate, dbDate).abs(); + if (duration.getSeconds() > 3600) { throw new DatabaseException("App and db time are over an hour apart (check your timezones) app: " - + DateTimeFormatter.ISO_INSTANT.format(appDate.toInstant()) + " db: " - + DateTimeFormatter.ISO_INSTANT.format(dbDate.toInstant())); + + DateTimeFormatter.ISO_INSTANT.format(appDate) + " db: " + + DateTimeFormatter.ISO_INSTANT.format(dbDate)); } - if (Math.abs(appDate.getTime() - dbDate.getTime()) > millisToError) { + if (duration.getSeconds() * 1000 > millisToError) { throw new DatabaseException("App and db time over " + millisToError + " millis apart (check your clocks) app: " - + DateTimeFormatter.ISO_INSTANT.format(appDate.toInstant()) + " db: " - + DateTimeFormatter.ISO_INSTANT.format(dbDate.toInstant())); + + DateTimeFormatter.ISO_INSTANT.format(appDate) + " db: " + + DateTimeFormatter.ISO_INSTANT.format(dbDate)); } - if (Math.abs(appDate.getTime() - dbDate.getTime()) > millisToWarn) { + if (duration.getSeconds() * 1000 > millisToWarn) { log.warning("App and db time are over " + millisToWarn + " millis apart (check your clocks) app: " - + DateTimeFormatter.ISO_INSTANT.format(appDate.toInstant()) + " db: " - + DateTimeFormatter.ISO_INSTANT.format(dbDate.toInstant())); + + DateTimeFormatter.ISO_INSTANT.format(appDate) + " db: " + + DateTimeFormatter.ISO_INSTANT.format(dbDate)); } return null; }); diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/Flavor.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/Flavor.java index 8eb8ea9..d98a58b 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/Flavor.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/Flavor.java @@ -1,8 +1,9 @@ package org.xbib.jdbc.query; +import java.sql.Date; +import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Calendar; -import java.util.Date; /** * Enumeration of supported databases with various compatibility settings. @@ -131,8 +132,8 @@ public enum Flavor { } @Override - public String dateAsSqlFunction(Date date, Calendar calendar) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000"); + public String dateAsSqlFunction(Timestamp date, Calendar calendar) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); dateFormat.setCalendar(calendar); return "timestamp('" + dateFormat.format(date) + "')"; } @@ -279,7 +280,7 @@ public enum Flavor { } @Override - public String dateAsSqlFunction(Date date, Calendar calendar) { + public String dateAsSqlFunction(Timestamp date, Calendar calendar) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000"); dateFormat.setCalendar(calendar); return "cast('" + dateFormat.format(date) + "' as datetime2(3))"; @@ -425,7 +426,7 @@ public enum Flavor { } @Override - public String dateAsSqlFunction(Date date, Calendar calendar) { + public String dateAsSqlFunction(Timestamp date, Calendar calendar) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000"); dateFormat.setCalendar(calendar); return "timestamp '" + dateFormat.format(date) + "'"; @@ -568,7 +569,7 @@ public enum Flavor { } @Override - public String dateAsSqlFunction(Date date, Calendar calendar) { + public String dateAsSqlFunction(Timestamp date, Calendar calendar) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000"); dateFormat.setCalendar(calendar); return "'" + dateFormat.format(date) + " GMT'::timestamp"; @@ -711,7 +712,7 @@ public enum Flavor { } @Override - public String dateAsSqlFunction(Date date, Calendar calendar) { + public String dateAsSqlFunction(Timestamp date, Calendar calendar) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000XXX"); dateFormat.setCalendar(calendar); return "cast(timestamp '" + dateFormat.format(date) + "' as timestamp without time zone)"; @@ -855,7 +856,7 @@ public enum Flavor { } @Override - public String dateAsSqlFunction(Date date, Calendar calendar) { + public String dateAsSqlFunction(Timestamp date, Calendar calendar) { // Construct a datetime literal SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000"); dateFormat.setCalendar(calendar); @@ -980,7 +981,7 @@ public enum Flavor { * Return a SQL function representing the specified date. For example, in PostgreSQL this * looks like "'1970-01-02 02:17:36.789000 GMT'::timestamp". */ - public abstract String dateAsSqlFunction(Date date, Calendar calendar); + public abstract String dateAsSqlFunction(Timestamp timestamp, Calendar calendar); /** * Return a SQL function representing the specified date without time. diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/Options.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/Options.java index 9667b6b..ddf5057 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/Options.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/Options.java @@ -1,7 +1,7 @@ package org.xbib.jdbc.query; +import java.time.LocalDateTime; import java.util.Calendar; -import java.util.Date; /** * Control various optional behavior for the database interactions. @@ -98,7 +98,7 @@ public interface Options { * The value returned by this method will be used for argDateNowPerApp() calls. It * may also be used for argDateNowPerDb() calls if you have enabled that. */ - Date currentDate(); + LocalDateTime currentDate(); /** * Wherever argDateNowPerDb() is specified, use argDateNowPerApp() instead. This is diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/OptionsDefault.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/OptionsDefault.java index 44a4911..1015de0 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/OptionsDefault.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/OptionsDefault.java @@ -1,6 +1,7 @@ package org.xbib.jdbc.query; import java.text.SimpleDateFormat; +import java.time.LocalDateTime; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; @@ -63,8 +64,8 @@ public class OptionsDefault implements Options { } @Override - public Date currentDate() { - return new Date(); + public LocalDateTime currentDate() { + return LocalDateTime.now(); } @Override diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/OptionsOverride.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/OptionsOverride.java index 6994a0a..1f684fb 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/OptionsOverride.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/OptionsOverride.java @@ -1,5 +1,6 @@ package org.xbib.jdbc.query; +import java.time.LocalDateTime; import java.util.Calendar; import java.util.Date; @@ -87,7 +88,7 @@ public class OptionsOverride implements Options { } @Override - public Date currentDate() { + public LocalDateTime currentDate() { return parent.currentDate(); } diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/Row.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/Row.java index 3f99ebe..3f3f322 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/Row.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/Row.java @@ -5,7 +5,7 @@ import java.io.Reader; import java.math.BigDecimal; import java.sql.ResultSetMetaData; import java.time.LocalDate; -import java.util.Date; +import java.time.LocalDateTime; /** * Interface for reading results from a database query. @@ -386,33 +386,20 @@ public interface Row { InputStream getBlobInputStreamOrEmpty(int columnOneBased); - InputStream getBlobInputStreamOrEmpty(String columnName); - /** - * Return the millisecond precision Date, which should be represented as a TIMESTAMP - * in the database. The nanoseconds are truncated. - */ + LocalDateTime getLocalDateTimeOrNull(); - Date getDateOrNull(); - - /** - * Return the millisecond precision Date, which should be represented as a TIMESTAMP - * in the database. The nanoseconds are truncated. - */ + LocalDateTime getLocalDateTimeOrNull(int columnOneBased); - Date getDateOrNull(int columnOneBased); - - - Date getDateOrNull(String columnName); + LocalDateTime getLocalDateTimeOrNull(String columnName); /** * Retrieve column as LocalDate, .i.e, date with no time. * * @return LocalDate of the database column value */ - LocalDate getLocalDateOrNull(); /** diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/RowsAdaptor.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/RowsAdaptor.java index c427f31..0782c86 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/RowsAdaptor.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/RowsAdaptor.java @@ -10,7 +10,7 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Timestamp; import java.time.LocalDate; -import java.util.Date; +import java.time.LocalDateTime; /** * Safely wrap a ResultSet and provide access to the data it contains. @@ -52,7 +52,6 @@ class RowsAdaptor implements Rows { throw new DatabaseException("Unable to retrieve metadata from ResultSet", e); } } - @Override public ResultSetMetaData getMetadata() { @@ -62,13 +61,11 @@ class RowsAdaptor implements Rows { throw new DatabaseException("Unable to retrieve metadata from ResultSet", e); } } - @Override public Boolean getBooleanOrNull() { return getBooleanOrNull(column++); } - @Override public Boolean getBooleanOrNull(int columnOneBased) { @@ -79,7 +76,6 @@ class RowsAdaptor implements Rows { throw new DatabaseException(e); } } - @Override public Boolean getBooleanOrNull(String columnName) { @@ -660,36 +656,32 @@ class RowsAdaptor implements Rows { } return result; } - @Override - public Date getDateOrNull() { - return getDateOrNull(column++); + public LocalDateTime getLocalDateTimeOrNull() { + return getLocalDateTimeOrNull(column++); } - @Override - public Date getDateOrNull(int columnOneBased) { + public LocalDateTime getLocalDateTimeOrNull(int columnOneBased) { try { column = columnOneBased + 1; - return toDate(rs, columnOneBased); + return toLocalDateTime(rs, columnOneBased); } catch (SQLException e) { throw new DatabaseException(e); } } - @Override - public Date getDateOrNull(String columnName) { + public LocalDateTime getLocalDateTimeOrNull(String columnName) { try { column = rs.findColumn(columnName) + 1; - return toDate(rs, columnName); + return toLocalDateTime(rs, columnName); } catch (SQLException e) { throw new DatabaseException(e); } } - @Override public LocalDate getLocalDateOrNull() { return getLocalDateOrNull(column++); @@ -720,31 +712,21 @@ class RowsAdaptor implements Rows { @Override public Integer rowCount() { try { - //rs.last(); + rs.last(); return rs.getRow(); } catch (SQLException e) { throw new DatabaseException(e); } } - /** - * Make sure the Timestamp will return getTime() accurate to the millisecond - * (if possible) and truncate away nanoseconds. - */ - private Date timestampToDate(Timestamp ts) { - long millis = ts.getTime(); - int nanos = ts.getNanos(); - return new Date(millis / 1000 * 1000 + nanos / 1000000); + private LocalDateTime toLocalDateTime(ResultSet rs, int col) throws SQLException { + Timestamp val = rs.getTimestamp(col, options.calendarForTimestamps()); + return val == null ? null : val.toLocalDateTime(); } - private Date toDate(ResultSet rs, int col) throws SQLException { + private LocalDateTime toLocalDateTime(ResultSet rs, String col) throws SQLException { Timestamp val = rs.getTimestamp(col, options.calendarForTimestamps()); - return val == null ? null : timestampToDate(val); - } - - private Date toDate(ResultSet rs, String col) throws SQLException { - Timestamp val = rs.getTimestamp(col, options.calendarForTimestamps()); - return val == null ? null : timestampToDate(val); + return val == null ? null : val.toLocalDateTime(); } private LocalDate toLocalDate(ResultSet rs, int col) throws SQLException { diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/Sql.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/Sql.java index 091e159..0af84da 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/Sql.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/Sql.java @@ -3,9 +3,9 @@ package org.xbib.jdbc.query; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; -import java.util.Date; import java.util.List; import java.util.Stack; @@ -309,15 +309,14 @@ public class Sql implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Apply { sqlArgs.argString(argName, arg); return this; } - - public Sql argDate(Date arg) { + public Sql argDate(LocalDateTime arg) { sqlArgs.argDate(arg); return this; } - public Sql argDate( String argName, Date arg) { + public Sql argDate( String argName, LocalDateTime arg) { sqlArgs.argDate(argName, arg); return this; } diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlArgs.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlArgs.java index 7ee86cf..4190755 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlArgs.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlArgs.java @@ -7,8 +7,8 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; @@ -20,7 +20,6 @@ import java.util.Set; */ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Apply { private final List invocations = new ArrayList<>(); - public static Builder fromMetadata(Row r) { return new Builder(r); @@ -147,14 +146,14 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl } - public SqlArgs argDate(Date arg) { + public SqlArgs argDate(LocalDateTime arg) { // date argument with a time on it invocations.add(new Invocation(ColumnType.Date, null, arg)); return this; } - public SqlArgs argDate( String argName, Date arg) { + public SqlArgs argDate( String argName, LocalDateTime arg) { // date argument with a time on it invocations.add(new Invocation(ColumnType.Date, argName, arg)); return this; @@ -347,7 +346,6 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl case BlobStream: throw new DatabaseException("Don't use Blob parameters with select statements"); case LocalDate: - // date argument with no time on it if (i.argName == null) { select.argLocalDate((LocalDate) i.arg); } else { @@ -355,11 +353,10 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl } break; case Date: - // date argument with a time on it if (i.argName == null) { - select.argDate((Date) i.arg); + select.argDate((LocalDateTime) i.arg); } else { - select.argDate(i.argName, (Date) i.arg); + select.argDate(i.argName, (LocalDateTime) i.arg); } break; case DateNowPerApp: @@ -473,9 +470,9 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl case Date: // date argument with a time on it if (i.argName == null) { - insert.argDate((Date) i.arg); + insert.argDate((LocalDateTime) i.arg); } else { - insert.argDate(i.argName, (Date) i.arg); + insert.argDate(i.argName, (LocalDateTime) i.arg); } break; case DateNowPerApp: @@ -579,7 +576,6 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl } break; case LocalDate: - // date argument with no time on it if (i.argName == null) { update.argLocalDate((LocalDate) i.arg); } else { @@ -587,11 +583,10 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl } break; case Date: - // date argument with a time on it if (i.argName == null) { - update.argDate((Date) i.arg); + update.argDate((LocalDateTime) i.arg); } else { - update.argDate(i.argName, (Date) i.arg); + update.argDate(i.argName, (LocalDateTime) i.arg); } break; case DateNowPerApp: @@ -748,7 +743,7 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl // Anything with a time will have a non-zero scale args.argLocalDate(names[i], r.getLocalDateOrNull()); } else { - args.argDate(names[i], r.getDateOrNull()); + args.argDate(names[i], r.getLocalDateTimeOrNull()); } break; diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlInsert.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlInsert.java index ff5119c..ccdfecd 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlInsert.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlInsert.java @@ -4,7 +4,7 @@ import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.time.LocalDate; -import java.util.Date; +import java.time.LocalDateTime; /** * Interface for configuring (setting parameters) and executing a chunk of SQL. @@ -33,15 +33,15 @@ public interface SqlInsert { SqlInsert argBigDecimal(BigDecimal arg); - SqlInsert argBigDecimal( String argName, BigDecimal arg); + SqlInsert argBigDecimal(String argName, BigDecimal arg); SqlInsert argString(String arg); SqlInsert argString( String argName, String arg); - SqlInsert argDate(Date arg); // date with time + SqlInsert argDate(LocalDateTime arg); // date with time - SqlInsert argDate( String argName, Date arg); // date with time + SqlInsert argDate(String argName, LocalDateTime arg); // date with time SqlInsert argLocalDate(LocalDate arg); // date only - no timestamp diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlInsertImpl.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlInsertImpl.java index 9fcdcea..09db1fd 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlInsertImpl.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlInsertImpl.java @@ -13,9 +13,9 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -125,43 +125,36 @@ public class SqlInsertImpl implements SqlInsert { } @Override - public SqlInsert argBigDecimal( String argName, BigDecimal arg) { return namedArg(argName, adaptor.nullNumeric(arg)); } @Override - public SqlInsert argString(String arg) { return positionalArg(adaptor.nullString(arg)); } @Override - public SqlInsert argString( String argName, String arg) { return namedArg(argName, adaptor.nullString(arg)); } @Override - - public SqlInsert argDate(Date arg) { + public SqlInsert argDate(LocalDateTime arg) { return positionalArg(adaptor.nullDate(arg)); } @Override - - public SqlInsert argDate( String argName, Date arg) { + public SqlInsert argDate( String argName, LocalDateTime arg) { return namedArg(argName, adaptor.nullDate(arg)); } @Override - public SqlInsert argLocalDate( String argName, LocalDate arg) { return namedArg(argName, adaptor.nullLocalDate(arg)); } @Override - public SqlInsert argLocalDate(LocalDate arg) { return positionalArg(adaptor.nullLocalDate(arg)); } @@ -173,11 +166,9 @@ public class SqlInsertImpl implements SqlInsert { } @Override - public SqlInsert argDateNowPerApp( String argName) { return namedArg(argName, adaptor.nullDate(options.currentDate())); } - @Override public SqlInsert argDateNowPerDb() { diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlSelect.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlSelect.java index 82985c8..12ed371 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlSelect.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlSelect.java @@ -2,7 +2,7 @@ package org.xbib.jdbc.query; import java.math.BigDecimal; import java.time.LocalDate; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; /** @@ -67,11 +67,9 @@ public interface SqlSelect { - SqlSelect argDate(Date arg); // Date with time + SqlSelect argDate(LocalDateTime arg); // Date with time - - - SqlSelect argDate( String argName, Date arg); // Date with time + SqlSelect argDate(String argName, LocalDateTime arg); // Date with time @@ -207,11 +205,11 @@ public interface SqlSelect { - Date queryDateOrNull(); // Date with time + LocalDateTime queryDateOrNull(); // Date with time - List queryDates(); // Date with time + List queryDates(); // Date with time diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlSelectImpl.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlSelectImpl.java index 7d4963c..7c92936 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlSelectImpl.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlSelectImpl.java @@ -10,8 +10,8 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -140,14 +140,14 @@ public class SqlSelectImpl implements SqlSelect { @Override - public SqlSelect argDate(Date arg) { + public SqlSelect argDate(LocalDateTime arg) { // Date with time return positionalArg(adaptor.nullDate(arg)); } @Override - public SqlSelect argDate( String argName, Date arg) { + public SqlSelect argDate( String argName, LocalDateTime arg) { // Date with time return namedArg(argName, adaptor.nullDate(arg)); } @@ -467,21 +467,21 @@ public class SqlSelectImpl implements SqlSelect { } @Override - public Date queryDateOrNull() { + public LocalDateTime queryDateOrNull() { return queryWithTimeout(rs -> { if (rs.next()) { - return rs.getDateOrNull(1); + return rs.getLocalDateTimeOrNull(1); } return null; }); } @Override - public List queryDates() { + public List queryDates() { return queryWithTimeout(rs -> { - List result = new ArrayList<>(); + List result = new ArrayList<>(); while (rs.next()) { - Date value = rs.getDateOrNull(1); + LocalDateTime value = rs.getLocalDateTimeOrNull(1); if (value != null) { result.add(value); } @@ -619,7 +619,9 @@ public class SqlSelectImpl implements SqlSelect { if (connection != null) { synchronized (cancelLock) { - ps = connection.prepareStatement(executeSql); + ps = connection.prepareStatement(executeSql, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); } if (timeoutSeconds >= 0) { diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlUpdate.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlUpdate.java index e2c14cc..a20f90f 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlUpdate.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlUpdate.java @@ -4,137 +4,74 @@ import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.time.LocalDate; -import java.util.Date; +import java.time.LocalDateTime; /** * Interface for configuring (setting parameters) and executing a chunk of SQL. */ public interface SqlUpdate { - SqlUpdate argBoolean(Boolean arg); - - SqlUpdate argBoolean( String argName, Boolean arg); - - SqlUpdate argInteger(Integer arg); - - SqlUpdate argInteger( String argName, Integer arg); - - SqlUpdate argLong(Long arg); - - SqlUpdate argLong( String argName, Long arg); - - SqlUpdate argFloat(Float arg); - - SqlUpdate argFloat( String argName, Float arg); - - SqlUpdate argDouble(Double arg); - - SqlUpdate argDouble( String argName, Double arg); - - SqlUpdate argBigDecimal(BigDecimal arg); - - SqlUpdate argBigDecimal( String argName, BigDecimal arg); - - SqlUpdate argString(String arg); - - SqlUpdate argString( String argName, String arg); + + SqlUpdate argDate(LocalDateTime arg); + + SqlUpdate argDate( String argName, LocalDateTime arg); - - - SqlUpdate argDate(Date arg); // Date with timestamp + SqlUpdate argLocalDate(LocalDate arg); - - - SqlUpdate argDate( String argName, Date arg); // Date with timestamp + SqlUpdate argLocalDate( String argName, LocalDate arg); - - - SqlUpdate argLocalDate(LocalDate arg); // Date only - no timestamp - - - - SqlUpdate argLocalDate( String argName, LocalDate arg); // Date only - no timestamp - - - SqlUpdate argDateNowPerApp(); - - SqlUpdate argDateNowPerApp( String argName); - - SqlUpdate argDateNowPerDb(); - - SqlUpdate argDateNowPerDb( String argName); - - SqlUpdate argBlobBytes(byte[] arg); - - SqlUpdate argBlobBytes( String argName, byte[] arg); - - SqlUpdate argBlobStream(InputStream arg); - - SqlUpdate argBlobStream( String argName, InputStream arg); - - SqlUpdate argClobString(String arg); - - SqlUpdate argClobString( String argName, String arg); - - SqlUpdate argClobReader(Reader arg); - - SqlUpdate argClobReader( String argName, Reader arg); - - SqlUpdate withArgs(SqlArgs args); - - SqlUpdate apply(Apply apply); @@ -151,14 +88,6 @@ public interface SqlUpdate { */ void update(int expectedRowsUpdated); - /** - * Call this between setting rows of parameters for a SQL statement. You may call it before - * setting any parameters, after setting all, or multiple times between rows. - */ -// SqlUpdate batch(); - -// SqlUpdate withTimeoutSeconds(int seconds); - interface Apply { void apply(SqlUpdate update); } diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlUpdateImpl.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlUpdateImpl.java index 98d01ed..822d34a 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlUpdateImpl.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/SqlUpdateImpl.java @@ -11,8 +11,8 @@ import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -131,32 +131,27 @@ public class SqlUpdateImpl implements SqlUpdate { @Override - public SqlUpdate argDate(Date arg) { - // Date with time + public SqlUpdate argDate(LocalDateTime arg) { return positionalArg(adaptor.nullDate(arg)); } @Override - public SqlUpdate argDate(String argName, Date arg) { - // Date with time + public SqlUpdate argDate(String argName, LocalDateTime arg) { return namedArg(argName, adaptor.nullDate(arg)); } @Override public SqlUpdate argLocalDate(LocalDate arg) { - // Date with no time return positionalArg(adaptor.nullLocalDate(arg)); } @Override public SqlUpdate argLocalDate(String argName, LocalDate arg) { - // Date with no time return namedArg(argName, adaptor.nullLocalDate(arg)); } - @Override public SqlUpdate argDateNowPerApp() { @@ -169,7 +164,6 @@ public class SqlUpdateImpl implements SqlUpdate { return namedArg(argName, adaptor.nullDate(options.currentDate())); } - @Override public SqlUpdate argDateNowPerDb() { if (options.useDatePerAppOnly()) { diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/StatementAdaptor.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/StatementAdaptor.java index 47099da..e228108 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/StatementAdaptor.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/StatementAdaptor.java @@ -12,6 +12,7 @@ import java.sql.Statement; import java.sql.Timestamp; import java.sql.Types; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.Date; import java.util.Scanner; import java.util.logging.Level; @@ -142,11 +143,11 @@ public class StatementAdaptor { } } - public Object nullDate(Date arg) { + public Object nullDate(LocalDateTime arg) { if (arg == null) { return new SqlNull(Types.TIMESTAMP); } - return new Timestamp(arg.getTime()); + return Timestamp.valueOf(arg); } // Processes a true date without time information. diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/util/DebugSql.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/util/DebugSql.java index 00d662c..9876763 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/util/DebugSql.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/util/DebugSql.java @@ -6,8 +6,8 @@ import org.xbib.jdbc.query.SqlNull; import java.io.InputStream; import java.io.Reader; +import java.sql.Timestamp; import java.util.Arrays; -import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; @@ -77,9 +77,9 @@ public class DebugSql { } else if (argToPrint instanceof SqlNull || argToPrint == null) { buf.append("null"); } else if (argToPrint instanceof java.sql.Timestamp) { - buf.append(options.flavor().dateAsSqlFunction((Date) argToPrint, options.calendarForTimestamps())); + buf.append(options.flavor().dateAsSqlFunction((Timestamp) argToPrint, options.calendarForTimestamps())); } else if (argToPrint instanceof java.sql.Date) { - buf.append(options.flavor().localDateAsSqlFunction((Date) argToPrint)); + buf.append(options.flavor().localDateAsSqlFunction((java.sql.Date) argToPrint)); } else if (argToPrint instanceof Number) { buf.append(argToPrint); } else if (argToPrint instanceof Boolean) { diff --git a/jdbc-query/src/test/java/org/xbib/jdbc/query/test/CommonTest.java b/jdbc-query/src/test/java/org/xbib/jdbc/query/test/CommonTest.java index eac47ee..7461f86 100644 --- a/jdbc-query/src/test/java/org/xbib/jdbc/query/test/CommonTest.java +++ b/jdbc-query/src/test/java/org/xbib/jdbc/query/test/CommonTest.java @@ -25,15 +25,23 @@ import java.io.Reader; import java.io.StringReader; import java.math.BigDecimal; import java.sql.ResultSetMetaData; +import java.sql.Timestamp; import java.text.SimpleDateFormat; +import java.time.Instant; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.Month; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; -import java.util.Date; import java.util.List; import java.util.TimeZone; +import java.util.logging.Logger; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; @@ -50,6 +58,8 @@ import static org.junit.jupiter.api.Assertions.fail; */ public abstract class CommonTest { + private static final Logger logger = Logger.getLogger(CommonTest.class.getName()); + final static String TEST_TABLE_NAME = "dbtest"; /** @@ -60,7 +70,7 @@ public abstract class CommonTest { protected Database db; - protected Date now = new Date(); + protected LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS); protected LocalDate localDateNow = LocalDate.now(); @@ -68,7 +78,7 @@ public abstract class CommonTest { public void setupJdbc() throws Exception { dbp = createDatabaseProvider(new OptionsOverride() { @Override - public Date currentDate() { + public LocalDateTime currentDate() { return now; } @@ -197,8 +207,8 @@ public abstract class CommonTest { assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull("bin_blob")); assertArrayEquals("More".getBytes(), rs.getBlobBytesOrZeroLen(9)); assertArrayEquals("More".getBytes(), rs.getBlobBytesOrZeroLen("bin_blob")); - assertEquals(now, rs.getDateOrNull(10)); - assertEquals(now, rs.getDateOrNull("date_millis")); + assertEquals(now, rs.getLocalDateTimeOrNull(10)); + assertEquals(now, rs.getLocalDateTimeOrNull("date_millis")); assertEquals(localDateNow, rs.getLocalDateOrNull(11)); assertEquals(localDateNow, rs.getLocalDateOrNull("local_date")); return null; @@ -217,7 +227,7 @@ public abstract class CommonTest { assertEquals("T", rs.getStringOrNull()); assertEquals("World", rs.getClobStringOrNull()); assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull()); - assertEquals(now, rs.getDateOrNull()); + assertEquals(now, rs.getLocalDateTimeOrNull()); assertEquals(localDateNow, rs.getLocalDateOrNull()); return null; }); @@ -350,8 +360,8 @@ public abstract class CommonTest { assertNull(rs.getClobStringOrNull("str_lob")); assertNull(rs.getBlobBytesOrNull(9)); assertNull(rs.getBlobBytesOrNull("bin_blob")); - assertNull(rs.getDateOrNull(10)); - assertNull(rs.getDateOrNull("date_millis")); + assertNull(rs.getLocalDateTimeOrNull(10)); + assertNull(rs.getLocalDateTimeOrNull("date_millis")); assertNull(rs.getLocalDateOrNull(11)); assertNull(rs.getLocalDateOrNull("local_date")); return null; @@ -381,8 +391,8 @@ public abstract class CommonTest { assertEquals("World", rs.getClobStringOrNull("str_lob")); assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull(9)); assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull("bin_blob")); - assertEquals(now, rs.getDateOrNull(10)); - assertEquals(now, rs.getDateOrNull("date_millis")); + assertEquals(now, rs.getLocalDateTimeOrNull(10)); + assertEquals(now, rs.getLocalDateTimeOrNull("date_millis")); assertEquals(localDateNow, rs.getLocalDateOrNull(11)); assertEquals(localDateNow, rs.getLocalDateOrNull("local_date")); return null; @@ -457,8 +467,8 @@ public abstract class CommonTest { assertNull(rs.getClobStringOrNull("str_lob")); assertNull(rs.getBlobBytesOrNull(9)); assertNull(rs.getBlobBytesOrNull("bin_blob")); - assertNull(rs.getDateOrNull(10)); - assertNull(rs.getDateOrNull("date_millis")); + assertNull(rs.getLocalDateTimeOrNull(10)); + assertNull(rs.getLocalDateTimeOrNull("date_millis")); assertNull(rs.getLocalDateOrNull(11)); assertNull(rs.getLocalDateOrNull("local_date")); return null; @@ -491,8 +501,8 @@ public abstract class CommonTest { assertEquals("World", rs.getClobStringOrNull("str_lob")); assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull(9)); assertArrayEquals("More".getBytes(), rs.getBlobBytesOrNull("bin_blob")); - assertEquals(now, rs.getDateOrNull(10)); - assertEquals(now, rs.getDateOrNull("date_millis")); + assertEquals(now, rs.getLocalDateTimeOrNull(10)); + assertEquals(now, rs.getLocalDateTimeOrNull("date_millis")); assertEquals(localDateNow, rs.getLocalDateOrNull(11)); assertEquals(localDateNow, rs.getLocalDateOrNull("local_date")); return null; @@ -560,8 +570,8 @@ public abstract class CommonTest { assertNull(rs.getClobStringOrNull("str_lob")); assertNull(rs.getBlobBytesOrNull(9)); assertNull(rs.getBlobBytesOrNull("bin_blob")); - assertNull(rs.getDateOrNull(10)); - assertNull(rs.getDateOrNull("date_millis")); + assertNull(rs.getLocalDateTimeOrNull(10)); + assertNull(rs.getLocalDateTimeOrNull("date_millis")); assertNull(rs.getLocalDateOrNull(11)); assertNull(rs.getLocalDateOrNull("local_date")); return null; @@ -1324,10 +1334,9 @@ public abstract class CommonTest { @Test public void argBigDecimal38Precision38() { new Schema().addTable("dbtest").addColumn("i").asBigDecimal(38, 38).schema().execute(db); - BigDecimal value = new BigDecimal("0.99999999999999999999999999999999999999"); // 38 digits db.toInsert("insert into dbtest (i) values (?)").argBigDecimal(value).insert(1); - System.out.println(db.toSelect("select i from dbtest").queryBigDecimalOrNull()); + logger.info(db.toSelect("select i from dbtest").queryBigDecimalOrNull().toString()); assertEquals(value, db.toSelect("select i from dbtest where i=?").argBigDecimal(value).queryBigDecimalOrNull()); } @@ -1379,7 +1388,7 @@ public abstract class CommonTest { .insertReturning("dbtest", "pk", rs -> { assertTrue(rs.next()); assertEquals(Long.valueOf(1L), rs.getLongOrNull(1)); - assertThat(rs.getDateOrNull(2), equalTo(now)); + assertThat(rs.getLocalDateTimeOrNull(2), equalTo(now)); assertFalse(rs.next()); return null; }, "d"); @@ -1511,13 +1520,13 @@ public abstract class CommonTest { .addColumn("d").asDate().table().schema() .addSequence("dbtest_seq").schema() .execute(db); - Date dbNow = db.toInsert("insert into dbtest (pk, d) values (:seq, :d)") + LocalDateTime dbNow = db.toInsert("insert into dbtest (pk, d) values (:seq, :d)") .argPkSeq(":seq", "dbtest_seq") .argDateNowPerDb(":d") .insertReturning("dbtest", "pk", rs -> { assertTrue(rs.next()); assertEquals(Long.valueOf(1L), rs.getLongOrNull(1)); - Date dbDate = rs.getDateOrNull(2); + LocalDateTime dbDate = rs.getLocalDateTimeOrNull(2); assertFalse(rs.next()); return dbDate; }, "d"); @@ -1583,11 +1592,11 @@ public abstract class CommonTest { db.toInsert("insert into dbtest (d) values (?)") .argDateNowPerDb() .insert(1); - Date dbNow = db.toSelect("select d from dbtest").queryDateOrNull(); - if (dbNow != null && dbNow.getTime() % 10 != 0) { + LocalDateTime dbNow = db.toSelect("select d from dbtest").queryDateOrNull(); + if (dbNow != null && dbNow.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() % 10 != 0) { return; } - System.out.println("Zero in least significant digit (attempt " + attempts + ")"); + logger.info("Zero in least significant digit (attempt " + attempts + ")"); db.dropTableQuietly(TEST_TABLE_NAME); } fail("Timestamp had zero in the least significant digit"); @@ -1605,7 +1614,7 @@ public abstract class CommonTest { .argDateNowPerDb() .insert(1); // Now pull it out, put it back in, and verify it matches in the database - Date dbNow = db.toSelect("select d1 from dbtest").queryDateOrNull(); + LocalDateTime dbNow = db.toSelect("select d1 from dbtest").queryDateOrNull(); db.toUpdate("update dbtest set d2=?") .argDate(dbNow) .update(1); @@ -1619,21 +1628,23 @@ public abstract class CommonTest { .addTable("dbtest") .addColumn("d").asDate().table().schema() .execute(db); - Date date = new Date(166656789L); + Instant instant = Instant.ofEpochMilli(166656789L); + LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, ZoneId.ofOffset("GMT", ZoneOffset.ofHours(-4))); + LocalDateTime datePlus = LocalDateTime.ofInstant(instant, ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4))); TimeZone defaultTZ = TimeZone.getDefault(); try { TimeZone.setDefault(TimeZone.getTimeZone("GMT-4:00")); - db.toInsert("insert into dbtest (d) values (?)").argDate(date).insert(1); - assertEquals(date, db.toSelect("select d from dbtest").queryDateOrNull()); - assertEquals("1970-01-02 18:17:36.789000-0400", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000Z").format( - db.toSelect("select d from dbtest").queryDateOrNull())); - db.toDelete("delete from dbtest where d=?").argDate(date).update(1); + db.toInsert("insert into dbtest (d) values (?)").argDate(dateMinus).insert(1); + LocalDateTime localDateTimeMinus = db.toSelect("select d from dbtest").queryDateOrNull(); + assertEquals(dateMinus, localDateTimeMinus); + assertEquals("1970-01-02 18:17:36.789", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTimeMinus)); + db.toDelete("delete from dbtest where d=?").argDate(dateMinus).update(1); TimeZone.setDefault(TimeZone.getTimeZone("GMT+4:00")); - db.toInsert("insert into dbtest (d) values (?)").argDate(date).insert(1); - assertEquals(date, db.toSelect("select d from dbtest").queryDateOrNull()); - assertEquals("1970-01-03 02:17:36.789000+0400", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000Z").format( - db.toSelect("select d from dbtest").queryDateOrNull())); - db.toDelete("delete from dbtest where d=?").argDate(date).update(1); + db.toInsert("insert into dbtest (d) values (?)").argDate(datePlus).insert(1); + LocalDateTime localDateTimePlus = db.toSelect("select d from dbtest").queryDateOrNull(); + assertEquals(datePlus, localDateTimePlus); + assertEquals("1970-01-03 02:17:36.789", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(localDateTimePlus)); + db.toDelete("delete from dbtest where d=?").argDate(datePlus).update(1); } finally { TimeZone.setDefault(defaultTZ); } @@ -1647,30 +1658,30 @@ public abstract class CommonTest { */ @Test public void stringDateFunctions() { - Date date = new Date(166656789L); - System.out.println("Date: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000Z").format(date)); + Instant instant = Instant.ofEpochMilli(166656789L); + LocalDateTime dateMinus = LocalDateTime.ofInstant(instant, ZoneId.ofOffset("GMT", ZoneOffset.ofHours(-4))); + LocalDateTime datePlus = LocalDateTime.ofInstant(instant, ZoneId.ofOffset("GMT", ZoneOffset.ofHours(+4))); + logger.info("LocalDateTime: " + dateMinus + " " + datePlus); TimeZone defaultTZ = TimeZone.getDefault(); try { TimeZone.setDefault(TimeZone.getTimeZone("GMT-4:00")); - new Schema() - .addTable("dbtest") - .addColumn("d").asDate().schema().execute(db); + new Schema().addTable("dbtest").addColumn("d").asDate().schema().execute(db); db.toInsert("insert into dbtest (d) values (" - + db.flavor().dateAsSqlFunction(date, db.options().calendarForTimestamps()).replace(":", "::") + ")") + + db.flavor().dateAsSqlFunction(Timestamp.valueOf(dateMinus), db.options().calendarForTimestamps()).replace(":", "::") + ")") .insert(1); - assertEquals("1970-01-02 18:17:36.789000-0400", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000Z").format( - db.toSelect("select d from dbtest").queryDateOrNull())); + assertEquals("1970-01-02 18:17:36.789", + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(db.toSelect("select d from dbtest").queryDateOrNull())); // Now do some client operations in a different time zone TimeZone.setDefault(TimeZone.getTimeZone("GMT+4:00")); // Verify regular arg maps date the same way even though our TimeZone is now different - db.toDelete("delete from dbtest where d=?").argDate(date).update(1); + db.toDelete("delete from dbtest where d=?").argDate(datePlus).update(1); db.toInsert("insert into dbtest (d) values (" - + db.flavor().dateAsSqlFunction(date, db.options().calendarForTimestamps()).replace(":", "::") + ")") + + db.flavor().dateAsSqlFunction(Timestamp.valueOf(datePlus), db.options().calendarForTimestamps()).replace(":", "::") + ")") .insert(1); - assertEquals("1970-01-03 02:17:36.789000+0400", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS000Z").format( - db.toSelect("select d from dbtest").queryDateOrNull())); + assertEquals("1970-01-03 02:17:36.789", + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(db.toSelect("select d from dbtest").queryDateOrNull())); // Verify the function maps correctly for equals operations as well - db.toDelete("delete from dbtest where d=" + db.flavor().dateAsSqlFunction(date, + db.toDelete("delete from dbtest where d=" + db.flavor().dateAsSqlFunction(Timestamp.valueOf(datePlus), db.options().calendarForTimestamps()).replace(":", "::")).update(1); } finally { TimeZone.setDefault(defaultTZ); diff --git a/jdbc-query/src/test/java/org/xbib/jdbc/query/test/RowStub.java b/jdbc-query/src/test/java/org/xbib/jdbc/query/test/RowStub.java index 41be9ac..4c0b6c5 100644 --- a/jdbc-query/src/test/java/org/xbib/jdbc/query/test/RowStub.java +++ b/jdbc-query/src/test/java/org/xbib/jdbc/query/test/RowStub.java @@ -10,11 +10,10 @@ import java.io.StringReader; import java.math.BigDecimal; import java.sql.ResultSetMetaData; import java.sql.Types; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; -import java.util.Date; import java.util.List; /** @@ -628,20 +627,20 @@ public class RowStub { @Override - public Date getDateOrNull() { + public LocalDateTime getLocalDateTimeOrNull() { return toDate(rows.get(row)[++col]); } @Override - public Date getDateOrNull(int columnOneBased) { + public LocalDateTime getLocalDateTimeOrNull(int columnOneBased) { col = columnOneBased; return toDate(rows.get(row)[columnOneBased - 1]); } @Override - public Date getDateOrNull(String columnName) { + public LocalDateTime getLocalDateTimeOrNull(String columnName) { col = columnIndexByName(columnName) + 1; return toDate(rows.get(row)[columnIndexByName(columnName)]); } @@ -759,29 +758,18 @@ public class RowStub { return (String) o; } - /** - * Returns a java.util.Date. It may be used for dates or times. - */ - private Date toDate(Object o) { + private LocalDateTime toDate(Object o) { if (o instanceof String) { String s = (String) o; if (s.length() == "yyyy-MM-dd".length()) { - try { - return new SimpleDateFormat("yyyy-MM-dd").parse(s); - } catch (ParseException e) { - throw new DatabaseException("Could not parse date as yyyy-MM-dd for " + s); - } + return LocalDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd")); } if (s.length() == "yyyy-MM-ddThh:mm:ss".length()) { - try { - return new SimpleDateFormat("yyyy-MM-ddThh:mm:ss").parse(s); - } catch (ParseException e) { - throw new DatabaseException("Could not parse date as yyyy-MM-ddThh:mm:ss for " + s); - } + return LocalDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-ddThh:mm:ss")); } throw new DatabaseException("Didn't understand date string: " + s); } - return (Date) o; + return (LocalDateTime) o; } /** diff --git a/jdbc-query/src/test/java/org/xbib/jdbc/query/test/example/Sample.java b/jdbc-query/src/test/java/org/xbib/jdbc/query/test/example/Sample.java index 4c2d887..9a4f99e 100644 --- a/jdbc-query/src/test/java/org/xbib/jdbc/query/test/example/Sample.java +++ b/jdbc-query/src/test/java/org/xbib/jdbc/query/test/example/Sample.java @@ -1,6 +1,6 @@ package org.xbib.jdbc.query.test.example; -import java.util.Date; +import java.time.LocalDateTime; /** * Simple bean for use with SampleDao. @@ -13,7 +13,7 @@ public class Sample { private Integer updateSequence; - private Date updateTime; + private LocalDateTime updateTime; public Long getSampleId() { return sampleId; @@ -39,11 +39,11 @@ public class Sample { this.updateSequence = updateSequence; } - public Date getUpdateTime() { + public LocalDateTime getUpdateTime() { return updateTime; } - public void setUpdateTime(Date updateTime) { + public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; } } diff --git a/jdbc-query/src/test/java/org/xbib/jdbc/query/test/example/SampleDao.java b/jdbc-query/src/test/java/org/xbib/jdbc/query/test/example/SampleDao.java index eb8b573..750b026 100644 --- a/jdbc-query/src/test/java/org/xbib/jdbc/query/test/example/SampleDao.java +++ b/jdbc-query/src/test/java/org/xbib/jdbc/query/test/example/SampleDao.java @@ -2,6 +2,7 @@ package org.xbib.jdbc.query.test.example; import org.xbib.jdbc.query.Database; +import java.time.LocalDateTime; import java.util.Date; import java.util.function.Supplier; @@ -19,7 +20,7 @@ public class SampleDao { public void createSample(final Sample sample, Long userIdMakingChange) { Database db = dbp.get(); - Date updateTime = db.nowPerApp(); + LocalDateTime updateTime = db.nowPerApp(); Long sampleId = db.toInsert( "insert into sample (sample_id, sample_name, update_sequence, update_time) values (?,?,0,?)") .argPkSeq("id_seq") @@ -49,7 +50,7 @@ public class SampleDao { result.setSampleId(sampleId); result.setName(r.getStringOrNull()); result.setUpdateSequence(r.getIntegerOrNull()); - result.setUpdateTime(r.getDateOrNull()); + result.setUpdateTime(r.getLocalDateTimeOrNull()); return result; }); } @@ -60,7 +61,7 @@ public class SampleDao { // Insert the history row first, so it will fail (non-unique sample_id + update_sequence) // if someone else modified the row. This is an optimistic locking strategy. int newUpdateSequence = sample.getUpdateSequence() + 1; - Date newUpdateTime = db.nowPerApp(); + LocalDateTime newUpdateTime = db.nowPerApp(); db.toInsert("insert into sample_history (sample_id, sample_name, update_sequence, update_time, update_user_id," + " is_deleted) values (?,?,?,?,?,'N')") .argLong(sample.getSampleId()) @@ -88,7 +89,7 @@ public class SampleDao { // Insert the history row first, so it will fail (non-unique sample_id + update_sequence) // if someone else modified the row. This is an optimistic locking strategy. int newUpdateSequence = sample.getUpdateSequence() + 1; - Date newUpdateTime = db.nowPerApp(); + LocalDateTime newUpdateTime = db.nowPerApp(); db.toInsert("insert into sample_history (sample_id, sample_name, update_sequence, update_time, update_user_id," + " is_deleted) values (?,?,?,?,?,'Y')") .argLong(sample.getSampleId())