diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-01-08 11:07:53 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-01-08 11:07:59 -0500 |
commit | 913bbd88dc6b859c70ebb48107b38d693c4c6673 (patch) | |
tree | 5a6f17fd59677039ad33cd91e69ce1b7e03b8c43 /doc/src | |
parent | 8dd1511e39acd729020e151deb15a958300ebff5 (diff) | |
download | postgresql-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.sgml | 44 |
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> |