summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas G. Lockhart2000-01-04 07:56:23 +0000
committerThomas G. Lockhart2000-01-04 07:56:23 +0000
commit621e3721895f0f64cdc602306ae5c144fed06938 (patch)
tree94cd399ef6139c933d8e03493ae4eb773778fefa
parent424ff563bac6735ed87a3347534b8a12cbafd9a2 (diff)
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 <[email protected]> and Tulassay Zsolt <[email protected]> for problem reports and to Tom Lane for accurate analyses.
-rw-r--r--src/backend/utils/adt/dt.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c
index 72004e9b1db..0a99cfe8bbe 100644
--- a/src/backend/utils/adt/dt.c
+++ b/src/backend/utils/adt/dt.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.72.2.1 1999/08/02 05:24:51 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.72.2.2 2000/01/04 07:56:23 thomas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -811,6 +811,7 @@ datetime_mi(DateTime *datetime1, DateTime *datetime2)
* To add a month, increment the month, and use the same day of month.
* Then, if the next month has fewer days, set the day of month
* to the last day of month.
+ * Lastly, add in the "quantitative time".
*/
DateTime *
datetime_pl_span(DateTime *datetime, TimeSpan *span)
@@ -843,12 +844,6 @@ datetime_pl_span(DateTime *datetime, TimeSpan *span)
{
dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
-#ifdef ROUND_ALL
- dt = JROUND(dt + span->time);
-#else
- dt += span->time;
-#endif
-
if (span->month != 0)
{
struct tm tt,
@@ -889,6 +884,12 @@ datetime_pl_span(DateTime *datetime, TimeSpan *span)
DATETIME_INVALID(dt);
}
+#ifdef ROUND_ALL
+ dt = JROUND(dt + span->time);
+#else
+ dt += span->time;
+#endif
+
*result = dt;
}
@@ -2569,7 +2570,10 @@ static int
tm2timespan(struct tm * tm, double fsec, TimeSpan *span)
{
span->month = ((tm->tm_year * 12) + tm->tm_mon);
- span->time = ((((((tm->tm_mday * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60) + tm->tm_sec);
+ span->time = ((((((tm->tm_mday * 24.0)
+ + tm->tm_hour) * 60.0)
+ + tm->tm_min) * 60.0)
+ + tm->tm_sec);
span->time = JROUND(span->time + fsec);
#ifdef DATEDEBUG