From: Date: February 7 2006 1:26pm Subject: bk commit into 5.0 tree (gunnar:1.2032) BUG#8461 List-Archive: http://lists.mysql.com/commits/2240 X-Bug: 8461 Message-Id: <20060207122654.0D1E64156@phoenix> Below is the list of changes that have just been committed into a local 5.0 repository of gvb. When gvb does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.2032 06/02/07 13:26:35 gunnar@stripped. +3 -0 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. mysql-test/r/func_math.result 1.33 06/02/07 13:24:39 gunnar@stripped. +15 -0 mysql-test/t/func_math.test 1.26 06/02/07 13:24:35 gunnar@stripped. +14 -0 sql/item_func.cc 1.273 06/02/07 13:21:41 gunnar@stripped. +18 -16 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. # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: gunnar # Host: titan. # Root: /data/BK/mysql-5.0_8461_b --- 1.272/sql/item_func.cc 2006-01-21 15:50:01 +01:00 +++ 1.273/sql/item_func.cc 2006-02-07 13:21:41 +01:00 @@ -1863,28 +1863,30 @@ 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; } --- 1.32/mysql-test/r/func_math.result 2005-10-28 03:45:56 +02:00 +++ 1.33/mysql-test/r/func_math.result 2006-02-07 13:24:39 +01:00 @@ -203,3 +203,18 @@ 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 --- 1.25/mysql-test/t/func_math.test 2006-01-21 15:39:32 +01:00 +++ 1.26/mysql-test/t/func_math.test 2006-02-07 13:24:35 +01:00 @@ -141,3 +141,17 @@ 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); +