summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgi Kodinov <kgeorge@mysql.com>2008-12-01 16:18:35 +0200
committerGeorgi Kodinov <kgeorge@mysql.com>2008-12-01 16:18:35 +0200
commitf56e43ce521e4265f09682dd52ffa07ae1433afa (patch)
tree93de2370363802838016898bcf9c0c2941dfb252
parent56b9586fd1d94ebd70662417a1d2ac1921da4ad2 (diff)
downloadmariadb-git-f56e43ce521e4265f09682dd52ffa07ae1433afa.tar.gz
Bug #39920: MySQL cannot deal with Leap Second expression in string literal.
Updated MySQL time handling code to react correctly on UTC leap second additions. MySQL functions that return the OS current time, like e.g. CURDATE(), NOW() etc will return :59:59 instead of :59:60 or 59:61. As a result the reader will receive :59:59 for 2 or 3 consecutive seconds during the leap second. This fix will not affect the values returned by UNIX_TIMESTAMP() for leap seconds. But note that when converting the value returned by UNIX_TIMESTAMP() to broken down time the correction of leap seconds will still be applied. Note that this fix will make a difference *only* if the OS is specially configured to return leap seconds from the OS time calls or when using a MySQL time zone defintion that has leap seconds. Even after this change date/time literals (or other broken down time representations) with leap seconds (ending on :59:60 or 59:61) will still be considered illegal and discarded by the server with an error or a warning depending on the sql mode. Added a test case to demonstrate the effect of the fix. mysql-test/r/timezone3.result: Bug #39920: test case mysql-test/std_data/Moscow_leap: Bug #39920: updated the Moscow time zone to Dr. Olson's tzdata 2008i to accomodate for the 2008 leap second mysql-test/t/timezone3.test: Bug #39920: test case sql/tztime.cc: Bug #39920: adjust leap seconds (:60 or :61) to :59 sql/tztime.h: Bug #39920: adjust leap seconds (:60 or :61) to :59
-rw-r--r--mysql-test/r/timezone3.result8
-rw-r--r--mysql-test/std_data/Moscow_leapbin991 -> 2674 bytes
-rw-r--r--mysql-test/t/timezone3.test12
-rw-r--r--sql/tztime.cc22
-rw-r--r--sql/tztime.h3
5 files changed, 45 insertions, 0 deletions
diff --git a/mysql-test/r/timezone3.result b/mysql-test/r/timezone3.result
index ec0b6045f93..ceac4a5aefb 100644
--- a/mysql-test/r/timezone3.result
+++ b/mysql-test/r/timezone3.result
@@ -17,6 +17,9 @@ insert into t1 values
insert into t1 values
(unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'),
(unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00');
+insert into t1 values
+(unix_timestamp('2009-01-01 02:59:59'),'2009-01-01 02:59:59'),
+(unix_timestamp('2009-01-01 03:00:00'),'2009-01-01 03:00:00');
select i, from_unixtime(i), c from t1;
i from_unixtime(i) c
1072904422 2004-01-01 00:00:00 2004-01-01 00:00:00
@@ -31,6 +34,8 @@ i from_unixtime(i) c
1099180821 2004-10-31 02:59:59 2004-10-31 02:59:59
362793608 1981-07-01 03:59:59 1981-07-01 03:59:59
362793610 1981-07-01 04:00:00 1981-07-01 04:00:00
+1230768022 2009-01-01 02:59:59 2009-01-01 02:59:59
+1230768024 2009-01-01 03:00:00 2009-01-01 03:00:00
drop table t1;
create table t1 (ts timestamp);
insert into t1 values (19730101235900), (20040101235900);
@@ -39,3 +44,6 @@ ts
1973-01-01 23:59:00
2004-01-01 23:59:00
drop table t1;
+SELECT FROM_UNIXTIME(1230768022), FROM_UNIXTIME(1230768023), FROM_UNIXTIME(1230768024);
+FROM_UNIXTIME(1230768022) FROM_UNIXTIME(1230768023) FROM_UNIXTIME(1230768024)
+2009-01-01 02:59:59 2009-01-01 02:59:59 2009-01-01 03:00:00
diff --git a/mysql-test/std_data/Moscow_leap b/mysql-test/std_data/Moscow_leap
index 4994c005595..3e73923cfb3 100644
--- a/mysql-test/std_data/Moscow_leap
+++ b/mysql-test/std_data/Moscow_leap
Binary files differ
diff --git a/mysql-test/t/timezone3.test b/mysql-test/t/timezone3.test
index 0aedbafcec4..8a9941f6383 100644
--- a/mysql-test/t/timezone3.test
+++ b/mysql-test/t/timezone3.test
@@ -45,6 +45,10 @@ insert into t1 values
(unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'),
(unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00');
+insert into t1 values
+ (unix_timestamp('2009-01-01 02:59:59'),'2009-01-01 02:59:59'),
+ (unix_timestamp('2009-01-01 03:00:00'),'2009-01-01 03:00:00');
+
select i, from_unixtime(i), c from t1;
drop table t1;
@@ -58,4 +62,12 @@ insert into t1 values (19730101235900), (20040101235900);
select * from t1;
drop table t1;
+#
+# Test Bug #39920: MySQL cannot deal with Leap Second expression in string
+# literal
+#
+
+# 2009-01-01 02:59:59, 2009-01-01 02:59:60 and 2009-01-01 03:00:00
+SELECT FROM_UNIXTIME(1230768022), FROM_UNIXTIME(1230768023), FROM_UNIXTIME(1230768024);
+
# End of 4.1 tests
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 709e3b64752..d3d952e3c1e 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1073,6 +1073,7 @@ Time_zone_system::gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const
localtime_r(&tmp_t, &tmp_tm);
localtime_to_TIME(tmp, &tmp_tm);
tmp->time_type= MYSQL_TIMESTAMP_DATETIME;
+ adjust_leap_second(tmp);
}
@@ -1157,6 +1158,7 @@ Time_zone_utc::gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const
gmtime_r(&tmp_t, &tmp_tm);
localtime_to_TIME(tmp, &tmp_tm);
tmp->time_type= MYSQL_TIMESTAMP_DATETIME;
+ adjust_leap_second(tmp);
}
@@ -1260,6 +1262,7 @@ void
Time_zone_db::gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const
{
::gmt_sec_to_TIME(tmp, t, tz_info);
+ adjust_leap_second(tmp);
}
@@ -2373,6 +2376,25 @@ Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name)
DBUG_RETURN(tz);
}
+
+/**
+ Convert leap seconds into non-leap
+
+ This function will convert the leap seconds added by the OS to
+ non-leap seconds, e.g. 23:59:59, 23:59:60 -> 23:59:59, 00:00:01 ...
+ This check is not checking for years on purpose : although it's not a
+ complete check this way it doesn't require looking (and having installed)
+ the leap seconds table.
+
+ @param[in,out] broken down time structure as filled in by the OS
+*/
+
+void Time_zone::adjust_leap_second(MYSQL_TIME *t)
+{
+ if (t->second == 60 || t->second == 61)
+ t->second= 59;
+}
+
#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
diff --git a/sql/tztime.h b/sql/tztime.h
index 32a942a26e1..750b8dacbe1 100644
--- a/sql/tztime.h
+++ b/sql/tztime.h
@@ -55,6 +55,9 @@ public:
allocated on MEM_ROOT and should not require destruction.
*/
virtual ~Time_zone() {};
+
+protected:
+ static inline void adjust_leap_second(MYSQL_TIME *t);
};
extern Time_zone * my_tz_UTC;