Unix Technical Forum

Fix for timestamp rouding

This is a discussion on Fix for timestamp rouding within the Pgsql Patches forums, part of the PostgreSQL category; --> Michael Fuhr wrote: > I'm getting time, timetz, and horology regression failures in HEAD > on Solaris 9 / ...


Go Back   Unix Technical Forum > Database Server Software > PostgreSQL > Pgsql Patches

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 04-18-2008, 12:22 AM
Bruce Momjian
 
Posts: n/a
Default Fix for timestamp rouding

Michael Fuhr wrote:
> I'm getting time, timetz, and horology regression failures in HEAD
> on Solaris 9 / gcc 3.4.2. So are other machines in the build farm,
> such as this one:
>
> http://www.pgbuildfarm.org/cgi-bin/s...-26%2004:21:00
>
> I'm getting the same regression failures shown in that link; here's
> an example:


OK, I have a new patch, which simplifies the code by using
TrimTrailingZeros(), gives more consistent subsecond display, and
subpresses the rounding 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)

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

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

--
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.147
diff -c -c -r1.147 datetime.c
*** src/backend/utils/adt/datetime.c 26 May 2005 15:26:00 -0000 1.147
--- src/backend/utils/adt/datetime.c 26 May 2005 18:10:03 -0000
***************
*** 3461,3472 ****
#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 &&
! *(str + strlen(str) - 3) != '.')
! *(str + strlen(str) - 2) = '\0';
}
else
sprintf(str + strlen(str), ":%02d", tm->tm_sec);
--- 3461,3469 ----
#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
! TrimTrailingZeros(str);
}
else
sprintf(str + strlen(str), ":%02d", tm->tm_sec);
***************
*** 3804,3810 ****
sprintf(cp, ".%06d", Abs(fsec));
#else
fsec += tm->tm_sec;
! sprintf(cp, ":%013.10f", fabs(fsec));
#endif
TrimTrailingZeros(cp);
cp += strlen(cp);
--- 3801,3807 ----
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.19
diff -c -c -r1.19 interval.c
*** src/interfaces/ecpg/pgtypeslib/interval.c 26 May 2005 16:44:05 -0000 1.19
--- src/interfaces/ecpg/pgtypeslib/interval.c 26 May 2005 18:10:04 -0000
***************
*** 511,517 ****
sprintf(cp, ".%06d", Abs(fsec));
#else
fsec += tm->tm_sec;
! sprintf(cp, ":%013.10f", fabs(fsec));
#endif
TrimTrailingZeros(cp);
cp += strlen(cp);
--- 511,517 ----
sprintf(cp, ".%06d", Abs(fsec));
#else
fsec += tm->tm_sec;
! sprintf(cp, ":%012.9f", fabs(fsec));
#endif
TrimTrailingZeros(cp);
cp += strlen(cp);
Index: src/test/regress/expected/horology.out
================================================== =================
RCS file: /cvsroot/pgsql/src/test/regress/expected/horology.out,v
retrieving revision 1.53
diff -c -c -r1.53 horology.out
*** src/test/regress/expected/horology.out 7 Apr 2005 01:51:40 -0000 1.53
--- src/test/regress/expected/horology.out 26 May 2005 18:10:07 -0000
***************
*** 205,266 ****
-- As of 7.4, allow time without time zone having a time zone specified
SELECT time without time zone '040506.789+08';
time
! ---------------
! 04:05:06.7890
(1 row)

SELECT time without time zone '040506.789-08';
time
! ---------------
! 04:05:06.7890
(1 row)

SELECT time without time zone 'T040506.789+08';
time
! ---------------
! 04:05:06.7890
(1 row)

SELECT time without time zone 'T040506.789-08';
time
! ---------------
! 04:05:06.7890
(1 row)

SELECT time with time zone '040506.789+08';
timetz
! ------------------
! 04:05:06.7890+08
(1 row)

SELECT time with time zone '040506.789-08';
timetz
! ------------------
! 04:05:06.7890-08
(1 row)

SELECT time with time zone 'T040506.789+08';
timetz
! ------------------
! 04:05:06.7890+08
(1 row)

SELECT time with time zone 'T040506.789-08';
timetz
! ------------------
! 04:05:06.7890-08
(1 row)

SELECT time with time zone 'T040506.789 +08';
timetz
! ------------------
! 04:05:06.7890+08
(1 row)

SELECT time with time zone 'T040506.789 -08';
timetz
! ------------------
! 04:05:06.7890-08
(1 row)

