mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in operator/function resolution. Introduce a well-defined promotion hierarchy for numeric datatypes (int2->int4->int8->numeric->float4->float8). Change make_const to initially label numeric literals as int4, int8, or numeric (never float8 anymore). Explicitly mark Func and RelabelType nodes to indicate whether they came from a function call, explicit cast, or implicit cast; use this to do reverse-listing more accurately and without so many heuristics. Explicit casts to char, varchar, bit, varbit will truncate or pad without raising an error (the pre-7.2 behavior), while assigning to a column without any explicit cast will still raise an error for wrong-length data like 7.3. This more nearly follows the SQL spec than 7.2 behavior (we should be reporting a 'completion condition' in the explicit-cast cases, but we have no mechanism for that, so just do silent truncation). Fix some problems with enforcement of typmod for array elements; it didn't work at all in 'UPDATE ... SET array[n] = foo', for example. Provide a generalized array_length_coerce() function to replace the specialized per-array-type functions that used to be needed (and were missing for NUMERIC as well as all the datetime types). Add missing conversions int8<->float4, text<->numeric, oid<->int8. initdb forced.
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
<!--
|
||||
Documentation of the system catalogs, directed toward PostgreSQL developers
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.59 2002/09/03 01:04:40 tgl Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.60 2002/09/18 21:35:20 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="catalogs">
|
||||
@ -841,9 +841,8 @@
|
||||
<title>pg_cast</title>
|
||||
|
||||
<para>
|
||||
<structname>pg_cast</structname> stores data type conversion paths
|
||||
defined with <command>CREATE CAST</command> plus the built-in
|
||||
conversions.
|
||||
<structname>pg_cast</structname> stores data type conversion paths,
|
||||
both built-in paths and those defined with <command>CREATE CAST</command>.
|
||||
</para>
|
||||
|
||||
<table>
|
||||
@ -879,17 +878,25 @@
|
||||
<entry><type>oid</type></entry>
|
||||
<entry>pg_proc.oid</entry>
|
||||
<entry>
|
||||
The OID of the function to use to perform this cast. A 0 is
|
||||
stored if the data types are binary compatible (that is, no
|
||||
function is needed to perform the cast).
|
||||
The OID of the function to use to perform this cast. Zero is
|
||||
stored if the data types are binary coercible (that is, no
|
||||
run-time operation is needed to perform the cast).
|
||||
</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>castimplicit</entry>
|
||||
<entry><type>bool</type></entry>
|
||||
<entry>castcontext</entry>
|
||||
<entry><type>char</type></entry>
|
||||
<entry></entry>
|
||||
<entry>Indication whether this cast can be invoked implicitly</entry>
|
||||
<entry>
|
||||
Indicates what contexts the cast may be invoked in.
|
||||
<literal>e</> means only as an explicit cast (using
|
||||
<literal>CAST</>, <literal>::</>, or function-call syntax).
|
||||
<literal>a</> means implicitly in assignment
|
||||
to a target column, as well as explicitly.
|
||||
<literal>i</> means implicitly in expressions, as well as the
|
||||
other cases.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.102 2002/08/23 02:54:18 momjian Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.103 2002/09/18 21:35:20 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="datatype">
|
||||
@ -823,8 +823,19 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Prior to <productname>PostgreSQL</> 7.2, strings that were too long were silently
|
||||
truncated, no error was raised.
|
||||
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 SQL standard.)
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Prior to <productname>PostgreSQL</> 7.2, strings that were too long were
|
||||
always truncated without raising an error, in either explicit or
|
||||
implicit casting contexts.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
@ -897,12 +908,14 @@ INSERT INTO test2 VALUES ('ok');
|
||||
INSERT INTO test2 VALUES ('good ');
|
||||
INSERT INTO test2 VALUES ('too long');
|
||||
<computeroutput>ERROR: value too long for type character varying(5)</computeroutput>
|
||||
INSERT INTO test2 VALUES ('too long'::varchar(5)); -- explicit truncation
|
||||
SELECT b, char_length(b) FROM test2;
|
||||
<computeroutput>
|
||||
b | char_length
|
||||
-------+-------------
|
||||
ok | 2
|
||||
good | 5
|
||||
too l | 5
|
||||
</computeroutput>
|
||||
</programlisting>
|
||||
<calloutlist>
|
||||
@ -932,7 +945,7 @@ SELECT b, char_length(b) FROM test2;
|
||||
</para>
|
||||
|
||||
<table tocentry="1">
|
||||
<title>Specialty Character Type</title>
|
||||
<title>Specialty Character Types</title>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
@ -2832,29 +2845,39 @@ SELECT * FROM test1 WHERE a;
|
||||
<para>
|
||||
Bit strings are strings of 1's and 0's. They can be used to store
|
||||
or visualize bit masks. There are two SQL bit types:
|
||||
<type>BIT(<replaceable>x</replaceable>)</type> and <type>BIT
|
||||
VARYING(<replaceable>x</replaceable>)</type>; where
|
||||
<replaceable>x</replaceable> is a positive integer.
|
||||
<type>BIT(<replaceable>n</replaceable>)</type> and <type>BIT
|
||||
VARYING(<replaceable>n</replaceable>)</type>, where
|
||||
<replaceable>n</replaceable> is a positive integer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<type>BIT</type> type data must match the length
|
||||
<replaceable>x</replaceable> exactly; it is an error to attempt to
|
||||
store shorter or longer bit strings. <type>BIT VARYING</type> is
|
||||
<replaceable>n</replaceable> exactly; it is an error to attempt to
|
||||
store shorter or longer bit strings. <type>BIT VARYING</type> data is
|
||||
of variable length up to the maximum length
|
||||
<replaceable>x</replaceable>; longer strings will be rejected.
|
||||
<type>BIT</type> without length is equivalent to
|
||||
<literal>BIT(1)</literal>, <type>BIT VARYING</type> without length
|
||||
<replaceable>n</replaceable>; longer strings will be rejected.
|
||||
Writing <type>BIT</type> without a length is equivalent to
|
||||
<literal>BIT(1)</literal>, while <type>BIT VARYING</type> without a length
|
||||
specification means unlimited length.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Prior to <productname>PostgreSQL</> 7.2, <type>BIT</type> type data was
|
||||
zero-padded on the right. This was changed to comply with the
|
||||
SQL standard. To implement zero-padded bit strings, a
|
||||
combination of the concatenation operator and the
|
||||
<function>substring</function> function can be used.
|
||||
If one explicitly casts a bit-string value to
|
||||
<type>BIT(<replaceable>n</>)</type>, it will be truncated or
|
||||
zero-padded on the right to be exactly <replaceable>n</> bits,
|
||||
without raising an error. Similarly,
|
||||
if one explicitly casts a bit-string value to
|
||||
<type>BIT VARYING(<replaceable>n</>)</type>, it will be truncated
|
||||
on the right if it is more than <replaceable>n</> bits.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Prior to <productname>PostgreSQL</> 7.2, <type>BIT</type> data was
|
||||
always silently truncated or zero-padded on the right, with or without an
|
||||
explicit cast. This was changed to comply with the SQL standard.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
@ -2874,9 +2897,16 @@ CREATE TABLE test (a BIT(3), b BIT VARYING(5));
|
||||
INSERT INTO test VALUES (B'101', B'00');
|
||||
INSERT INTO test VALUES (B'10', B'101');
|
||||
<computeroutput>
|
||||
ERROR: bit string length does not match type bit(3)
|
||||
ERROR: Bit string length 2 does not match type BIT(3)
|
||||
</computeroutput>
|
||||
INSERT INTO test VALUES (B'10'::bit(3), B'101');
|
||||
SELECT * FROM test;
|
||||
<computeroutput>
|
||||
a | b
|
||||
-----+-----
|
||||
101 | 00
|
||||
100 | 101
|
||||
</computeroutput>
|
||||
SELECT SUBSTRING(b FROM 1 FOR 2) FROM test;
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.4 2002/09/15 13:04:16 petere Exp $ -->
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.5 2002/09/18 21:35:20 tgl Exp $ -->
|
||||
|
||||
<refentry id="SQL-CREATECAST">
|
||||
<refmeta>
|
||||
@ -15,11 +15,11 @@
|
||||
<synopsis>
|
||||
CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
|
||||
WITH FUNCTION <replaceable>funcname</replaceable> (<replaceable>argtype</replaceable>)
|
||||
[AS ASSIGNMENT]
|
||||
[ AS ASSIGNMENT | AS IMPLICIT ]
|
||||
|
||||
CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
|
||||
WITHOUT FUNCTION
|
||||
[AS ASSIGNMENT]
|
||||
[ AS ASSIGNMENT | AS IMPLICIT ]
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@ -49,20 +49,44 @@ SELECT CAST(42 AS text);
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A cast can be marked <literal>AS ASSIGNMENT</>, which means that it
|
||||
can be invoked implicitly in any context where the conversion it
|
||||
defines is required. Cast functions not so marked can be invoked
|
||||
only by explicit <literal>CAST</>,
|
||||
By default, a cast can be invoked only by an explicit cast request,
|
||||
that is an explicit <literal>CAST(<replaceable>x</> AS
|
||||
<replaceable>typename</>)</literal>,
|
||||
<replaceable>x</><literal>::</><replaceable>typename</>, or
|
||||
<replaceable>typename</>(<replaceable>x</>) constructs. For
|
||||
example, supposing that <literal>foo.f1</literal> is a column of
|
||||
<replaceable>typename</>(<replaceable>x</>) construct.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the cast is marked <literal>AS ASSIGNMENT</> then it can be invoked
|
||||
implicitly when assigning to a column of the target data type.
|
||||
For example, supposing that <literal>foo.f1</literal> is a column of
|
||||
type <type>text</type>, then
|
||||
<programlisting>
|
||||
INSERT INTO foo(f1) VALUES(42);
|
||||
</programlisting>
|
||||
will be allowed if the cast from type <type>integer</type> to type
|
||||
<type>text</type> is marked <literal>AS ASSIGNMENT</>, otherwise
|
||||
not. (We generally use the term <firstterm>implicit
|
||||
not.
|
||||
(We generally use the term <firstterm>assignment
|
||||
cast</firstterm> to describe this kind of cast.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the cast is marked <literal>AS IMPLICIT</> then it can be invoked
|
||||
implicitly in any context, whether assignment or internally in an
|
||||
expression. For example, since <literal>||</> takes <type>text</>
|
||||
arguments,
|
||||
<programlisting>
|
||||
SELECT 'The time is ' || now();
|
||||
</programlisting>
|
||||
will be allowed only if the cast from type <type>timestamp</> to
|
||||
<type>text</type> is marked <literal>AS IMPLICIT</>. Otherwise it
|
||||
will be necessary to write one of
|
||||
<programlisting>
|
||||
SELECT 'The time is ' || CAST(now() AS text);
|
||||
SELECT 'The time is ' || now()::text;
|
||||
</programlisting>
|
||||
(We generally use the term <firstterm>implicit
|
||||
cast</firstterm> to describe this kind of cast.)
|
||||
</para>
|
||||
|
||||
@ -74,10 +98,11 @@ INSERT INTO foo(f1) VALUES(42);
|
||||
all because there are multiple possible interpretations. A good
|
||||
rule of thumb is to make a cast implicitly invokable only for
|
||||
information-preserving transformations between types in the same
|
||||
general type category. For example, <type>int2</type> to
|
||||
<type>int4</type> casts can reasonably be implicit, but be wary of
|
||||
marking <type>int4</type> to <type>text</type> or
|
||||
<type>float8</type> to <type>int4</type> as implicit casts.
|
||||
general type category. For example, the cast from <type>int2</type> to
|
||||
<type>int4</type> can reasonably be implicit, but the cast from
|
||||
<type>float8</type> to <type>int4</type> should probably be
|
||||
assignment-only. Cross-type-category casts, such as <type>text</>
|
||||
to <type>int4</>, are best made explicit-only.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -138,7 +163,18 @@ INSERT INTO foo(f1) VALUES(42);
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Indicates that the cast may be invoked implicitly.
|
||||
Indicates that the cast may be invoked implicitly in assignment
|
||||
contexts.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>AS IMPLICIT</literal></term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Indicates that the cast may be invoked implicitly in any context.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -163,10 +199,10 @@ INSERT INTO foo(f1) VALUES(42);
|
||||
data type, returned that data type, and took one argument of a
|
||||
different type was automatically a cast function. This convention has
|
||||
been abandoned in face of the introduction of schemas and to be
|
||||
able to represent binary compatible casts in the catalogs. The built-in
|
||||
able to represent binary compatible casts in the catalogs. (The built-in
|
||||
cast functions
|
||||
still follow this naming scheme, but they have to be declared as
|
||||
casts explicitly now.
|
||||
still follow this naming scheme, but they have to be shown as
|
||||
casts in <literal>pg_cast</> now.)
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
@ -191,7 +227,8 @@ CREATE CAST (text AS int4) WITH FUNCTION int4(text);
|
||||
<para>
|
||||
The <command>CREATE CAST</command> command conforms to SQL99,
|
||||
except that SQL99 does not make provisions for binary compatible
|
||||
types.
|
||||
types. <literal>AS IMPLICIT</> is a <productname>PostgreSQL</productname>
|
||||
extension, too.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.158 2002/09/04 07:16:32 momjian Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.159 2002/09/18 21:35:20 tgl Exp $
|
||||
-->
|
||||
|
||||
<appendix id="release">
|
||||
@ -24,6 +24,8 @@ CDATA means the content is "SGML-free", so you can write without
|
||||
worries about funny characters.
|
||||
-->
|
||||
<literallayout><![CDATA[
|
||||
Mixed numeric-and-float expressions are evaluated as float, per SQL spec
|
||||
Explicit casts to char, varchar, bit, varbit will truncate or pad without error
|
||||
CREATE OR REPLACE VIEW, CREATE OR REPLACE RULE are available
|
||||
No-autocommit mode is available (set autocommit to off)
|
||||
Substantial improvements in functionality for functions returning sets
|
||||
|
@ -804,13 +804,9 @@ If the non-unknown inputs are not all of the same type category, fail.
|
||||
|
||||
<step performance="required">
|
||||
<para>
|
||||
If one or more non-unknown inputs are of a preferred type in that category,
|
||||
resolve as that type.
|
||||
</para></step>
|
||||
|
||||
<step performance="required">
|
||||
<para>
|
||||
Otherwise, resolve as the type of the first non-unknown input.
|
||||
Choose the first non-unknown input type which is a preferred type in
|
||||
that category or allows all the non-unknown inputs to be implicitly
|
||||
coerced to it.
|
||||
</para></step>
|
||||
|
||||
<step performance="required">
|
||||
@ -842,15 +838,16 @@ Here, the unknown-type literal <literal>'b'</literal> will be resolved as type t
|
||||
|
||||
<para>
|
||||
<screen>
|
||||
tgl=> SELECT 1.2 AS "Double" UNION SELECT 1;
|
||||
Double
|
||||
--------
|
||||
1
|
||||
1.2
|
||||
tgl=> SELECT 1.2 AS "Numeric" UNION SELECT 1;
|
||||
Numeric
|
||||
---------
|
||||
1
|
||||
1.2
|
||||
(2 rows)
|
||||
</screen>
|
||||
The literal <literal>1.2</> is of type <type>double precision</>,
|
||||
the preferred type in the numeric category, so that type is used.
|
||||
The literal <literal>1.2</> is of type <type>numeric</>,
|
||||
and the integer value <literal>1</> can be cast implicitly to
|
||||
<type>numeric</>, so that type is used.
|
||||
</para>
|
||||
</example>
|
||||
|
||||
@ -858,27 +855,18 @@ the preferred type in the numeric category, so that type is used.
|
||||
<title>Type Conversion in a Transposed Union</title>
|
||||
|
||||
<para>
|
||||
Here the output type of the union is forced to match the type of
|
||||
the first clause in the union:
|
||||
|
||||
<screen>
|
||||
tgl=> SELECT 1 AS "All integers"
|
||||
tgl=> SELECT 1 AS "Real"
|
||||
tgl-> UNION SELECT CAST('2.2' AS REAL);
|
||||
All integers
|
||||
--------------
|
||||
1
|
||||
2
|
||||
Real
|
||||
------
|
||||
1
|
||||
2.2
|
||||
(2 rows)
|
||||
</screen>
|
||||
</para>
|
||||
<para>
|
||||
Since <type>REAL</type> is not a preferred type, the parser sees no reason
|
||||
to select it over <type>INTEGER</type> (which is what the 1 is), and instead
|
||||
falls back on the use-the-first-alternative rule.
|
||||
This example demonstrates that the preferred-type mechanism doesn't encode
|
||||
as much information as we'd like. Future versions of
|
||||
<productname>PostgreSQL</productname> may support a more general notion of
|
||||
type preferences.
|
||||
Here, since type <type>real</> cannot be implicitly cast to <type>integer</>,
|
||||
but <type>integer</> can be implicitly cast to <type>real</>, the union
|
||||
result type is resolved as <type>real</>.
|
||||
</para>
|
||||
</example>
|
||||
|
||||
|
Reference in New Issue
Block a user