mirror of
https://github.com/postgres/postgres.git
synced 2025-09-11 00:12:06 +03:00
Repair array subscript overrun identified by Yichen Xie. Reduce the
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.)
This commit is contained in:
@@ -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">
|
<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>
|
<entry>binary data</entry>
|
||||||
</row>
|
</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>
|
<row>
|
||||||
<entry><type>character varying(<replaceable>n</replaceable>)</type></entry>
|
<entry><type>character varying(<replaceable>n</replaceable>)</type></entry>
|
||||||
<entry><type>varchar(<replaceable>n</replaceable>)</type></entry>
|
<entry><type>varchar(<replaceable>n</replaceable>)</type></entry>
|
||||||
<entry>variable-length character string</entry>
|
<entry>variable-length character string</entry>
|
||||||
</row>
|
</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>
|
<row>
|
||||||
<entry><type>cidr</type></entry>
|
<entry><type>cidr</type></entry>
|
||||||
<entry></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
|
The following types (or spellings thereof) are specified by
|
||||||
<acronym>SQL</acronym>: <type>bit</type>, <type>bit
|
<acronym>SQL</acronym>: <type>bit</type>, <type>bit
|
||||||
varying</type>, <type>boolean</type>, <type>char</type>,
|
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
|
<type>varchar</type>, <type>date</type>, <type>double
|
||||||
precision</type>, <type>integer</type>, <type>interval</type>,
|
precision</type>, <type>integer</type>, <type>interval</type>,
|
||||||
<type>numeric</type>, <type>decimal</type>, <type>real</type>,
|
<type>numeric</type>, <type>decimal</type>, <type>real</type>,
|
||||||
@@ -654,10 +654,11 @@ NUMERIC
|
|||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <type>serial</type> data types are not truly types, but are a
|
The <type>serial</type> data type is not a true type, but merely
|
||||||
notational convenience for setting up unique identifier columns
|
a notational convenience for setting up identifier columns
|
||||||
in tables.
|
(similar to the <literal>AUTO_INCREMENT</literal> property
|
||||||
In the current implementation, specifying
|
supported by some other databases). In the current
|
||||||
|
implementation, specifying
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
|
CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
|
||||||
@@ -683,33 +684,50 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
|
|||||||
not automatic.
|
not automatic.
|
||||||
</para>
|
</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>
|
<para>
|
||||||
The type names <type>serial</type> and <type>serial4</type> are
|
The type names <type>serial</type> and <type>serial4</type> are
|
||||||
equivalent: both create <type>integer</type> columns. The type
|
equivalent: both create <type>integer</type> columns. The type
|
||||||
names <type>bigserial</type> and <type>serial8</type> work just
|
names <type>bigserial</type> and <type>serial8</type> work just
|
||||||
the same way, except that they create a <type>bigint</type>
|
the same way, except that they create a <type>bigint</type>
|
||||||
column. <type>bigserial</type> should be used if you anticipate
|
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>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The sequence created by a <type>serial</type> type is automatically
|
The sequence created by a <type>serial</type> type is
|
||||||
dropped when
|
automatically dropped when the owning column is dropped, and
|
||||||
the owning column is dropped, and cannot be dropped otherwise.
|
cannot be dropped otherwise. (This was not true in
|
||||||
(This was not true in <productname>PostgreSQL</productname> releases
|
<productname>PostgreSQL</productname> releases before 7.3. Note
|
||||||
before 7.3. Note that this automatic drop linkage will not occur for a
|
that this automatic drop linkage will not occur for a sequence
|
||||||
sequence created by reloading a dump from a pre-7.3 database; the dump
|
created by reloading a dump from a pre-7.3 database; the dump
|
||||||
file does not contain the information needed to establish the dependency
|
file does not contain the information needed to establish the
|
||||||
link.)
|
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>
|
</para>
|
||||||
|
|
||||||
<note><para>
|
<note>
|
||||||
Prior to <productname>PostgreSQL</productname> 7.3, <type>serial</type>
|
<para>
|
||||||
implied <literal>UNIQUE</literal>. This is no longer automatic. If
|
Prior to <productname>PostgreSQL</> 7.3, <type>serial</type>
|
||||||
you wish a serial column to be <literal>UNIQUE</literal> or a
|
implied <literal>UNIQUE</literal>. This is no longer automatic.
|
||||||
<literal>PRIMARY KEY</literal> it must now be specified, same as with
|
If you wish a serial column to be <literal>UNIQUE</literal> or a
|
||||||
any other data type.
|
<literal>PRIMARY KEY</literal> it must now be specified, just as
|
||||||
</para></note>
|
with any other data type.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
@@ -793,14 +811,14 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
|
|||||||
</row>
|
</row>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
|
||||||
<entry><type>character(<replaceable>n</>)</type>, <type>char(<replaceable>n</>)</type></entry>
|
|
||||||
<entry>fixed-length, blank padded</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
<row>
|
||||||
<entry><type>character varying(<replaceable>n</>)</type>, <type>varchar(<replaceable>n</>)</type></entry>
|
<entry><type>character varying(<replaceable>n</>)</type>, <type>varchar(<replaceable>n</>)</type></entry>
|
||||||
<entry>variable-length with limit</entry>
|
<entry>variable-length with limit</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><type>character(<replaceable>n</>)</type>, <type>char(<replaceable>n</>)</type></entry>
|
||||||
|
<entry>fixed-length, blank padded</entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><type>text</type></entry>
|
<entry><type>text</type></entry>
|
||||||
<entry>variable unlimited length</entry>
|
<entry>variable unlimited length</entry>
|
||||||
@@ -817,29 +835,29 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
<acronym>SQL</acronym> defines two primary character types:
|
<acronym>SQL</acronym> defines two primary character types:
|
||||||
<type>character(<replaceable>n</>)</type> and <type>character
|
<type>character varying(<replaceable>n</>)</type> and
|
||||||
varying(<replaceable>n</>)</type>, where <replaceable>n</> is a
|
<type>character(<replaceable>n</>)</type>, where <replaceable>n</>
|
||||||
positive integer. Both of these types can store strings up to
|
is a positive integer. Both of these types can store strings up to
|
||||||
<replaceable>n</> characters in length. An attempt to store a
|
<replaceable>n</> characters in length. An attempt to store a
|
||||||
longer string into a column of these types will result in an
|
longer string into a column of these types will result in an
|
||||||
error, unless the excess characters are all spaces, in which case
|
error, unless the excess characters are all spaces, in which case
|
||||||
the string will be truncated to the maximum length. (This
|
the string will be truncated to the maximum length. (This somewhat
|
||||||
somewhat bizarre exception is required by the
|
bizarre exception is required by the <acronym>SQL</acronym>
|
||||||
<acronym>SQL</acronym> standard.) If the string to be stored is
|
standard.) If the string to be stored is shorter than the declared
|
||||||
shorter than the declared length, values of type
|
length, values of type <type>character</type> will be space-padded;
|
||||||
<type>character</type> will be space-padded; values of type
|
values of type <type>character varying</type> will simply store the
|
||||||
<type>character varying</type> will simply store the shorter
|
shorter
|
||||||
string.
|
string.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
If one explicitly casts a value to
|
If one explicitly casts a value to <type>character
|
||||||
<type>character(<replaceable>n</>)</type> or <type>character
|
varying(<replaceable>n</>)</type> or
|
||||||
varying(<replaceable>n</>)</type>, then an overlength value will
|
<type>character(<replaceable>n</>)</type>, then an over-length
|
||||||
be truncated to <replaceable>n</> characters without raising an
|
value will be truncated to <replaceable>n</> characters without
|
||||||
error. (This too is required by the <acronym>SQL</acronym>
|
raising an error. (This too is required by the
|
||||||
standard.)
|
<acronym>SQL</acronym> standard.)
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
@@ -852,14 +870,14 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
|
|||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The notations <type>char(<replaceable>n</>)</type> and
|
The notations <type>varchar(<replaceable>n</>)</type> and
|
||||||
<type>varchar(<replaceable>n</>)</type> are aliases for
|
<type>char(<replaceable>n</>)</type> are aliases for <type>character
|
||||||
<type>character(<replaceable>n</>)</type> and <type>character
|
varying(<replaceable>n</>)</type> and
|
||||||
varying(<replaceable>n</>)</type>,
|
<type>character(<replaceable>n</>)</type>, respectively.
|
||||||
respectively. <type>character</type> without length specifier is
|
<type>character</type> without length specifier is equivalent to
|
||||||
equivalent to <type>character(1)</type>; if <type>character
|
<type>character(1)</type>; if <type>character varying</type> is used
|
||||||
varying</type> is used without length specifier, the type accepts
|
without length specifier, the type accepts strings of any size. The
|
||||||
strings of any size. The latter is a <productname>PostgreSQL</> extension.
|
latter is a <productname>PostgreSQL</> extension.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -943,19 +961,18 @@ SELECT b, char_length(b) FROM test2;
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
There are two other fixed-length character types in
|
There are two other fixed-length character types in
|
||||||
<productname>PostgreSQL</productname>, shown in <xref linkend="datatype-character-special-table">.
|
<productname>PostgreSQL</productname>, shown in <xref
|
||||||
The <type>name</type> type
|
linkend="datatype-character-special-table">. The <type>name</type>
|
||||||
exists <emphasis>only</emphasis> for storage of internal catalog
|
type exists <emphasis>only</emphasis> for storage of internal
|
||||||
names and is not intended for use by the general user. Its length
|
catalog names and is not intended for use by the general user. Its
|
||||||
is currently defined as 64 bytes (63 usable characters plus terminator)
|
length is currently defined as 64 bytes (63 usable characters plus
|
||||||
but should be referenced using the constant
|
terminator) but should be referenced using the constant
|
||||||
<symbol>NAMEDATALEN</symbol>. The length is set at compile time
|
<symbol>NAMEDATALEN</symbol>. The length is set at compile time (and
|
||||||
(and is therefore adjustable for special uses); the default
|
is therefore adjustable for special uses); the default maximum
|
||||||
maximum length may change in a future release. The type
|
length may change in a future release. The type <type>"char"</type>
|
||||||
<type>"char"</type> (note the quotes) is different from
|
(note the quotes) is different from <type>char(1)</type> in that it
|
||||||
<type>char(1)</type> in that it only uses one byte of storage. It
|
only uses one byte of storage. It is internally used in the system
|
||||||
is internally used in the system catalogs as a poor-man's
|
catalogs as a poor-man's enumeration type.
|
||||||
enumeration type.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<table id="datatype-character-special-table">
|
<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
|
fractional digits retained in the seconds field. By default, there
|
||||||
is no explicit bound on precision. The allowed range of
|
is no explicit bound on precision. The allowed range of
|
||||||
<replaceable>p</replaceable> is from 0 to 6 for the
|
<replaceable>p</replaceable> is from 0 to 6 for the
|
||||||
<type>timestamp</type> and <type>interval</type> types, 0 to 13
|
<type>timestamp</type> and <type>interval</type> types.
|
||||||
for the <type>time</type> types.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
@@ -1297,6 +1313,12 @@ SELECT b, char_length(b) FROM test2;
|
|||||||
</para>
|
</para>
|
||||||
</note>
|
</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>
|
<para>
|
||||||
Time zones, and time-zone conventions, are influenced by
|
Time zones, and time-zone conventions, are influenced by
|
||||||
political decisions, not just earth geometry. Time zones around the
|
political decisions, not just earth geometry. Time zones around the
|
||||||
@@ -1468,7 +1490,7 @@ SELECT b, char_length(b) FROM test2;
|
|||||||
<para>
|
<para>
|
||||||
The <type>time</type> type can be specified as <type>time</type> or
|
The <type>time</type> type can be specified as <type>time</type> or
|
||||||
as <type>time without time zone</type>. The optional precision
|
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.
|
defaults to the precision of the input time literal.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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)
|
AdjustTimeForTypmod(TimeADT *time, int32 typmod)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
static const int64 TimeScales[MAX_TIMESTAMP_PRECISION + 1] = {
|
static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
|
||||||
INT64CONST(1000000),
|
INT64CONST(1000000),
|
||||||
INT64CONST(100000),
|
INT64CONST(100000),
|
||||||
INT64CONST(10000),
|
INT64CONST(10000),
|
||||||
@@ -629,7 +629,7 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
|
|||||||
INT64CONST(1)
|
INT64CONST(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int64 TimeOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
|
static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = {
|
||||||
INT64CONST(500000),
|
INT64CONST(500000),
|
||||||
INT64CONST(50000),
|
INT64CONST(50000),
|
||||||
INT64CONST(5000),
|
INT64CONST(5000),
|
||||||
@@ -640,14 +640,19 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
|
|||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#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,
|
1,
|
||||||
10,
|
10,
|
||||||
100,
|
100,
|
||||||
1000,
|
1000,
|
||||||
10000,
|
10000,
|
||||||
100000,
|
100000,
|
||||||
1000000
|
1000000,
|
||||||
|
10000000,
|
||||||
|
100000000,
|
||||||
|
1000000000,
|
||||||
|
10000000000
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -656,7 +661,7 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
|
|||||||
/*
|
/*
|
||||||
* Note: this round-to-nearest code is not completely consistent
|
* Note: this round-to-nearest code is not completely consistent
|
||||||
* about rounding values that are exactly halfway between integral
|
* 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
|
* but the integer code always rounds up (away from zero). Is it
|
||||||
* worth trying to be consistent?
|
* worth trying to be consistent?
|
||||||
*/
|
*/
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
#endif
|
||||||
|
|
||||||
/* chop off trailing zeros... */
|
/* chop off trailing zeros... but leave at least 2 fractional digits */
|
||||||
while ((*(str + len - 1) == '0')
|
while ((*(str + len - 1) == '0')
|
||||||
&& (*(str + len - 3) != '.'))
|
&& (*(str + len - 3) != '.'))
|
||||||
{
|
{
|
||||||
len--;
|
len--;
|
||||||
*(str + len) = '\0';
|
*(str + len) = '\0';
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3145,33 +3144,22 @@ EncodeDateOnly(struct tm * tm, int style, char *str)
|
|||||||
int
|
int
|
||||||
EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str)
|
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))
|
if ((tm->tm_hour < 0) || (tm->tm_hour > 24))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifndef HAVE_INT64_TIMESTAMP
|
|
||||||
sec = (tm->tm_sec + fsec);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min);
|
sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have fractional seconds, then include a decimal point We will
|
* Print fractional seconds if any. The field widths here should be
|
||||||
* do up to 6 fractional digits, and we have rounded any inputs to
|
* at least equal to the larger of MAX_TIME_PRECISION and
|
||||||
* eliminate anything to the right of 6 digits anyway. If there are no
|
* MAX_TIMESTAMP_PRECISION.
|
||||||
* fractional seconds, then do not bother printing a decimal point at
|
|
||||||
* all. - thomas 2001-09-29
|
|
||||||
*/
|
*/
|
||||||
if (fsec != 0)
|
if (fsec != 0)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
|
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
|
||||||
sprintf((str + strlen(str)), ".%06d", fsec);
|
|
||||||
#else
|
#else
|
||||||
sprintf((str + strlen(str)), ":%013.10f", sec);
|
sprintf((str + strlen(str)), ":%013.10f", tm->tm_sec + fsec);
|
||||||
#endif
|
#endif
|
||||||
/* chop off trailing pairs of zeros... */
|
/* chop off trailing pairs of zeros... */
|
||||||
while ((strcmp((str + strlen(str) - 2), "00") == 0)
|
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';
|
*(str + strlen(str) - 2) = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
|
||||||
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
|
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
|
||||||
#else
|
|
||||||
sprintf((str + strlen(str)), ":%02.0f", sec);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (tzp != NULL)
|
if (tzp != NULL)
|
||||||
{
|
{
|
||||||
@@ -3217,20 +3201,12 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
|
|||||||
hour,
|
hour,
|
||||||
min;
|
min;
|
||||||
|
|
||||||
#ifndef HAVE_INT64_TIMESTAMP
|
|
||||||
fsec_t sec;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Why are we checking only the month field? Change this to an
|
* 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... if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) return -1;
|
||||||
*/
|
*/
|
||||||
Assert((tm->tm_mon >= 1) && (tm->tm_mon <= 12));
|
Assert((tm->tm_mon >= 1) && (tm->tm_mon <= 12));
|
||||||
|
|
||||||
#ifndef HAVE_INT64_TIMESTAMP
|
|
||||||
sec = (tm->tm_sec + fsec);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (style)
|
switch (style)
|
||||||
{
|
{
|
||||||
case USE_ISO_DATES:
|
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);
|
tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have fractional seconds, then include a decimal point
|
* Print fractional seconds if any. The field widths here should
|
||||||
* We will do up to 6 fractional digits, and we have rounded
|
* be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||||
* any inputs to eliminate anything to the right of 6 digits
|
*
|
||||||
* anyway. If there are no fractional seconds, then do not
|
* In float mode, don't print fractional seconds before 1 AD,
|
||||||
* bother printing a decimal point at all. - thomas 2001-09-29
|
* since it's unlikely there's any precision left ...
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
if (fsec != 0)
|
if (fsec != 0)
|
||||||
{
|
{
|
||||||
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
|
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
|
||||||
sprintf((str + strlen(str)), ".%06d", fsec);
|
|
||||||
#else
|
#else
|
||||||
if ((fsec != 0) && (tm->tm_year > 0))
|
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
|
#endif
|
||||||
TrimTrailingZeros(str);
|
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);
|
tm->tm_hour, tm->tm_min);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have fractional seconds, then include a decimal point
|
* Print fractional seconds if any. The field widths here should
|
||||||
* We will do up to 6 fractional digits, and we have rounded
|
* be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||||
* any inputs to eliminate anything to the right of 6 digits
|
*
|
||||||
* anyway. If there are no fractional seconds, then do not
|
* In float mode, don't print fractional seconds before 1 AD,
|
||||||
* bother printing a decimal point at all. - thomas 2001-09-29
|
* since it's unlikely there's any precision left ...
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
if (fsec != 0)
|
if (fsec != 0)
|
||||||
{
|
{
|
||||||
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
|
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
|
||||||
sprintf((str + strlen(str)), ".%06d", fsec);
|
|
||||||
#else
|
#else
|
||||||
if ((fsec != 0) && (tm->tm_year > 0))
|
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
|
#endif
|
||||||
TrimTrailingZeros(str);
|
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);
|
tm->tm_hour, tm->tm_min);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have fractional seconds, then include a decimal point
|
* Print fractional seconds if any. The field widths here should
|
||||||
* We will do up to 6 fractional digits, and we have rounded
|
* be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||||
* any inputs to eliminate anything to the right of 6 digits
|
*
|
||||||
* anyway. If there are no fractional seconds, then do not
|
* In float mode, don't print fractional seconds before 1 AD,
|
||||||
* bother printing a decimal point at all. - thomas 2001-09-29
|
* since it's unlikely there's any precision left ...
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
if (fsec != 0)
|
if (fsec != 0)
|
||||||
{
|
{
|
||||||
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
|
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
|
||||||
sprintf((str + strlen(str)), ".%06d", fsec);
|
|
||||||
#else
|
#else
|
||||||
if ((fsec != 0) && (tm->tm_year > 0))
|
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
|
#endif
|
||||||
TrimTrailingZeros(str);
|
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);
|
sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have fractional seconds, then include a decimal point
|
* Print fractional seconds if any. The field widths here should
|
||||||
* We will do up to 6 fractional digits, and we have rounded
|
* be at least equal to MAX_TIMESTAMP_PRECISION.
|
||||||
* any inputs to eliminate anything to the right of 6 digits
|
*
|
||||||
* anyway. If there are no fractional seconds, then do not
|
* In float mode, don't print fractional seconds before 1 AD,
|
||||||
* bother printing a decimal point at all. - thomas 2001-09-29
|
* since it's unlikely there's any precision left ...
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
if (fsec != 0)
|
if (fsec != 0)
|
||||||
{
|
{
|
||||||
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
|
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
|
||||||
sprintf((str + strlen(str)), ".%06d", fsec);
|
|
||||||
#else
|
#else
|
||||||
if ((fsec != 0) && (tm->tm_year > 0))
|
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
|
#endif
|
||||||
TrimTrailingZeros(str);
|
TrimTrailingZeros(str);
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
#define MAX_TIME_PRECISION 6
|
#define MAX_TIME_PRECISION 6
|
||||||
#else
|
#else
|
||||||
#define MAX_TIME_PRECISION 13
|
#define MAX_TIME_PRECISION 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user