List:Commits« Previous MessageNext Message »
From:Tor Didriksen Date:July 21 2011 3:11pm
Subject:bzr push into mysql-trunk branch (tor.didriksen:3285 to 3286) Bug#12532830
View as plain text  
 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).
Thread
bzr push into mysql-trunk branch (tor.didriksen:3285 to 3286) Bug#12532830Tor Didriksen21 Jul