]> granicus.if.org Git - postgresql/commitdiff
Repair array subscript overrun identified by Yichen Xie. Reduce the
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 29 Jan 2003 01:09:03 +0000 (01:09 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 29 Jan 2003 01:09:03 +0000 (01:09 +0000)
value of MAX_TIME_PRECISION in floating-point-timestamp-storage case
from 13 to 10, which is as much as time_out is actually willing to print.
(The alternative of increasing the number of digits we are willing to
print looks risky; we might find ourselves printing roundoff garbage.)

doc/src/sgml/datatype.sgml
src/backend/utils/adt/date.c
src/backend/utils/adt/datetime.c
src/include/utils/date.h

index c81c0bb97004ff2dcbccc91887633d0d4861a436..e4f3f7adabd83047dcd6701dc131b51528d36c13 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.106.2.2 2002/11/21 23:31:37 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.106.2.3 2003/01/29 01:09:03 tgl Exp $
 -->
 
  <chapter id="datatype">
@@ -86,18 +86,18 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.106.2.2 2002/11/21 23:31:
        <entry>binary data</entry>
       </row>
 
-      <row>
-       <entry><type>character(<replaceable>n</replaceable>)</type></entry>
-       <entry><type>char(<replaceable>n</replaceable>)</type></entry>
-       <entry>fixed-length character string</entry>
-      </row>
-
       <row>
        <entry><type>character varying(<replaceable>n</replaceable>)</type></entry>
        <entry><type>varchar(<replaceable>n</replaceable>)</type></entry>
        <entry>variable-length character string</entry>
       </row>
 
+      <row>
+       <entry><type>character(<replaceable>n</replaceable>)</type></entry>
+       <entry><type>char(<replaceable>n</replaceable>)</type></entry>
+       <entry>fixed-length character string</entry>
+      </row>
+
       <row>
        <entry><type>cidr</type></entry>
        <entry></entry>
@@ -248,7 +248,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.106.2.2 2002/11/21 23:31:
     The following types (or spellings thereof) are specified by
     <acronym>SQL</acronym>: <type>bit</type>, <type>bit
     varying</type>, <type>boolean</type>, <type>char</type>,
-    <type>character</type>, <type>character varying</type>,
+    <type>character varying</type>, <type>character</type>,
     <type>varchar</type>, <type>date</type>, <type>double
     precision</type>, <type>integer</type>, <type>interval</type>,
     <type>numeric</type>, <type>decimal</type>, <type>real</type>,
@@ -654,10 +654,11 @@ NUMERIC
     </indexterm>
 
     <para>
-     The <type>serial</type> data types are not truly types, but are a
-     notational convenience for setting up unique identifier columns
-     in tables.
-     In the current implementation, specifying
+     The <type>serial</type> data type is not a true type, but merely
+     a notational convenience for setting up identifier columns
+     (similar to the <literal>AUTO_INCREMENT</literal> property
+     supported by some other databases). In the current
+     implementation, specifying
 
 <programlisting>
 CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
@@ -683,33 +684,50 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
      not automatic.
     </para>
 
+    <para>
+     To use a <type>serial</type> column to insert the next value of
+     the sequence into the table, specify that the <type>serial</type>
+     column should be assigned the default value. This can be done
+     either be excluding from the column from the list of columns in
+     the <command>INSERT</command> statement, or through the use of
+     the <literal>DEFAULT</literal> keyword.
+    </para>
+
     <para>
      The type names <type>serial</type> and <type>serial4</type> are
      equivalent: both create <type>integer</type> columns.  The type
      names <type>bigserial</type> and <type>serial8</type> work just
      the same way, except that they create a <type>bigint</type>
      column.  <type>bigserial</type> should be used if you anticipate
-     the use of more than 2<superscript>31</> identifiers over the lifetime of the table.
+     the use of more than 2<superscript>31</> identifiers over the
+     lifetime of the table.
     </para>
 
     <para>
-     The sequence created by a <type>serial</type> type is automatically
-     dropped when
-     the owning column is dropped, and cannot be dropped otherwise.
-     (This was not true in <productname>PostgreSQL</productname> releases
-     before 7.3.  Note that this automatic drop linkage will not occur for a
-     sequence created by reloading a dump from a pre-7.3 database; the dump
-     file does not contain the information needed to establish the dependency
-     link.)
+     The sequence created by a <type>serial</type> type is
+     automatically dropped when the owning column is dropped, and
+     cannot be dropped otherwise.  (This was not true in
+     <productname>PostgreSQL</productname> releases before 7.3.  Note
+     that this automatic drop linkage will not occur for a sequence
+     created by reloading a dump from a pre-7.3 database; the dump
+     file does not contain the information needed to establish the
+     dependency link.) Furthermore, this dependency between sequence
+     and column is made only for the <type>serial</> column itself; if
+     any other columns reference the sequence (perhaps by manually
+     calling the <function>nextval()</>) function), they may be broken
+     if the sequence is removed. Using <type>serial</> columns in
+     fashion is considered bad form.
     </para>
 
