Commit 9bc15d49 authored by Tom Lane's avatar Tom Lane

Update examples of type coercion rules --- some of them no longer worked

as the example claimed, because of changes elsewhere in the system.
parent e3b3eb20
......@@ -23,7 +23,7 @@ using <emphasis>explicit</emphasis> type coercion.
<para>
This chapter introduces the <productname>PostgreSQL</productname>
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
operators.
</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
much more general and flexible than other <acronym>RDBMS</acronym> implementations.
Hence, most type conversion behavior in <productname>PostgreSQL</productname>
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.
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.
</para>
<para>
......@@ -64,8 +64,8 @@ tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value";
(1 row)
</screen>
has two strings, of type <type>text</type> and <type>point</type>.
If a type is not specified for a string, then the placeholder type
has two literal constants, of type <type>text</type> and <type>point</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
stages as described below.
</para>
......@@ -218,7 +218,7 @@ should use this new function and will no longer do the implicit conversion using
<para>
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
linkend="sql-precedence"> for more information.
</para>
......@@ -283,7 +283,7 @@ If only one candidate remains, use it; else continue to the next step.
<para>
If any input arguments are <quote>unknown</quote>, check the type
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
since an unknown-type literal does look like a string). Otherwise, if
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>
One unspecified argument:
An example with one unspecified argument:
<screen>
tgl=> SELECT text 'abc' || 'def' AS "Text and Unknown";
Text and Unknown
......@@ -405,34 +405,50 @@ type to resolve the unknown literals to.
</example>
<example>
<title>Factorial Operator Type Resolution</title>
<title>Absolute-Value and Factorial Operator Type Resolution</title>
<para>
This example illustrates an interesting result. Traditionally, the
factorial operator is defined for integers only. The <productname>PostgreSQL</productname>
operator catalog has only one entry for factorial, taking an integer operand.
If given a non-integer numeric argument, <productname>PostgreSQL</productname>
will try to convert that argument to an integer for evaluation of the
factorial.
The <productname>PostgreSQL</productname> operator catalog has several
entries for the prefix operator <literal>@</>, all of which implement
absolute-value operations for various numeric datatypes. One of these
entries is for type <type>float8</type>, which is the preferred type in
the numeric category. Therefore, <productname>PostgreSQL</productname>
will use that entry when faced with a non-numeric input:
<screen>
tgl=> SELECT (4.3 !);
?column?
----------
24
tgl=> select @ text '-4.5' as "abs";
abs
-----
4.5
(1 row)
</screen>
Here the system has performed an implicit text-to-float8 conversion
before applying the chosen operator. We can verify that float8 and
not some other type was used:
<screen>
tgl=> select @ text '-4.5e500' as "abs";
ERROR: Input '-4.5e500' is out of range for float8
</screen>
</para>
<note>
<para>
Of course, this leads to a mathematically suspect result,
since in principle the factorial of a non-integer is not defined.
However, the role of a database is not to teach mathematics, but
to be a tool for data manipulation. If a user chooses to take the
factorial of a floating point number, <productname>PostgreSQL</productname>
will try to oblige.
</para>
</note>
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>
</example>
......@@ -507,13 +523,14 @@ If only one candidate remains, use it; else continue to the next step.
<para>
If any input arguments are <type>unknown</type>, check the type categories accepted
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).
Otherwise, if all the remaining candidates accept the same type category,
select that category; otherwise fail because
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.
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
position, discard candidates that accept non-preferred types for that
argument.
......@@ -536,7 +553,8 @@ then fail.
<title>Factorial Function Argument Type Resolution</title>
<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
to <type>int4</type>:
......@@ -619,7 +637,7 @@ tgl=> SELECT substr(1234, 3);
34
(1 row)
</screen>
actually executes as
which actually executes as
<screen>
tgl=> SELECT substr(text(1234), 3);
substr
......@@ -637,6 +655,12 @@ system catalog.
<sect1 id="typeconv-query">
<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>
<title>Query Target Type Resolution</title>
......@@ -666,33 +690,36 @@ passing the column's declared length as the second parameter.
</procedure>
<example>
<title><type>varchar</type> Storage Type Conversion</title>
<title><type>character</type> Storage Type Conversion</title>
<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:
<screen>
tgl=> CREATE TABLE vv (v varchar(4));
tgl=> CREATE TABLE vv (v character(20));
CREATE
tgl=> INSERT INTO vv SELECT 'abc' || 'def';
INSERT 392905 1
tgl=> SELECT * FROM vv;
v
------
abcd
tgl=> SELECT v, length(v) FROM vv;
v | length
----------------------+--------
abcdef | 20
(1 row)
</screen>
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
resolved as <type>text</type> concatenation. Then the <type>text</type> result of the operator
is coerced to <type>varchar</type> to match the target column type. (But, since the
parser knows that <type>text</type> and <type>varchar</type> are binary-compatible, this coercion
is implicit and does not insert any real function call.) Finally, the
sizing function <literal>varchar(varchar, 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 desired truncation.
to <type>text</type> by default, allowing the <literal>||</literal> operator
to be resolved as <type>text</type> concatenation. Then the <type>text</type>
result of the operator is coerced to <type>bpchar</type> (<quote>blank-padded
char</>, the internal name of the character datatype) to match the target
column type. (Since the parser knows that <type>text</type> and
<type>bpchar</type> are binary-compatible, this coercion is implicit and does
not insert any real function call.) Finally, the sizing function
<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>
</example>
</sect1>
......@@ -701,10 +728,13 @@ This type-specific function performs the desired truncation.
<title><literal>UNION</> and <literal>CASE</> Constructs</title>
<para>
The <literal>UNION</> and <literal>CASE</> constructs must match up possibly dissimilar types to
become a single result set. The resolution algorithm is applied separately to
each output column of a union. <literal>CASE</> uses the identical algorithm to match
up its result expressions.
SQL <literal>UNION</> constructs must match up possibly dissimilar types to
become a single result set. The resolution algorithm is applied separately
to each output column of a union query. The <literal>INTERSECT</> and
<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>
<procedure>
<title><literal>UNION</> and <literal>CASE</> Type Resolution</title>
......@@ -768,6 +798,8 @@ tgl=> SELECT 1.2 AS "Double" UNION SELECT 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.
</para>
</example>
......@@ -776,7 +808,7 @@ tgl=> SELECT 1.2 AS "Double" UNION SELECT 1;
<para>
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>
tgl=> SELECT 1 AS "All integers"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment