Skip to content

Commit 3ec826f

Browse files
author
Thomas G. Lockhart
committed
Repair two recently reported problems:
1) datetime_pl_span() added the seconds field before adding the months field. This lead to erroneous results for e.g. select datetime '1999-11-30' + timespan '1 mon - 1 sec'; Reverse the order of operations to add months first. 2) tm2timespan() did all intermediate math as integer, converting to double at the very end. This resulted in hidden overflows when given very large integer days, hours, etc. For example, select '74565 days'::timespan; produced the wrong result. Change code to ensure that doubles are used for intermediate calculations. Thanks to Olivier PRENANT <ohp@pyrenet.fr> and Tulassay Zsolt <zsolt@tek.bke.hu> for problem reports and to Tom Lane for accurate analyses.
1 parent aae7b19 commit 3ec826f

File tree

1 file changed

+12
-8
lines changed
  • src/backend/utils/adt

1 file changed

+12
-8
lines changed

src/backend/utils/adt/dt.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.79 2000/01/02 02:32:37 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.80 2000/01/04 07:53:27 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -787,6 +787,7 @@ datetime_mi(DateTime *datetime1, DateTime *datetime2)
787787
* To add a month, increment the month, and use the same day of month.
788788
* Then, if the next month has fewer days, set the day of month
789789
* to the last day of month.
790+
* Lastly, add in the "quantitative time".
790791
*/
791792
DateTime *
792793
datetime_pl_span(DateTime *datetime, TimeSpan *span)
@@ -815,12 +816,6 @@ datetime_pl_span(DateTime *datetime, TimeSpan *span)
815816
{
816817
dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
817818

818-
#ifdef ROUND_ALL
819-
dt = JROUND(dt + span->time);
820-
#else
821-
dt += span->time;
822-
#endif
823-
824819
if (span->month != 0)
825820
{
826821
struct tm tt,
@@ -853,6 +848,12 @@ datetime_pl_span(DateTime *datetime, TimeSpan *span)
853848
DATETIME_INVALID(dt);
854849
}
855850

851+
#ifdef ROUND_ALL
852+
dt = JROUND(dt + span->time);
853+
#else
854+
dt += span->time;
855+
#endif
856+
856857
*result = dt;
857858
}
858859

@@ -2441,7 +2442,10 @@ static int
24412442
tm2timespan(struct tm * tm, double fsec, TimeSpan *span)
24422443
{
24432444
span->month = ((tm->tm_year * 12) + tm->tm_mon);
2444-
span->time = ((((((tm->tm_mday * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60) + tm->tm_sec);
2445+
span->time = ((((((tm->tm_mday * 24.0)
2446+
+ tm->tm_hour) * 60.0)
2447+
+ tm->tm_min) * 60.0)
2448+
+ tm->tm_sec);
24452449
span->time = JROUND(span->time + fsec);
24462450

24472451
return 0;

0 commit comments

Comments
 (0)