Re: [BUGS] BUG #1609: Bug in interval datatype for 64 Bit timestamps - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: [BUGS] BUG #1609: Bug in interval datatype for 64 Bit timestamps
Date
Msg-id 200505240416.j4O4GcO18190@candle.pha.pa.us
Whole thread Raw
List pgsql-patches
Tom Lane wrote:
> Oliver Siegmar <oliver@siegmar.net> writes:
> > On Thursday 21 April 2005 15:57, Tom Lane wrote:
> >> If it is only the float case, some imprecision is to be expected.
>
> > So everything is okay?
>
> Well, it's not necessarily *wrong*, but maybe we could improve it.
> The code currently assumes it can print 10 fractional digits in the
> float case, which is overly optimistic once you get a large number
> of days in the "days" component.  Maybe we should add some code
> to back off the precision depending on the number of days?

I decided to trim off just the last digit to show only 9 digits instead
of 10.  The logic is that the last digit is giving us problems, and 9
digits is nano-second resolution, while 10 is 100 picoseconds, which is
kind of a weird default.

It does fix the problem:

    test=> select '2005 years 4 mons 20 days 15 hours 57 mins 12.1 secs
    ago'::interval;
                     interval
    -------------------------------------------
     -2005 years -4 mons -20 days -15:57:12.10
    (1 row)

Doing like 200 days still shows the failure:

    test=> select '2005 years 4 mons 200 days 15 hours 57 mins 12.1 secs
    ago'::interval;
                         interval
    ---------------------------------------------------
     -2005 years -4 mons -200 days -15:57:12.100000001
    (1 row)

but I figure 20 days is much more common than 200.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/backend/utils/adt/datetime.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v
retrieving revision 1.144
diff -c -c -r1.144 datetime.c
*** src/backend/utils/adt/datetime.c    24 May 2005 02:09:45 -0000    1.144
--- src/backend/utils/adt/datetime.c    24 May 2005 04:11:57 -0000
***************
*** 3444,3450 ****
  #ifdef HAVE_INT64_TIMESTAMP
          sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
  #else
!         sprintf(str + strlen(str), ":%013.10f", tm->tm_sec + fsec);
  #endif
          /* chop off trailing pairs of zeros... */
          while (strcmp((str + strlen(str) - 2), "00") == 0 &&
--- 3444,3450 ----
  #ifdef HAVE_INT64_TIMESTAMP
          sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
  #else
!         sprintf(str + strlen(str), ":%012.9f", tm->tm_sec + fsec);
  #endif
          /* chop off trailing pairs of zeros... */
          while (strcmp((str + strlen(str) - 2), "00") == 0 &&
***************
*** 3787,3793 ****
                      sprintf(cp, ".%06d", Abs(fsec));
  #else
                      fsec += tm->tm_sec;
!                     sprintf(cp, ":%013.10f", fabs(fsec));
  #endif
                      TrimTrailingZeros(cp);
                      cp += strlen(cp);
--- 3787,3793 ----
                      sprintf(cp, ".%06d", Abs(fsec));
  #else
                      fsec += tm->tm_sec;
!                     sprintf(cp, ":%012.9f", fabs(fsec));
  #endif
                      TrimTrailingZeros(cp);
                      cp += strlen(cp);
Index: src/interfaces/ecpg/pgtypeslib/interval.c
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v
retrieving revision 1.16
diff -c -c -r1.16 interval.c
*** src/interfaces/ecpg/pgtypeslib/interval.c    24 May 2005 02:09:45 -0000    1.16
--- src/interfaces/ecpg/pgtypeslib/interval.c    24 May 2005 04:12:00 -0000
***************
*** 511,517 ****
                      sprintf(cp, ".%06d", (fsec >= 0) ? fsec : -(fsec));
  #else
                      fsec += tm->tm_sec;
!                     sprintf(cp, ":%013.10f", fabs(fsec));
  #endif
                      TrimTrailingZeros(cp);
                      cp += strlen(cp);
--- 511,517 ----
                      sprintf(cp, ".%06d", (fsec >= 0) ? fsec : -(fsec));
  #else
                      fsec += tm->tm_sec;
!                     sprintf(cp, ":%012.9f", fabs(fsec));
  #endif
                      TrimTrailingZeros(cp);
                      cp += strlen(cp);

pgsql-patches by date:

Previous
From: Neil Conway
Date:
Subject: Re: plperl tests for currently untested features
Next
From: Bruce Momjian
Date:
Subject: Re: Exec statement logging