-    <note><para>
-     Prior to <productname>PostgreSQL</productname> 7.3, <type>serial</type>
-     implied <literal>UNIQUE</literal>.  This is no longer automatic.  If
-     you wish a serial column to be <literal>UNIQUE</literal> or a 
-     <literal>PRIMARY KEY</literal> it must now be specified, same as with
-     any other data type.
-    </para></note>
+    <note>
+     <para>
+      Prior to <productname>PostgreSQL</> 7.3, <type>serial</type>
+      implied <literal>UNIQUE</literal>.  This is no longer automatic.
+      If you wish a serial column to be <literal>UNIQUE</literal> or a
+      <literal>PRIMARY KEY</literal> it must now be specified, just as
+      with any other data type.
+     </para>
+    </note>
    </sect2>
   </sect1>
 
@@ -793,14 +811,14 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
        </row>
       </thead>
       <tbody>
-       <row>
-       <entry><type>character(<replaceable>n</>)</type>, <type>char(<replaceable>n</>)</type></entry>
-       <entry>fixed-length, blank padded</entry>
-       </row>
        <row>
        <entry><type>character varying(<replaceable>n</>)</type>, <type>varchar(<replaceable>n</>)</type></entry>
        <entry>variable-length with limit</entry>
        </row>
+       <row>
+       <entry><type>character(<replaceable>n</>)</type>, <type>char(<replaceable>n</>)</type></entry>
+       <entry>fixed-length, blank padded</entry>
+       </row>
        <row>
        <entry><type>text</type></entry>
        <entry>variable unlimited length</entry>
@@ -817,29 +835,29 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
 
    <para>
     <acronym>SQL</acronym> defines two primary character types:
-    <type>character(<replaceable>n</>)</type> and <type>character
-    varying(<replaceable>n</>)</type>, where <replaceable>n</> is a
-    positive integer.  Both of these types can store strings up to
+    <type>character varying(<replaceable>n</>)</type> and
+    <type>character(<replaceable>n</>)</type>, where <replaceable>n</>
+    is a positive integer.  Both of these types can store strings up to
     <replaceable>n</> characters in length.  An attempt to store a
     longer string into a column of these types will result in an
     error, unless the excess characters are all spaces, in which case
-    the string will be truncated to the maximum length.  (This
-    somewhat bizarre exception is required by the
-    <acronym>SQL</acronym> standard.)  If the string to be stored is
-    shorter than the declared length, values of type
-    <type>character</type> will be space-padded; values of type
-    <type>character varying</type> will simply store the shorter
+    the string will be truncated to the maximum length. (This somewhat
+    bizarre exception is required by the <acronym>SQL</acronym>
+    standard.) If the string to be stored is shorter than the declared
+    length, values of type <type>character</type> will be space-padded;
+    values of type <type>character varying</type> will simply store the
+    shorter
     string.
    </para>
 
    <note>
     <para>
-     If one explicitly casts a value to
-     <type>character(<replaceable>n</>)</type> or <type>character
-     varying(<replaceable>n</>)</type>, then an overlength value will
-     be truncated to <replaceable>n</> characters without raising an
-     error.  (This too is required by the <acronym>SQL</acronym>
-     standard.)
+     If one explicitly casts a value to <type>character
+     varying(<replaceable>n</>)</type> or
+     <type>character(<replaceable>n</>)</type>, then an over-length
+     value will be truncated to <replaceable>n</> characters without
+     raising an error. (This too is required by the
+     <acronym>SQL</acronym> standard.)
     </para>
    </note>
 
@@ -852,14 +870,14 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
    </note>
 
    <para>
