summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <dlenev@mysql.com>2005-04-18 17:00:02 +0400
committerunknown <dlenev@mysql.com>2005-04-18 17:00:02 +0400
commit7d84532fdd68027997259049de0716a77b6b9e7a (patch)
tree31e7e8b8502a93ad090375179d6cf28fc6f69f68
parent12f720f28f5d1d18a4f71d137195776d6f5440bf (diff)
parentaf5c9db68cbb65c5094de0c6297e1719b4881eb9 (diff)
downloadmariadb-git-7d84532fdd68027997259049de0716a77b6b9e7a.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/dlenev/src/mysql-5.0-merges
-rw-r--r--mysql-test/r/func_sapdb.result5
-rw-r--r--mysql-test/t/func_sapdb.test1
-rw-r--r--sql/item_timefunc.cc204
3 files changed, 99 insertions, 111 deletions
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index 6556d2be6ad..f209866d953 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -195,6 +195,7 @@ insert into test values
('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"),
('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'),
('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null),
+('2001-01-01 01:01:01', '-01:01:01', '1 01:01:01', '2001-01-01 01:01:01'),
('2001-01-01 01:01:01', null, '-1 01:01:01', null),
(null, null, null, null),
('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
@@ -204,6 +205,7 @@ ttt qqq
2001-01-01 00:00:00 -25:01:00
1997-12-31 00:00:00 -25:01:00
2001-01-01 02:02:02 -24:00:00
+2001-01-01 00:00:00 24:00:00
NULL NULL
NULL NULL
2001-01-01 02:02:02 26:02:02
@@ -213,7 +215,8 @@ ttt qqq eee rrr
-744:00:00 NULL NULL NULL
26305:01:02 22:58:58 -22:58:58 NULL
-26305:01:02 -22:58:58 22:58:58 NULL
-NULL 26:02:02 26:02:02 NULL
+NULL 26:02:02 -26:02:02 NULL
+00:00:00 -26:02:02 26:02:02 NULL
NULL NULL NULL NULL
NULL NULL NULL NULL
00:00:00 -24:00:00 24:00:00 NULL
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
index cb3ab12b5fc..bb9159eefbe 100644
--- a/mysql-test/t/func_sapdb.test
+++ b/mysql-test/t/func_sapdb.test
@@ -106,6 +106,7 @@ insert into test values
('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"),
('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'),
('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null),
+('2001-01-01 01:01:01', '-01:01:01', '1 01:01:01', '2001-01-01 01:01:01'),
('2001-01-01 01:01:01', null, '-1 01:01:01', null),
(null, null, null, null),
('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 85ba3bfd0e4..cd4777d542b 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -775,6 +775,81 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
}
+/*
+ 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 - 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
+ Returns sign of difference.
+ 1 means negative result
+ 0 means positive result
+
+*/
+
+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 microseconds;
+
+ /*
+ We suppose that if first argument is MYSQL_TIMESTAMP_TIME
+ the second argument should be TIMESTAMP_TIME also.
+ We should check it before calc_time_diff call.
+ */
+ if (l_time1->time_type == MYSQL_TIMESTAMP_TIME) // Time value
+ days= l_time1->day - l_sign*l_time2->day;
+ else
+ {
+ days= calc_daynr((uint) l_time1->year,
+ (uint) l_time1->month,
+ (uint) l_time1->day);
+ if (l_time2->time_type == MYSQL_TIMESTAMP_TIME)
+ days-= l_sign*l_time2->day;
+ else
+ days-= l_sign*calc_daynr((uint) l_time2->year,
+ (uint) l_time2->month,
+ (uint) l_time2->day);
+ }
+
+ microseconds= ((longlong)days*LL(86400) +
+ (longlong)(l_time1->hour*3600L +
+ l_time1->minute*60L +
+ l_time1->second) -
+ l_sign*(longlong)(l_time2->hour*3600L +
+ l_time2->minute*60L +
+ l_time2->second)) * LL(1000000) +
+ (longlong)l_time1->second_part -
+ l_sign*(longlong)l_time2->second_part;
+
+ neg= 0;
+ if (microseconds < 0)
+ {
+ microseconds= -microseconds;
+ neg= 1;
+ }
+ *seconds_out= microseconds/1000000L;
+ *microseconds_out= (long) (microseconds%1000000L);
+ return neg;
+}
+
+
longlong Item_func_period_add::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -2373,11 +2448,11 @@ String *Item_func_add_time::val_str(String *str)
DBUG_ASSERT(fixed == 1);
TIME l_time1, l_time2, l_time3;
bool is_time= 0;
- long microseconds, seconds, days= 0;
+ long days, microseconds;
+ longlong seconds;
int l_sign= sign;
null_value=0;
- l_time3.neg= 0;
if (is_date) // TIMESTAMP function
{
if (get_arg0_date(&l_time1, TIME_FUZZY_DATE) ||
@@ -2393,51 +2468,26 @@ String *Item_func_add_time::val_str(String *str)
l_time2.time_type == MYSQL_TIMESTAMP_DATETIME)
goto null_date;
is_time= (l_time1.time_type == MYSQL_TIMESTAMP_TIME);
- if (is_time && (l_time2.neg == l_time1.neg && l_time1.neg))
- l_time3.neg= 1;
}
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
- microseconds= l_time1.second_part + l_sign*l_time2.second_part;
- seconds= (l_time1.hour*3600L + l_time1.minute*60L + l_time1.second +
- (l_time2.day*86400L + l_time2.hour*3600L +
- l_time2.minute*60L + l_time2.second)*l_sign);
- if (is_time)
- seconds+= l_time1.day*86400L;
- else
- days+= calc_daynr((uint) l_time1.year,(uint) l_time1.month,
- (uint) l_time1.day);
- seconds= seconds + microseconds/1000000L;
- microseconds= microseconds%1000000L;
- days+= seconds/86400L;
- seconds= seconds%86400L;
+ l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
+ &seconds, &microseconds);
- if (microseconds < 0)
- {
- microseconds+= 1000000L;
- seconds--;
- }
- if (seconds < 0)
- {
- days+= seconds/86400L - 1;
- seconds+= 86400L;
- }
- if (days < 0)
- {
- if (!is_time)
- goto null_date;
- if (microseconds)
- {
- microseconds= 1000000L - microseconds;
- seconds++;
- }
- seconds= 86400L - seconds;
- days= -(++days);
- l_time3.neg= 1;
- }
+ /*
+ If first argument was negative and diff between arguments
+ is non-zero we need to swap sign to get proper result.
+ */
+ if (l_time1.neg && (seconds || microseconds))
+ l_time3.neg= 1-l_time3.neg; // Swap sign of result
+
+ if (!is_time && l_time3.neg)
+ goto null_date;
+
+ days= (long)(seconds/86400L);
- calc_time_from_sec(&l_time3, seconds, microseconds);
+ calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
if (!is_time)
{
get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
@@ -2483,71 +2533,6 @@ 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 - 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
- Returns sign of difference.
- 1 means negative result
- 0 means positive result
-
-*/
-
-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 microseconds;
-
- /*
- We suppose that if first argument is MYSQL_TIMESTAMP_TIME
- the second argument should be TIMESTAMP_TIME also.
- We should check it before calc_time_diff call.
- */
- if (l_time1->time_type == MYSQL_TIMESTAMP_TIME) // Time value
- days= l_time1->day - l_sign*l_time2->day;
- else // DateTime value
- days= (calc_daynr((uint) l_time1->year,
- (uint) l_time1->month,
- (uint) l_time1->day) -
- l_sign*calc_daynr((uint) l_time2->year,
- (uint) l_time2->month,
- (uint) l_time2->day));
-
- 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 (microseconds < 0)
- {
- microseconds= -microseconds;
- neg= 1;
- }
- *seconds_out= microseconds/1000000L;
- *microseconds_out= (long) (microseconds%1000000L);
- return neg;
-}
-
-/*
TIMEDIFF(t,s) is a time function that calculates the
time value between a start and end time.
@@ -2572,16 +2557,15 @@ String *Item_func_timediff::val_str(String *str)
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
- l_time3.neg= calc_time_diff(&l_time1,&l_time2, l_sign,
+ l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
&seconds, &microseconds);
/*
For MYSQL_TIMESTAMP_TIME only:
- If both argumets are negative values and diff between them
+ If first argument was negative and diff between arguments
is non-zero we need to swap sign to get proper result.
*/
- if ((l_time2.neg == l_time1.neg) && l_time1.neg &&
- (seconds || microseconds))
+ if (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);