1
0
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:
Tom Lane
2002-09-18 21:35:25 +00:00
parent cc70ba2e4d
commit b26dfb9522
70 changed files with 1642 additions and 1528 deletions

View File

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

View File

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

View File

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

View File

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

View File

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