From eae949a9da8865462a523a339ca8703cf5432fb2 Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 6 Nov 2024 13:54:17 +0100 Subject: [PATCH] [CONJ-1196] setObject on java.util.Date was considered was a java.sql.Date and truncate hour/minutes/seconds/ms while it must be considered like a java.sql.Timestamp --- .../mariadb/jdbc/plugin/codec/DateCodec.java | 2 +- .../jdbc/plugin/codec/TimestampCodec.java | 38 +++++++++++++------ .../integration/codec/DateTimeCodecTest.java | 7 +++- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java index 59343dcda..c60ecfa14 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java @@ -44,7 +44,7 @@ public boolean canDecode(ColumnDecoder column, Class type) { } public boolean canEncode(Object value) { - return value instanceof Date || java.util.Date.class.equals(value.getClass()); + return value instanceof Date; } @Override diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java index b3b5f45fa..6a592b026 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java @@ -45,7 +45,7 @@ public boolean canDecode(ColumnDecoder column, Class type) { } public boolean canEncode(Object value) { - return value instanceof Timestamp; + return value instanceof Timestamp || java.util.Date.class.equals(value.getClass()); } @Override @@ -76,16 +76,20 @@ public Timestamp decodeBinary( public void encodeText( Writer encoder, Context context, Object val, Calendar providedCal, Long maxLen) throws IOException { - Timestamp ts = (Timestamp) val; Calendar cal = providedCal == null ? context.getDefaultCalendar() : providedCal; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdf.setTimeZone(cal.getTimeZone()); - String dateString = sdf.format(ts); + String dateString = sdf.format(val); encoder.writeByte('\''); encoder.writeAscii(dateString); + int microseconds = 0; + if (val instanceof Timestamp) { + microseconds = ((Timestamp) val).getNanos() / 1000; + } else if (val instanceof java.util.Date) { + microseconds = (int) ((((java.util.Date) val).getTime() % 1000) * 1000); + } - int microseconds = ts.getNanos() / 1000; if (microseconds > 0) { if (microseconds % 1000 == 0) { encoder.writeAscii("." + Integer.toString(microseconds / 1000 + 1000).substring(1)); @@ -101,12 +105,24 @@ public void encodeText( public void encodeBinary( Writer encoder, Context context, Object value, Calendar providedCal, Long maxLength) throws IOException { - Timestamp ts = (Timestamp) value; + + int microseconds = 0; + long timeInMillis = 0; + if (value instanceof Timestamp) { + Timestamp ts = (Timestamp) value; + microseconds = ts.getNanos() / 1000; + timeInMillis = ts.getTime(); + } else if (value instanceof java.util.Date) { + java.util.Date dt = (java.util.Date) value; + timeInMillis = dt.getTime(); + microseconds = (int) ((timeInMillis % 1000) * 1000); + } + if (providedCal == null) { Calendar cal = context.getDefaultCalendar(); cal.clear(); - cal.setTimeInMillis(ts.getTime()); - if (ts.getNanos() == 0) { + cal.setTimeInMillis(timeInMillis); + if (microseconds == 0) { encoder.writeByte(7); // length encoder.writeShort((short) cal.get(Calendar.YEAR)); encoder.writeByte((cal.get(Calendar.MONTH) + 1)); @@ -122,13 +138,13 @@ public void encodeBinary( encoder.writeByte(cal.get(Calendar.HOUR_OF_DAY)); encoder.writeByte(cal.get(Calendar.MINUTE)); encoder.writeByte(cal.get(Calendar.SECOND)); - encoder.writeInt(ts.getNanos() / 1000); + encoder.writeInt(microseconds); } } else { synchronized (providedCal) { providedCal.clear(); - providedCal.setTimeInMillis(ts.getTime()); - if (ts.getNanos() == 0) { + providedCal.setTimeInMillis(timeInMillis); + if (microseconds == 0) { encoder.writeByte(7); // length encoder.writeShort((short) providedCal.get(Calendar.YEAR)); encoder.writeByte((providedCal.get(Calendar.MONTH) + 1)); @@ -144,7 +160,7 @@ public void encodeBinary( encoder.writeByte(providedCal.get(Calendar.HOUR_OF_DAY)); encoder.writeByte(providedCal.get(Calendar.MINUTE)); encoder.writeByte(providedCal.get(Calendar.SECOND)); - encoder.writeInt(ts.getNanos() / 1000); + encoder.writeInt(microseconds); } } } diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java index ced3b577f..9821b81ab 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java @@ -1513,7 +1513,7 @@ private void sendParam(Connection con) throws SQLException { prep.execute(); prep.setTimestamp(1, Timestamp.valueOf("2015-12-12 01:55:12.654")); prep.execute(); - prep.setObject(1, Timestamp.valueOf("2016-12-12 01:55:12")); + prep.setObject(1, new java.util.Date(Timestamp.valueOf("2016-12-18 01:55:12.2").getTime())); prep.execute(); prep.setObject(1, Timestamp.valueOf("2016-12-12 01:55:12.654")); prep.execute(); @@ -1624,9 +1624,12 @@ private void sendParam(Connection con) throws SQLException { assertTrue(rs.next()); assertEquals(Timestamp.valueOf("2015-12-12 01:55:12.654"), rs.getTimestamp(2)); assertTrue(rs.next()); - assertEquals(Timestamp.valueOf("2016-12-12 01:55:12"), rs.getTimestamp(2)); + assertEquals(Timestamp.valueOf("2016-12-18 01:55:12.2"), rs.getTimestamp(2)); assertTrue(rs.next()); assertEquals(Timestamp.valueOf("2016-12-12 01:55:12.654"), rs.getTimestamp(2)); + assertEquals( + new java.util.Date(Timestamp.valueOf("2016-12-12 01:55:12.654").getTime()), + rs.getObject(2, java.util.Date.class)); assertTrue(rs.next()); assertEquals(Timestamp.from(Instant.ofEpochSecond(10, 654000)), rs.getTimestamp(2)); assertTrue(rs.next());