Commit d853e732 authored by unknown's avatar unknown
Browse files

Fix for bug #7586 "TIMEDIFF for sec+microsec not working properly".


mysql-test/r/func_sapdb.result:
  Added test for bug #7586 "TIMEDIFF for sec+microsec not working
  properly". Corrected previously wrong results of couple other
  statements.
mysql-test/t/func_sapdb.test:
  Added test for bug #7586 "TIMEDIFF for sec+microsec not working
  properly".
sql/item_timefunc.cc:
  Item_func_timediff::val_str():
   Use simplier and less error-prone implementation. Now we are counting 
   difference between time values in microseconds and convert it to time
   value (instead of using seconds and taking difference in "second_part"s 
   into account).
parent 39ee25b3
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -97,13 +97,16 @@ timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002")
46:58:57.999999
select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002");
timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002")
-23:59:59.999999
-24:00:00.000001
select timediff("1997-12-31 23:59:59.000001","23:59:59.000001");
timediff("1997-12-31 23:59:59.000001","23:59:59.000001")
NULL
select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001");
timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001")
-00:00:00.000001
select timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50");
timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50")
-00:00:00.000001
select maketime(10,11,12);
maketime(10,11,12)
10:11:12
@@ -175,7 +178,7 @@ f8 date YES NULL
f9	time	YES		NULL	
select * from t1;
f1	f2	f3	f4	f5	f6	f7	f8	f9
1997-01-01	1998-01-02 01:01:00	49:01:01	46:58:57	-23:59:59	10:11:12	2001-12-01 01:01:01	1997-12-31	23:59:59
1997-01-01	1998-01-02 01:01:00	49:01:01	46:58:57	-24:00:00	10:11:12	2001-12-01 01:01:01	1997-12-31	23:59:59
create table test(t1 datetime, t2 time, t3 time, t4 datetime);
insert into test values 
('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'),
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002");
select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002");
select timediff("1997-12-31 23:59:59.000001","23:59:59.000001");
select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001");
select timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50");
--enable_ps_protocol

select maketime(10,11,12);
+10 −20
Original line number Diff line number Diff line
@@ -2432,8 +2432,7 @@ void Item_func_add_time::print(String *str)
String *Item_func_timediff::val_str(String *str)
{
  DBUG_ASSERT(fixed == 1);
  longlong seconds;
  long microseconds;
  longlong microseconds;
  long days;
  int l_sign= 1;
  TIME l_time1 ,l_time2, l_time3;
@@ -2457,32 +2456,23 @@ String *Item_func_timediff::val_str(String *str)
			     (uint) l_time2.month,
			     (uint) l_time2.day));

  microseconds= l_time1.second_part - l_sign*l_time2.second_part;
  seconds= ((longlong) days*86400L + l_time1.hour*3600L + 
	    l_time1.minute*60L + l_time1.second + microseconds/1000000L -
  microseconds= ((longlong)days*86400L +
                 l_time1.hour*3600L + l_time1.minute*60L + l_time1.second -
                 (longlong)l_sign*(l_time2.hour*3600L + l_time2.minute*60L +
			      l_time2.second));
                                   l_time2.second))*1000000 +
                 l_time1.second_part - l_sign*l_time2.second_part;

  l_time3.neg= 0;
  if (seconds < 0)
  {
    seconds= -seconds;
    l_time3.neg= 1;
  }
  else if (seconds == 0 && microseconds < 0)
  if (microseconds < 0)
  {
    microseconds= -microseconds;
    l_time3.neg= 1;
  }
  if (microseconds < 0)
  {
    microseconds+= 1000000L;
    seconds--;
  }
  if ((l_time2.neg == l_time1.neg) && l_time1.neg)
  if ((l_time2.neg == l_time1.neg) && l_time1.neg && microseconds)
    l_time3.neg= l_time3.neg ? 0 : 1;

  calc_time_from_sec(&l_time3, (long) seconds, microseconds);
  calc_time_from_sec(&l_time3, (long)(microseconds/1000000),
                               (long)(microseconds%1000000));

  if (!make_datetime(l_time1.second_part || l_time2.second_part ?
		     TIME_MICROSECOND : TIME_ONLY,