-    The notations <type>char(<replaceable>n</>)</type> and
-    <type>varchar(<replaceable>n</>)</type> are aliases for
-    <type>character(<replaceable>n</>)</type> and <type>character
-    varying(<replaceable>n</>)</type>,
-    respectively. <type>character</type> without length specifier is
-    equivalent to <type>character(1)</type>; if <type>character
-    varying</type> is used without length specifier, the type accepts
-    strings of any size.  The latter is a <productname>PostgreSQL</> extension.
+    The notations <type>varchar(<replaceable>n</>)</type> and
+    <type>char(<replaceable>n</>)</type> are aliases for <type>character
+    varying(<replaceable>n</>)</type> and
+    <type>character(<replaceable>n</>)</type>, respectively.
+    <type>character</type> without length specifier is equivalent to
+    <type>character(1)</type>; if <type>character varying</type> is used
+    without length specifier, the type accepts strings of any size. The
+    latter is a <productname>PostgreSQL</> extension.
    </para>
 
    <para>
@@ -943,19 +961,18 @@ SELECT b, char_length(b) FROM test2;
 
    <para>
     There are two other fixed-length character types in
-    <productname>PostgreSQL</productname>, shown in <xref linkend="datatype-character-special-table">.
-    The <type>name</type> type
-    exists <emphasis>only</emphasis> for storage of internal catalog
-    names and is not intended for use by the general user.  Its length
-    is currently defined as 64 bytes (63 usable characters plus terminator)
-    but should be referenced using the constant
-    <symbol>NAMEDATALEN</symbol>.  The length is set at compile time
-    (and is therefore adjustable for special uses); the default
-    maximum length may change in a future release.  The type
-    <type>"char"</type> (note the quotes) is different from
-    <type>char(1)</type> in that it only uses one byte of storage.  It
-    is internally used in the system catalogs as a poor-man's
-    enumeration type.
+    <productname>PostgreSQL</productname>, shown in <xref
+    linkend="datatype-character-special-table">. The <type>name</type>
+    type exists <emphasis>only</emphasis> for storage of internal
+    catalog names and is not intended for use by the general user. Its
+    length is currently defined as 64 bytes (63 usable characters plus
+    terminator) but should be referenced using the constant
+    <symbol>NAMEDATALEN</symbol>. The length is set at compile time (and
+    is therefore adjustable for special uses); the default maximum
+    length may change in a future release. The type <type>"char"</type>
+    (note the quotes) is different from <type>char(1)</type> in that it
+    only uses one byte of storage. It is internally used in the system
+    catalogs as a poor-man's enumeration type.
    </para>
 
     <table id="datatype-character-special-table">
@@ -1280,8 +1297,7 @@ SELECT b, char_length(b) FROM test2;
     fractional digits retained in the seconds field. By default, there
     is no explicit bound on precision.  The allowed range of
     <replaceable>p</replaceable> is from 0 to 6 for the
-    <type>timestamp</type> and <type>interval</type> types, 0 to 13
-    for the <type>time</type> types.
+    <type>timestamp</type> and <type>interval</type> types.
    </para>
 
    <note>
@@ -1297,6 +1313,12 @@ SELECT b, char_length(b) FROM test2;
    </para>
    </note>
 
+   <para>
+    For the <type>time</type> types, the allowed range of
+    <replaceable>p</replaceable> is from 0 to 6 when eight-byte integer
+    storage is used, or from 0 to 10 when floating-point storage is used.
+   </para>
+
    <para>
     Time zones, and time-zone conventions, are influenced by
     political decisions, not just earth geometry. Time zones around the
@@ -1468,7 +1490,7 @@ SELECT b, char_length(b) FROM test2;
      <para>
       The <type>time</type> type can be specified as <type>time</type> or
       as <type>time without time zone</type>. The optional precision
-      <replaceable>p</replaceable> should be between 0 and 13, and
+      <replaceable>p</replaceable> should be between 0 and 6, and
       defaults to the precision of the input time literal.
      </para>
 
