Porting fix for bug #7586 "TIMEDIFF for sec+microsec not working properly"
to 5.0 tree (since it was lost during last merge).
This commit is contained in:
parent
8d616390e9
commit
31d3aabb49
@ -107,7 +107,7 @@ timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002")
|
|||||||
46:58:57.999999
|
46:58:57.999999
|
||||||
select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002");
|
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")
|
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");
|
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")
|
timediff("1997-12-31 23:59:59.000001","23:59:59.000001")
|
||||||
NULL
|
NULL
|
||||||
@ -116,7 +116,7 @@ timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001")
|
|||||||
-00:00:00.000001
|
-00:00:00.000001
|
||||||
select timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50");
|
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")
|
timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50")
|
||||||
-00:00:01.999999
|
-00:00:00.000001
|
||||||
select maketime(10,11,12);
|
select maketime(10,11,12);
|
||||||
maketime(10,11,12)
|
maketime(10,11,12)
|
||||||
10:11:12
|
10:11:12
|
||||||
@ -188,7 +188,7 @@ f8 date YES NULL
|
|||||||
f9 time YES NULL
|
f9 time YES NULL
|
||||||
select * from t1;
|
select * from t1;
|
||||||
f1 f2 f3 f4 f5 f6 f7 f8 f9
|
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);
|
create table test(t1 datetime, t2 time, t3 time, t4 datetime);
|
||||||
insert into test values
|
insert into test values
|
||||||
('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'),
|
('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'),
|
||||||
|
@ -2441,36 +2441,37 @@ void Item_func_add_time::print(String *str)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Calculate difference between two datetime values as seconds + microseconds.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
calc_time_diff()
|
calc_time_diff()
|
||||||
l_time1 TIME/DATE/DATETIME value
|
l_time1 - TIME/DATE/DATETIME value
|
||||||
l_time2 TIME/DATE/DATETIME value
|
l_time2 - TIME/DATE/DATETIME value
|
||||||
l_sign Can be 1 (operation of addition)
|
l_sign - 1 absolute values are substracted,
|
||||||
or -1 (substraction)
|
-1 absolute values are added.
|
||||||
seconds_out Returns count of seconds bitween
|
seconds_out - Out parameter where difference between
|
||||||
l_time1 and l_time2
|
l_time1 and l_time2 in seconds is stored.
|
||||||
microseconds_out Returns count of microseconds bitween
|
microseconds_out- Out parameter where microsecond part of difference
|
||||||
l_time1 and l_time2.
|
between l_time1 and l_time2 is stored.
|
||||||
|
|
||||||
DESCRIPTION
|
NOTE
|
||||||
Calculates difference in seconds(seconds_out)
|
This function calculates difference between l_time1 and l_time2 absolute
|
||||||
and microseconds(microseconds_out)
|
values. So one should set l_sign and correct result if he want to take
|
||||||
bitween two TIME/DATE/DATETIME values.
|
signs into account (i.e. for TIME values).
|
||||||
|
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
Rertuns sign of difference.
|
Returns sign of difference.
|
||||||
1 means negative result
|
1 means negative result
|
||||||
0 means positive result
|
0 means positive result
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool calc_time_diff(TIME *l_time1,TIME *l_time2, int l_sign,
|
static bool calc_time_diff(TIME *l_time1, TIME *l_time2, int l_sign,
|
||||||
longlong *seconds_out, long *microseconds_out)
|
longlong *seconds_out, long *microseconds_out)
|
||||||
{
|
{
|
||||||
long days;
|
long days;
|
||||||
bool neg;
|
bool neg;
|
||||||
longlong seconds= *seconds_out;
|
longlong microseconds;
|
||||||
long microseconds= *microseconds_out;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We suppose that if first argument is MYSQL_TIMESTAMP_TIME
|
We suppose that if first argument is MYSQL_TIMESTAMP_TIME
|
||||||
@ -2487,29 +2488,20 @@ bool calc_time_diff(TIME *l_time1,TIME *l_time2, int l_sign,
|
|||||||
(uint) l_time2->month,
|
(uint) l_time2->month,
|
||||||
(uint) l_time2->day));
|
(uint) l_time2->day));
|
||||||
|
|
||||||
microseconds= l_time1->second_part - l_sign*l_time2->second_part;
|
microseconds= ((longlong)days*86400L +
|
||||||
seconds= ((longlong) days*86400L + l_time1->hour*3600L +
|
l_time1->hour*3600L + l_time1->minute*60L + l_time1->second -
|
||||||
l_time1->minute*60L + l_time1->second + microseconds/1000000L -
|
(longlong)l_sign*(l_time2->hour*3600L + l_time2->minute*60L +
|
||||||
(longlong)l_sign*(l_time2->hour*3600L+l_time2->minute*60L+l_time2->second));
|
l_time2->second))*1000000L +
|
||||||
|
l_time1->second_part - l_sign*l_time2->second_part;
|
||||||
|
|
||||||
neg= 0;
|
neg= 0;
|
||||||
if (seconds < 0)
|
if (microseconds < 0)
|
||||||
{
|
|
||||||
seconds= -seconds;
|
|
||||||
neg= 1;
|
|
||||||
}
|
|
||||||
else if (seconds == 0 && microseconds < 0)
|
|
||||||
{
|
{
|
||||||
microseconds= -microseconds;
|
microseconds= -microseconds;
|
||||||
neg= 1;
|
neg= 1;
|
||||||
}
|
}
|
||||||
if (microseconds < 0)
|
*seconds_out= microseconds/1000000L;
|
||||||
{
|
*microseconds_out= (long) (microseconds%1000000L);
|
||||||
microseconds+= 1000000L;
|
|
||||||
seconds--;
|
|
||||||
}
|
|
||||||
*seconds_out= seconds;
|
|
||||||
*microseconds_out= microseconds;
|
|
||||||
return neg;
|
return neg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2544,9 +2536,10 @@ String *Item_func_timediff::val_str(String *str)
|
|||||||
/*
|
/*
|
||||||
For MYSQL_TIMESTAMP_TIME only:
|
For MYSQL_TIMESTAMP_TIME only:
|
||||||
If both argumets are negative values and diff between them
|
If both argumets are negative values and diff between them
|
||||||
is negative we need to swap sign as result should be positive.
|
is non-zero we need to swap sign to get proper result.
|
||||||
*/
|
*/
|
||||||
if ((l_time2.neg == l_time1.neg) && l_time1.neg)
|
if ((l_time2.neg == l_time1.neg) && l_time1.neg &&
|
||||||
|
(seconds || microseconds))
|
||||||
l_time3.neg= 1-l_time3.neg; // Swap sign of result
|
l_time3.neg= 1-l_time3.neg; // Swap sign of result
|
||||||
|
|
||||||
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
|
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
|
||||||
@ -2712,13 +2705,11 @@ longlong Item_func_timestamp_diff::val_int()
|
|||||||
case INTERVAL_SECOND:
|
case INTERVAL_SECOND:
|
||||||
return seconds*neg;
|
return seconds*neg;
|
||||||
case INTERVAL_MICROSECOND:
|
case INTERVAL_MICROSECOND:
|
||||||
{
|
/*
|
||||||
longlong max_sec= LONGLONG_MAX/1000000;
|
In MySQL difference between any two valid datetime values
|
||||||
if (max_sec > seconds ||
|
in microseconds fits into longlong.
|
||||||
max_sec == seconds && LONGLONG_MAX%1000000 >= microseconds)
|
*/
|
||||||
return (longlong) (seconds*1000000L+microseconds)*neg;
|
return (seconds*1000000L+microseconds)*neg;
|
||||||
goto null_date;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user