Re: [HACKERS] Interval aggregate regression failure (expected seems

From: Michael Glaesemann <grzm(at)seespotcode(dot)net>
To: Michael Glaesemann <grzm(at)seespotcode(dot)net>
Cc: Bruce Momjian <bruce(at)momjian(dot)us>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Michael Paesold <mpaesold(at)gmx(dot)at>, PostgreSQL-patches <pgsql-patches(at)postgresql(dot)org>
Subject: Re: [HACKERS] Interval aggregate regression failure (expected seems
Date: 2006-08-29 06:38:46
Message-ID: 1C8B0D37-C09C-479E-B47B-B0C957A05F16@seespotcode.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-patches

I think I've got it. I plan to update the regression tests this
evening, but I wanted to post what I believe is a solution.

select '41 mon'::interval / 10;
?column?
---------------
4 mons 3 days
(1 row)

select '41 mon 360:00'::interval / 10 as "pos"
, '-41 mon -360:00'::interval / 10 as "neg";
pos | neg
------------------------+---------------------------
4 mons 3 days 36:00:00 | -4 mons -3 days -36:00:00
(1 row)

select '41 mon -360:00'::interval / 10 as "pos"
, '-41 mon 360:00'::interval / 10 as "neg";
pos | neg
-------------------------+---------------------------
4 mons 3 days -36:00:00 | -4 mons -3 days +36:00:00
(1 row)

If anyone sees anything untoward, please let me know and I'll do my
best to fix it. Also, should the duplicate code in interval_mul and
interval_div be refactored into its own function?

Thanks!

Michael Glaesemann
grzm seespotcode net

---8<-----
Index: src/backend/utils/adt/timestamp.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v
retrieving revision 1.165
diff -c -r1.165 timestamp.c
*** src/backend/utils/adt/timestamp.c 13 Jul 2006 16:49:16 -0000 1.165
--- src/backend/utils/adt/timestamp.c 29 Aug 2006 06:20:03 -0000
***************
*** 2494,2500 ****
float8 factor = PG_GETARG_FLOAT8(1);
double month_remainder,
day_remainder,
! month_remainder_days;
Interval *result;

result = (Interval *) palloc(sizeof(Interval));
--- 2494,2502 ----
float8 factor = PG_GETARG_FLOAT8(1);
double month_remainder,
day_remainder,
! month_remainder_days,
! month_remainder_day_frac,
! month_remainder_time;
Interval *result;

result = (Interval *) palloc(sizeof(Interval));
***************
*** 2519,2526 ****
/* fractional months full days into days */
month_remainder_days = month_remainder * DAYS_PER_MONTH;
result->day += (int32) month_remainder_days;
! /* fractional months partial days into time */
! day_remainder += month_remainder_days - (int32) month_remainder_days;

#ifdef HAVE_INT64_TIMESTAMP
result->time = rint(span->time * factor + day_remainder *
USECS_PER_DAY);
--- 2521,2556 ----
/* fractional months full days into days */
month_remainder_days = month_remainder * DAYS_PER_MONTH;
result->day += (int32) month_remainder_days;
!
! month_remainder_day_frac = month_remainder_days - (int32)
month_remainder_days;
!
! #ifdef HAVE_INT64_TIMESTAMP
! month_remainder_day_frac = month_remainder_days - (int32)
month_remainder_days;
! month_remainder_time = month_remainder_day_frac * USECS_PER_DAY;
! if (rint(month_remainder_time) == USECS_PER_DAY)
! {
! result->day++;
! }
! else if ((rint(month_remainder_time)) == -USECS_PER_DAY)
! {
! result->day--;
! }
! #else
! month_remainder_time = month_remainder_day_frac * SECS_PER_DAY;
! if ((TSROUND(month_remainder_time) == SECS_PER_DAY))
! {
! result->day++;
! }
! else if ((TSROUND(month_remainder_time) == -SECS_PER_DAY))
! {
! result->day--;
! }
! #endif
! else
! {
! /* fractional months partial days into time */
! day_remainder += month_remainder_day_frac;
! }

#ifdef HAVE_INT64_TIMESTAMP
result->time = rint(span->time * factor + day_remainder *
USECS_PER_DAY);
***************
*** 2548,2558 ****
float8 factor = PG_GETARG_FLOAT8(1);
double month_remainder,
day_remainder,
! month_remainder_days;
Interval *result;

result = (Interval *) palloc(sizeof(Interval));

if (factor == 0.0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
--- 2578,2596 ----
float8 factor = PG_GETARG_FLOAT8(1);
double month_remainder,
day_remainder,
! month_remainder_days,
! month_remainder_day_frac,
! month_remainder_time;
Interval *result;

result = (Interval *) palloc(sizeof(Interval));

+ /*
+ a: (fl) select '41 mon'::interval / 10;
+ *span = { time = 0., day = 0, month = 41 }
+ factor = 10.
+ */
+
if (factor == 0.0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
***************
*** 2560,2579 ****

month_remainder = span->month / factor;
day_remainder = span->day / factor;
result->month = (int32) month_remainder;
- result->day = (int32) day_remainder;
month_remainder -= result->month;
- day_remainder -= result->day;

! /*
! * Handle any fractional parts the same way as in interval_mul.
! */

/* fractional months full days into days */
month_remainder_days = month_remainder * DAYS_PER_MONTH;
result->day += (int32) month_remainder_days;
! /* fractional months partial days into time */
! day_remainder += month_remainder_days - (int32) month_remainder_days;

#ifdef HAVE_INT64_TIMESTAMP
result->time = rint(span->time / factor + day_remainder *
USECS_PER_DAY);
--- 2598,2648 ----

month_remainder = span->month / factor;
day_remainder = span->day / factor;
+
result->month = (int32) month_remainder;
month_remainder -= result->month;

! result->day = (int32) day_remainder;
! day_remainder -= result->day;

/* fractional months full days into days */
month_remainder_days = month_remainder * DAYS_PER_MONTH;
result->day += (int32) month_remainder_days;
!
! month_remainder_day_frac = month_remainder_days - (int32)
month_remainder_days;
!
! /*
! * Add to result->day any fractional days from the month
component that
! * round to 24 hour periods after being converted to time.
! * Handle any fractional parts the same way as in interval_mul.
! */
!
! #ifdef HAVE_INT64_TIMESTAMP
! month_remainder_time = month_remainder_day_frac * USECS_PER_DAY;
! if (rint(month_remainder_time) == USECS_PER_DAY)
! {
! result->day++;
! }
! else if ((rint(month_remainder_time)) == -USECS_PER_DAY)
! {
! result->day--;
! }
! #else
! month_remainder_time = month_remainder_day_frac * SECS_PER_DAY;
! if ((TSROUND(month_remainder_time) == SECS_PER_DAY))
! {
! result->day++;
! }
! else if ((TSROUND(month_remainder_time) == -SECS_PER_DAY))
! {
! result->day--;
! }
! #endif
! else
! {
! /* fractional months partial days into time */
! day_remainder += month_remainder_day_frac;
! }

#ifdef HAVE_INT64_TIMESTAMP
result->time = rint(span->time / factor + day_remainder *
USECS_PER_DAY);

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Andreas Pflug 2006-08-29 09:14:44 Re: autovacuum causing numerous regression-test failures
Previous Message Lee 2006-08-29 04:36:16 would like to stop it auto-starting on boot on HP-UX IPF

Browse pgsql-patches by date

  From Date Subject
Next Message Guillaume Smet 2006-08-29 11:22:58 Re: [HACKERS] [PATCHES] log_statement output for protocol
Previous Message Bruce Momjian 2006-08-29 02:33:30 Re: [HACKERS] [PATCHES] log_statement output for protocol