MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Alexey Kopytov Date:March 18 2010 10:38am
Subject:bzr commit into mysql-next-mr branch (Alexey.Kopytov:2938) Bug#8433
View as plain text  
#At file:///data/src/bzr/bugteam/bug8433/mysql-next-mr-bug8433/ based on revid:alik@stripped

 2938 Alexey Kopytov	2010-03-18
      Bug #8433: Overflow must be an error 
       
      All numeric operators and functions on integer, floating point 
      and DECIMAL values now throw an 'out of range' error rather 
      than returning an incorrect value or NULL,  when the result is 
      out of supported range for the corresponding data type. 
       
      Some test cases in the test suite had to be updated 
      accordingly either because the test case itself relied on a 
      value returned in case of a numeric overflow, or because a 
      numeric overflow was the root cause of the corresponding bugs. 
      The latter tests are no longer relevant, since the expressions 
      used to trigger the corresponding bugs are not valid anymore. 
      However, such test cases have been adjusted and kept "for the 
      record". 
     @ mysql-test/r/func_math.result
        Added test cases for bug #8433. 
        Updated results of the test case for bug #31236.
     @ mysql-test/r/func_misc.result
        Streamlined test cases.
     @ mysql-test/r/func_test.result
        Streamlined test cases.
     @ mysql-test/r/select.result
        Streamlined test cases.
     @ mysql-test/r/sp.result
        Streamlined test cases.
     @ mysql-test/r/strict.result
        Streamlined test cases.
     @ mysql-test/r/type_newdecimal.result
        Streamlined test cases.
     @ mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result
        Streamlined test cases.
     @ mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test
        Streamlined test cases.
     @ mysql-test/t/func_math.test
        Added test cases for bug #8433. 
        Updated results of the test case for bug #31236.
     @ mysql-test/t/func_misc.test
        Streamlined test cases.
     @ mysql-test/t/func_test.test
        Streamlined test cases.
     @ mysql-test/t/select.test
        Streamlined test cases.
     @ mysql-test/t/sp.test
        Streamlined test cases.
     @ mysql-test/t/strict.test
        Streamlined test cases.
     @ mysql-test/t/type_newdecimal.test
        Streamlined test cases.
     @ sql/item_create.cc
        Changed Item_func_cot() to be defined as a standalone Item
        rather than a combination of "1 / TAN(x)".
     @ sql/item_func.cc
        Throw an 'out of range' error rather than returning an  
        incorrect value or NULL,  when the result of a numeric 
        operator or a function is out of supported range for  
        the corresponding data type.
     @ sql/item_func.h
        Added validation helpers as inline methods of Item_func.
     @ sql/share/errmsg-utf8.txt
        New ER_DATA_OUT_OF_RANGE error.

    modified:
      mysql-test/r/func_math.result
      mysql-test/r/func_misc.result
      mysql-test/r/func_test.result
      mysql-test/r/select.result
      mysql-test/r/sp.result
      mysql-test/r/strict.result
      mysql-test/r/type_newdecimal.result
      mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result
      mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test
      mysql-test/t/func_math.test
      mysql-test/t/func_misc.test
      mysql-test/t/func_test.test
      mysql-test/t/select.test
      mysql-test/t/sp.test
      mysql-test/t/strict.test
      mysql-test/t/type_newdecimal.test
      sql/item_create.cc
      sql/item_func.cc
      sql/item_func.h
      sql/share/errmsg-utf8.txt
