Re: Interval month, week -> day - Mailing list pgsql-patches
| From | Bruce Momjian |
|---|---|
| Subject | Re: Interval month, week -> day |
| Date | |
| Msg-id | 200608300422.k7U4M5x14509@momjian.us Whole thread Raw |
| In response to | Interval month, week -> day (Michael Glaesemann <grzm@seespotcode.net>) |
| List | pgsql-patches |
The masks don't need changing.
Your patch has been added to the PostgreSQL unapplied patches list at:
http://momjian.postgresql.org/cgi-bin/pgpatches
It will be applied as soon as one of the PostgreSQL committers reviews
and approves it.
---------------------------------------------------------------------------
Michael Glaesemann wrote:
> When trying to improve the rounding in interval_div and interval_mul,
> I came across some behavior that seems counterintuitive to me:
>
> test=# select '1.5 mon'::interval;
> interval
> -----------------
> 1 mon 360:00:00
> (1 row)
>
> With the time/day/month interval struct introduced in 8.1, I'd expect
> this to return '1 mon 15 days'. The reason is that the DecodeInterval
> converts fractional months to time directly, rather than cascading
> first to days.
>
> Similar behavior happens with weeks:
>
> select '1.5 week'::interval;
> interval
> -----------------
> 7 days 84:00:00
> (1 row)
>
> Similarly, I believe should return 10 days 12 hours (7 days + 3.5 days).
>
> I've patched DecodeInterval and the regression tests to check this. I
> think tmask lines need to be updated, but I'm not sure how these work
> so I've left them as is. I'd appreciate it if someone could look at
> these areas in particular.
>
> I think this is a behavior changing bug fix, as it was the intention
> of the Interval struct change to treat days and time differently.
> This patch brings the DecodeInterval function more in line with that
> intention.
>
> Thanks for your consideration.
>
> Michael Glaesemann
> grzm seespotcode net
>
>
> Index: src/backend/utils/adt/datetime.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/datetime.c,v
> retrieving revision 1.169
> diff -c -r1.169 datetime.c
> *** src/backend/utils/adt/datetime.c 25 Jul 2006 03:51:21 -0000 1.169
> --- src/backend/utils/adt/datetime.c 27 Aug 2006 23:25:53 -0000
> ***************
> *** 2920,2935 ****
> tm->tm_mday += val * 7;
> if (fval != 0)
> {
> ! int sec;
> !
> ! fval *= 7 * SECS_PER_DAY;
> ! sec = fval;
> ! tm->tm_sec += sec;
> #ifdef HAVE_INT64_TIMESTAMP
> ! *fsec += (fval - sec) * 1000000;
> #else
> ! *fsec += fval - sec;
> #endif
> }
> tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);
> break;
> --- 2920,2942 ----
> tm->tm_mday += val * 7;
> if (fval != 0)
> {
> ! 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;
> #else
> ! *fsec += fval - sec;
> #endif
> + }
> }
> tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);
> break;
> ***************
> *** 2938,2953 ****
> tm->tm_mon += val;
> if (fval != 0)
> {
> ! int sec;
> !
> ! fval *= DAYS_PER_MONTH * SECS_PER_DAY;
> ! sec = fval;
> ! tm->tm_sec += sec;
> #ifdef HAVE_INT64_TIMESTAMP
> ! *fsec += (fval - sec) * 1000000;
> #else
> ! *fsec += fval - sec;
> #endif
> }
> tmask = DTK_M(MONTH);
> break;
> --- 2945,2967 ----
> tm->tm_mon += val;
> if (fval != 0)
> {
> ! 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;
> #else
> ! *fsec += fval - sec;
> #endif
> + }
> }
> tmask = DTK_M(MONTH);
> break;
> Index: src/test/regress/expected/interval.out
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/
> interval.out,v
> retrieving revision 1.15
> diff -c -r1.15 interval.out
> *** src/test/regress/expected/interval.out 6 Mar 2006 22:49:17 -0000
> 1.15
> --- src/test/regress/expected/interval.out 27 Aug 2006 23:25:56 -0000
> ***************
> *** 39,44 ****
> --- 39,56 ----
> -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...
> ----------------------------------
> Index: src/test/regress/sql/interval.sql
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/interval.sql,v
> retrieving revision 1.9
> diff -c -r1.9 interval.sql
> *** src/test/regress/sql/interval.sql 6 Mar 2006 22:49:17 -0000 1.9
> --- src/test/regress/sql/interval.sql 27 Aug 2006 23:25:56 -0000
> ***************
> *** 11,16 ****
> --- 11,18 ----
> 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);
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 3: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/docs/faq
--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com
+ If your life is a hard drive, Christ can be your backup. +
pgsql-patches by date: