Merge lp:~massimo-siani/mariadb-java-client/CONJ-86 into lp:mariadb-java-client

Proposed by Massimo Siani
Status: Needs review
Proposed branch: lp:~massimo-siani/mariadb-java-client/CONJ-86
Merge into: lp:mariadb-java-client
Diff against target: 136 lines (+106/-1)
2 files modified
src/main/java/org/mariadb/jdbc/internal/common/AbstractValueObject.java (+13/-1)
src/test/java/org/mariadb/jdbc/TimestampTest.java (+93/-0)
To merge this branch: bzr merge lp:~massimo-siani/mariadb-java-client/CONJ-86
Reviewer Review Type Date Requested Status
Maria-captains Pending
Review via email: mp+224263@code.launchpad.net

Commit message

Fix for CONJ-86

Description of the change

CONJ-86:
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.

Proposed solution: if an exception is thrown while parsing the timestamp, and no explicit calendar has been set, try with UTC. Otherwise, works as before (throws the exception).

To post a comment you must log in.
513. By Massimo Siani

Merge changes from trunk and retest

Unmerged revisions

513. By Massimo Siani

Merge changes from trunk and retest

512. By Massimo Siani

If a calendar has been given, do not try with UTC

511. By Massimo Siani

Fix for CONJ-86

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/main/java/org/mariadb/jdbc/internal/common/AbstractValueObject.java'
2--- src/main/java/org/mariadb/jdbc/internal/common/AbstractValueObject.java 2014-03-25 17:00:46 +0000
3+++ src/main/java/org/mariadb/jdbc/internal/common/AbstractValueObject.java 2014-07-07 10:12:18 +0000
4@@ -52,6 +52,7 @@
5 import org.mariadb.jdbc.MySQLBlob;
6 import org.mariadb.jdbc.MySQLClob;
7 import org.mariadb.jdbc.internal.mysql.MySQLType;
8+
9 import java.io.ByteArrayInputStream;
10 import java.io.InputStream;
11 import java.io.UnsupportedEncodingException;
12@@ -61,6 +62,7 @@
13 import java.text.ParseException;
14 import java.text.SimpleDateFormat;
15 import java.util.Calendar;
16+import java.util.TimeZone;
17
18
19 public abstract class AbstractValueObject implements ValueObject {
20@@ -259,7 +261,17 @@
21 if (cal != null) {
22 sdf.setCalendar(cal);
23 }
24- final java.util.Date utilTime = sdf.parse(rawValue);
25+ java.util.Date utilTime;
26+ try {
27+ utilTime = sdf.parse(rawValue);
28+ } catch (ParseException pe) {
29+ if (cal == null) {
30+ sdf.setCalendar(Calendar.getInstance(TimeZone.getTimeZone("UTC")));
31+ utilTime = sdf.parse(rawValue);
32+ } else {
33+ throw pe;
34+ }
35+ }
36 Timestamp ts = new Timestamp(utilTime.getTime());
37 if(rawValue.indexOf('.') != -1) {
38 ts.setNanos(extractNanos(rawValue));
39
40=== added file 'src/test/java/org/mariadb/jdbc/TimestampTest.java'
41--- src/test/java/org/mariadb/jdbc/TimestampTest.java 1970-01-01 00:00:00 +0000
42+++ src/test/java/org/mariadb/jdbc/TimestampTest.java 2014-07-07 10:12:18 +0000
43@@ -0,0 +1,93 @@
44+package org.mariadb.jdbc;
45+
46+import static org.junit.Assert.*;
47+
48+import java.sql.PreparedStatement;
49+import java.sql.ResultSet;
50+import java.sql.SQLException;
51+import java.sql.Statement;
52+import java.sql.Timestamp;
53+import java.util.Calendar;
54+import java.util.Locale;
55+import java.util.TimeZone;
56+
57+import org.junit.After;
58+import org.junit.Before;
59+import org.junit.Test;
60+
61+public class TimestampTest extends BaseTest {
62+
63+ private Statement stmt;
64+ private Locale previousFormatLocale;
65+ private TimeZone previousTimeZone;
66+ private TimeZone swedishTimeZone;
67+ private String prevTimeZone;
68+
69+ @Before
70+ public void setUp() throws SQLException {
71+ //Save the previous FORMAT locate so we can restore it later
72+ previousFormatLocale = Locale.getDefault(Locale.Category.FORMAT);
73+ //Save the previous timezone so we can restore it later
74+ previousTimeZone = TimeZone.getDefault();
75+
76+ swedishTimeZone = TimeZone.getTimeZone("Europe/Stockholm");
77+ TimeZone.setDefault(swedishTimeZone); //Everybody running this test case should be in Sweden
78+
79+ stmt = connection.createStatement();
80+
81+ ResultSet rs = stmt.executeQuery("SELECT @@time_zone");
82+ rs.next();
83+ prevTimeZone = rs.getString(1);
84+ rs.close();
85+ stmt.execute("SET time_zone = '+00:00'");
86+ stmt.execute("drop table if exists timestamptest");
87+ stmt.execute("create table timestamptest (id int not null primary key auto_increment, tm timestamp)");
88+ }
89+
90+ @After
91+ public void tearDown() throws SQLException {
92+ //Reset the FORMAT locate so other test cases are not disturbed.
93+ Locale.setDefault(Locale.Category.FORMAT, previousFormatLocale);
94+ //Reset the timezone so so other test cases are not disturbed.
95+ TimeZone.setDefault(previousTimeZone);
96+ stmt.execute("SET time_zone = '" + prevTimeZone + "'");
97+ }
98+
99+
100+ @Test
101+ public void testGetTimestamp() throws SQLException {
102+ Calendar _20140101_1320_59 = Calendar.getInstance(TimeZone.getTimeZone("utc"));
103+ _20140101_1320_59.clear();
104+ _20140101_1320_59.set(2014, 0, 1, 13, 20, 59);
105+
106+ PreparedStatement ps = connection.prepareStatement("insert into timestamptest values(1, ?)");
107+ ps.setTimestamp(1, new Timestamp(_20140101_1320_59.getTimeInMillis()));
108+ ps.execute();
109+
110+ ResultSet rs = stmt.executeQuery("select * from timestamptest");
111+ while(rs.next()) {
112+ Timestamp timestamp = rs.getTimestamp(2);
113+ assertEquals(_20140101_1320_59.getTimeInMillis(), timestamp.getTime());
114+ }
115+ }
116+
117+ @Test
118+ public void testGetTimestampWhenDaylightSavingRemovesHour() throws SQLException {
119+ //The time 2014-03-30 01:15:00 is valid in UTC
120+ Calendar quaterPastTwo30thOfMarth2014 = Calendar.getInstance(TimeZone.getTimeZone("utc"));
121+ quaterPastTwo30thOfMarth2014.clear();
122+ quaterPastTwo30thOfMarth2014.set(2014, 2, 30, 2, 15, 0);
123+
124+ PreparedStatement ps = connection.prepareStatement("insert into timestamptest values(1, ?)");
125+ //Explicitly set a time that does not exists in Swedish timezone
126+ //Note: this query will only work if the server is set to UTC (set time_zone = '+00:00' above)
127+ ps.setString(1, "2014-03-30 02:15:00");
128+ ps.execute();
129+
130+ ResultSet rs = stmt.executeQuery("select * from timestamptest");
131+ while(rs.next()) {
132+ Timestamp timestamp = rs.getTimestamp(2);
133+ assertEquals(quaterPastTwo30thOfMarth2014.getTimeInMillis(), timestamp.getTime());
134+ }
135+ }
136+}

Subscribers

People subscribed via source and target branches