diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-09-18 21:35:25 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-09-18 21:35:25 +0000 |
commit | b26dfb95222fddd25322bdddf3a5a58d3392d8b1 (patch) | |
tree | 757cf0bafab985d38a5c84d3afebe5edd34c4f27 /doc/src | |
parent | cc70ba2e4daa78ba99619770e19beb06de3dfd1c (diff) | |
download | postgresql-b26dfb95222fddd25322bdddf3a5a58d3392d8b1.tar.gz postgresql-b26dfb95222fddd25322bdddf3a5a58d3392d8b1.zip |
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.
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 27 | ||||
-rw-r--r-- | doc/src/sgml/datatype.sgml | 68 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_cast.sgml | 75 | ||||
-rw-r--r-- | doc/src/sgml/release.sgml | 4 | ||||
-rw-r--r-- | doc/src/sgml/typeconv.sgml | 50 |
5 files changed, 144 insertions, 80 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index a8fd81e19c9..01dfe6ad73b 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -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> diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 41ca3c00e53..28d3fcb7ede 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -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> diff --git a/doc/src/sgml/ref/create_cast.sgml b/doc/src/sgml/ref/create_cast.sgml index bc9f71e566e..e64d696f81a 100644 --- a/doc/src/sgml/ref/create_cast.sgml +++ b/doc/src/sgml/ref/create_cast.sgml @@ -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> diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index b7f2b4be71b..f373cc6e25d 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -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 diff --git a/doc/src/sgml/typeconv.sgml b/doc/src/sgml/typeconv.sgml index 0bfc40b1edf..e6ff564be96 100644 --- a/doc/src/sgml/typeconv.sgml +++ b/doc/src/sgml/typeconv.sgml @@ -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> |