diff options
author | unknown <dlenev@mysql.com> | 2005-04-18 17:00:02 +0400 |
---|---|---|
committer | unknown <dlenev@mysql.com> | 2005-04-18 17:00:02 +0400 |
commit | 7d84532fdd68027997259049de0716a77b6b9e7a (patch) | |
tree | 31e7e8b8502a93ad090375179d6cf28fc6f69f68 | |
parent | 12f720f28f5d1d18a4f71d137195776d6f5440bf (diff) | |
parent | af5c9db68cbb65c5094de0c6297e1719b4881eb9 (diff) | |
download | mariadb-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.result | 5 | ||||
-rw-r--r-- | mysql-test/t/func_sapdb.test | 1 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 204 |
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, µseconds); - 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, µseconds); /* 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); |