summaryrefslogtreecommitdiff
path: root/sql/item_timefunc.cc
diff options
context:
space:
mode:
authorunknown <dlenev@brandersnatch.localdomain>2005-01-15 20:02:46 +0300
committerunknown <dlenev@brandersnatch.localdomain>2005-01-15 20:02:46 +0300
commit9e60778daeeead4a9470ecdf7c2d008635c197a8 (patch)
tree495065916f2afa9d80b2bed614e60acfc6fdad75 /sql/item_timefunc.cc
parent6ead860060ebeae29f46d6c89f0bf7a45e748819 (diff)
downloadmariadb-git-9e60778daeeead4a9470ecdf7c2d008635c197a8.tar.gz
Porting fix for bug #7586 "TIMEDIFF for sec+microsec not working properly"
to 5.0 tree (since it was lost during last merge). mysql-test/r/func_sapdb.result: Updated test result after fixing bug #7586 "TIMEDIFF for sec+microsec not working properly" in 5.0 tree. sql/item_timefunc.cc: calc_time_diff(): Use simplier and less error-prone implementation. Now we are counting difference between time values in microseconds and then convert it to seconds + microseconds value (instead of using seconds and taking difference in "second_part"s into account).
Diffstat (limited to 'sql/item_timefunc.cc')
-rw-r--r--sql/item_timefunc.cc79
1 files changed, 35 insertions, 44 deletions
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 2d0e5d7632f..0c1cd3cbad3 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2441,36 +2441,37 @@ void Item_func_add_time::print(String *str)
/*
+ Calculate difference between two datetime values as seconds + microseconds.
+
SYNOPSIS
calc_time_diff()
- l_time1 TIME/DATE/DATETIME value
- l_time2 TIME/DATE/DATETIME value
- l_sign Can be 1 (operation of addition)
- or -1 (substraction)
- seconds_out Returns count of seconds bitween
- l_time1 and l_time2
- microseconds_out Returns count of microseconds bitween
- l_time1 and l_time2.
-
- DESCRIPTION
- Calculates difference in seconds(seconds_out)
- and microseconds(microseconds_out)
- bitween two TIME/DATE/DATETIME values.
+ l_time1 - TIME/DATE/DATETIME value
+ l_time2 - TIME/DATE/DATETIME value
+ l_sign - 1 absolute values are substracted,
+ -1 absolute values are added.
+ seconds_out - Out parameter where difference between
+ l_time1 and l_time2 in seconds is stored.
+ microseconds_out- Out parameter where microsecond part of difference
+ between l_time1 and l_time2 is stored.
+
+ NOTE
+ This function calculates difference between l_time1 and l_time2 absolute
+ values. So one should set l_sign and correct result if he want to take
+ signs into account (i.e. for TIME values).
RETURN VALUES
- Rertuns sign of difference.
+ Returns sign of difference.
1 means negative result
0 means positive result
*/
-bool calc_time_diff(TIME *l_time1,TIME *l_time2, int l_sign,
- longlong *seconds_out, long *microseconds_out)
+static bool calc_time_diff(TIME *l_time1, TIME *l_time2, int l_sign,
+ longlong *seconds_out, long *microseconds_out)
{
long days;
bool neg;
- longlong seconds= *seconds_out;
- long microseconds= *microseconds_out;
+ longlong microseconds;
/*
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->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 -
- (longlong)l_sign*(l_time2->hour*3600L+l_time2->minute*60L+l_time2->second));
+ 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))*1000000L +
+ l_time1->second_part - l_sign*l_time2->second_part;
neg= 0;
- if (seconds < 0)
- {
- seconds= -seconds;
- neg= 1;
- }
- else if (seconds == 0 && microseconds < 0)
+ if (microseconds < 0)
{
microseconds= -microseconds;
neg= 1;
}
- if (microseconds < 0)
- {
- microseconds+= 1000000L;
- seconds--;
- }
- *seconds_out= seconds;
- *microseconds_out= microseconds;
+ *seconds_out= microseconds/1000000L;
+ *microseconds_out= (long) (microseconds%1000000L);
return neg;
}
@@ -2544,9 +2536,10 @@ String *Item_func_timediff::val_str(String *str)
/*
For MYSQL_TIMESTAMP_TIME only:
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
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
@@ -2712,13 +2705,11 @@ longlong Item_func_timestamp_diff::val_int()
case INTERVAL_SECOND:
return seconds*neg;
case INTERVAL_MICROSECOND:
- {
- longlong max_sec= LONGLONG_MAX/1000000;
- if (max_sec > seconds ||
- max_sec == seconds && LONGLONG_MAX%1000000 >= microseconds)
- return (longlong) (seconds*1000000L+microseconds)*neg;
- goto null_date;
- }
+ /*
+ In MySQL difference between any two valid datetime values
+ in microseconds fits into longlong.
+ */
+ return (seconds*1000000L+microseconds)*neg;
default:
break;
}