Skip to content

Commit 9bc15d4

Browse files
committed
Update examples of type coercion rules --- some of them no longer worked
as the example claimed, because of changes elsewhere in the system.
1 parent e3b3eb2 commit 9bc15d4

File tree

1 file changed

+85
-53
lines changed

1 file changed

+85
-53
lines changed

doc/src/sgml/typeconv.sgml

+85-53
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ using <emphasis>explicit</emphasis> type coercion.
2323
<para>
2424
This chapter introduces the <productname>PostgreSQL</productname>
2525
type conversion mechanisms and conventions.
26-
Refer to the relevant sections in the <xref linkend="datatype"> and <xref linkend="functions">
26+
Refer to the relevant sections in <xref linkend="datatype"> and <xref linkend="functions">
2727
for more information on specific data types and allowed functions and
2828
operators.
2929
</para>
@@ -43,8 +43,8 @@ has an associated data type which determines its behavior and allowed usage.
4343
<productname>PostgreSQL</productname> has an extensible type system that is
4444
much more general and flexible than other <acronym>RDBMS</acronym> implementations.
4545
Hence, most type conversion behavior in <productname>PostgreSQL</productname>
46-
should be governed by general rules rather than by ad-hoc heuristics to allow
47-
mixed-type expressions to be meaningful, even with user-defined types.
46+
should be governed by general rules rather than by ad-hoc heuristics, to allow
47+
mixed-type expressions to be meaningful even with user-defined types.
4848
</para>
4949

5050
<para>
@@ -64,8 +64,8 @@ tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value";
6464
(1 row)
6565
</screen>
6666

67-
has two strings, of type <type>text</type> and <type>point</type>.
68-
If a type is not specified for a string, then the placeholder type
67+
has two literal constants, of type <type>text</type> and <type>point</type>.
68+
If a type is not specified for a string literal, then the placeholder type
6969
<firstterm>unknown</firstterm> is assigned initially, to be resolved in later
7070
stages as described below.
7171
</para>
@@ -218,7 +218,7 @@ should use this new function and will no longer do the implicit conversion using
218218

219219
<para>
220220
The operand types of an operator invocation are resolved following
221-
to the procedure below. Note that this procedure is indirectly affected
221+
the procedure below. Note that this procedure is indirectly affected
222222
by the precedence of the involved operators. See <xref
223223
linkend="sql-precedence"> for more information.
224224
</para>
@@ -283,7 +283,7 @@ If only one candidate remains, use it; else continue to the next step.
283283
<para>
284284
If any input arguments are <quote>unknown</quote>, check the type
285285
categories accepted at those argument positions by the remaining
286-
candidates. At each position, try the "string" category if any
286+
candidates. At each position, select the "string" category if any
287287
candidate accepts that category (this bias towards string is appropriate
288288
since an unknown-type literal does look like a string). Otherwise, if
289289
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.
366366
</para>
367367

368368
<para>
369-
One unspecified argument:
369+
An example with one unspecified argument:
370370
<screen>
371371
tgl=> SELECT text 'abc' || 'def' AS "Text and Unknown";
372372
Text and Unknown
@@ -405,34 +405,50 @@ type to resolve the unknown literals to.
405405
</example>
406406

407407
<example>
408-
<title>Factorial Operator Type Resolution</title>
408+
<title>Absolute-Value and Factorial Operator Type Resolution</title>
409409

410410
<para>
411-
This example illustrates an interesting result. Traditionally, the
412-
factorial operator is defined for integers only. The <productname>PostgreSQL</productname>
413-
operator catalog has only one entry for factorial, taking an integer operand.
414-
If given a non-integer numeric argument, <productname>PostgreSQL</productname>
415-
will try to convert that argument to an integer for evaluation of the
416-
factorial.
417-
411+
The <productname>PostgreSQL</productname> operator catalog has several
412+
entries for the prefix operator <literal>@</>, all of which implement
413+
absolute-value operations for various numeric datatypes. One of these
414+
entries is for type <type>float8</type>, which is the preferred type in
415+
the numeric category. Therefore, <productname>PostgreSQL</productname>
416+
will use that entry when faced with a non-numeric input:
418417
<screen>
419-
tgl=> SELECT (4.3 !);
420-
?column?
421-
----------
422-
24
418+
tgl=> select @ text '-4.5' as "abs";
419+
abs
420+
-----
421+
4.5
423422
(1 row)
424423
</screen>
424+
Here the system has performed an implicit text-to-float8 conversion
425+
before applying the chosen operator. We can verify that float8 and
426+
not some other type was used:
427+
<screen>
428+
tgl=> select @ text '-4.5e500' as "abs";
429+
ERROR: Input '-4.5e500' is out of range for float8
430+
</screen>
431+
</para>
425432