SET DateStyle = 'Postgres, MDY';
--- 205,266 ----
-- As of 7.4, allow time without time zone having a time zone specified
SELECT time without time zone '040506.789+08';
time
! --------------
! 04:05:06.789
(1 row)

SELECT time without time zone '040506.789-08';
time
! --------------
! 04:05:06.789
(1 row)

SELECT time without time zone 'T040506.789+08';
time
! --------------
! 04:05:06.789
(1 row)

SELECT time without time zone 'T040506.789-08';
time
! --------------
! 04:05:06.789
(1 row)

SELECT time with time zone '040506.789+08';
timetz
! -----------------
! 04:05:06.789+08
(1 row)

SELECT time with time zone '040506.789-08';
timetz
! -----------------
! 04:05:06.789-08
(1 row)

SELECT time with time zone 'T040506.789+08';
timetz
! -----------------
! 04:05:06.789+08
(1 row)

SELECT time with time zone 'T040506.789-08';
timetz
! -----------------
! 04:05:06.789-08
(1 row)

SELECT time with time zone 'T040506.789 +08';
timetz
! -----------------
! 04:05:06.789+08
(1 row)

SELECT time with time zone 'T040506.789 -08';
timetz
! -----------------
! 04:05:06.789-08
(1 row)

SET DateStyle = 'Postgres, MDY';


---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 04-18-2008, 12:22 AM
Tom Lane
 
Posts: n/a
Default Re: Fix for timestamp rouding

Bruce Momjian <pgman@candle.pha.pa.us> writes:
> OK, I have a new patch, which simplifies the code by using
> TrimTrailingZeros(), gives more consistent subsecond display, and
> subpresses the rounding problem:


Does anyone have any idea why the existing code is designed to keep the
number of displayed fractional digits even? It seems a bit silly to
me too, but we probably ought not remove what was clearly an intentional
behavior without understanding why it was intentional.

Also, I will point out once more that the problem is not "we only have
nine digits of precision not ten". The problem is that the precision
degrades as the interval gets larger.

regression=# select '20 days 15 hours 57 mins 12.1 secs ago'::interval;
interval
-------------------------------
-20 days -15:57:12.1000000001
(1 row)

regression=# select '100020 days 15 hours 57 mins 12.1 secs ago'::interval;
interval
-----------------------------------
-100020 days -15:57:12.1000003815
(1 row)

regression=# select '100000020 days 15 hours 57 mins 12.1 secs ago'::interval;
interval
-------------------------------------
-100000020 days -15:57:12.099609375
(1 row)

regression=#

Without accounting for that fundamental fact, you will not have a
solution, only a kluge.

regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 04-18-2008, 12:22 AM
Bruce Momjian
 
Posts: n/a
Default Re: Fix for timestamp rouding

Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > OK, I have a new patch, which simplifies the code by using
> > TrimTrailingZeros(), gives more consistent subsecond display, and
> > subpresses the rounding problem:

>
> Does anyone have any idea why the existing code is designed to keep the
> number of displayed fractional digits even? It seems a bit silly to
> me too, but we probably ought not remove what was clearly an intentional
> behavior without understanding why it was intentional.


If you look at TrimTrailingZeros(), you will see it keeps at least two
decimal digits of display, so I suppose the special case while() loop
was just an older version of that. I can't imagine why they would only
want even digits, but given the other weird things in the datetime code,
it isn't surprising.

> Also, I will point out once more that the problem is not "we only have
> nine digits of precision not ten". The problem is that the precision
> degrades as the interval gets larger.
>
> regression=# select '20 days 15 hours 57 mins 12.1 secs ago'::interval;
> interval
> -------------------------------
> -20 days -15:57:12.1000000001
> (1 row)
>
> regression=# select '100020 days 15 hours 57 mins 12.1 secs ago'::interval;
> interval
> -----------------------------------
> -100020 days -15:57:12.1000003815
> (1 row)
>
> regression=# select '100000020 days 15 hours 57 mins 12.1 secs ago'::interval;
> interval
> -------------------------------------
> -100000020 days -15:57:12.099609375
> (1 row)
>
> regression=#
>
> Without accounting for that fundamental fact, you will not have a
> solution, only a kluge.


Yep, it just hits the most common complaint for <30 days --- larger
values are going to round funny. I can't think of how to round it
cleanly without adding a lot of hacky code dealing with floats and
exponents.

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

---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
joining column's datatypes do not match

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 04:43 PM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com