Commit a0b0cb55 authored by gunnar@mysql.com's avatar gunnar@mysql.com

Merge mysql.com.:/data/BK/mysql-5.0

into  mysql.com.:/data/BK/mysql-5.0_8461_b
parents 6fe11666 001224c0
...@@ -203,3 +203,18 @@ NULL ...@@ -203,3 +203,18 @@ NULL
Warnings: Warnings:
Error 1365 Division by 0 Error 1365 Division by 0
set sql_mode=''; 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
...@@ -141,3 +141,17 @@ select log(2,-1); ...@@ -141,3 +141,17 @@ select log(2,-1);
select log(-2,1); select log(-2,1);
set sql_mode=''; 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);
...@@ -1863,28 +1863,30 @@ longlong Item_func_round::int_op() ...@@ -1863,28 +1863,30 @@ longlong Item_func_round::int_op()
return value; // integer have not digits after point return value; // integer have not digits after point
abs_dec= -dec; abs_dec= -dec;
double tmp; longlong 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) ? if(abs_dec >= array_elements(log_10_int))
log_10[abs_dec] : pow(10.0, (double) abs_dec)); return 0;
tmp= log_10_int[abs_dec];
if (truncate) if (truncate)
{ {
if (unsigned_flag) if (unsigned_flag)
tmp2= floor(ulonglong2double(value)/tmp)*tmp; value= (ulonglong(value)/tmp)*tmp;
else if (value >= 0)
tmp2= floor(((double)value)/tmp)*tmp;
else else
tmp2= ceil(((double)value)/tmp)*tmp; value= (value/tmp)*tmp;
} }
else 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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment