From aeaeb3f02240af14c1c3f6d095387c1b38e2dc5f Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Thu, 16 Dec 2004 16:31:50 +0300 Subject: [PATCH 1/2] Fix for bug #7297 "Two digit year should be interpreted correctly even with zero month and day" aka "Date decoding trouble" Two digit year should be interpreted correctly as year in 20th or 21st century even with zero month and day. Only exception should be zero date '00-00-00' or '00-00-00 00:00:00'. --- mysql-test/r/type_datetime.result | 10 ++++++++++ mysql-test/t/type_datetime.test | 12 ++++++++++++ sql/time.cc | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 756deab80e0..fcadba016fa 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -102,3 +102,13 @@ insert into t1 values (now(), now()); select * from t1 where a is null or b is null; a b drop table t1; +create table t1 (dt datetime); +insert into t1 values ("12-00-00"), ("00-00-00 01:00:00"); +insert into t1 values ("00-00-00"), ("00-00-00 00:00:00"); +select * from t1; +dt +2012-00-00 00:00:00 +2000-00-00 01:00:00 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +drop table t1; diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 850e5238111..a7f9004d062 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -68,3 +68,15 @@ insert into t1 values (now(), now()); insert into t1 values (now(), now()); select * from t1 where a is null or b is null; drop table t1; + +# +# Test for bug #7297 "Two digit year should be interpreted correctly even +# with zero month and day" +# +create table t1 (dt datetime); +# These dates should be treated as dates in 21st century +insert into t1 values ("12-00-00"), ("00-00-00 01:00:00"); +# Zero dates are still special :/ +insert into t1 values ("00-00-00"), ("00-00-00 00:00:00"); +select * from t1; +drop table t1; diff --git a/sql/time.cc b/sql/time.cc index 38670db054f..d8b4b80e351 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -410,7 +410,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) else date[6]=0; - if (year_length == 2 && i >=2 && (date[1] || date[2])) + if (year_length == 2 && not_zero_date) date[0]+= (date[0] < YY_PART_YEAR ? 2000 : 1900); number_of_fields=i; while (i < 6) From 2878395ab149838306719ba617dbe24507b21838 Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Thu, 30 Dec 2004 21:18:10 +0300 Subject: [PATCH 2/2] Fix for bug #7515 "from_unixtime(0) now returns NULL instead of the Epoch". (With after review fixes). --- mysql-test/r/func_time.result | 7 +++++-- mysql-test/t/func_time.test | 8 ++++++-- sql/item_timefunc.cc | 10 ++++++---- sql/item_timefunc.h | 3 +-- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 32034bf289d..c1e75b60e4f 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -470,9 +470,12 @@ unix_timestamp(@a) select unix_timestamp('1969-12-01 19:00:01'); unix_timestamp('1969-12-01 19:00:01') 0 -select from_unixtime(0); -from_unixtime(0) +select from_unixtime(-1); +from_unixtime(-1) NULL select from_unixtime(2145916800); from_unixtime(2145916800) NULL +select from_unixtime(0); +from_unixtime(0) +1970-01-01 03:00:00 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index da18269cf6a..60c7aa49fbf 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -228,7 +228,11 @@ select unix_timestamp('1969-12-01 19:00:01'); # # Test for bug #6439 "unix_timestamp() function returns wrong datetime -# values for too big argument". It should return error instead. +# values for too big argument" and bug #7515 "from_unixtime(0) now +# returns NULL instead of the epoch". unix_timestamp() should return error +# for too big or negative argument. It should return Epoch value for zero +# argument since it seems that many user's rely on this fact. # -select from_unixtime(0); +select from_unixtime(-1); select from_unixtime(2145916800); +select from_unixtime(0); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index d188310be24..b03fd151383 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -946,10 +946,12 @@ bool Item_func_from_unixtime::get_date(TIME *ltime, { struct tm tm_tmp; time_t tmp; - longlong arg= args[0]->val_int(); - if ((null_value= (args[0]->null_value || - arg < TIMESTAMP_MIN_VALUE || - arg > TIMESTAMP_MAX_VALUE))) + ulonglong arg= (ulonglong)(args[0]->val_int()); + /* + "arg > TIMESTAMP_MAX_VALUE" check also covers case of negative + from_unixtime() argument since arg is unsigned. + */ + if ((null_value= (args[0]->null_value || arg > TIMESTAMP_MAX_VALUE))) return 1; tmp= arg; localtime_r(&tmp,&tm_tmp); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index e04e24627d9..8ee2f935a80 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -359,8 +359,7 @@ class Item_func_from_unixtime :public Item_date_func longlong val_int(); String *val_str(String *str); const char *func_name() const { return "from_unixtime"; } - void fix_length_and_dec() { decimals=0; max_length=19; } -// enum Item_result result_type () const { return STRING_RESULT; } + void fix_length_and_dec() { decimals=0; max_length=19; maybe_null= 1; } bool get_date(TIME *res,bool fuzzy_date); };