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; diff --git a/src/interfaces/ecpg/pgtypeslib/interval.c b/src/interfaces/ecpg/pgtypeslib/interval.c index b6d9b19b64..22643dbd96 100644 --- a/src/interfaces/ecpg/pgtypeslib/interval.c +++ b/src/interfaces/ecpg/pgtypeslib/interval.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v 1.32 2006/06/06 11:31:55 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v 1.33 2006/09/04 01:26:28 tgl Exp $ */ #include "postgres_fe.h" #include @@ -307,16 +307,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fse 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; @@ -325,16 +332,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fse 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; diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out index 0adda4a981..3a5fb12cbc 100644 --- a/src/test/regress/expected/interval.out +++ b/src/test/regress/expected/interval.out @@ -39,6 +39,18 @@ SELECT INTERVAL '-1 days +02:03' AS "22 hours ago..."; -1 days +02:03:00 (1 row) +SELECT INTERVAL '1.5 weeks' AS "Ten days twelve hours"; + Ten days twelve hours +----------------------- + 10 days 12:00:00 +(1 row) + +SELECT INTERVAL '1.5 months' AS "One month 15 days"; + One month 15 days +------------------- + 1 mon 15 days +(1 row) + SELECT INTERVAL '10 years -11 month -12 days +13:14' AS "9 years..."; 9 years... ---------------------------------- diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql index bc384d0121..f38b01e45d 100644 --- a/src/test/regress/sql/interval.sql +++ b/src/test/regress/sql/interval.sql @@ -11,6 +11,8 @@ SELECT INTERVAL '-08:00' AS "Eight hours"; SELECT INTERVAL '-05' AS "Five hours"; SELECT INTERVAL '-1 +02:03' AS "22 hours ago..."; SELECT INTERVAL '-1 days +02:03' AS "22 hours ago..."; +SELECT INTERVAL '1.5 weeks' AS "Ten days twelve hours"; +SELECT INTERVAL '1.5 months' AS "One month 15 days"; SELECT INTERVAL '10 years -11 month -12 days +13:14' AS "9 years..."; CREATE TABLE INTERVAL_TBL (f1 interval);