=== modified file 'mysql-test/r/func_math.result'
--- a/mysql-test/r/func_math.result	2010-02-02 13:58:15 +0000
+++ b/mysql-test/r/func_math.result	2010-03-18 10:38:29 +0000
@@ -98,7 +98,7 @@ explain extended select pi(),format(sin(
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 Warnings:
-Note	1003	select pi() AS `pi()`,format(sin((pi() / 2)),6) AS `format(sin(pi()/2),6)`,format(cos((pi() / 2)),6) AS `format(cos(pi()/2),6)`,format(abs(tan(pi())),6) AS `format(abs(tan(pi())),6)`,format((1 / tan(1)),6) AS `format(cot(1),6)`,format(asin(1),6) AS `format(asin(1),6)`,format(acos(0),6) AS `format(acos(0),6)`,format(atan(1),6) AS `format(atan(1),6)`
+Note	1003	select pi() AS `pi()`,format(sin((pi() / 2)),6) AS `format(sin(pi()/2),6)`,format(cos((pi() / 2)),6) AS `format(cos(pi()/2),6)`,format(abs(tan(pi())),6) AS `format(abs(tan(pi())),6)`,format(cot(1),6) AS `format(cot(1),6)`,format(asin(1),6) AS `format(asin(1),6)`,format(acos(0),6) AS `format(acos(0),6)`,format(atan(1),6) AS `format(atan(1),6)`
 select degrees(pi()),radians(360);
 degrees(pi())	radians(360)
 180	6.283185307179586
@@ -451,23 +451,17 @@ SELECT 1 FROM (SELECT ROUND(f1, f1) AS a
 DROP TABLE t1;
 End of 5.0 tests
 SELECT 1e308 + 1e308;
-1e308 + 1e308
-NULL
+ERROR 22003: DOUBLE value is out of range in '(1e308 + 1e308)'
 SELECT -1e308 - 1e308;
--1e308 - 1e308
-NULL
+ERROR 22003: DOUBLE value is out of range in '(-(1e308) - 1e308)'
 SELECT 1e300 * 1e300;
-1e300 * 1e300
-NULL
+ERROR 22003: DOUBLE value is out of range in '(1e300 * 1e300)'
 SELECT 1e300 / 1e-300;
-1e300 / 1e-300
-NULL
+ERROR 22003: DOUBLE value is out of range in '(1e300 / 1e-300)'
 SELECT EXP(750);
-EXP(750)
-NULL
+ERROR 22003: DOUBLE value is out of range in 'exp(750)'
 SELECT POW(10, 309);
-POW(10, 309)
-NULL
+ERROR 22003: DOUBLE value is out of range in 'pow(10,309)'
 #
 # Bug #44768: SIGFPE crash when selecting rand from a view
 #             containing null
@@ -488,11 +482,121 @@ RAND(i)
 DROP TABLE t1;
 #
 select 123456789012345678901234567890.123456789012345678901234567890 div 1 as x;
-ERROR 22003: Out of range value for column 'x' at row 1
+ERROR 22003: BIGINT value is out of range in '(123456789012345678901234567890.123456789012345678901234567890 DIV 1)'
 select "123456789012345678901234567890.123456789012345678901234567890" div 1 as x;
-ERROR 22003: Out of range value for column 'x' at row 1
+ERROR 22003: BIGINT value is out of range in '('123456789012345678901234567890.123456789012345678901234567890' DIV 1)'
 SHOW WARNINGS;
 Level	Code	Message
 Warning	1292	Truncated incorrect DECIMAL value: ''
-Error	1264	Out of range value for column 'x' at row 1
+Error	1689	BIGINT value is out of range in '('123456789012345678901234567890.123456789012345678901234567890' DIV 1)'
 End of 5.1 tests
+#
+# Bug #8433: Overflow must be an error
+#
+SELECT 1e308 + 1e308;
+ERROR 22003: DOUBLE value is out of range in '(1e308 + 1e308)'
+SELECT -1e308 - 1e308;
+ERROR 22003: DOUBLE value is out of range in '(-(1e308) - 1e308)'
+SELECT 1e300 * 1e300;
+ERROR 22003: DOUBLE value is out of range in '(1e300 * 1e300)'
+SELECT 1e300 / 1e-300;
+ERROR 22003: DOUBLE value is out of range in '(1e300 / 1e-300)'
+SELECT EXP(750);
+ERROR 22003: DOUBLE value is out of range in 'exp(750)'
+SELECT POW(10, 309);
+ERROR 22003: DOUBLE value is out of range in 'pow(10,309)'
+SELECT COT(0);
+ERROR 22003: DOUBLE value is out of range in 'cot(0)'
+SELECT DEGREES(1e307);
+ERROR 22003: DOUBLE value is out of range in 'degrees(1e307)'
+SELECT 9223372036854775808 + 9223372036854775808;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(9223372036854775808 + 9223372036854775808)'
+SELECT 18446744073709551615 + 1;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(18446744073709551615 + 1)'
+SELECT 1 + 18446744073709551615;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(1 + 18446744073709551615)'
+SELECT -2 + CAST(1 AS UNSIGNED);
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(-(2) + cast(1 as unsigned))'
+SELECT CAST(1 AS UNSIGNED) + -2;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(cast(1 as unsigned) + -(2))'
+SELECT -9223372036854775808 + -9223372036854775808;
+ERROR 22003: BIGINT value is out of range in '(-(9223372036854775808) + -(9223372036854775808))'
+SELECT 9223372036854775807 + 9223372036854775807;
+ERROR 22003: BIGINT value is out of range in '(9223372036854775807 + 9223372036854775807)'
+SELECT CAST(0 AS UNSIGNED) - 9223372036854775809;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 9223372036854775809)'
+SELECT 9223372036854775808 - 9223372036854775809;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(9223372036854775808 - 9223372036854775809)'
+SELECT CAST(1 AS UNSIGNED) - 2;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(cast(1 as unsigned) - 2)'
+SELECT 18446744073709551615 - (-1);
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(18446744073709551615 - -(1))'
+SELECT -1 - 9223372036854775808;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(-(1) - 9223372036854775808)'
+SELECT -1 - CAST(1 AS UNSIGNED);
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(-(1) - cast(1 as unsigned))'
+SELECT -9223372036854775808 - 1;
+ERROR 22003: BIGINT value is out of range in '(-(9223372036854775808) - 1)'
+SELECT 9223372036854775807 - -9223372036854775808;
+ERROR 22003: BIGINT value is out of range in '(9223372036854775807 - -(9223372036854775808))'
+set SQL_MODE='NO_UNSIGNED_SUBTRACTION';
+SELECT 18446744073709551615 - 1;
+ERROR 22003: BIGINT value is out of range in '(18446744073709551615 - 1)'
+SELECT 18446744073709551615 - CAST(1 AS UNSIGNED);
+ERROR 22003: BIGINT value is out of range in '(18446744073709551615 - cast(1 as unsigned))'
+SELECT 18446744073709551614 - (-1);
+ERROR 22003: BIGINT value is out of range in '(18446744073709551614 - -(1))'
+SELECT 9223372036854775807 - -1;
+ERROR 22003: BIGINT value is out of range in '(9223372036854775807 - -(1))'
+set SQL_MODE=default;
+SELECT 4294967296 * 4294967296;
+ERROR 22003: BIGINT value is out of range in '(4294967296 * 4294967296)'
+SELECT 9223372036854775808 * 2;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(9223372036854775808 * 2)'
+SELECT 9223372036854775808 * 2;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(9223372036854775808 * 2)'
+SELECT 7158278827 * 3221225472;
+ERROR 22003: BIGINT value is out of range in '(7158278827 * 3221225472)'
+SELECT 9223372036854775807 * (-2);
+ERROR 22003: BIGINT value is out of range in '(9223372036854775807 * -(2))'
+SELECT CAST(1 as UNSIGNED) * (-1);
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(cast(1 as unsigned) * -(1))'
+SELECT 9223372036854775807 * 2;
+ERROR 22003: BIGINT value is out of range in '(9223372036854775807 * 2)'
+SELECT ABS(-9223372036854775808);
+ERROR 22003: BIGINT value is out of range in 'abs(-(9223372036854775808))'
+SELECT -9223372036854775808 DIV -1;
+ERROR 22003: BIGINT value is out of range in '(-(9223372036854775808) DIV -(1))'
+SELECT 18446744073709551615 DIV -1;
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(18446744073709551615 DIV -(1))'
+CREATE TABLE t1(a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES(-9223372036854775808, 9223372036854775809);
+SELECT -a FROM t1;
+ERROR 22003: BIGINT value is out of range in '-('-9223372036854775808')'
+SELECT -b FROM t1;
+ERROR 22003: BIGINT value is out of range in '-('9223372036854775809')'
+DROP TABLE t1;
+SET @a:=999999999999999999999999999999999999999999999999999999999999999999999999999999999;
+SELECT @a + @a;
+ERROR 22003: DECIMAL value is out of range in '((@a) + (@a))'
+SELECT @a * @a;
+ERROR 22003: DECIMAL value is out of range in '((@a) * (@a))'
+SELECT -@a - @a;
+ERROR 22003: DECIMAL value is out of range in '(-((@a)) - (@a))'
+SELECT @a / 0.5;
+ERROR 22003: DECIMAL value is out of range in '((@a) / 0.5)'
+SELECT COT(1/0);
+COT(1/0)
+NULL
+SELECT -1 + 9223372036854775808;
+-1 + 9223372036854775808
+9223372036854775807
+SELECT 2 DIV -2;
+2 DIV -2
+-1
+SELECT -(1 DIV 0);
+-(1 DIV 0)
+NULL
+SELECT -9223372036854775808 MOD -1;
+-9223372036854775808 MOD -1
+0

=== modified file 'mysql-test/r/func_misc.result'
--- a/mysql-test/r/func_misc.result	2009-06-11 16:21:32 +0000
+++ b/mysql-test/r/func_misc.result	2010-03-18 10:38:29 +0000
@@ -25,9 +25,9 @@ length(uuid())	charset(uuid())	length(un
 36	utf8	16
 set @a= uuid_short();
 set @b= uuid_short();
-select cast(@a - @b as signed);
-cast(@a - @b as signed)
--1
+select @b - @a;
+@b - @a
+1
 select length(format('nan', 2)) > 0;
 length(format('nan', 2)) > 0
 1

=== modified file 'mysql-test/r/func_test.result'
--- a/mysql-test/r/func_test.result	2009-10-19 11:13:26 +0000
+++ b/mysql-test/r/func_test.result	2010-03-18 10:38:29 +0000
@@ -63,8 +63,8 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 Warnings:
 Note	1003	select (10 % 7) AS `10 % 7`,(10 % 7) AS `10 mod 7`,(10 DIV 3) AS `10 div 3`
-select (1 << 64)-1, ((1 << 64)-1) DIV 1, ((1 << 64)-1) DIV 2;
-(1 << 64)-1	((1 << 64)-1) DIV 1	((1 << 64)-1) DIV 2
+select 18446744073709551615, 18446744073709551615 DIV 1, 18446744073709551615 DIV 2;
+18446744073709551615	18446744073709551615 DIV 1	18446744073709551615 DIV 2
 18446744073709551615	18446744073709551615	9223372036854775807
 explain extended select (1 << 64)-1, ((1 << 64)-1) DIV 1, ((1 << 64)-1) DIV 2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra

=== modified file 'mysql-test/r/select.result'
--- a/mysql-test/r/select.result	2010-02-20 10:07:32 +0000
+++ b/mysql-test/r/select.result	2010-03-18 10:38:29 +0000
@@ -2426,27 +2426,28 @@ city
 London
 DROP TABLE t1;
 create table t1 (a int(11) unsigned, b int(11) unsigned);
-insert into t1 values (1,0), (1,1), (1,2);
+insert into t1 values (1,0), (1,1), (18446744073709551615,0);
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 3
 select a-b  from t1 order by 1;
 a-b
 0
 1
-18446744073709551615
+4294967295
 select a-b , (a-b < 0)  from t1 order by 1;
 a-b	(a-b < 0)
 0	0
 1	0
-18446744073709551615	0
+4294967295	0
 select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0;
 d	(a-b >= 0)	b
 1	1	0
 0	1	1
-18446744073709551615	1	2
 select cast((a - b) as unsigned) from t1 order by 1;
 cast((a - b) as unsigned)
 0
 1
-18446744073709551615
+4294967295
 drop table t1;
 create table t1 (a int(11));
 select all all * from t1;
@@ -3419,6 +3420,7 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	t2	const	PRIMARY	PRIMARY	4	const	1	
 1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	2	Using where
 DROP TABLE t1,t2;
+SET SQL_MODE='NO_UNSIGNED_SUBTRACTION';
 CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
 INSERT t1 SET i = 0;
 UPDATE t1 SET i = -1;
@@ -3438,8 +3440,9 @@ Warnings:
 Warning	1264	Out of range value for column 'i' at row 1
 SELECT * FROM t1;
 i
-255
+0
 DROP TABLE t1;
+SET SQL_MODE=default;
 create table t1 (a int);
 insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
 create table t2 (a int, b int, c int, e int, primary key(a,b,c));

=== modified file 'mysql-test/r/sp.result'
--- a/mysql-test/r/sp.result	2010-02-20 10:07:32 +0000
+++ b/mysql-test/r/sp.result	2010-03-18 10:38:29 +0000
@@ -6022,16 +6022,12 @@ select bug20777(9223372036854775810) as 
 9223372036854775810   2**63+2
 9223372036854775810
 select bug20777(-9223372036854775808) as 'lower bounds signed bigint';
-lower bounds signed bigint
-0
-Warnings:
-Warning	1264	Out of range value for column 'f1' at row 1
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(f1@0 - 10)'
 select bug20777(9223372036854775807) as 'upper bounds signed bigint';
 upper bounds signed bigint
 9223372036854775807
 select bug20777(0) as 'lower bounds unsigned bigint';
-lower bounds unsigned bigint
-0
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(f1@0 - 10)'
 select bug20777(18446744073709551615) as 'upper bounds unsigned bigint';
 upper bounds unsigned bigint
 18446744073709551615
@@ -6041,10 +6037,7 @@ upper bounds unsigned bigint + 1
 Warnings:
 Warning	1264	Out of range value for column 'f1' at row 1
 select bug20777(-1) as 'lower bounds unsigned bigint - 1';
-lower bounds unsigned bigint - 1
-0
-Warnings:
-Warning	1264	Out of range value for column 'f1' at row 1
+ERROR 22003: BIGINT UNSIGNED value is out of range in '(f1@0 - 10)'
 create table examplebug20777 as select 
 0 as 'i',
 bug20777(9223372036854775806) as '2**63-2',
@@ -6053,15 +6046,10 @@ bug20777(9223372036854775808) as '2**63'
 bug20777(9223372036854775809) as '2**63+1',
 bug20777(18446744073709551614) as '2**64-2',
 bug20777(18446744073709551615) as '2**64-1', 
-bug20777(18446744073709551616) as '2**64',
-bug20777(0) as '0',
-bug20777(-1) as '-1';
+bug20777(18446744073709551616) as '2**64';
 Warnings:
 Warning	1264	Out of range value for column 'f1' at row 1
-Warning	1264	Out of range value for column 'f1' at row 1
-insert into examplebug20777 values (1, 9223372036854775806, 9223372036854775807, 223372036854775808, 9223372036854775809, 18446744073709551614, 18446744073709551615, 8446744073709551616, 0, -1);
-Warnings:
-Warning	1264	Out of range value for column '-1' at row 1
+insert into examplebug20777 values (1, 9223372036854775806, 9223372036854775807, 223372036854775808, 9223372036854775809, 18446744073709551614, 18446744073709551615, 8446744073709551616);
 show create table examplebug20777;
 Table	Create Table
 examplebug20777	CREATE TABLE `examplebug20777` (
@@ -6072,14 +6060,12 @@ examplebug20777	CREATE TABLE `examplebug
   `2**63+1` bigint(20) unsigned DEFAULT NULL,
   `2**64-2` bigint(20) unsigned DEFAULT NULL,
   `2**64-1` bigint(20) unsigned DEFAULT NULL,
-  `2**64` bigint(20) unsigned DEFAULT NULL,
-  `0` bigint(20) unsigned DEFAULT NULL,
-  `-1` bigint(20) unsigned DEFAULT NULL
+  `2**64` bigint(20) unsigned DEFAULT NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 select * from examplebug20777 order by i;
-i	2**63-2	2**63-1	2**63	2**63+1	2**64-2	2**64-1	2**64	0	-1
-0	9223372036854775806	9223372036854775807	9223372036854775808	9223372036854775809	18446744073709551614	18446744073709551615	18446744073709551615	0	0
-1	9223372036854775806	9223372036854775807	223372036854775808	9223372036854775809	18446744073709551614	18446744073709551615	8446744073709551616	0	0
+i	2**63-2	2**63-1	2**63	2**63+1	2**64-2	2**64-1	2**64
+0	9223372036854775806	9223372036854775807	9223372036854775808	9223372036854775809	18446744073709551614	18446744073709551615	18446744073709551615
+1	9223372036854775806	9223372036854775807	223372036854775808	9223372036854775809	18446744073709551614	18446744073709551615	8446744073709551616
 drop table examplebug20777;
 select bug20777(18446744073709551613)+1;
 bug20777(18446744073709551613)+1

=== modified file 'mysql-test/r/strict.result'
--- a/mysql-test/r/strict.result	2010-02-20 10:07:32 +0000
+++ b/mysql-test/r/strict.result	2010-03-18 10:38:29 +0000
@@ -895,6 +895,7 @@ ERROR 22003: Out of range value for colu
 INSERT INTO t1 (col2) VALUES ('-1.2E-3');
 ERROR 22003: Out of range value for column 'col2' at row 1
 UPDATE t1 SET col1 =col1 * 5000 WHERE col1 > 0;
+ERROR 22003: DOUBLE value is out of range in '("test"."t1"."col1" * 5000)'
 UPDATE t1 SET col2 =col2 / 0 WHERE col2 > 0;
 ERROR 22012: Division by 0
 UPDATE t1 SET col2= MOD(col2,0) WHERE col2 > 0;
@@ -922,10 +923,10 @@ SELECT * FROM t1;
 col1	col2
 -2.2e-307	0
 1e-303	0
-NULL	1.7e308
+1.7e308	1.7e308
 -2.2e-307	0
 -2e-307	0
-NULL	1.7e308
+1.7e308	1.7e308
 0	NULL
 2	NULL
 NULL	NULL

=== modified file 'mysql-test/r/type_newdecimal.result'
--- a/mysql-test/r/type_newdecimal.result	2009-12-22 16:23:13 +0000
+++ b/mysql-test/r/type_newdecimal.result	2010-03-18 10:38:29 +0000
@@ -1385,11 +1385,7 @@ Warning	1264	Out of range value for colu
 insert into t1 values(
 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 *
 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999);
-Warnings:
-Warning	1292	Truncated incorrect DECIMAL value: ''
-Warning	1292	Truncated incorrect DECIMAL value: ''
-Warning	1292	Truncated incorrect DECIMAL value: ''
-Warning	1264	Out of range value for column 'c1' at row 1
+ERROR 22003: DECIMAL value is out of range in '(99999999999999999999999999999999999999999999999999999999999999999 * 99999999999999999999999999999999999999999999999999999999999999999)'
 insert into t1 values(1e100);
 Warnings:
 Warning	1264	Out of range value for column 'c1' at row 1
@@ -1397,7 +1393,6 @@ select * from t1;
 c1
 9999999999999999999999999999999999999999999999999999999999999999
 9999999999999999999999999999999999999999999999999999999999999999
-9999999999999999999999999999999999999999999999999999999999999999
 drop table t1;
 create table t1(a decimal(7,2));
 insert into t1 values(123.12);

=== modified file 'mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result'
--- a/mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result	2009-12-22 09:35:56 +0000
+++ b/mysql-test/suite/sys_vars/r/sql_slave_skip_counter_basic.result	2010-03-18 10:38:29 +0000
@@ -14,9 +14,9 @@ SET @@global.sql_slave_skip_counter = 21
 Warnings:
 Warning	1292	Truncated incorrect sql_slave_skip_counter value: '4294967296'
 SET @@global.sql_slave_skip_counter = 2147483648*2-1;
-SET @@global.sql_slave_skip_counter = 4294967295*4294967295;
+SET @@global.sql_slave_skip_counter = 18446744065119617025;
 Warnings:
-Warning	1292	Truncated incorrect sql_slave_skip_counter value: '-8589934591'
+Warning	1292	Truncated incorrect sql_slave_skip_counter value: '18446744065119617025'
 '#--------------------FN_DYNVARS_165_03-------------------------#'
 SET @@global.sql_slave_skip_counter = '5';
 ERROR 42000: Incorrect argument type to variable 'sql_slave_skip_counter'

=== modified file 'mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test'
--- a/mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test	2009-12-22 09:35:56 +0000
+++ b/mysql-test/suite/sys_vars/t/sql_slave_skip_counter_basic.test	2010-03-18 10:38:29 +0000
@@ -56,7 +56,7 @@ SET @@global.sql_slave_skip_counter = 10
 SET @@global.sql_slave_skip_counter = 2147483648;
 SET @@global.sql_slave_skip_counter = 2147483648*2;
 SET @@global.sql_slave_skip_counter = 2147483648*2-1;
-SET @@global.sql_slave_skip_counter = 4294967295*4294967295;
+SET @@global.sql_slave_skip_counter = 18446744065119617025;
 
 --echo '#--------------------FN_DYNVARS_165_03-------------------------#'
 ###################################################################

=== modified file 'mysql-test/t/func_math.test'
--- a/mysql-test/t/func_math.test	2009-10-13 08:31:42 +0000
+++ b/mysql-test/t/func_math.test	2010-03-18 10:38:29 +0000
@@ -283,12 +283,20 @@ DROP TABLE t1;
 #
 # Bug #31236: Inconsistent division by zero behavior for floating point numbers
 #
+# After the fix for bug #8433 we throw an error in the below test cases
+# rather than just return a NULL value.
 
+--error ER_DATA_OUT_OF_RANGE
 SELECT 1e308 + 1e308;
+--error ER_DATA_OUT_OF_RANGE
 SELECT -1e308 - 1e308;
+--error ER_DATA_OUT_OF_RANGE
 SELECT 1e300 * 1e300;
+--error ER_DATA_OUT_OF_RANGE
 SELECT 1e300 / 1e-300;
+--error ER_DATA_OUT_OF_RANGE
 SELECT EXP(750);
+--error ER_DATA_OUT_OF_RANGE
 SELECT POW(10, 309);
 
 --echo #
@@ -314,10 +322,139 @@ DROP TABLE t1;
 #            DIV returns incorrect result with large decimal value
 # Bug #46606:Casting error for large numbers in 5.4 when 'div' is used
 
---error ER_WARN_DATA_OUT_OF_RANGE
+--error ER_DATA_OUT_OF_RANGE
 select 123456789012345678901234567890.123456789012345678901234567890 div 1 as x;
---error ER_WARN_DATA_OUT_OF_RANGE
+--error ER_DATA_OUT_OF_RANGE
 select "123456789012345678901234567890.123456789012345678901234567890" div 1 as x; 
 SHOW WARNINGS;
 
 --echo End of 5.1 tests
+
+--echo #
+--echo # Bug #8433: Overflow must be an error
+--echo #
+
+# Floating point overflows
+# ========================
+--error ER_DATA_OUT_OF_RANGE
+SELECT 1e308 + 1e308;
+--error ER_DATA_OUT_OF_RANGE
+SELECT -1e308 - 1e308;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 1e300 * 1e300;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 1e300 / 1e-300;
+--error ER_DATA_OUT_OF_RANGE
+SELECT EXP(750);
+--error ER_DATA_OUT_OF_RANGE
+SELECT POW(10, 309);
+--error ER_DATA_OUT_OF_RANGE
+SELECT COT(0);
+--error ER_DATA_OUT_OF_RANGE
+SELECT DEGREES(1e307);
+
+# Integer overflows
+# =================
+
+--error ER_DATA_OUT_OF_RANGE
+SELECT 9223372036854775808 + 9223372036854775808;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 18446744073709551615 + 1;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 1 + 18446744073709551615;
+--error ER_DATA_OUT_OF_RANGE
+SELECT -2 + CAST(1 AS UNSIGNED);
+--error ER_DATA_OUT_OF_RANGE
+SELECT CAST(1 AS UNSIGNED) + -2;
+--error ER_DATA_OUT_OF_RANGE
+SELECT -9223372036854775808 + -9223372036854775808;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 9223372036854775807 + 9223372036854775807;
+
+--error ER_DATA_OUT_OF_RANGE
+SELECT CAST(0 AS UNSIGNED) - 9223372036854775809;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 9223372036854775808 - 9223372036854775809;
+--error ER_DATA_OUT_OF_RANGE
+SELECT CAST(1 AS UNSIGNED) - 2;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 18446744073709551615 - (-1);
+--error ER_DATA_OUT_OF_RANGE
+SELECT -1 - 9223372036854775808;
+--error ER_DATA_OUT_OF_RANGE
+SELECT -1 - CAST(1 AS UNSIGNED);
+--error ER_DATA_OUT_OF_RANGE
+SELECT -9223372036854775808 - 1;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 9223372036854775807 - -9223372036854775808;
+
+# To test SIGNED overflow when subtraction arguments are both UNSIGNED
+set SQL_MODE='NO_UNSIGNED_SUBTRACTION';
+--error ER_DATA_OUT_OF_RANGE
+SELECT 18446744073709551615 - 1;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 18446744073709551615 - CAST(1 AS UNSIGNED);
+--error ER_DATA_OUT_OF_RANGE
+SELECT 18446744073709551614 - (-1);
+--error ER_DATA_OUT_OF_RANGE
+SELECT 9223372036854775807 - -1;
+set SQL_MODE=default;
+
+--error ER_DATA_OUT_OF_RANGE
+SELECT 4294967296 * 4294967296;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 9223372036854775808 * 2;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 9223372036854775808 * 2;
+# The following one triggers condition #3 from the comments in
+# Item_func_mul::int_op()
+--error ER_DATA_OUT_OF_RANGE
+SELECT 7158278827 * 3221225472;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 9223372036854775807 * (-2);
+--error ER_DATA_OUT_OF_RANGE
+SELECT CAST(1 as UNSIGNED) * (-1);
+--error ER_DATA_OUT_OF_RANGE
+SELECT 9223372036854775807 * 2;
+
+--error ER_DATA_OUT_OF_RANGE
+SELECT ABS(-9223372036854775808);
+
+--error ER_DATA_OUT_OF_RANGE
+SELECT -9223372036854775808 DIV -1;
+--error ER_DATA_OUT_OF_RANGE
+SELECT 18446744073709551615 DIV -1;
+
+
+# Have to create a table because the negation op may convert literals to DECIMAL
+CREATE TABLE t1(a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES(-9223372036854775808, 9223372036854775809);
+
+--error ER_DATA_OUT_OF_RANGE
+SELECT -a FROM t1;
+--error ER_DATA_OUT_OF_RANGE
+SELECT -b FROM t1;
+
+DROP TABLE t1;
+
+# Decimal overflows
+# =================
+
+SET @a:=999999999999999999999999999999999999999999999999999999999999999999999999999999999;
+--error ER_DATA_OUT_OF_RANGE
+SELECT @a + @a;
+--error ER_DATA_OUT_OF_RANGE
+SELECT @a * @a;
+--error ER_DATA_OUT_OF_RANGE
+SELECT -@a - @a;
+--error ER_DATA_OUT_OF_RANGE
+SELECT @a / 0.5;
+
+# Non-overflow tests to improve code coverage
+# ===========================================
+SELECT COT(1/0);
+SELECT -1 + 9223372036854775808;
+SELECT 2 DIV -2;
+SELECT -(1 DIV 0);
+# Crashed the server with SIGFPE before the bugfix
+SELECT -9223372036854775808 MOD -1;

=== modified file 'mysql-test/t/func_misc.test'
--- a/mysql-test/t/func_misc.test	2009-06-11 16:21:32 +0000
+++ b/mysql-test/t/func_misc.test	2010-03-18 10:38:29 +0000
@@ -22,7 +22,7 @@ select length(uuid()), charset(uuid()), 
 # between two calls should be -1
 set @a= uuid_short();
 set @b= uuid_short();
-select cast(@a - @b as signed);
+select @b - @a;
 
 #
 # Test for core dump with nan

=== modified file 'mysql-test/t/func_test.test'
--- a/mysql-test/t/func_test.test	2006-11-06 22:45:47 +0000
+++ b/mysql-test/t/func_test.test	2010-03-18 10:38:29 +0000
@@ -24,7 +24,7 @@ select 1 XOR 1, 1 XOR 0, 0 XOR 1, 0 XOR 
 select 1 like 2 xor 2 like 1;
 select 10 % 7, 10 mod 7, 10 div 3;
 explain extended select 10 % 7, 10 mod 7, 10 div 3;
-select (1 << 64)-1, ((1 << 64)-1) DIV 1, ((1 << 64)-1) DIV 2;
+select 18446744073709551615, 18446744073709551615 DIV 1, 18446744073709551615 DIV 2;
 explain extended select (1 << 64)-1, ((1 << 64)-1) DIV 1, ((1 << 64)-1) DIV 2;
 
 create table t1 (a int);

=== modified file 'mysql-test/t/select.test'
--- a/mysql-test/t/select.test	2010-01-30 22:10:29 +0000
+++ b/mysql-test/t/select.test	2010-03-18 10:38:29 +0000
@@ -1989,7 +1989,7 @@ DROP TABLE t1;
 #
 
 create table t1 (a int(11) unsigned, b int(11) unsigned);
-insert into t1 values (1,0), (1,1), (1,2);
+insert into t1 values (1,0), (1,1), (18446744073709551615,0);
 select a-b  from t1 order by 1;
 select a-b , (a-b < 0)  from t1 order by 1;
 select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0;
@@ -2910,6 +2910,7 @@ DROP TABLE t1,t2;
 # cases to prevent fixing this accidently. It is intended behaviour)
 #
 
+SET SQL_MODE='NO_UNSIGNED_SUBTRACTION';
 CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
 INSERT t1 SET i = 0;
 UPDATE t1 SET i = -1;
@@ -2919,6 +2920,7 @@ SELECT * FROM t1;
 UPDATE t1 SET i = i - 1;
 SELECT * FROM t1;
 DROP TABLE t1;
+SET SQL_MODE=default;
 
 # BUG#17379
 

=== modified file 'mysql-test/t/sp.test'
--- a/mysql-test/t/sp.test	2010-02-06 10:28:06 +0000
+++ b/mysql-test/t/sp.test	2010-03-18 10:38:29 +0000
@@ -7076,11 +7076,14 @@ select bug20777(9223372036854775807) as 
 select bug20777(9223372036854775808) as '9223372036854775808   2**63+0';
 select bug20777(9223372036854775809) as '9223372036854775809   2**63+1';
 select bug20777(9223372036854775810) as '9223372036854775810   2**63+2';
+--error ER_DATA_OUT_OF_RANGE
 select bug20777(-9223372036854775808) as 'lower bounds signed bigint';
 select bug20777(9223372036854775807) as 'upper bounds signed bigint';
+--error ER_DATA_OUT_OF_RANGE
 select bug20777(0) as 'lower bounds unsigned bigint';
 select bug20777(18446744073709551615) as 'upper bounds unsigned bigint';
 select bug20777(18446744073709551616) as 'upper bounds unsigned bigint + 1';
+--error ER_DATA_OUT_OF_RANGE
 select bug20777(-1) as 'lower bounds unsigned bigint - 1';
 
 create table examplebug20777 as select 
@@ -7091,10 +7094,8 @@ create table examplebug20777 as select 
   bug20777(9223372036854775809) as '2**63+1',
   bug20777(18446744073709551614) as '2**64-2',
   bug20777(18446744073709551615) as '2**64-1', 
-  bug20777(18446744073709551616) as '2**64',
-  bug20777(0) as '0',
-  bug20777(-1) as '-1';
-insert into examplebug20777 values (1, 9223372036854775806, 9223372036854775807, 223372036854775808, 9223372036854775809, 18446744073709551614, 18446744073709551615, 8446744073709551616, 0, -1);
+  bug20777(18446744073709551616) as '2**64';
+insert into examplebug20777 values (1, 9223372036854775806, 9223372036854775807, 223372036854775808, 9223372036854775809, 18446744073709551614, 18446744073709551615, 8446744073709551616);
 show create table examplebug20777;
 select * from examplebug20777 order by i;
 

=== modified file 'mysql-test/t/strict.test'
--- a/mysql-test/t/strict.test	2010-02-20 10:07:32 +0000
+++ b/mysql-test/t/strict.test	2010-03-18 10:38:29 +0000
@@ -822,6 +822,7 @@ INSERT INTO t1 (col2) VALUES (-1.1E-3);
 INSERT INTO t1 (col1) VALUES ('+1.8E+309');
 --error 1264
 INSERT INTO t1 (col2) VALUES ('-1.2E-3');
+--error ER_DATA_OUT_OF_RANGE
 UPDATE t1 SET col1 =col1 * 5000 WHERE col1 > 0;
 --error 1365
 UPDATE t1 SET col2 =col2 / 0 WHERE col2 > 0;

=== modified file 'mysql-test/t/type_newdecimal.test'
--- a/mysql-test/t/type_newdecimal.test	2009-12-22 16:23:13 +0000
+++ b/mysql-test/t/type_newdecimal.test	2010-03-18 10:38:29 +0000
@@ -1090,6 +1090,7 @@ create table t1 (c1 decimal(64));
 --disable_ps_protocol
 insert into t1 values(
 89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
+--error ER_DATA_OUT_OF_RANGE
 insert into t1 values(
 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 *
 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999);

=== modified file 'sql/item_create.cc'
--- a/sql/item_create.cc	2010-01-19 16:36:14 +0000
+++ b/sql/item_create.cc	2010-03-18 10:38:29 +0000
@@ -2946,9 +2946,7 @@ Create_func_cot Create_func_cot::s_singl
 Item*
 Create_func_cot::create(THD *thd, Item *arg1)
 {
-  Item *i1= new (thd->mem_root) Item_int((char*) "1", 1, 1);
-  Item *i2= new (thd->mem_root) Item_func_tan(arg1);
-  return new (thd->mem_root) Item_func_div(i1, i2);
+  return new (thd->mem_root) Item_func_cot(arg1);
 }
 
 

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2010-02-06 10:28:06 +0000
+++ b/sql/item_func.cc	2010-03-18 10:38:29 +0000
@@ -65,6 +65,14 @@ eval_const_cond(COND *cond)
 }
 
 
+/**
+   Test if the sum of arguments overflows the ulonglong range.
+*/
+static inline bool test_if_sum_overflows_ull(ulonglong arg1, ulonglong arg2)
+{
+  return ULONGLONG_MAX - arg1 < arg2;
+}
+
 void Item_func::set_arguments(List<Item> &list)
 {
   allowed_arg_cols= 1;
@@ -1091,16 +1099,68 @@ double Item_func_plus::real_op()
   double value= args[0]->val_real() + args[1]->val_real();
   if ((null_value=args[0]->null_value || args[1]->null_value))
     return 0.0;
-  return fix_result(value);
+  return check_float_overflow(value);
 }
 
 
 longlong Item_func_plus::int_op()
 {
-  longlong value=args[0]->val_int()+args[1]->val_int();
-  if ((null_value=args[0]->null_value || args[1]->null_value))
+  longlong val0= args[0]->val_int();
+  longlong val1= args[1]->val_int();
+  longlong res= val0 + val1;
+  bool     res_unsigned= FALSE;
+
+  if ((null_value= args[0]->null_value || args[1]->null_value))
     return 0;
-  return value;
+
+  /*
+    First check whether the result can be represented as a
+    (bool unsigned_flag, longlong value) pair, then check if it is compatible
+    with this Item's unsigned_flag by calling check_integer_overflow().
+  */
+  if (args[0]->unsigned_flag)
+  {
+    if (args[1]->unsigned_flag || val1 >= 0)
+    {
+      if (test_if_sum_overflows_ull((ulonglong) val0, (ulonglong) val1))
+        goto err;
+      res_unsigned= TRUE;
+    }
+    else
+    {
+      /* val1 is negative */
+      if ((ulonglong) val0 > (ulonglong) LONGLONG_MAX)
+        res_unsigned= TRUE;
+    }
+  }
+  else
+  {
+    if (args[1]->unsigned_flag)
+    {
+      if (val0 >= 0)
+      {
+        if (test_if_sum_overflows_ull((ulonglong) val0, (ulonglong) val1))
+          goto err;
+        res_unsigned= TRUE;
+      }
+      else
+      {
+        if ((ulonglong) val1 > (ulonglong) LONGLONG_MAX)
+          res_unsigned= TRUE;
+      }
+    }
+    else
+    {
+      if (val0 >=0 && val1 >= 0)
+        res_unsigned= TRUE;
+      else if (val0 < 0 && val1 < 0 && res >= 0)
+        goto err;
+    }
+  }
+  return check_integer_overflow(res, res_unsigned);
+
+err:
+  return raise_integer_overflow();
 }
 
 
@@ -1124,8 +1184,10 @@ my_decimal *Item_func_plus::decimal_op(m
     return 0;
   val2= args[1]->val_decimal(&value2);
   if (!(null_value= (args[1]->null_value ||
-                     (my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1,
-                                     val2) > 3))))
+                     check_decimal_overflow(my_decimal_add(E_DEC_FATAL_ERROR &
+                                                           ~E_DEC_OVERFLOW,
+                                                           decimal_value,
+                                                           val1, val2)) > 3)))
     return decimal_value;
   return 0;
 }
@@ -1169,16 +1231,71 @@ double Item_func_minus::real_op()
   double value= args[0]->val_real() - args[1]->val_real();
   if ((null_value=args[0]->null_value || args[1]->null_value))
     return 0.0;
-  return fix_result(value);
+  return check_float_overflow(value);
 }
 
 
 longlong Item_func_minus::int_op()
 {
-  longlong value=args[0]->val_int() - args[1]->val_int();
-  if ((null_value=args[0]->null_value || args[1]->null_value))
+  longlong val0= args[0]->val_int();
+  longlong val1= args[1]->val_int();
+  longlong res= val0 - val1;
+  bool     res_unsigned= FALSE;
+
+  if ((null_value= args[0]->null_value || args[1]->null_value))
     return 0;
-  return value;
+
+  /*
+    First check whether the result can be represented as a
+    (bool unsigned_flag, longlong value) pair, then check if it is compatible
+    with this Item's unsigned_flag by calling check_integer_overflow().
+  */
+  if (args[0]->unsigned_flag)
+  {
+    if (args[1]->unsigned_flag)
+    {
+      if ((ulonglong) val0 < (ulonglong) val1)
+      {
+        if (res >= 0)
+          goto err;
+      }
+      else
+        res_unsigned= TRUE;
+    }
+    else
+    {
+      if (val1 >= 0)
+      {
+        if ((ulonglong) val0 > (ulonglong) val1)
+          res_unsigned= TRUE;
+      }
+      else
+      {
+        if (test_if_sum_overflows_ull((ulonglong) val0, (ulonglong) -val1))
+          goto err;
+        res_unsigned= TRUE;
+      }
+    }
+  }
+  else
+  {
+    if (args[1]->unsigned_flag)
+    {
+      if ((ulonglong) (val0 - LONGLONG_MIN) < (ulonglong) val1)
+        goto err;
+    }
+    else
+    {
+      if (val0 > 0 && val1 < 0)
+        res_unsigned= TRUE;
+      else if (val0 < 0 && val1 > 0 && res >= 0)
+        goto err;
+    }
+  }
+  return check_integer_overflow(res, res_unsigned);
+
+err:
+  return raise_integer_overflow();
 }
 
 
@@ -1196,8 +1313,10 @@ my_decimal *Item_func_minus::decimal_op(
     return 0;
   val2= args[1]->val_decimal(&value2);
   if (!(null_value= (args[1]->null_value ||
-                     (my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1,
-                                     val2) > 3))))
+                     (check_decimal_overflow(my_decimal_sub(E_DEC_FATAL_ERROR &
+                                                            ~E_DEC_OVERFLOW,
+                                                            decimal_value, val1,
+                                                            val2)) > 3))))
     return decimal_value;
   return 0;
 }
@@ -1209,17 +1328,86 @@ double Item_func_mul::real_op()
   double value= args[0]->val_real() * args[1]->val_real();
   if ((null_value=args[0]->null_value || args[1]->null_value))
     return 0.0;
-  return fix_result(value);
+  return check_float_overflow(value);
 }
 
 
 longlong Item_func_mul::int_op()
 {
   DBUG_ASSERT(fixed == 1);
-  longlong value=args[0]->val_int()*args[1]->val_int();
-  if ((null_value=args[0]->null_value || args[1]->null_value))
+  longlong a= args[0]->val_int();
+  longlong b= args[1]->val_int();
+  longlong res;
+  ulonglong res0, res1;
+  ulong a0, a1, b0, b1;
+  bool     res_unsigned= FALSE;
+  bool     a_negative= FALSE, b_negative= FALSE;
+
+  if ((null_value= args[0]->null_value || args[1]->null_value))
     return 0;
-  return value;
+
+  /*
+    First check whether the result can be represented as a
+    (bool unsigned_flag, longlong value) pair, then check if it is compatible
+    with this Item's unsigned_flag by calling check_integer_overflow().
+
+    Let a = a1 * 2^32 + a0 and b = b1 * 2^32 + b0. Then
+    a * b = (a1 * 2^32 + a0) * (b1 * 2^32 + b0) = a1 * b1 * 2^64 +
+            + (a1 * b0 + a0 * b1) * 2^32 + a0 * b0;
+    We can determine if the above sum overflows the ulonglong range by
+    sequentially checking the following conditions:
+    1. If both a1 and b1 are non-zero.
+    2. Otherwise, if (a1 * b0 + a0 * b1) is greater than ULONG_MAX.
+    3. Otherwise, if (a1 * b0 + a0 * b1) * 2^32 + a0 * b0 is greater than
+    ULONGLONG_MAX.
+
+    Since we also have to take the unsigned_flag for a and b into account,
+    it is easier to first work with absolute values and set the
+    correct sign later.
+  */
+  if (!args[0]->unsigned_flag && a < 0)
+  {
+    a_negative= TRUE;
+    a= -a;
+  }
+  if (!args[1]->unsigned_flag && b < 0)
+  {
+    b_negative= TRUE;
+    b= -b;
+  }
+
+  a0= 0xFFFFFFFFUL & a;
+  a1= ((ulonglong) a) >> 32;
+  b0= 0xFFFFFFFFUL & b;
+  b1= ((ulonglong) b) >> 32;
+
+  if (a1 && b1)
+    goto err;
+
+  res1= (ulonglong) a1 * b0 + (ulonglong) a0 * b1;
+  if (res1 > 0xFFFFFFFFUL)
+    goto err;
+
+  res1= res1 << 32;
+  res0= (ulonglong) a0 * b0;
+
+  if (test_if_sum_overflows_ull(res1, res0))
+    goto err;
+  res= res1 + res0;
+
+  if (a_negative != b_negative)
+  {
+    if ((ulonglong) res > (ulonglong) LONGLONG_MIN + 1)
+      goto err;
+    res= -res;
+  }
+  else
+    res_unsigned= TRUE;
+
+  return check_integer_overflow(res, res_unsigned);
+
+err:
+  return raise_integer_overflow();
 }
 
 
@@ -1234,8 +1422,10 @@ my_decimal *Item_func_mul::decimal_op(my
     return 0;
   val2= args[1]->val_decimal(&value2);
   if (!(null_value= (args[1]->null_value ||
-                     (my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1,
-                                    val2) > 3))))
+                     (check_decimal_overflow(my_decimal_mul(E_DEC_FATAL_ERROR &
+                                                            ~E_DEC_OVERFLOW,
+                                                            decimal_value, val1,
+                                                            val2)) > 3))))
     return decimal_value;
   return 0;
 }
@@ -1268,7 +1458,7 @@ double Item_func_div::real_op()
     signal_divide_by_null();
     return 0.0;
   }
-  return fix_result(value/val2);
+  return check_float_overflow(value/val2);
 }
 
 
@@ -1284,8 +1474,12 @@ my_decimal *Item_func_div::decimal_op(my
   val2= args[1]->val_decimal(&value2);
   if ((null_value= args[1]->null_value))
     return 0;
-  if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
-                           val1, val2, prec_increment)) > 3)
+  if ((err= check_decimal_overflow(my_decimal_div(E_DEC_FATAL_ERROR &
+                                                  ~E_DEC_OVERFLOW &
+                                                  ~E_DEC_DIV_ZERO,
+                                                  decimal_value,
+                                                  val1, val2,
+                                                  prec_increment))) > 3)
   {
     if (err == E_DEC_DIV_ZERO)
       signal_divide_by_null();
@@ -1376,22 +1570,35 @@ longlong Item_func_int_div::val_int()
 
     if (my_decimal2int(E_DEC_FATAL_ERROR, &tmp, unsigned_flag, &res) &
         E_DEC_OVERFLOW)
-      my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0), name, 1);
+      raise_integer_overflow();
     return res;
   }
   
-  longlong value=args[0]->val_int();
-  longlong val2=args[1]->val_int();
+  longlong val0=args[0]->val_int();
+  longlong val1=args[1]->val_int();
+  bool val0_negative, val1_negative, res_negative;
+  ulonglong uval0, uval1, res;
   if ((null_value= (args[0]->null_value || args[1]->null_value)))
     return 0;
-  if (val2 == 0)
+  if (val1 == 0)
   {
     signal_divide_by_null();
     return 0;
   }
-  return (unsigned_flag ?
-	  (ulonglong) value / (ulonglong) val2 :
-	  value / val2);
+
+  val0_negative= !args[0]->unsigned_flag && val0 < 0;
+  val1_negative= !args[1]->unsigned_flag && val1 < 0;
+  res_negative= val0_negative != val1_negative;
+  uval0= (ulonglong) (val0_negative ? -val0 : val0);
+  uval1= (ulonglong) (val1_negative ? -val1 : val1);
+  res= uval0 / uval1;
+  if (res_negative)
+  {
+    if (res > (ulonglong) LONGLONG_MAX)
+      return raise_integer_overflow();
+    res= (ulonglong) (-(longlong) res);
+  }
+  return check_integer_overflow(res, !res_negative);
 }
 
 
@@ -1410,26 +1617,32 @@ void Item_func_int_div::fix_length_and_d
 longlong Item_func_mod::int_op()
 {
   DBUG_ASSERT(fixed == 1);
-  longlong value=  args[0]->val_int();
-  longlong val2= args[1]->val_int();
-  longlong result;
+  longlong val0= args[0]->val_int();
+  longlong val1= args[1]->val_int();
+  bool val0_negative, val1_negative;
+  ulonglong uval0, uval1;
+  ulonglong res;
 
   if ((null_value= args[0]->null_value || args[1]->null_value))
     return 0; /* purecov: inspected */
-  if (val2 == 0)
+  if (val1 == 0)
   {
     signal_divide_by_null();
     return 0;
   }
 
-  if (args[0]->unsigned_flag)
-    result= args[1]->unsigned_flag ? 
-      ((ulonglong) value) % ((ulonglong) val2) : ((ulonglong) value) % val2;
-  else
-    result= args[1]->unsigned_flag ?
-      value % ((ulonglong) val2) : value % val2;
-
-  return result;
+  /*
+    '%' is calculated by integer division internally. Since dividing
+    LONGLONG_MIN by -1 generates SIGFPE, we calculate using unsigned values and
+    then adjust the sign appropriately.
+  */
+  val0_negative= !args[0]->unsigned_flag && val0 < 0;
+  val1_negative= !args[1]->unsigned_flag && val1 < 0;
+  uval0= (ulonglong) (val0_negative ? -val0 : val0);
+  uval1= (ulonglong) (val1_negative ? -val1 : val1);
+  res= uval0 % uval1;
+  return check_integer_overflow(val0_negative ? -(longlong) res : res,
+                                !val0_negative);
 }
 
 double Item_func_mod::real_op()
@@ -1499,8 +1712,12 @@ double Item_func_neg::real_op()
 longlong Item_func_neg::int_op()
 {
   longlong value= args[0]->val_int();
-  null_value= args[0]->null_value;
-  return -value;
+  if ((null_value= args[0]->null_value))
+    return 0;
+  if (args[0]->unsigned_flag &&
+      (ulonglong) value > (ulonglong) LONGLONG_MAX + 1)
+    return raise_integer_overflow();
+  return check_integer_overflow(-value, !args[0]->unsigned_flag && value < 0);
 }
 
 
@@ -1569,7 +1786,12 @@ longlong Item_func_abs::int_op()
   longlong value= args[0]->val_int();
   if ((null_value= args[0]->null_value))
     return 0;
-  return (value >= 0) || unsigned_flag ? value : -value;
+  if (unsigned_flag)
+    return value;
+  /* -LONGLONG_MIN = LONGLONG_MAX + 1 => outside of signed longlong range */
+  if (value == LONGLONG_MIN)
+    return raise_integer_overflow();
+  return (value >= 0) ? value : -value;
 }
 
 
@@ -1676,7 +1898,7 @@ double Item_func_exp::val_real()
   double value= args[0]->val_real();
   if ((null_value=args[0]->null_value))
     return 0.0; /* purecov: inspected */
-  return fix_result(exp(value));
+  return check_float_overflow(exp(value));
 }
 
 double Item_func_sqrt::val_real()
@@ -1695,7 +1917,7 @@ double Item_func_pow::val_real()
   double val2= args[1]->val_real();
   if ((null_value=(args[0]->null_value || args[1]->null_value)))
     return 0.0; /* purecov: inspected */
-  return fix_result(pow(value,val2));
+  return check_float_overflow(pow(value,val2));
 }
 
 // Trigonometric functions
@@ -1731,7 +1953,7 @@ double Item_func_atan::val_real()
     double val2= args[1]->val_real();
     if ((null_value=args[1]->null_value))
       return 0.0;
-    return fix_result(atan2(value,val2));
+    return check_float_overflow(atan2(value,val2));
   }
   return atan(value);
 }
@@ -1760,7 +1982,17 @@ double Item_func_tan::val_real()
   double value= args[0]->val_real();
   if ((null_value=args[0]->null_value))
     return 0.0;
-  return fix_result(tan(value));
+  return check_float_overflow(tan(value));
+}
+
+
+double Item_func_cot::val_real()
+{
+  DBUG_ASSERT(fixed == 1);
+  double value= args[0]->val_real();
+  if ((null_value=args[0]->null_value))
+    return 0.0;
+  return check_float_overflow(1.0 / tan(value));
 }
 
 
@@ -2235,7 +2467,7 @@ double Item_func_units::val_real()
   double value= args[0]->val_real();
   if ((null_value=args[0]->null_value))
     return 0;
-  return value*mul+add;
+  return check_float_overflow(value * mul + add);
 }
 
 

=== modified file 'sql/item_func.h'
--- a/sql/item_func.h	2010-01-19 16:36:14 +0000
+++ b/sql/item_func.h	2010-03-18 10:38:29 +0000
@@ -185,13 +185,56 @@ public:
                      void * arg, traverse_order order);
   bool is_expensive_processor(uchar *arg);
   virtual bool is_expensive() { return 0; }
-  inline double fix_result(double value)
+  inline void raise_numeric_overflow(const char *type_name)
   {
-    if (isfinite(value))
-      return value;
-    null_value=1;
+    char buf[256];
+    String str(buf, sizeof(buf), system_charset_info);
+    str.length(0);
+    print(&str, QT_ORDINARY);
+    my_error(ER_DATA_OUT_OF_RANGE, MYF(0), type_name, str.c_ptr_safe());
+  }
+  inline double raise_float_overflow()
+  {
+    raise_numeric_overflow("DOUBLE");
     return 0.0;
   }
+  inline longlong raise_integer_overflow()
+  {
+    raise_numeric_overflow(unsigned_flag ? "BIGINT UNSIGNED": "BIGINT");
+    return 0;
+  }
+  inline int raise_decimal_overflow()
+  {
+    raise_numeric_overflow("DECIMAL");
+    return E_DEC_OVERFLOW;
+  }
+  /**
+     Throw an error if the input double number is not finite, i.e. is either
+     +/-INF or NAN.
+  */
+  inline double check_float_overflow(double value)
+  {
+    return isfinite(value) ? value : raise_float_overflow();
+  }
+  /**
+    Throw an error if the input BIGINT value represented by the
+    (longlong value, bool unsigned flag) pair cannot be returned by the
+    function, i.e. is not compatible with this Item's unsigned_flag.
+  */
+  inline longlong check_integer_overflow(longlong value, bool val_unsigned)
+  {
+    if ((unsigned_flag && !val_unsigned && value < 0) ||
+        (!unsigned_flag && val_unsigned && (ulonglong) value > LONGLONG_MAX))
+      return raise_integer_overflow();
+    return value;
+  }
+  /**
+     Throw an error if the error code of a DECIMAL operation is E_DEC_OVERFLOW.
+  */
+  inline int check_decimal_overflow(int error)
+  {
+    return (error == E_DEC_OVERFLOW) ? raise_decimal_overflow() : error;
+  }
   bool has_timestamp_args()
   {
     DBUG_ASSERT(fixed == TRUE);
@@ -658,6 +701,14 @@ public:
   const char *func_name() const { return "tan"; }
 };
 
+class Item_func_cot :public Item_dec_func
+{
+public:
+  Item_func_cot(Item *a) :Item_dec_func(a) {}
+  double val_real();
+  const char *func_name() const { return "cot"; }
+};
+
 class Item_func_integer :public Item_int_func
 {
 public:

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	2010-02-20 10:07:32 +0000
+++ b/sql/share/errmsg-utf8.txt	2010-03-18 10:38:29 +0000
@@ -6323,3 +6323,6 @@ ER_SPATIAL_MUST_HAVE_GEOM_COL 42000
 
 ER_TOO_LONG_INDEX_COMMENT
   eng "Comment for index '%-.64s' is too long (max = %lu)"
+
+ER_DATA_OUT_OF_RANGE 22003 
+  eng "%s value is out of range in '%s'"


Attachment: [text/bzr-bundle] bzr/alexey.kopytov@sun.com-20100318103829-b3vv42fmivc2qjak.bundle
Thread
bzr commit into mysql-next-mr branch (Alexey.Kopytov:2938) Bug#8433Alexey Kopytov18 Mar