Bug #80201 | PreparedStatement.setTimestamp doesn't comply with JDBC specification | ||
---|---|---|---|
Submitted: | 29 Jan 2016 17:21 | Modified: | 21 Oct 2020 12:56 |
Reporter: | Stephen Halsey | Email Updates: | |
Status: | Duplicate | Impact on me: | |
Category: | Connector / J | Severity: | S3 (Non-critical) |
Version: | 5.1.36 | OS: | Windows |
Assigned to: | Assigned Account | CPU Architecture: | Any |
Tags: | gettimestamp, settimestamp, time zone, timestamp, useLegacyDatetimeCode |
[29 Jan 2016 17:21]
Stephen Halsey
[27 Dec 2017 20:14]
Ryan Senior
Users of Metabase (https://github.com/metabase/metabase) are experiencing this issue as well. While debugging Metabase to try and figure out why incorrect times were being specified as query parameters, what I found what a bug in how the timestamps are being shifted (the same setTimestamp call referenced in this ticket). I think the bug is in this method: https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/TimeUtil.ja.... The time is being converted to the target calendar correctly I think. The last call though https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/TimeUtil.ja... calls getTime on a date, which I think is wrong. That call will convert the Date back to UTC (https://docs.oracle.com/javase/7/docs/api/java/util/Date.html#getTime()). Users that have "useJDBCCompliantTimezoneShift=true" will always have UTC as their sessionCalendar (that happens higher up in the callstack, PreparedStatement.setTimestampInternal). So that code is taking a timestamp, setting it to a UTC calendar, converting it from the UTC calendar to the calendar the user provided (in my example, a calendar in the America/Chicago timezone) and then calling targetCalendar.getTime().getTime() just converts it from America/Chicago back to UTC. That UTC timestamp is then assumed to be in the correct timezone for the database. It converts it to a string (leaving off the timezone part) and sends it to the database https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/PreparedSta.... This issue has been open for a while. Would a patch be accepted that fixes this?
[27 Dec 2017 20:14]
Ryan Senior
Users of Metabase (https://github.com/metabase/metabase) are experiencing this issue as well. While debugging Metabase to try and figure out why incorrect times were being specified as query parameters, what I found what a bug in how the timestamps are being shifted (the same setTimestamp call referenced in this ticket). I think the bug is in this method: https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/TimeUtil.ja.... The time is being converted to the target calendar correctly I think. The last call though https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/TimeUtil.ja... calls getTime on a date, which I think is wrong. That call will convert the Date back to UTC (https://docs.oracle.com/javase/7/docs/api/java/util/Date.html#getTime()). Users that have "useJDBCCompliantTimezoneShift=true" will always have UTC as their sessionCalendar (that happens higher up in the callstack, PreparedStatement.setTimestampInternal). So that code is taking a timestamp, setting it to a UTC calendar, converting it from the UTC calendar to the calendar the user provided (in my example, a calendar in the America/Chicago timezone) and then calling targetCalendar.getTime().getTime() just converts it from America/Chicago back to UTC. That UTC timestamp is then assumed to be in the correct timezone for the database. It converts it to a string (leaving off the timezone part) and sends it to the database https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/PreparedSta.... This issue has been open for a while. Would a patch be accepted that fixes this?
[20 Mar 2018 23:44]
Michael Krueger
I just filed a similar Bug #90150: getString() retrieves bad DATETIME value when client, server time zones differ. Based on my research so far, I think this bug (Bug #80201) may actually represent a misreading of the JDBC specification. The reporter of this bug (Stephen Halsey) states that the time zone conversion is to be skipped if no calendar is specified. My reading is that the conversion is always to be done: the only question is which calendar is used. If a calendar is specified in the call to setTimestamp(), then that calendar is used for the conversion; otherwise, the calendar for the current time zone of the Java client is used for the conversion. Under this reading, the issue reported here is not a bug, but correct behavior. Perhaps the assignee can comment on the correct reading of the spec.
[5 Dec 2018 18:44]
Filipe Silva
Hi, First of all, my apologies for the time this report was left unanswered. This is quite a sensitive issue and there's no right or wrong way of "fixing" it. It was decided long time ago that the default behavior in Connector/J was to not do any time zone adjustments by default, even when Calendars are used. This, however, is also not entirely true since there are some corner cases where TZ adjustments are being made. In the newer implementation (useLegacyDatetimeCode=false) it was decided to apply TZ adjustments all the time, even though it is not clear how those are made in some cases too. So, there are definitely buggy behaviors in both cases and we will revise them entirely. As for now, I'll mark this report as verified but it is still not defined what the final behavior should be. Thanks,
[15 Feb 2019 8:38]
Alexander Soklakov
Hi guys, This functionality was reworked in Connector/J 5.1.47 and Connector/J 8.0.13 under Bug#72609 fix. Could you check if the problem still exists?
[16 Mar 2019 1:00]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
[19 Mar 2019 22:00]
Michael Krueger
I finally had a chance to test the suggestion of using noDatetimeStringSync=true and I can confirm that this does resolve the issue demonstrated in the test case for Bug #90150: getString() retrieves bad DATETIME value when client, server time zones differ: https://bugs.mysql.com/bug.php?id=90150 Thank you for following up on this!
[19 Mar 2019 22:07]
Michael Krueger
I should clarify that I did my test on the older version of the JDBC driver agains which I filed Bug #90150: mysql-connector-java-5.1.18 ( Revision: tonci.grgin@oracle.com-20110930151701-jfj14ddfq48ifkfq ) The use of noDatetimeStringSync=true is a good workaround for the the related issue described in Bug #90150; I did not have a chance to test the behavior of the newer driver versions with prepared statements.
[21 Oct 2020 12:56]
Alexander Soklakov
This functionality will be reworked under Bug#95644. Closed as a duplicate.