fixed bug in Item_func_div::val_int() that broke all functions that

do val_int() on their arguments before starting the computation. 
Similar fixes are need for +-* and probably several other but I want
to make sure Monty is fine with my fix approach before changing a lot
of code. 

Amazingly,
this bug is not as critical as you would expect since very few functions do val_int()
on their arguments ( from_unixtime(), sec_to_time()), and those not
very frequently perform a computation on their floating point arguments.
which is probably why no one has yet reported this bug. Another 
possibility is that the result is usually wrong by no more than 5%,
which makes it hard to catch it. I found it when trying to compute mile
splits for 30:47 10K - it told me 5:07, and I knew it was wrong because
5:00 mile gives you 31:08. However, if I had not run as many 10K races,
I would have easily believed that 30:47 10K is a 5:07 mile pace and 
would not have noticed the bug.
parent c68d7caa
...@@ -6,8 +6,8 @@ now()-now() weekday(curdate())-weekday(now()) unix_timestamp()-unix_timestamp(no ...@@ -6,8 +6,8 @@ now()-now() weekday(curdate())-weekday(now()) unix_timestamp()-unix_timestamp(no
0 0 0 0 0 0
from_unixtime(unix_timestamp("1994-03-02 10:11:12")) from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s") from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0 from_unixtime(unix_timestamp("1994-03-02 10:11:12")) from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s") from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0
1994-03-02 10:11:12 1994-03-02 10:11:12 19940302101112 1994-03-02 10:11:12 1994-03-02 10:11:12 19940302101112
sec_to_time(9001) sec_to_time(9001)+0 time_to_sec("15:12:22") sec_to_time(9001) sec_to_time(9001)+0 time_to_sec("15:12:22") sec_to_time(time_to_sec("0:30:47")/6.21)
02:30:01 23001 54742 02:30:01 23001 54742 00:04:57
now()-curdate()*1000000-curtime() now()-curdate()*1000000-curtime()
0 0
strcmp(current_timestamp(),concat(current_date()," ",current_time())) strcmp(current_timestamp(),concat(current_date()," ",current_time()))
......
...@@ -7,7 +7,8 @@ select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days( ...@@ -7,7 +7,8 @@ select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(
select period_add("9602",-12),period_diff(199505,"9404") ; select period_add("9602",-12),period_diff(199505,"9404") ;
select now()-now(),weekday(curdate())-weekday(now()),unix_timestamp()-unix_timestamp(now()); select now()-now(),weekday(curdate())-weekday(now()),unix_timestamp()-unix_timestamp(now());
select from_unixtime(unix_timestamp("1994-03-02 10:11:12")),from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s"),from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0; select from_unixtime(unix_timestamp("1994-03-02 10:11:12")),from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s"),from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0;
select sec_to_time(9001),sec_to_time(9001)+0,time_to_sec("15:12:22"); select sec_to_time(9001),sec_to_time(9001)+0,time_to_sec("15:12:22"),
sec_to_time(time_to_sec("0:30:47")/6.21);
select now()-curdate()*1000000-curtime(); select now()-curdate()*1000000-curtime();
select strcmp(current_timestamp(),concat(current_date()," ",current_time())); select strcmp(current_timestamp(),concat(current_date()," ",current_time()));
select date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w"); select date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w");
......
...@@ -309,11 +309,14 @@ double Item_func_div::val() ...@@ -309,11 +309,14 @@ double Item_func_div::val()
longlong Item_func_div::val_int() longlong Item_func_div::val_int()
{ {
longlong value=args[0]->val_int(); // the integer result of division of two arguments needs to be computed
longlong val2=args[1]->val_int(); // as a type-cast division of val(), not as diviion of val_int() of each
if ((null_value= val2 == 0 || args[0]->null_value || args[1]->null_value)) // argument. For example, val_int(41.5/3.4) = val_int(12.206) = 12, but
return 0; // if you do val_int(41.5)/val_int(3.4), as in the old code, we get 42/3=
return value/val2; // 14, which is wrong. This would break sec_to_time(a/b),
// from_unixtime(a/b), and
// all functions that do val_int() on their arguments
return (longlong)val();
} }
void Item_func_div::fix_length_and_dec() void Item_func_div::fix_length_and_dec()
......
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