summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/func_math.result15
-rw-r--r--mysql-test/t/func_math.test14
-rw-r--r--sql/item_func.cc34
3 files changed, 47 insertions, 16 deletions
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index fba274b9bb1..1507f959ae6 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -203,3 +203,18 @@ NULL
Warnings:
Error 1365 Division by 0
set sql_mode='';
+select round(111,-10);
+round(111,-10)
+0
+select round(-5000111000111000155,-1);
+round(-5000111000111000155,-1)
+-5000111000111000160
+select round(15000111000111000155,-1);
+round(15000111000111000155,-1)
+15000111000111000160
+select truncate(-5000111000111000155,-1);
+truncate(-5000111000111000155,-1)
+-5000111000111000150
+select truncate(15000111000111000155,-1);
+truncate(15000111000111000155,-1)
+15000111000111000150
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index 9cf0ee452cd..8dc4eb215c7 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -141,3 +141,17 @@ select log(2,-1);
select log(-2,1);
set sql_mode='';
+#
+# Bug #8461 truncate() and round() return false results 2nd argument negative.
+#
+# round(a,-b) log_10(b) > a
+select round(111,-10);
+# round on bigint
+select round(-5000111000111000155,-1);
+# round on unsigned bigint
+select round(15000111000111000155,-1);
+# truncate on bigint
+select truncate(-5000111000111000155,-1);
+# truncate on unsigned bigint
+select truncate(15000111000111000155,-1);
+
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 2d595e5fdc8..a85f05c2e22 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1863,28 +1863,30 @@ longlong Item_func_round::int_op()
return value; // integer have not digits after point
abs_dec= -dec;
- double tmp;
- /*
- tmp2 is here to avoid return the value with 80 bit precision
- This will fix that the test round(0.1,1) = round(0.1,1) is true
- */
- volatile double tmp2;
-
- tmp= (abs_dec < array_elements(log_10) ?
- log_10[abs_dec] : pow(10.0, (double) abs_dec));
-
+ longlong tmp;
+
+ if(abs_dec >= array_elements(log_10_int))
+ return 0;
+
+ tmp= log_10_int[abs_dec];
+
if (truncate)
{
if (unsigned_flag)
- tmp2= floor(ulonglong2double(value)/tmp)*tmp;
- else if (value >= 0)
- tmp2= floor(((double)value)/tmp)*tmp;
+ value= (ulonglong(value)/tmp)*tmp;
else
- tmp2= ceil(((double)value)/tmp)*tmp;
+ value= (value/tmp)*tmp;
}
else
- tmp2= rint(((double)value)/tmp)*tmp;
- return (longlong)tmp2;
+ {
+ if (unsigned_flag)
+ value= ((ulonglong(value)+(tmp>>1))/tmp)*tmp;
+ else if ( value >= 0)
+ value= ((value+(tmp>>1))/tmp)*tmp;
+ else
+ value= ((value-(tmp>>1))/tmp)*tmp;
+ }
+ return value;
}