From: Alexander Barkov Date: January 13 2012 8:37am Subject: bzr push into mysql-trunk branch (alexander.barkov:3726 to 3727) Bug#13354387 List-Archive: http://lists.mysql.com/commits/142388 X-Bug: 13354387 Message-Id: <201201130839.q0D8dWnm019570@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3727 Alexander Barkov 2012-01-13 BUG#13354387 - CRASH IN IN MY_DECIMAL::OPERATOR FOR VIEW AND FUNCTION UNIX_TIME Fixing the 5.6 part (the 5.5 was earlier committed in a separate commit). Problem: UNIX_TIMESTAMP() could return NULL in case of maybe_null==0. Fix: Moving NULL/0 decision logic from Item_func_unix_timestamp::val_timeval() to Item::get_timeval() Item_field::get_timeval() modified: mysql-test/r/func_time.result mysql-test/t/func_time.test sql/item.cc sql/item_timefunc.cc 3726 Tor Didriksen 2012-01-12 [merge] empty merge 5.5 => trunk === modified file 'mysql-test/r/func_time.result' --- a/mysql-test/r/func_time.result 2012-01-12 13:27:57 +0000 +++ b/mysql-test/r/func_time.result 2012-01-13 08:36:43 +0000 @@ -1505,3 +1505,31 @@ select 1 from t1 where 1 < some (select 1 1 drop table t1; +# +# End of 5.5 tests +# +# +# Start of 5.6 tests +# +# +# BUG#13354387 - CRASH IN IN MY_DECIMAL::OPERATOR FOR VIEW AND FUNCTION UNIX_TIMESTAMP +# Part2 (5.6) +CREATE TABLE t1 (a VARCHAR(32) NOT NULL); +INSERT INTO t1 VALUES ('a'); +SELECT 1 FROM t1 GROUP BY @a:=UNIX_TIMESTAMP(a); +1 +1 +Warnings: +Warning 1292 Incorrect datetime value: 'a' +SELECT a, UNIX_TIMESTAMP(a), UNIX_TIMESTAMP('a') FROM t1; +a UNIX_TIMESTAMP(a) UNIX_TIMESTAMP('a') +a 0.000000 0.000000 +Warnings: +Warning 1292 Incorrect datetime value: 'a' +Warning 1292 Incorrect datetime value: 'a' +DELETE FROM t1; +INSERT INTO t1 VALUES ('5000-01-01 00:00:00'); +SELECT a, UNIX_TIMESTAMP(a), UNIX_TIMESTAMP('5000-01-01 00:00:00') FROM t1; +a UNIX_TIMESTAMP(a) UNIX_TIMESTAMP('5000-01-01 00:00:00') +5000-01-01 00:00:00 0.000000 0 +DROP TABLE t1; === modified file 'mysql-test/t/func_time.test' --- a/mysql-test/t/func_time.test 2012-01-12 13:27:57 +0000 +++ b/mysql-test/t/func_time.test 2012-01-13 08:36:43 +0000 @@ -995,3 +995,23 @@ 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 # End of 5.5 tests +--echo # + +--echo # +--echo # Start of 5.6 tests +--echo # + +--echo # +--echo # BUG#13354387 - CRASH IN IN MY_DECIMAL::OPERATOR FOR VIEW AND FUNCTION UNIX_TIMESTAMP +--echo # Part2 (5.6) +CREATE TABLE t1 (a VARCHAR(32) NOT NULL); +INSERT INTO t1 VALUES ('a'); +SELECT 1 FROM t1 GROUP BY @a:=UNIX_TIMESTAMP(a); +SELECT a, UNIX_TIMESTAMP(a), UNIX_TIMESTAMP('a') FROM t1; +DELETE FROM t1; +INSERT INTO t1 VALUES ('5000-01-01 00:00:00'); +SELECT a, UNIX_TIMESTAMP(a), UNIX_TIMESTAMP('5000-01-01 00:00:00') FROM t1; +DROP TABLE t1; === modified file 'sql/item.cc' --- a/sql/item.cc 2012-01-12 13:27:57 +0000 +++ b/sql/item.cc 2012-01-13 08:36:43 +0000 @@ -1378,12 +1378,27 @@ bool Item::get_time_from_non_temporal(MY } +/* +- Return NULL if argument is NULL. +- Return zero if argument is not NULL, but we could not convert it to DATETIME. +- Return zero if argument is not NULL and represents a valid DATETIME value, + but the value is out of the supported Unix timestamp range. +*/ bool Item::get_timeval(struct timeval *tm, int *warnings) { MYSQL_TIME ltime; - return (null_value= - (get_date(<ime, TIME_FUZZY_DATE) || - datetime_to_timeval(current_thd, <ime, tm, warnings))); + if (get_date(<ime, TIME_FUZZY_DATE)) + { + if (null_value) + return true; /* Value is NULL */ + goto zero; /* Could not extract date from the value */ + } + if (datetime_to_timeval(current_thd, <ime, tm, warnings)) + goto zero; /* Value is out of the supported range */ + return false; /* Value is a good Unix timestamp */ +zero: + tm->tv_sec= tm->tv_usec= 0; + return false; } @@ -2670,8 +2685,11 @@ bool Item_field::get_time(MYSQL_TIME *lt bool Item_field::get_timeval(struct timeval *tm, int *warnings) { - return (null_value= (field->is_null() || - field->get_timestamp(tm, warnings))); + if ((null_value= field->is_null())) + return true; + if (field->get_timestamp(tm, warnings)) + tm->tv_sec= tm->tv_usec= 0; + return false; } double Item_field::val_result() === modified file 'sql/item_timefunc.cc' --- a/sql/item_timefunc.cc 2011-12-16 16:57:46 +0000 +++ b/sql/item_timefunc.cc 2012-01-13 08:36:43 +0000 @@ -1456,20 +1456,7 @@ bool Item_func_unix_timestamp::val_timev return false; // no args: null_value is set in constructor and is always 0. } int warnings= 0; - if (args[0]->get_timeval(tm, &warnings)) // Don't set null_value here - { - /* - We set null_value only if args[0]->get_date() invoked - inside args[0]->get_timeval() returned null, - which is indicated by "warnings == 0". - In case of wrong non-null datetime parameter we return 0. - "warnings" will not be equal to 0 in this case. - */ - if (warnings == 0) - return (null_value= true); - tm->tv_sec= tm->tv_usec= 0; - } - return (null_value= false); + return (null_value= args[0]->get_timeval(tm, &warnings)); } No bundle (reason: useless for push emails).