mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Update examples of type coercion rules --- some of them no longer worked
as the example claimed, because of changes elsewhere in the system.
This commit is contained in:
parent
e3b3eb20a4
commit
9bc15d499d
@ -23,7 +23,7 @@ using <emphasis>explicit</emphasis> type coercion.
|
|||||||
<para>
|
<para>
|
||||||
This chapter introduces the <productname>PostgreSQL</productname>
|
This chapter introduces the <productname>PostgreSQL</productname>
|
||||||
type conversion mechanisms and conventions.
|
type conversion mechanisms and conventions.
|
||||||
Refer to the relevant sections in the <xref linkend="datatype"> and <xref linkend="functions">
|
Refer to the relevant sections in <xref linkend="datatype"> and <xref linkend="functions">
|
||||||
for more information on specific data types and allowed functions and
|
for more information on specific data types and allowed functions and
|
||||||
operators.
|
operators.
|
||||||
</para>
|
</para>
|
||||||
@ -43,8 +43,8 @@ has an associated data type which determines its behavior and allowed usage.
|
|||||||
<productname>PostgreSQL</productname> has an extensible type system that is
|
<productname>PostgreSQL</productname> has an extensible type system that is
|
||||||
much more general and flexible than other <acronym>RDBMS</acronym> implementations.
|
much more general and flexible than other <acronym>RDBMS</acronym> implementations.
|
||||||
Hence, most type conversion behavior in <productname>PostgreSQL</productname>
|
Hence, most type conversion behavior in <productname>PostgreSQL</productname>
|
||||||
should be governed by general rules rather than by ad-hoc heuristics to allow
|
should be governed by general rules rather than by ad-hoc heuristics, to allow
|
||||||
mixed-type expressions to be meaningful, even with user-defined types.
|
mixed-type expressions to be meaningful even with user-defined types.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -64,8 +64,8 @@ tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value";
|
|||||||
(1 row)
|
(1 row)
|
||||||
</screen>
|
</screen>
|
||||||
|
|
||||||
has two strings, of type <type>text</type> and <type>point</type>.
|
has two literal constants, of type <type>text</type> and <type>point</type>.
|
||||||
If a type is not specified for a string, then the placeholder type
|
If a type is not specified for a string literal, then the placeholder type
|
||||||
<firstterm>unknown</firstterm> is assigned initially, to be resolved in later
|
<firstterm>unknown</firstterm> is assigned initially, to be resolved in later
|
||||||
stages as described below.
|
stages as described below.
|
||||||
</para>
|
</para>
|
||||||
@ -218,7 +218,7 @@ should use this new function and will no longer do the implicit conversion using
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The operand types of an operator invocation are resolved following
|
The operand types of an operator invocation are resolved following
|
||||||
to the procedure below. Note that this procedure is indirectly affected
|
the procedure below. Note that this procedure is indirectly affected
|
||||||
by the precedence of the involved operators. See <xref
|
by the precedence of the involved operators. See <xref
|
||||||
linkend="sql-precedence"> for more information.
|
linkend="sql-precedence"> for more information.
|
||||||
</para>
|
</para>
|
||||||
@ -283,7 +283,7 @@ If only one candidate remains, use it; else continue to the next step.
|
|||||||
<para>
|
<para>
|
||||||
If any input arguments are <quote>unknown</quote>, check the type
|
If any input arguments are <quote>unknown</quote>, check the type
|
||||||
categories accepted at those argument positions by the remaining
|
categories accepted at those argument positions by the remaining
|
||||||
candidates. At each position, try the "string" category if any
|
candidates. At each position, select the "string" category if any
|
||||||
candidate accepts that category (this bias towards string is appropriate
|
candidate accepts that category (this bias towards string is appropriate
|
||||||
since an unknown-type literal does look like a string). Otherwise, if
|
since an unknown-type literal does look like a string). Otherwise, if
|
||||||
all the remaining candidates accept the same type category, select that
|
all the remaining candidates accept the same type category, select that
|
||||||
@ -366,7 +366,7 @@ Strings with unspecified type are matched with likely operator candidates.
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
One unspecified argument:
|
An example with one unspecified argument:
|
||||||
<screen>
|
<screen>
|
||||||
tgl=> SELECT text 'abc' || 'def' AS "Text and Unknown";
|
tgl=> SELECT text 'abc' || 'def' AS "Text and Unknown";
|
||||||
Text and Unknown
|
Text and Unknown
|
||||||
@ -405,34 +405,50 @@ type to resolve the unknown literals to.
|
|||||||
</example>
|
</example>
|
||||||
|
|
||||||
<example>
|
<example>
|
||||||
<title>Factorial Operator Type Resolution</title>
|
<title>Absolute-Value and Factorial Operator Type Resolution</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This example illustrates an interesting result. Traditionally, the
|
The <productname>PostgreSQL</productname> operator catalog has several
|
||||||
factorial operator is defined for integers only. The <productname>PostgreSQL</productname>
|
entries for the prefix operator <literal>@</>, all of which implement
|
||||||
operator catalog has only one entry for factorial, taking an integer operand.
|
absolute-value operations for various numeric datatypes. One of these
|
||||||
If given a non-integer numeric argument, <productname>PostgreSQL</productname>
|
entries is for type <type>float8</type>, which is the preferred type in
|
||||||
will try to convert that argument to an integer for evaluation of the
|
the numeric category. Therefore, <productname>PostgreSQL</productname>
|
||||||
factorial.
|
will use that entry when faced with a non-numeric input:
|
||||||
|
|
||||||
<screen>
|
<screen>
|
||||||
tgl=> SELECT (4.3 !);
|
tgl=> select @ text '-4.5' as "abs";
|
||||||
?column?
|
abs
|
||||||
----------
|
-----
|
||||||
24
|
4.5
|
||||||
(1 row)
|
(1 row)
|
||||||
</screen>
|
</screen>
|
||||||
|
Here the system has performed an implicit text-to-float8 conversion
|
||||||
<note>
|
before applying the chosen operator. We can verify that float8 and
|
||||||
<para>
|
not some other type was used:
|
||||||
Of course, this leads to a mathematically suspect result,
|
<screen>
|
||||||
since in principle the factorial of a non-integer is not defined.
|
tgl=> select @ text '-4.5e500' as "abs";
|
||||||
However, the role of a database is not to teach mathematics, but
|
ERROR: Input '-4.5e500' is out of range for float8
|
||||||
to be a tool for data manipulation. If a user chooses to take the
|
</screen>
|
||||||
factorial of a floating point number, <productname>PostgreSQL</productname>
|
|
||||||
will try to oblige.
|
|
||||||
</para>
|
</para>
|
||||||
</note>
|
|
||||||
|
<para>
|
||||||
|
On the other hand, the postfix operator <literal>!</> (factorial)
|
||||||
|
is defined only for integer datatypes, not for float8. So, if we
|
||||||
|
try a similar case with <literal>!</>, we get:
|
||||||
|
<screen>
|
||||||
|
tgl=> select text '44' ! as "factorial";
|
||||||
|
ERROR: Unable to identify a postfix operator '!' for type 'text'
|
||||||
|
You may need to add parentheses or an explicit cast
|
||||||
|
</screen>
|
||||||
|
This happens because the system can't decide which of the several
|
||||||
|
possible <literal>!</> operators should be preferred. We can help
|
||||||
|
it out with an explicit cast:
|
||||||
|
<screen>
|
||||||
|
tgl=> select cast(text '44' as int8) ! as "factorial";
|
||||||
|
factorial
|
||||||
|
---------------------
|
||||||
|
2673996885588443136
|
||||||
|
(1 row)
|
||||||
|
</screen>
|
||||||
</para>
|
</para>
|
||||||
</example>
|
</example>
|
||||||
|
|
||||||
@ -507,13 +523,14 @@ If only one candidate remains, use it; else continue to the next step.
|
|||||||
<para>
|
<para>
|
||||||
If any input arguments are <type>unknown</type>, check the type categories accepted
|
If any input arguments are <type>unknown</type>, check the type categories accepted
|
||||||
at those argument positions by the remaining candidates. At each position,
|
at those argument positions by the remaining candidates. At each position,
|
||||||
try the <type>string</type> category if any candidate accepts that category (this bias towards string
|
select the <type>string</type> category if any candidate accepts that category
|
||||||
|
(this bias towards string
|
||||||
is appropriate since an unknown-type literal does look like a string).
|
is appropriate since an unknown-type literal does look like a string).
|
||||||
Otherwise, if all the remaining candidates accept the same type category,
|
Otherwise, if all the remaining candidates accept the same type category,
|
||||||
select that category; otherwise fail because
|
select that category; otherwise fail because
|
||||||
the correct choice cannot be deduced without more clues. Also note whether
|
the correct choice cannot be deduced without more clues. Also note whether
|
||||||
any of the candidates accept a preferred data type within the selected category.
|
any of the candidates accept a preferred data type within the selected category.
|
||||||
Now discard operator candidates that do not accept the selected type category;
|
Now discard candidates that do not accept the selected type category;
|
||||||
furthermore, if any candidate accepts a preferred type at a given argument
|
furthermore, if any candidate accepts a preferred type at a given argument
|
||||||
position, discard candidates that accept non-preferred types for that
|
position, discard candidates that accept non-preferred types for that
|
||||||
argument.
|
argument.
|
||||||
@ -536,7 +553,8 @@ then fail.
|
|||||||
<title>Factorial Function Argument Type Resolution</title>
|
<title>Factorial Function Argument Type Resolution</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
There is only one factorial function defined in the <classname>pg_proc</classname> catalog.
|
There is only one <function>int4fac</function> function defined in the
|
||||||
|
<classname>pg_proc</classname> catalog.
|
||||||
So the following query automatically converts the <type>int2</type> argument
|
So the following query automatically converts the <type>int2</type> argument
|
||||||
to <type>int4</type>:
|
to <type>int4</type>:
|
||||||
|
|
||||||
@ -619,7 +637,7 @@ tgl=> SELECT substr(1234, 3);
|
|||||||
34
|
34
|
||||||
(1 row)
|
(1 row)
|
||||||
</screen>
|
</screen>
|
||||||
actually executes as
|
which actually executes as
|
||||||
<screen>
|
<screen>
|
||||||
tgl=> SELECT substr(text(1234), 3);
|
tgl=> SELECT substr(text(1234), 3);
|
||||||
substr
|
substr
|
||||||
@ -637,6 +655,12 @@ system catalog.
|
|||||||
<sect1 id="typeconv-query">
|
<sect1 id="typeconv-query">
|
||||||
<title>Query Targets</title>
|
<title>Query Targets</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Values to be inserted into a table are coerced to the destination
|
||||||
|
column's datatype according to the
|
||||||
|
following steps.
|
||||||
|
</para>
|
||||||
|
|
||||||
<procedure>
|
<procedure>
|
||||||
<title>Query Target Type Resolution</title>
|
<title>Query Target Type Resolution</title>
|
||||||
|
|
||||||
@ -666,33 +690,36 @@ passing the column's declared length as the second parameter.
|
|||||||
</procedure>
|
</procedure>
|
||||||
|
|
||||||
<example>
|
<example>
|
||||||
<title><type>varchar</type> Storage Type Conversion</title>
|
<title><type>character</type> Storage Type Conversion</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For a target column declared as <type>varchar(4)</type> the following query
|
For a target column declared as <type>character(20)</type> the following query
|
||||||
ensures that the target is sized correctly:
|
ensures that the target is sized correctly:
|
||||||
|
|
||||||
<screen>
|
<screen>
|
||||||
tgl=> CREATE TABLE vv (v varchar(4));
|
tgl=> CREATE TABLE vv (v character(20));
|
||||||
CREATE
|
CREATE
|
||||||
tgl=> INSERT INTO vv SELECT 'abc' || 'def';
|
tgl=> INSERT INTO vv SELECT 'abc' || 'def';
|
||||||
INSERT 392905 1
|
INSERT 392905 1
|
||||||
tgl=> SELECT * FROM vv;
|
tgl=> SELECT v, length(v) FROM vv;
|
||||||
v
|
v | length
|
||||||
------
|
----------------------+--------
|
||||||
abcd
|
abcdef | 20
|
||||||
(1 row)
|
(1 row)
|
||||||
</screen>
|
</screen>
|
||||||
|
|
||||||
What has really happened here is that the two unknown literals are resolved
|
What has really happened here is that the two unknown literals are resolved
|
||||||
to <type>text</type> by default, allowing the <literal>||</literal> operator to be
|
to <type>text</type> by default, allowing the <literal>||</literal> operator
|
||||||
resolved as <type>text</type> concatenation. Then the <type>text</type> result of the operator
|
to be resolved as <type>text</type> concatenation. Then the <type>text</type>
|
||||||
is coerced to <type>varchar</type> to match the target column type. (But, since the
|
result of the operator is coerced to <type>bpchar</type> (<quote>blank-padded
|
||||||
parser knows that <type>text</type> and <type>varchar</type> are binary-compatible, this coercion
|
char</>, the internal name of the character datatype) to match the target
|
||||||
is implicit and does not insert any real function call.) Finally, the
|
column type. (Since the parser knows that <type>text</type> and
|
||||||
sizing function <literal>varchar(varchar, integer)</literal> is found in the system
|
<type>bpchar</type> are binary-compatible, this coercion is implicit and does
|
||||||
catalogs and applied to the operator's result and the stored column length.
|
not insert any real function call.) Finally, the sizing function
|
||||||
This type-specific function performs the desired truncation.
|
<literal>bpchar(bpchar, integer)</literal> is found in the system catalogs
|
||||||
|
and applied to the operator's result and the stored column length. This
|
||||||
|
type-specific function performs the required length check and addition of
|
||||||
|
padding spaces.
|
||||||
</para>
|
</para>
|
||||||
</example>
|
</example>
|
||||||
</sect1>
|
</sect1>
|
||||||
@ -701,10 +728,13 @@ This type-specific function performs the desired truncation.
|
|||||||
<title><literal>UNION</> and <literal>CASE</> Constructs</title>
|
<title><literal>UNION</> and <literal>CASE</> Constructs</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <literal>UNION</> and <literal>CASE</> constructs must match up possibly dissimilar types to
|
SQL <literal>UNION</> constructs must match up possibly dissimilar types to
|
||||||
become a single result set. The resolution algorithm is applied separately to
|
become a single result set. The resolution algorithm is applied separately
|
||||||
each output column of a union. <literal>CASE</> uses the identical algorithm to match
|
to each output column of a union query. The <literal>INTERSECT</> and
|
||||||
up its result expressions.
|
<literal>EXCEPT</> constructs resolve dissimilar types in the same way as
|
||||||
|
<literal>UNION</>.
|
||||||
|
A <literal>CASE</> construct also uses the identical algorithm to match up its
|
||||||
|
component expressions and select a result datatype.
|
||||||
</para>
|
</para>
|
||||||
<procedure>
|
<procedure>
|
||||||
<title><literal>UNION</> and <literal>CASE</> Type Resolution</title>
|
<title><literal>UNION</> and <literal>CASE</> Type Resolution</title>
|
||||||
@ -768,6 +798,8 @@ tgl=> SELECT 1.2 AS "Double" UNION SELECT 1;
|
|||||||
1.2
|
1.2
|
||||||
(2 rows)
|
(2 rows)
|
||||||
</screen>
|
</screen>
|
||||||
|
The literal <literal>1.2</> is of type <type>double precision</>,
|
||||||
|
the preferred type in the numeric category, so that type is used.
|
||||||
</para>
|
</para>
|
||||||
</example>
|
</example>
|
||||||
|
|
||||||
@ -776,7 +808,7 @@ tgl=> SELECT 1.2 AS "Double" UNION SELECT 1;
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
Here the output type of the union is forced to match the type of
|
Here the output type of the union is forced to match the type of
|
||||||
the first/top clause in the union:
|
the first clause in the union:
|
||||||
|
|
||||||
<screen>
|
<screen>
|
||||||
tgl=> SELECT 1 AS "All integers"
|
tgl=> SELECT 1 AS "All integers"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user