426-
<note>
427433
<para>
428-
Of course, this leads to a mathematically suspect result,
429-
since in principle the factorial of a non-integer is not defined.
430-
However, the role of a database is not to teach mathematics, but
431-
to be a tool for data manipulation. If a user chooses to take the
432-
factorial of a floating point number, <productname>PostgreSQL</productname>
433-
will try to oblige.
434-
</para>
435-
</note>
434+
On the other hand, the postfix operator <literal>!</> (factorial)
435+
is defined only for integer datatypes, not for float8. So, if we
436+
try a similar case with <literal>!</>, we get:
437+
<screen>
438+
tgl=> select text '44' ! as "factorial";
439+
ERROR: Unable to identify a postfix operator '!' for type 'text'
440+
You may need to add parentheses or an explicit cast
441+
</screen>
442+
This happens because the system can't decide which of the several
443+
possible <literal>!</> operators should be preferred. We can help
444+
it out with an explicit cast:
445+
<screen>
446+
tgl=> select cast(text '44' as int8) ! as "factorial";
447+
factorial
448+
---------------------
449+
2673996885588443136
450+
(1 row)
451+
</screen>
436452
</para>
437453
</example>
438454

@@ -507,13 +523,14 @@ If only one candidate remains, use it; else continue to the next step.
507523
<para>
508524
If any input arguments are <type>unknown</type>, check the type categories accepted
509525
at those argument positions by the remaining candidates. At each position,
510-
try the <type>string</type> category if any candidate accepts that category (this bias towards string
526+
select the <type>string</type> category if any candidate accepts that category
527+
(this bias towards string
511528
is appropriate since an unknown-type literal does look like a string).
512529
Otherwise, if all the remaining candidates accept the same type category,
513530
select that category; otherwise fail because
514531
the correct choice cannot be deduced without more clues. Also note whether
515532
any of the candidates accept a preferred data type within the selected category.
516-
Now discard operator candidates that do not accept the selected type category;
533+
Now discard candidates that do not accept the selected type category;
517534
furthermore, if any candidate accepts a preferred type at a given argument
518535
position, discard candidates that accept non-preferred types for that
519536
argument.
@@ -536,7 +553,8 @@ then fail.
536553
<title>Factorial Function Argument Type Resolution</title>
537554

538555
<para>
539-
There is only one factorial function defined in the <classname>pg_proc</classname> catalog.
556+
There is only one <function>int4fac</function> function defined in the
557+
<classname>pg_proc</classname> catalog.
540558
So the following query automatically converts the <type>int2</type> argument
541559
to <type>int4</type>:
542560

@@ -619,7 +637,7 @@ tgl=> SELECT substr(1234, 3);
619637
34
620638
(1 row)
621639
</screen>
622-
actually executes as
640+
which actually executes as
623641
<screen>
624642
tgl=> SELECT substr(text(1234), 3);
625643
substr
@@ -637,6 +655,12 @@ system catalog.
637655
<sect1 id="typeconv-query">
638656
<title>Query Targets</title>
639657

658+
<para>
659+
Values to be inserted into a table are coerced to the destination
660+
column's datatype according to the
661+
following steps.
662+
</para>
663+
640664
<procedure>
641665
<title>Query Target Type Resolution</title>
642666

@@ -666,33 +690,36 @@ passing the column's declared length as the second parameter.
666690
</procedure>
667691

668692
<example>
669-
<title><type>varchar</type> Storage Type Conversion</title>
693+
<title><type>character</type> Storage Type Conversion</title>
670694

671695
<para>
672-
For a target column declared as <type>varchar(4)</type> the following query
696+
For a target column declared as <type>character(20)</type> the following query
673697
ensures that the target is sized correctly:
674698

675699
<screen>
676-
tgl=> CREATE TABLE vv (v varchar(4));
700+
tgl=> CREATE TABLE vv (v character(20));
677701
CREATE
678702
tgl=> INSERT INTO vv SELECT 'abc' || 'def';
679703
INSERT 392905 1
680-
tgl=> SELECT * FROM vv;
681-
v
682-
------
683-
abcd
704+
tgl=> SELECT v, length(v) FROM vv;
705+
v | length
706+
----------------------+--------
707+
abcdef | 20
684708
(1 row)
685709
</screen>
686710

687711
What has really happened here is that the two unknown literals are resolved
688-
to <type>text</type> by default, allowing the <literal>||</literal> operator to be
689-
resolved as <type>text</type> concatenation. Then the <type>text</type> result of the operator
690-
is coerced to <type>varchar</type> to match the target column type. (But, since the
691-
parser knows that <type>text</type> and <type>varchar</type> are binary-compatible, this coercion
692-
is implicit and does not insert any real function call.) Finally, the
693-
sizing function <literal>varchar(varchar, integer)</literal> is found in the system
694-
catalogs and applied to the operator's result and the stored column length.
695-
This type-specific function performs the desired truncation.
712+
to <type>text</type> by default, allowing the <literal>||</literal> operator
713+
to be resolved as <type>text</type> concatenation. Then the <type>text</type>
714+
result of the operator is coerced to <type>bpchar</type> (<quote>blank-padded
715+
char</>, the internal name of the character datatype) to match the target
716+
column type. (Since the parser knows that <type>text</type> and
717+
<type>bpchar</type> are binary-compatible, this coercion is implicit and does
718+
not insert any real function call.) Finally, the sizing function
719+
<literal>bpchar(bpchar, integer)</literal> is found in the system catalogs
720+
and applied to the operator's result and the stored column length. This
721+
type-specific function performs the required length check and addition of
722+
padding spaces.
696723
</para>
697724
</example>
698725
</sect1>
@@ -701,10 +728,13 @@ This type-specific function performs the desired truncation.
701728
<title><literal>UNION</> and <literal>CASE</> Constructs</title>
702729

703730
<para>
704-
The <literal>UNION</> and <literal>CASE</> constructs must match up possibly dissimilar types to
705-
become a single result set. The resolution algorithm is applied separately to
706-
each output column of a union. <literal>CASE</> uses the identical algorithm to match
707-
up its result expressions.
731+
SQL <literal>UNION</> constructs must match up possibly dissimilar types to
732+
become a single result set. The resolution algorithm is applied separately
733+
to each output column of a union query. The <literal>INTERSECT</> and
734+
<literal>EXCEPT</> constructs resolve dissimilar types in the same way as
735+
<literal>UNION</>.
736+
A <literal>CASE</> construct also uses the identical algorithm to match up its
737+
component expressions and select a result datatype.
708738
</para>
709739
<procedure>
710740
<title><literal>UNION</> and <literal>CASE</> Type Resolution</title>
@@ -768,6 +798,8 @@ tgl=> SELECT 1.2 AS "Double" UNION SELECT 1;
768798
1.2
769799
(2 rows)
770800
</screen>
801+
The literal <literal>1.2</> is of type <type>double precision</>,
802+
the preferred type in the numeric category, so that type is used.
771803
</para>
772804
</example>
773805

@@ -776,7 +808,7 @@ tgl=> SELECT 1.2 AS "Double" UNION SELECT 1;
776808

777809
<para>
778810
Here the output type of the union is forced to match the type of
779-
the first/top clause in the union:
811+
the first clause in the union:
780812

781813
<screen>
782814
tgl=> SELECT 1 AS "All integers"

0 commit comments

Comments
 (0)