diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index d8b8a14afc6..f469564c78b 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -382,6 +382,9 @@ y SELECT b DIV 900 y FROM t1 GROUP BY y; y 0 +Warnings: +Warning 1366 Incorrect decimal value: '' for column '' at row -1 +Warning 1366 Incorrect decimal value: '' for column '' at row -1 SELECT c DIV 900 y FROM t1 GROUP BY y; y 0 @@ -482,4 +485,12 @@ RAND(i) 0.155220427694936 DROP TABLE t1; # +select 123456789012345678901234567890.123456789012345678901234567890 div 1 as x; +ERROR 22003: Out of range value for column 'x' at row 1 +select "123456789012345678901234567890.123456789012345678901234567890" div 1 as x; +ERROR 22003: Out of range value for column 'x' at row 1 +SHOW WARNINGS; +Level Code Message +Warning 1292 Truncated incorrect DECIMAL value: '' +Error 1264 Out of range value for column 'x' at row 1 End of 5.1 tests diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index 96042a91bae..94628eb16ee 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -475,8 +475,9 @@ a (a DIV 2) 60 30 t 0 Warnings: -Warning 1292 Truncated incorrect INTEGER value: '1a' -Warning 1292 Truncated incorrect INTEGER value: 't ' +Warning 1292 Truncated incorrect DECIMAL value: '1a' +Warning 1366 Incorrect decimal value: '' for column '' at row -1 +Warning 1292 Truncated incorrect DECIMAL value: 't ' SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a; a CAST(a AS SIGNED) 10 10 diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 91fdce8addb..b999b1e8c1b 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -309,4 +309,15 @@ DROP TABLE t1; --echo # +# +# Bug #8457: Precision math: +# 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 +select 123456789012345678901234567890.123456789012345678901234567890 div 1 as x; +--error ER_WARN_DATA_OUT_OF_RANGE +select "123456789012345678901234567890.123456789012345678901234567890" div 1 as x; +SHOW WARNINGS; + --echo End of 5.1 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index cf499aaf93c..c0a84e3be28 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1348,6 +1348,38 @@ void Item_func_div::fix_length_and_dec() longlong Item_func_int_div::val_int() { DBUG_ASSERT(fixed == 1); + + /* + Perform division using DECIMAL math if either of the operands has a + non-integer type + */ + if (args[0]->result_type() != INT_RESULT || + args[1]->result_type() != INT_RESULT) + { + my_decimal value0, value1, tmp; + my_decimal *val0, *val1; + longlong res; + int err; + + val0= args[0]->val_decimal(&value0); + val1= args[1]->val_decimal(&value1); + if ((null_value= (args[0]->null_value || args[1]->null_value))) + return 0; + + if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp, + val0, val1, 0)) > 3) + { + if (err == E_DEC_DIV_ZERO) + signal_divide_by_null(); + return 0; + } + + 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); + return res; + } + longlong value=args[0]->val_int(); longlong val2=args[1]->val_int(); if ((null_value= (args[0]->null_value || args[1]->null_value)))