From 57bfb27e60055c10e42b87e68a894720c2f78e70 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 4 Sep 2006 01:26:28 +0000 Subject: Fix interval input parser so that fractional weeks and months are cascaded first to days and only what is leftover into seconds. This seems to satisfy the principle of least surprise given the general conversion to three-part interval values --- it was an oversight that these cases weren't dealt with in 8.1. Michael Glaesemann --- src/backend/utils/adt/datetime.c | 44 ++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) (limited to 'src/backend/utils/adt/datetime.c') diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index f4aceed0aa..ab0a3b4e89 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.169 2006/07/25 03:51:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.170 2006/09/04 01:26:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2920,16 +2920,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm, tm->tm_mday += val * 7; if (fval != 0) { - int sec; - - fval *= 7 * SECS_PER_DAY; - sec = fval; - tm->tm_sec += sec; + int extra_days; + fval *= 7; + extra_days = (int32) fval; + tm->tm_mday += extra_days; + fval -= extra_days; + if (fval != 0) + { + int sec; + fval *= SECS_PER_DAY; + sec = fval; + tm->tm_sec += sec; #ifdef HAVE_INT64_TIMESTAMP - *fsec += (fval - sec) * 1000000; + *fsec += (fval - sec) * 1000000; #else - *fsec += fval - sec; + *fsec += fval - sec; #endif + } } tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY); break; @@ -2938,16 +2945,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm, tm->tm_mon += val; if (fval != 0) { - int sec; - - fval *= DAYS_PER_MONTH * SECS_PER_DAY; - sec = fval; - tm->tm_sec += sec; + int day; + fval *= DAYS_PER_MONTH; + day = fval; + tm->tm_mday += day; + fval -= day; + if (fval != 0) + { + int sec; + fval *= SECS_PER_DAY; + sec = fval; + tm->tm_sec += sec; #ifdef HAVE_INT64_TIMESTAMP - *fsec += (fval - sec) * 1000000; + *fsec += (fval - sec) * 1000000; #else - *fsec += fval - sec; + *fsec += fval - sec; #endif + } } tmask = DTK_M(MONTH); break; -- cgit v1.2.1