From 9bc15d499dbc6ca7a8a2fd4ab2f687df6323cb8c Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 15 Oct 2001 01:00:59 +0000
Subject: [PATCH] Update examples of type coercion rules --- some of them no
 longer worked as the example claimed, because of changes elsewhere in the
 system.

---
 doc/src/sgml/typeconv.sgml | 138 +++++++++++++++++++++++--------------
 1 file changed, 85 insertions(+), 53 deletions(-)

diff --git a/doc/src/sgml/typeconv.sgml b/doc/src/sgml/typeconv.sgml
index 55ce51b2c10..567f184e943 100644
--- a/doc/src/sgml/typeconv.sgml
+++ b/doc/src/sgml/typeconv.sgml
@@ -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"
-- 
GitLab