aboutsummaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-01-08 11:07:53 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2020-01-08 11:07:59 -0500
commit913bbd88dc6b859c70ebb48107b38d693c4c6673 (patch)
tree5a6f17fd59677039ad33cd91e69ce1b7e03b8c43 /doc/src
parent8dd1511e39acd729020e151deb15a958300ebff5 (diff)
downloadpostgresql-913bbd88dc6b859c70ebb48107b38d693c4c6673.tar.gz
postgresql-913bbd88dc6b859c70ebb48107b38d693c4c6673.zip
Improve the handling of result type coercions in SQL functions.
Use the parser's standard type coercion machinery to convert the output column(s) of a SQL function's final SELECT or RETURNING to the type(s) they should have according to the function's declared result type. We'll allow any case where an assignment-level coercion is available. Previously, we failed unless the required coercion was a binary-compatible one (and the documentation ignored this, falsely claiming that the types must match exactly). Notably, the coercion now accounts for typmods, so that cases where a SQL function is declared to return a composite type whose columns are typmod-constrained now behave as one would expect. Arguably this aspect is a bug fix, but the overall behavioral change here seems too large to consider back-patching. A nice side-effect is that functions can now be inlined in a few cases where we previously failed to do so because of type mismatches. Discussion: https://postgr.es/m/18929.1574895430@sss.pgh.pa.us
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/xfunc.sgml44
1 files changed, 21 insertions, 23 deletions
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index d9afd3be4d0..5616524cfd3 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -388,11 +388,15 @@ $$ LANGUAGE SQL;
</para>
<para>
- A <acronym>SQL</acronym> function must return exactly its declared
- result type. This may require inserting an explicit cast.
+ If the final <literal>SELECT</literal> or <literal>RETURNING</literal>
+ clause in a <acronym>SQL</acronym> function does not return exactly
+ the function's declared result
+ type, <productname>PostgreSQL</productname> will automatically cast
+ the value to the required type, if that is possible with an implicit
+ or assignment cast. Otherwise, you must write an explicit cast.
For example, suppose we wanted the
previous <function>add_em</function> function to return
- type <type>float8</type> instead. This won't work:
+ type <type>float8</type> instead. It's sufficient to write
<programlisting>
CREATE FUNCTION add_em(integer, integer) RETURNS float8 AS $$
@@ -400,16 +404,10 @@ CREATE FUNCTION add_em(integer, integer) RETURNS float8 AS $$
$$ LANGUAGE SQL;
</programlisting>
- even though in other contexts <productname>PostgreSQL</productname>
- would be willing to insert an implicit cast to
- convert <type>integer</type> to <type>float8</type>.
- We need to write it as
-
-<programlisting>
-CREATE FUNCTION add_em(integer, integer) RETURNS float8 AS $$
- SELECT ($1 + $2)::float8;
-$$ LANGUAGE SQL;
-</programlisting>
+ since the <type>integer</type> sum can be implicitly cast
+ to <type>float8</type>.
+ (See <xref linkend="typeconv"/> or <xref linkend="sql-createcast"/>
+ for more about casts.)
</para>
</sect2>
@@ -503,23 +501,24 @@ $$ LANGUAGE SQL;
<listitem>
<para>
The select list order in the query must be exactly the same as
- that in which the columns appear in the table associated
- with the composite type. (Naming the columns, as we did above,
+ that in which the columns appear in the composite type.
+ (Naming the columns, as we did above,
is irrelevant to the system.)
</para>
</listitem>
<listitem>
<para>
- We must ensure each expression's type matches the corresponding
- column of the composite type, inserting a cast if necessary.
+ We must ensure each expression's type can be cast to that of
+ the corresponding column of the composite type.
Otherwise we'll get errors like this:
<screen>
<computeroutput>
-ERROR: function declared to return emp returns varchar instead of text at column 1
+ERROR: return type mismatch in function declared to return emp
+DETAIL: Final statement returns text instead of point at column 4.
</computeroutput>
</screen>
- As with the base-type case, the function will not insert any casts
- automatically.
+ As with the base-type case, the system will not insert explicit
+ casts automatically, only implicit or assignment casts.
</para>
</listitem>
</itemizedlist>
@@ -542,8 +541,7 @@ $$ LANGUAGE SQL;
Another example is that if we are trying to write a function that
returns a domain over composite, rather than a plain composite type,
it is always necessary to write it as returning a single column,
- since there is no other way to produce a value that is exactly of
- the domain type.
+ since there is no way to cause a coercion of the whole row result.
</para>
<para>
@@ -1263,7 +1261,7 @@ SELECT make_array(1, 2) AS intarray, make_array('a'::text, 'b') AS textarray;
Without the typecast, you will get errors like this:
<screen>
<computeroutput>
-ERROR: could not determine polymorphic type because input has type "unknown"
+ERROR: could not determine polymorphic type because input has type unknown
</computeroutput>
</screen>
</para>