When checking for datetime field overflow, we should allow a fractional-second
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 1 May 2009 19:29:42 +0000 (19:29 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 1 May 2009 19:29:42 +0000 (19:29 +0000)
part that rounds up to exactly 1.0 second.  The previous coding rejected input
like "00:12:57.9999999999999999999999999999", with the exact number of nines
needed to cause failure varying depending on float-timestamp option and
possibly on platform.  Obviously this should round up to the next integral
second, if we don't have enough precision to distinguish the value from that.
Per bug #4789 from Robert Kruus.

In passing, fix a missed check for fractional seconds in one copy of the
"is it greater than 24:00:00" code.

Broken all the way back, so patch all the way back.

src/backend/utils/adt/datetime.c

index c2a8a46b301a070f47ebdeab801bfa1c5c334305..cb57d8182fec5d349020b97d27ceee5832079ee2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.118.2.11 2009/03/05 14:29:26 heikki Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.118.2.12 2009/05/01 19:29:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2217,13 +2217,13 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
    if ((tm->tm_hour < 0) || (tm->tm_hour > 23)
        || (tm->tm_min < 0) || (tm->tm_min > 59)
        || (tm->tm_sec < 0) || (tm->tm_sec > 60)
-       || (*fsec < INT64CONST(0)) || (*fsec >= INT64CONST(1000000)))
+       || (*fsec < INT64CONST(0)) || (*fsec > INT64CONST(1000000)))
        return DTERR_FIELD_OVERFLOW;
 #else
    if ((tm->tm_hour < 0) || (tm->tm_hour > 23)
        || (tm->tm_min < 0) || (tm->tm_min > 59)
        || (tm->tm_sec < 0) || (tm->tm_sec > 60)
-       || (*fsec < 0) || (*fsec >= 1))
+       || (*fsec < 0) || (*fsec > 1))
        return DTERR_FIELD_OVERFLOW;
 #endif
 
@@ -2482,13 +2482,13 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec)
    if ((tm->tm_hour < 0)
        || (tm->tm_min < 0) || (tm->tm_min > 59)
        || (tm->tm_sec < 0) || (tm->tm_sec > 60)
-       || (*fsec < INT64CONST(0)) || (*fsec >= INT64CONST(1000000)))
+       || (*fsec < INT64CONST(0)) || (*fsec > INT64CONST(1000000)))
        return DTERR_FIELD_OVERFLOW;
 #else
    if ((tm->tm_hour < 0)
        || (tm->tm_min < 0) || (tm->tm_min > 59)
        || (tm->tm_sec < 0) || (tm->tm_sec > 60)
-       || (*fsec < 0) || (*fsec >= 1))
+       || (*fsec < 0) || (*fsec > 1))
        return DTERR_FIELD_OVERFLOW;
 #endif