index 7f15784320caf7c57a45091bbee90e124db16e0b..f9d976ad65d6e1c062724bdfdf15d8094a92156a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.73.2.2 2003/01/09 01:07:17 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.73.2.3 2003/01/29 01:09:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -619,7 +619,7 @@ static void
 AdjustTimeForTypmod(TimeADT *time, int32 typmod)
 {
 #ifdef HAVE_INT64_TIMESTAMP
-       static const int64 TimeScales[MAX_TIMESTAMP_PRECISION + 1] = {
+       static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
                INT64CONST(1000000),
                INT64CONST(100000),
                INT64CONST(10000),
@@ -629,7 +629,7 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
                INT64CONST(1)
        };
 
-       static const int64 TimeOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
+       static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = {
                INT64CONST(500000),
                INT64CONST(50000),
                INT64CONST(5000),
@@ -640,14 +640,19 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
        };
 
 #else
-       static const double TimeScales[MAX_TIMESTAMP_PRECISION + 1] = {
+       /* note MAX_TIME_PRECISION differs in this case */
+       static const double TimeScales[MAX_TIME_PRECISION + 1] = {
                1,
                10,
                100,
                1000,
                10000,
                100000,
-               1000000
+               1000000,
+               10000000,
+               100000000,
+               1000000000,
+               10000000000
        };
 #endif
 
@@ -656,7 +661,7 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
                /*
                 * Note: this round-to-nearest code is not completely consistent
                 * about rounding values that are exactly halfway between integral
-                * values.  On most platforms, rint() will implement round-to-nearest,
+                * values.  On most platforms, rint() will implement round-to-nearest-even,
                 * but the integer code always rounds up (away from zero).  Is it
                 * worth trying to be consistent?
                 */
index 38655ceb5b138c46d0ca39764445fee22dc37529..b21c5f217d154f6e0a6cdaefd748bcad55332959 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.96.2.2 2003/01/16 00:27:17 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.96.2.3 2003/01/29 01:09:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -667,14 +667,13 @@ TrimTrailingZeros(char *str)
        }
 #endif
 
-       /* chop off trailing zeros... */
+       /* chop off trailing zeros... but leave at least 2 fractional digits */
        while ((*(str + len - 1) == '0')
                   && (*(str + len - 3) != '.'))
        {
                len--;
                *(str + len) = '\0';
        }
-       return;
 }
 
 
@@ -3145,33 +3144,22 @@ EncodeDateOnly(struct tm * tm, int style, char *str)
 int
 EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str)
 {
-#ifndef HAVE_INT64_TIMESTAMP
-       fsec_t          sec;
-#endif
-
        if ((tm->tm_hour < 0) || (tm->tm_hour > 24))
                return -1;
 
-#ifndef HAVE_INT64_TIMESTAMP
-       sec = (tm->tm_sec + fsec);
-#endif
-
        sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min);
 
        /*
-        * If we have fractional seconds, then include a decimal point We will
-        * do up to 6 fractional digits, and we have rounded any inputs to
-        * eliminate anything to the right of 6 digits anyway. If there are no
-        * fractional seconds, then do not bother printing a decimal point at
-        * all. - thomas 2001-09-29
+        * Print fractional seconds if any.  The field widths here should be
+        * at least equal to the larger of MAX_TIME_PRECISION and
+        * MAX_TIMESTAMP_PRECISION.
         */
        if (fsec != 0)
        {
 #ifdef HAVE_INT64_TIMESTAMP
-               sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
-               sprintf((str + strlen(str)), ".%06d", fsec);
+               sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
 #else
-               sprintf((str + strlen(str)), ":%013.10f", sec);
+               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)
@@ -3179,11 +3167,7 @@ EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str)
                        *(str + strlen(str) - 2) = '\0';
        }
        else
-#ifdef HAVE_INT64_TIMESTAMP
                sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
