diff options
author | Sreeharsha Ramanavarapu <sreeharsha.ramanavarapu@oracle.com> | 2015-12-31 07:31:12 +0530 |
---|---|---|
committer | Sreeharsha Ramanavarapu <sreeharsha.ramanavarapu@oracle.com> | 2015-12-31 07:31:12 +0530 |
commit | cb15cce746db6c32cb62c70bd356b2db61267fd9 (patch) | |
tree | a2d122afa60bd1c2c7923edf7a540439e3cdb4a2 | |
parent | 1ec594dd60aa3b58e7d1c686016695b5b0bc1aa1 (diff) | |
download | mariadb-git-cb15cce746db6c32cb62c70bd356b2db61267fd9.tar.gz |
Bug #21564557: INCONSISTENT OUTPUT FROM 5.5 AND 5.6
UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%M"
Issue:
-----
When an invalid date is supplied to the UNIX_TIMESTAMP
function from STR_TO_DATE, no check is performed before
converting it to a timestamp value.
SOLUTION:
---------
Add the check_date function and only if it succeeds,
proceed to the timestamp conversion.
No warning will be returned for dates having zero in
month/date, since partial dates are allowed. UNIX_TIMESTAMP
will return only a zero for such values.
The problem has been handled in 5.6+ with WL#946.
-rw-r--r-- | mysql-test/r/func_time.result | 31 | ||||
-rw-r--r-- | mysql-test/t/func_time.test | 18 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 13 | ||||
-rw-r--r-- | sql/sql_time.h | 7 |
4 files changed, 64 insertions, 5 deletions
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 7f3ecc0d602..2db5711a4b9 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -1672,3 +1672,34 @@ insert into t1 values ('00:00:00'),('00:01:00'); select 1 from t1 where 1 < some (select cast(a as datetime) from t1); 1 drop table t1; +# +# Bug #21564557: INCONSISTENT OUTPUT FROM 5.5 AND 5.6 +# UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%M" +# +SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")); +UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")) +0 +SELECT UNIX_TIMESTAMP('2015-06-00'); +UNIX_TIMESTAMP('2015-06-00') +0 +SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')); +UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')) +0 +set sql_mode= 'TRADITIONAL'; +SELECT @@sql_mode; +@@sql_mode +STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION +SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")); +UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")) +NULL +Warnings: +Warning 1411 Incorrect datetime value: '201506' for function str_to_date +SELECT UNIX_TIMESTAMP('2015-06-00'); +UNIX_TIMESTAMP('2015-06-00') +0 +SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')); +UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')) +NULL +Warnings: +Warning 1411 Incorrect datetime value: '0000-00-00 10:30:30' for function str_to_date +set sql_mode= default; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index b6c70485dbc..3abfdc616ff 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -1026,3 +1026,21 @@ create table t1(a time); insert into t1 values ('00:00:00'),('00:01:00'); select 1 from t1 where 1 < some (select cast(a as datetime) from t1); drop table t1; + +--echo # +--echo # Bug #21564557: INCONSISTENT OUTPUT FROM 5.5 AND 5.6 +--echo # UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%M" +--echo # + +SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")); +SELECT UNIX_TIMESTAMP('2015-06-00'); +SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')); + +set sql_mode= 'TRADITIONAL'; +SELECT @@sql_mode; + +SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")); +SELECT UNIX_TIMESTAMP('2015-06-00'); +SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')); + +set sql_mode= default; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 840c8e55efe..00145540e6d 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1378,7 +1378,7 @@ longlong Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp) longlong Item_func_unix_timestamp::val_int() { MYSQL_TIME ltime; - my_bool not_used; + my_bool not_used= 0; DBUG_ASSERT(fixed == 1); if (arg_count == 0) @@ -1390,7 +1390,7 @@ longlong Item_func_unix_timestamp::val_int() return ((Field_timestamp*) field)->get_timestamp(&null_value); } - if (get_arg0_date(<ime, 0)) + if (get_arg0_date(<ime, TIME_FUZZY_DATE)) { /* We have to set null_value again because get_arg0_date will also set it @@ -1400,7 +1400,11 @@ longlong Item_func_unix_timestamp::val_int() null_value= args[0]->null_value; return 0; } - + + int dummy= 0; + if (check_date(<ime, non_zero_date(<ime), TIME_NO_ZERO_IN_DATE, &dummy)) + return 0; + return (longlong) TIME_to_timestamp(current_thd, <ime, ¬_used); } @@ -3482,6 +3486,7 @@ bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, uint fuzzy_date) String val_string(val_buff, sizeof(val_buff), &my_charset_bin), *val; String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format; + fuzzy_date|= sql_mode; val= args[0]->val_str(&val_string); format= args[1]->val_str(&format_str); if (args[0]->null_value || args[1]->null_value) diff --git a/sql/sql_time.h b/sql/sql_time.h index 0418a0e9621..3e3cd693613 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -91,6 +91,11 @@ inline bool parse_date_time_format(timestamp_type format_type, date_time_format); } +static inline bool +non_zero_date(const MYSQL_TIME *ltime) +{ + return ltime->year || ltime->month || ltime->day; +} extern DATE_TIME_FORMAT global_date_format; extern DATE_TIME_FORMAT global_datetime_format; |