From 75d276ad61a63c8734e959758670256ccac1eac0 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Mon, 12 Jan 2009 17:40:29 +0100 Subject: [PATCH] Backport of a 5.0.74 fix into 5.0.72sp1: 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. Original changesets: > revision-id: kgeorge@mysql.com-20081201141835-rg8nnnadujj5wl9f > parent: gshchepa@mysql.com-20081114172557-xh0jlzwal8ze3cy6 > committer: Georgi Kodinov > branch nick: B39920-5.0-bugteam > timestamp: Mon 2008-12-01 16:18:35 +0200 > revision-id: kgeorge@mysql.com-20081201154106-c310zzy5or043rqa > parent: kgeorge@mysql.com-20081201145656-6kjq91oga5nxbbob > committer: Georgi Kodinov > branch nick: B39920-merge-5.0-bugteam > timestamp: Mon 2008-12-01 17:41:06 +0200 --- mysql-test/r/timezone2.result | 2 +- mysql-test/r/timezone3.result | 8 ++++++++ mysql-test/std_data/Moscow_leap | Bin 991 -> 2674 bytes mysql-test/t/timezone3.test | 12 ++++++++++++ sql/tztime.cc | 22 ++++++++++++++++++++++ sql/tztime.h | 3 +++ 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result index bb1d764ac8c..e115ce16fa4 100644 --- a/mysql-test/r/timezone2.result +++ b/mysql-test/r/timezone2.result @@ -110,7 +110,7 @@ i ts 362793610 1981-07-01 04:00:00 select from_unixtime(362793609); from_unixtime(362793609) -1981-07-01 03:59:60 +1981-07-01 03:59:59 drop table t1; create table t1 (ts timestamp); set time_zone='UTC'; 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 4994c005595dc06bc6d288e9ecea38307ce11c82..3e73923cfb323ed1f7fe38d1b1929a0dc2bc8eeb 100644 GIT binary patch literal 2674 zcmb`|eN0t#7{Kv!x%b@r;{t*&2qYlB5QvDpq+o$)cvTb%1&IjKLM+FwX)oDuBkEGTv_NJtz6~GS{u32i#^|CXCrI<t`6l1$@YN2uK4ik7SC?>TtLSq)S-A^$vYh}3nG&aeKj=t@~kM;QyKMV__^q71A1b53X1MK z|H|cIAMU>udu02qxYwHl@mp5~hHqFDNLV&6FrsRDU}RBt->BT=zR{^MeTlK&zWYON z-cB-;8k2gXHzi+<+BT-)<85OuUMNX9{r1$c$1gXfc6`=6Zs$kMX)SMU9>043=JZ9| zH)m9zbY-sG<;u!ycRet7ojD<{$()#3Wljv#xO0Xz_;arK+>>rr`X4-*EWRCnn`!#AqMc{}tHwOiN5t=6?atk-pca=rA^YW?(;9R1AUe7)?e)J{Ug3{X&&^3tD;M8Xt1^PrYTp(0e8hKZP1+xN&97%v!+;*$aN)38d;O$d*Y%QG z-`%b^?C#VXk2dKS)@t3@R-=O)K~9I$beV3`<#CCeD!AY24N<16|BZV)8^)+)`44Gi z)Hz%-S1{){IFw)BO1dNF&i&%zGNZUuu4#Of&X#MM z;q#TrB{y8htbf>HcKqa!F9`DZhc}DP;M!8B=n9$XZxPL~u_0STcX(*NTl7Tyys}kP zgStEAiHzXL_OmaF-l$D|UNIzQVaCg1Xk6koUaznbUtg7HHU=c_+uJ6FCpCT^E=Hu3 z^llRere=C?k`7DB2a*sZBS=b+oFGX-vVx=q$qSMgBr`~AklY~2L9&CS2g#46 zBnZh6k|ImV5t1Y%OGuiKJRylfGKHiH$rX|;BwI+jkbEHtvy_Y>DYKNEAxT5BhNKP2 z8qy!yCGSY$k<25hM{&58SL$MhJ*&Y&Hgv;?aceh)5r#pw?a06vNnLsvH_&0vH_%) zvH_%tvH|2XHo=hI_rEV2AnwlnA~wMPZUMf_-UQ6{Hej|l0<*mpnC;ELY;Olo``MBx@*yvy~4gN=U6CPZiix9 z-ZFEx{0!!{f;LIE!axPKqSW7P#fD65C9ZebN(G*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;