-#else
-               sprintf((str + strlen(str)), ":%02.0f", sec);
-#endif
 
        if (tzp != NULL)
        {
@@ -3217,20 +3201,12 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                                hour,
                                min;
 
-#ifndef HAVE_INT64_TIMESTAMP
-       fsec_t          sec;
-#endif
-
        /*
         * Why are we checking only the month field? Change this to an
         * assert... if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) return -1;
         */
        Assert((tm->tm_mon >= 1) && (tm->tm_mon <= 12));
 
-#ifndef HAVE_INT64_TIMESTAMP
-       sec = (tm->tm_sec + fsec);
-#endif
-
        switch (style)
        {
                case USE_ISO_DATES:
@@ -3241,21 +3217,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                                        tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
 
                        /*
-                        * If we have fractional seconds, then include a decimal point
-                        * We will do up to 6 fractional digits, and we have rounded
-                        * any inputs to eliminate anything to the right of 6 digits
-                        * anyway. If there are no fractional seconds, then do not
-                        * bother printing a decimal point at all. - thomas 2001-09-29
+                        * Print fractional seconds if any.  The field widths here should
+                        * be at least equal to MAX_TIMESTAMP_PRECISION.
+                        *
+                        * In float mode, don't print fractional seconds before 1 AD,
+                        * since it's unlikely there's any precision left ...
                         */
 #ifdef HAVE_INT64_TIMESTAMP
                        if (fsec != 0)
                        {
-                               sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
-                               sprintf((str + strlen(str)), ".%06d", fsec);
+                               sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
 #else
                        if ((fsec != 0) && (tm->tm_year > 0))
                        {
-                               sprintf((str + strlen(str)), ":%013.10f", sec);
+                               sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);
 #endif
                                TrimTrailingZeros(str);
                        }
@@ -3292,21 +3267,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                                        tm->tm_hour, tm->tm_min);
 
                        /*
-                        * If we have fractional seconds, then include a decimal point
-                        * We will do up to 6 fractional digits, and we have rounded
-                        * any inputs to eliminate anything to the right of 6 digits
-                        * anyway. If there are no fractional seconds, then do not
-                        * bother printing a decimal point at all. - thomas 2001-09-29
+                        * Print fractional seconds if any.  The field widths here should
+                        * be at least equal to MAX_TIMESTAMP_PRECISION.
+                        *
+                        * In float mode, don't print fractional seconds before 1 AD,
+                        * since it's unlikely there's any precision left ...
                         */
 #ifdef HAVE_INT64_TIMESTAMP
                        if (fsec != 0)
                        {
-                               sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
-                               sprintf((str + strlen(str)), ".%06d", fsec);
+                               sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
 #else
                        if ((fsec != 0) && (tm->tm_year > 0))
                        {
-                               sprintf((str + strlen(str)), ":%013.10f", sec);
+                               sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);
 #endif
                                TrimTrailingZeros(str);
                        }
@@ -3339,21 +3313,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                                        tm->tm_hour, tm->tm_min);
 
                        /*
-                        * If we have fractional seconds, then include a decimal point
-                        * We will do up to 6 fractional digits, and we have rounded
-                        * any inputs to eliminate anything to the right of 6 digits
-                        * anyway. If there are no fractional seconds, then do not
-                        * bother printing a decimal point at all. - thomas 2001-09-29
+                        * Print fractional seconds if any.  The field widths here should
+                        * be at least equal to MAX_TIMESTAMP_PRECISION.
+                        *
+                        * In float mode, don't print fractional seconds before 1 AD,
+                        * since it's unlikely there's any precision left ...
                         */
 #ifdef HAVE_INT64_TIMESTAMP
                        if (fsec != 0)
                        {
-                               sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
-                               sprintf((str + strlen(str)), ".%06d", fsec);
+                               sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
 #else
                        if ((fsec != 0) && (tm->tm_year > 0))
                        {
-                               sprintf((str + strlen(str)), ":%013.10f", sec);
+                               sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);
 #endif
                                TrimTrailingZeros(str);
                        }
@@ -3394,21 +3367,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                        sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min);
 
                        /*
-                        * If we have fractional seconds, then include a decimal point
-                        * We will do up to 6 fractional digits, and we have rounded
-                        * any inputs to eliminate anything to the right of 6 digits
-                        * anyway. If there are no fractional seconds, then do not
-                        * bother printing a decimal point at all. - thomas 2001-09-29
+                        * Print fractional seconds if any.  The field widths here should
+                        * be at least equal to MAX_TIMESTAMP_PRECISION.
+                        *
+                        * In float mode, don't print fractional seconds before 1 AD,
+                        * since it's unlikely there's any precision left ...
                         */
 #ifdef HAVE_INT64_TIMESTAMP
                        if (fsec != 0)
                        {
-                               sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
-                               sprintf((str + strlen(str)), ".%06d", fsec);
+                               sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
 #else
                        if ((fsec != 0) && (tm->tm_year > 0))
                        {
-                               sprintf((str + strlen(str)), ":%013.10f", sec);
+                               sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);
 #endif
                                TrimTrailingZeros(str);
                        }
index eaaac77c16a34973b712096598950fa93d0f4aa7..4b3edd0b98a9163f715c03ae3f127126847dce5f 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: date.h,v 1.21 2002/09/04 20:31:45 momjian Exp $
+ * $Id: date.h,v 1.21.2.1 2003/01/29 01:09:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -41,7 +41,7 @@ typedef struct
 #ifdef HAVE_INT64_TIMESTAMP
 #define MAX_TIME_PRECISION 6
 #else
-#define MAX_TIME_PRECISION 13
+#define MAX_TIME_PRECISION 10
 #endif
 
 /*