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);