Commit 4482604e authored by unknown's avatar unknown

hf's fix for bug #9060 (FORMAT returns incorrect result)

we need proper rounding there


mysql-test/r/func_math.result:
  test result fixed
mysql-test/t/func_math.test:
  test case added
sql/item_func.cc:
  my_double_round implementation added
sql/item_strfunc.cc:
  my_double_round used
sql/mysql_priv.h:
  my_double_round interface
parent 9c1bc425
...@@ -120,6 +120,9 @@ ASIN(0.8+0.2) ...@@ -120,6 +120,9 @@ ASIN(0.8+0.2)
SELECT ASIN(1.2-0.2); SELECT ASIN(1.2-0.2);
ASIN(1.2-0.2) ASIN(1.2-0.2)
1.5707963267949 1.5707963267949
select format(4.55, 1), format(4.551, 1);
format(4.55, 1) format(4.551, 1)
4.6 4.6
explain extended select degrees(pi()),radians(360); explain extended select degrees(pi()),radians(360);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
......
...@@ -54,6 +54,11 @@ SELECT ASIN(1.2-0.2); ...@@ -54,6 +54,11 @@ SELECT ASIN(1.2-0.2);
#select floor(log(8)/log(2)); #select floor(log(8)/log(2));
#select floor(log(16)/log(2)); #select floor(log(16)/log(2));
#
# Bug #9060 (format returns incorrect result)
#
select format(4.55, 1), format(4.551, 1);
explain extended select degrees(pi()),radians(360); explain extended select degrees(pi()),radians(360);
# #
......
...@@ -1880,22 +1880,16 @@ void Item_func_round::fix_length_and_dec() ...@@ -1880,22 +1880,16 @@ void Item_func_round::fix_length_and_dec()
} }
} }
double Item_func_round::real_op() double my_double_round(double value, int dec, bool truncate)
{ {
double value= args[0]->val_real();
int dec=(int) args[1]->val_int();
if (dec > 0)
decimals= dec; // to get correct output
uint abs_dec=abs(dec);
double tmp; double tmp;
uint abs_dec= abs(dec);
/* /*
tmp2 is here to avoid return the value with 80 bit precision 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 This will fix that the test round(0.1,1) = round(0.1,1) is true
*/ */
volatile double tmp2; volatile double tmp2;
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
tmp=(abs_dec < array_elements(log_10) ? tmp=(abs_dec < array_elements(log_10) ?
log_10[abs_dec] : pow(10.0,(double) abs_dec)); log_10[abs_dec] : pow(10.0,(double) abs_dec));
...@@ -1912,6 +1906,18 @@ double Item_func_round::real_op() ...@@ -1912,6 +1906,18 @@ double Item_func_round::real_op()
} }
double Item_func_round::real_op()
{
double value= args[0]->val_real();
int dec= (int) args[1]->val_int();
if (!(null_value= args[0]->null_value || args[1]->null_value))
return my_double_round(value, dec, truncate);
return 0.0;
}
longlong Item_func_round::int_op() longlong Item_func_round::int_op()
{ {
longlong value= args[0]->val_int(); longlong value= args[0]->val_int();
......
...@@ -1673,6 +1673,7 @@ String *Item_func_format::val_str(String *str) ...@@ -1673,6 +1673,7 @@ String *Item_func_format::val_str(String *str)
int diff; int diff;
if ((null_value=args[0]->null_value)) if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */ return 0; /* purecov: inspected */
nr= my_double_round(nr, decimals, FALSE);
dec= decimals ? decimals+1 : 0; dec= decimals ? decimals+1 : 0;
/* Here default_charset() is right as this is not an automatic conversion */ /* Here default_charset() is right as this is not an automatic conversion */
str->set(nr,decimals, default_charset()); str->set(nr,decimals, default_charset());
......
...@@ -1251,6 +1251,7 @@ ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder, ...@@ -1251,6 +1251,7 @@ ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
ha_rows max_rows, ha_rows *examined_rows); ha_rows max_rows, ha_rows *examined_rows);
void filesort_free_buffers(TABLE *table); void filesort_free_buffers(TABLE *table);
void change_double_for_sort(double nr,byte *to); void change_double_for_sort(double nr,byte *to);
double my_double_round(double value, int dec, bool truncate);
int get_quick_record(SQL_SELECT *select); int get_quick_record(SQL_SELECT *select);
int calc_weekday(long daynr,bool sunday_first_day_of_week); int calc_weekday(long daynr,bool sunday_first_day_of_week);
uint calc_week(TIME *l_time, uint week_behaviour, uint *year); uint calc_week(TIME *l_time, uint week_behaviour, uint *year);
......
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