From: Tor Didriksen Date: July 21 2011 3:11pm Subject: bzr push into mysql-trunk branch (tor.didriksen:3285 to 3286) Bug#12532830 List-Archive: http://lists.mysql.com/commits/140409 X-Bug: 12532830 Message-Id: <201107211511.p6LFBwlV008596@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3286 Tor Didriksen 2011-07-21 Bug#12532830 - SIGFPE OR ASSERTION (PRECISION <= ((9 * 9) - 8*2)) && (DEC <= 30) @ mysql-test/r/func_if.result New test case. @ mysql-test/suite/innodb/r/innodb_bug54044.result If(xxxx, null, null) now returns binary(0) rater than null. Add tests from bug#54044. @ mysql-test/t/func_if.test New test case. @ sql/field.cc Catch wrong value for decimals a bit earlier: when we create 'pack_flag' rather than when we use it later to create Field_new_decimal. @ sql/item_cmpfunc.cc In Item_func_if::fix_length_and_dec(): save decimals (in addition to misc other properties) whenever one of the branches is a null_item. Let other expressions (even if they evaluate to const-null) be handled by the general mechanisms. modified: mysql-test/r/func_if.result mysql-test/suite/innodb/r/innodb_bug54044.result mysql-test/suite/innodb/t/innodb_bug54044.test mysql-test/t/func_if.test sql/field.cc sql/item_cmpfunc.cc sql/item_cmpfunc.h 3285 Bjorn Munch 2011-07-21 Followup to mysqltest/mtr option --opt-trace-protocol Fixed some corner cases: --send followed by stmt on separate line: Drop doing optimizer trace in this case --lowercase_result on a non-trivial statement Turn off lower casing (as was done for sorting) The first is fixed also for --explain-protocol modified: client/mysqltest.cc === modified file 'mysql-test/r/func_if.result' --- a/mysql-test/r/func_if.result 2011-07-19 15:11:15 +0000 +++ b/mysql-test/r/func_if.result 2011-07-21 15:11:09 +0000 @@ -212,3 +212,17 @@ hello SELECT if(1, NULL, (SELECT min('hello'))); if(1, NULL, (SELECT min('hello'))) NULL +# +# Bug#12532830 +# SIGFPE OR ASSERTION (PRECISION <= ((9 * 9) - 8*2)) && (DEC <= 30) +# +select +sum(distinct(if('a', +(select adddate(elt(convert(9999999999999999999999999999999999999,decimal(64,0)),count(*)), +interval 1 day)) +, .1))) as foo; +foo +0.1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' === modified file 'mysql-test/suite/innodb/r/innodb_bug54044.result' --- a/mysql-test/suite/innodb/r/innodb_bug54044.result 2010-06-29 07:14:20 +0000 +++ b/mysql-test/suite/innodb/r/innodb_bug54044.result 2011-07-21 15:11:09 +0000 @@ -1,3 +1,12 @@ CREATE TEMPORARY TABLE table_54044 ENGINE = INNODB AS SELECT IF(NULL IS NOT NULL, NULL, NULL); -ERROR HY000: Can't create table 'test.table_54044' (errno: -1) +SHOW CREATE TABLE table_54044; +Table Create Table +table_54044 CREATE TEMPORARY TABLE `table_54044` ( + `IF(NULL IS NOT NULL, NULL, NULL)` binary(0) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE table_54044; +CREATE TABLE TMP ENGINE = INNODB AS SELECT COALESCE(NULL, NULL, NULL); +ERROR HY000: Can't create table 'test.TMP' (errno: -1) +CREATE TABLE TMP ENGINE = INNODB AS SELECT GREATEST(NULL, NULL); +ERROR HY000: Can't create table 'test.TMP' (errno: -1) === modified file 'mysql-test/suite/innodb/t/innodb_bug54044.test' --- a/mysql-test/suite/innodb/t/innodb_bug54044.test 2010-06-29 07:14:20 +0000 +++ b/mysql-test/suite/innodb/t/innodb_bug54044.test 2011-07-21 15:11:09 +0000 @@ -3,9 +3,17 @@ --source include/have_innodb.inc -# This 'create table' operation should fail because of -# using NULL datatype ---error ER_CANT_CREATE_TABLE +# This 'create table' operation no longer uses the NULL datatype. + CREATE TEMPORARY TABLE table_54044 ENGINE = INNODB AS SELECT IF(NULL IS NOT NULL, NULL, NULL); +SHOW CREATE TABLE table_54044; +DROP TABLE table_54044; +# These 'create table' operations should fail because of +# using NULL datatype + +--error ER_CANT_CREATE_TABLE +CREATE TABLE TMP ENGINE = INNODB AS SELECT COALESCE(NULL, NULL, NULL); +--error ER_CANT_CREATE_TABLE +CREATE TABLE TMP ENGINE = INNODB AS SELECT GREATEST(NULL, NULL); === modified file 'mysql-test/t/func_if.test' --- a/mysql-test/t/func_if.test 2011-06-30 12:57:20 +0000 +++ b/mysql-test/t/func_if.test 2011-07-21 15:11:09 +0000 @@ -187,3 +187,15 @@ SELECT if(0, (SELECT min('hello')), NULL SELECT if(1, (SELECT min('hello')), NULL); SELECT if(0, NULL, (SELECT min('hello'))); SELECT if(1, NULL, (SELECT min('hello'))); + +--echo # +--echo # Bug#12532830 +--echo # SIGFPE OR ASSERTION (PRECISION <= ((9 * 9) - 8*2)) && (DEC <= 30) +--echo # + +let $nines= 9999999999999999999999999999999999999; +eval select +sum(distinct(if('a', + (select adddate(elt(convert($nines,decimal(64,0)),count(*)), + interval 1 day)) + , .1))) as foo; === modified file 'sql/field.cc' --- a/sql/field.cc 2011-07-04 00:25:46 +0000 +++ b/sql/field.cc 2011-07-21 15:11:09 +0000 @@ -9190,8 +9190,9 @@ void Create_field::init_for_tmp_table(en pack_flag= FIELDFLAG_INTERVAL; break; - case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: + DBUG_ASSERT(decimals_arg <= DECIMAL_MAX_SCALE); + case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: pack_flag= FIELDFLAG_NUMBER | === modified file 'sql/item_cmpfunc.cc' --- a/sql/item_cmpfunc.cc 2011-07-19 15:11:15 +0000 +++ b/sql/item_cmpfunc.cc 2011-07-21 15:11:09 +0000 @@ -2720,37 +2720,43 @@ Item_func_if::fix_fields(THD *thd, Item } +void Item_func_if::cache_type_info(Item *source) +{ + collation.set(source->collation); + cached_field_type= source->field_type(); + cached_result_type= source->result_type(); + decimals= source->decimals; + max_length= source->max_length; + maybe_null= source->maybe_null; + unsigned_flag= source->unsigned_flag; +} + + void Item_func_if::fix_length_and_dec() { - maybe_null=args[1]->maybe_null || args[2]->maybe_null; - decimals= max(args[1]->decimals, args[2]->decimals); - unsigned_flag=args[1]->unsigned_flag && args[2]->unsigned_flag; - - enum Item_result arg1_type=args[1]->result_type(); - enum Item_result arg2_type=args[2]->result_type(); - bool null1=args[1]->const_item() && args[1]->null_value; - bool null2=args[2]->const_item() && args[2]->null_value; - - if (null1 && args[2]->type() != NULL_ITEM) - { - cached_result_type= arg2_type; - collation.set(args[2]->collation); - cached_field_type= args[2]->field_type(); - max_length= args[2]->max_length; + // Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr. + if (args[1]->type() == NULL_ITEM) + { + cache_type_info(args[2]); + maybe_null= true; + // If both arguments are NULL, make resulting type BINARY(0). + if (args[2]->type() == NULL_ITEM) + cached_field_type= MYSQL_TYPE_STRING; return; } - - if (null2 && args[1]->type() != NULL_ITEM) + if (args[2]->type() == NULL_ITEM) { - cached_result_type= arg1_type; - collation.set(args[1]->collation); - cached_field_type= args[1]->field_type(); - max_length= args[1]->max_length; + cache_type_info(args[1]); + maybe_null= true; return; } agg_result_type(&cached_result_type, args + 1, 2); + maybe_null= args[1]->maybe_null || args[2]->maybe_null; + decimals= max(args[1]->decimals, args[2]->decimals); + unsigned_flag=args[1]->unsigned_flag && args[2]->unsigned_flag; + if (cached_result_type == STRING_RESULT) { if (agg_arg_charsets_for_string_result(collation, args + 1, 2)) === modified file 'sql/item_cmpfunc.h' --- a/sql/item_cmpfunc.h 2011-07-19 15:11:15 +0000 +++ b/sql/item_cmpfunc.h 2011-07-21 15:11:09 +0000 @@ -818,6 +818,8 @@ public: void fix_length_and_dec(); uint decimal_precision() const; const char *func_name() const { return "if"; } +private: + void cache_type_info(Item *source); }; No bundle (reason: useless for push emails).