Commit 39fb7b24 authored by unknown's avatar unknown
Browse files

Fix for bug #22026: Warning when using IF statement and large unsigned bigint

  
We use INT_RESULT type if all arguments are of type INT for 'if', 'case', 
'coalesce' functions regardless of arguments' unsigned flag, so sometimes we can
exceed the INT bounds.


mysql-test/r/select.result:
  Fix for bug #22026: Warning when using IF statement and large unsigned bigint
    - test result.
mysql-test/t/select.test:
  Fix for bug #22026: Warning when using IF statement and large unsigned bigint
    - test case.
sql/item_cmpfunc.cc:
  Fix for bug #22026: Warning when using IF statement and large unsigned bigint
    - take into account unsigned flags aggregating result types:                    
      return INT_RESULT only if two items with INT_RESULT type                      
      have equal unsigned_flags, otherwise return REAL_RESULT.
parent 74eac22e
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -3634,3 +3634,33 @@ INSERT into t1 values (1), (2), (3);
SELECT * FROM t1 LIMIT 2, -1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1' at line 1
DROP TABLE t1;
create table t1 (a bigint unsigned);
insert into t1 values
(if(1, 9223372036854775808, 1)),
(case when 1 then 9223372036854775808 else 1 end),
(coalesce(9223372036854775808, 1));
select * from t1;
a
9223372036854775808
9223372036854775808
9223372036854775808
drop table t1;
create table t1 select
if(1, 9223372036854775808, 1) i,
case when 1 then 9223372036854775808 else 1 end c,
coalesce(9223372036854775808, 1) co;
show create table t1;
Table	Create Table
t1	CREATE TABLE `t1` (
  `i` decimal(19,0) NOT NULL default '0',
  `c` decimal(19,0) NOT NULL default '0',
  `co` decimal(19,0) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select 
if(1, cast(1111111111111111111 as unsigned), 1) i,
case when 1 then cast(1111111111111111111 as unsigned) else 1 end c,
coalesce(cast(1111111111111111111 as unsigned), 1) co;
i	c	co
1111111111111111111	1111111111111111111	1111111111111111111
End of 5.0 tests
+24 −0
Original line number Diff line number Diff line
@@ -3123,3 +3123,27 @@ SELECT * FROM t1 LIMIT 2, -1;

DROP TABLE t1;

#
# Bug #22026: Warning when using IF statement and large unsigned bigint
#

create table t1 (a bigint unsigned);
insert into t1 values
  (if(1, 9223372036854775808, 1)),
  (case when 1 then 9223372036854775808 else 1 end),
  (coalesce(9223372036854775808, 1));
select * from t1;
drop table t1;
create table t1 select
  if(1, 9223372036854775808, 1) i,
  case when 1 then 9223372036854775808 else 1 end c,
  coalesce(9223372036854775808, 1) co;
show create table t1;
drop table t1;
# Ensure we handle big values properly
select 
  if(1, cast(1111111111111111111 as unsigned), 1) i,
  case when 1 then cast(1111111111111111111 as unsigned) else 1 end c,
  coalesce(cast(1111111111111111111 as unsigned), 1) co;

--echo End of 5.0 tests
+9 −3
Original line number Diff line number Diff line
@@ -26,13 +26,17 @@

static bool convert_constant_item(THD *thd, Field *field, Item **item);

static Item_result item_store_type(Item_result a,Item_result b)
static Item_result item_store_type(Item_result a, Item *item,
                                   my_bool unsigned_flag)
{
  Item_result b= item->result_type();

  if (a == STRING_RESULT || b == STRING_RESULT)
    return STRING_RESULT;
  else if (a == REAL_RESULT || b == REAL_RESULT)
    return REAL_RESULT;
  else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT)
  else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT ||
           unsigned_flag != item->unsigned_flag)
    return DECIMAL_RESULT;
  else
    return INT_RESULT;
@@ -41,6 +45,7 @@ static Item_result item_store_type(Item_result a,Item_result b)
static void agg_result_type(Item_result *type, Item **items, uint nitems)
{
  Item **item, **item_end;
  my_bool unsigned_flag= 0;

  *type= STRING_RESULT;
  /* Skip beginning NULL items */
@@ -49,6 +54,7 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
    if ((*item)->type() != Item::NULL_ITEM)
    {
      *type= (*item)->result_type();
      unsigned_flag= (*item)->unsigned_flag;
      item++;
      break;
    }
@@ -57,7 +63,7 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
  for (; item < item_end; item++)
  {
    if ((*item)->type() != Item::NULL_ITEM)
      *type= item_store_type(type[0], (*item)->result_type());
      *type= item_store_type(*type, *item, unsigned_flag);
  }
}