summaryrefslogtreecommitdiff
path: root/sql/item_func.cc
diff options
context:
space:
mode:
authorunknown <gunnar@mysql.com.>2006-02-07 13:26:35 +0100
committerunknown <gunnar@mysql.com.>2006-02-07 13:26:35 +0100
commitc9bb7e1f0271b8e3866d8f84964501fd624612fe (patch)
tree8730bdd3f7f12b0bf11d3a61e393a2f84b650dd3 /sql/item_func.cc
parent26a81f6fb1dc253e9d0ed99768594ac27dae5bb3 (diff)
downloadmariadb-git-c9bb7e1f0271b8e3866d8f84964501fd624612fe.tar.gz
item_func.cc:
fix for bug#8461 BUG 8461 - TRUNCATE returns incorrect result if 2nd argument is negative Reason: Both TRUNCATE/ROUND converts INTEGERS to DOUBLE and back to INTEGERS Changed the integer routine to work on integers only. This bug affects 4.1, 5.0 and 5.1 Fixing in 4.1 will need to change the routine to handle different types individually. 5.0 did had different routines for different types already just the INTEGER routine was bad. sql/item_func.cc: fix for bug#8461 BUG 8461 - TRUNCATE returns incorrect result if 2nd argument is negative Reason: TRUNCATE converts INTEGERS to DOUBLE and back to INTEGERS Both ROUND and TRUNCATE are affected by this. Changed the integer routine to work on integers only. This bug affects 4.1 5,0 and 5 Fixing in 4.1 will need to change the routine to handle different types individually.
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r--sql/item_func.cc34
1 files changed, 18 insertions, 16 deletions
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;
}