[CONJ-86] getTimestamp use client timezone and fails on Daylight Savings Time Created: 2014-03-31 Updated: 2016-08-24 Resolved: 2015-09-21 |
|
| Status: | Closed |
| Project: | MariaDB Connector/J |
| Component/s: | Other |
| Affects Version/s: | 1.1.6 |
| Fix Version/s: | 1.3.0 |
| Type: | Bug | Priority: | Minor |
| Reporter: | Anders Karlsson | Assignee: | Diego Dupin |
| Resolution: | Fixed | Votes: | 1 |
| Labels: | None | ||
| Attachments: |
|
||||||||
| Issue Links: |
|
||||||||
| Sprint: | Sprint connector/j 1.3.0 | ||||||||
| Description |
|
It seems that the getTimestamp of the ResultSet class use the default client timestamp for time conversions. This works in most cases, but when Daylight Saving Time is used, it fails at certain times. For example if the TimeZone is Europe/Stockholm and the time is '2014-03-30 02:15:00' this is an invalid time (as the hour between 2 and 3 is "lost"). Using an explicit TimeZone works, and what seems like a workaround would be to use the UTC timezone instead of the default one when an explicit timezone is not set. |
| Comments |
| Comment by Lennart Schedin [ 2014-04-01 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
JUint test cases for getTimestamp() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Lennart Schedin [ 2014-04-01 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I attached the file TimestampTest.java. It must be run against a Mysql/MariaDB with UTC timezone to trigger the specific exception: When using MariaDB JDBC connector my test method testGetTimestampWhenDaylightSavingRemovesHour() will fail with the above exception. When using Mysql JDBC connector it works. I also tried the implied fix by Anders Karlsson, to add this in org.mariadb.jdbc.internal.common.AbstractValueObject.getTimestamp(): My guess is that MariaDB JDBC connector needs to use the timezone information provided by the server to perform the correct conversion. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Vladislav Vaintroub [ 2014-04-01 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
1. In JDBC API , there is a getTimestamp() that accepts Calendar instance. Did you try that Would not that help? | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Anders Karlsson [ 2014-04-02 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
1) Using a specific Calendar for getTimestamp sure works, but that was In general, that the default is to use the Client TimeZone though seems I'll check 2) above with the customer. Also, we need to get better at /Karlsson – Anders Karlsson, Senior Sales Engineer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Lennart Schedin [ 2014-04-02 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
The method ResultSet.getTimestamp(int columnIndex, Calendar cal) is not optimal for TIMESTAMP values. It is a legacy in the JDBC API (http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#getTimestamp%28int,%20java.util.Calendar%29) : What database does not store timezone information? Well maybe MySQL for the strange DATETIME datatype. But for that it is probably better to use getString() since it represents a time of day and not a point in time. I’m not that keen on adding a JDBC parameter. There is a danger on added more and more parameters. The MySQL JDBC parameter list has gotten a bit too long… My test case shows that the MariaDB JDBC driver is not a drop-in-replacement for MySQL since MySQL handles it. When I sniff the traffic with wireshark it looks like it is the server that has performed the conversion (but wrong!?). I’m confused. It is however clear that MariaDB and MySQL uses different code to parse the value. A simple solution I will try is to add this to getTimestamp(): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Lennart Schedin [ 2014-04-03 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Attaching my setLenient(true)-fix. I have tested it and for my purposes it works fine. Note: I have only tested it with Swedish timezone for the Java client and UTC timezone for server. As have debugged GregorianCalendar it looks like the fix will make the Calendar class accept and correct times that probably are wrong. It corrected the time 02:15 to 03:15 (30th of March 2014). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Vladislav Vaintroub [ 2014-04-03 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
While accepting wrong input and helpfully fixing it is inline with original MySQL philosophy, many people myself included came to think that defined behavior is better, i.e it is better to get exception and be warned than silently accept everything and produce incorrect results lenient=false is not well defined. IMO, everything is better compared to lenient=false. But this is just my opinion, and guys who are currently contributing to this driver will do whatever they think is better | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Lennart Schedin [ 2014-06-24 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I agree that the ”helpfully fixing” MySQL philosophy causes some problems. From my perspective it is mostly that the MySQL JDBC need some URL properties to properly work since backwards compatibility “must” be preserved. I suspect that the problem in this ticket is that the MySQL/MariaDB server sends the wrong timestamp (an invalid timestamp). I suspect that this is a bug in the server that has been smoothed over in the MySQL Java client by using a variant of my lenient fix. The suggested fix in https://code.launchpad.net/~massimo-siani/mariadb-java-client/CONJ-86 will only make any impact for the ResultSet.getTimestamp(int, Calendar) method? My testcase (in the | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Massimo Siani (Inactive) [ 2014-06-24 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi Lennart, I'd like to tell you that your test case has been included in the code. Thank you. Any comment is very welcome. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Lennart Schedin [ 2014-09-11 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I’ve had the gut feeling that the suggested fix in https://code.launchpad.net/~massimo-siani/mariadb-java-client/CONJ-86 did not work in all cases. I think I have found such a case now:
The test case testGetTimestampWithoutDaylightSavingIssue() uses a time without any daylight saving effects and will pass. The testGetTimestampWhenDaylightSavingRemovesHour() is very similar, it only differs on the time but will fail. The time is a daylight-saving-problem-hour. I have tried to make the Junit tests to behave the same regardless of with time zone the server of client uses. I don’t have any proposed good fix for this problem. A fix should probably be synced with | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Rasmus Johansson (Inactive) [ 2015-06-05 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Please verify if this bug still exists (I think it does) and try to fix | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Diego Dupin [ 2015-09-21 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
testing if the problem still exist with :
and all is working well. |