Home Explore Blog CI



postgresql

15th chunk of `doc/src/sgml/xfunc.sgml`
04e2b8598647cfab43a83acf844c4422e88b050215e804640000000100000fa0
 conditional execution (set-returning
      functions inside <literal>CASE</literal> etc.) was previously allowed,
      complicating things even more.
      Use of the <literal>LATERAL</literal> syntax is recommended when writing
      queries that need to work in older <productname>PostgreSQL</productname> versions,
      because that will give consistent results across different versions.
      If you have a query that is relying on conditional execution of a
      set-returning function, you may be able to fix it by moving the
      conditional test into a custom set-returning function.  For example,
<programlisting>
SELECT x, CASE WHEN y &gt; 0 THEN generate_series(1, z) ELSE 5 END FROM tab;
</programlisting>
      could become
<programlisting>
CREATE FUNCTION case_generate_series(cond bool, start int, fin int, els int)
  RETURNS SETOF int AS $$
BEGIN
  IF cond THEN
    RETURN QUERY SELECT generate_series(start, fin);
  ELSE
    RETURN QUERY SELECT els;
  END IF;
END$$ LANGUAGE plpgsql;

SELECT x, case_generate_series(y &gt; 0, 1, z, 5) FROM tab;
</programlisting>
      This formulation will work the same in all versions
      of <productname>PostgreSQL</productname>.
     </para>
    </note>
   </sect2>

   <sect2 id="xfunc-sql-functions-returning-table">
    <title><acronym>SQL</acronym> Functions Returning <literal>TABLE</literal></title>

    <indexterm>
     <primary>function</primary>
     <secondary>RETURNS TABLE</secondary>
    </indexterm>

    <para>
     There is another way to declare a function as returning a set,
     which is to use the syntax
     <literal>RETURNS TABLE(<replaceable>columns</replaceable>)</literal>.
     This is equivalent to using one or more <literal>OUT</literal> parameters plus
     marking the function as returning <literal>SETOF record</literal> (or
     <literal>SETOF</literal> a single output parameter's type, as appropriate).
     This notation is specified in recent versions of the SQL standard, and
     thus may be more portable than using <literal>SETOF</literal>.
    </para>

    <para>
     For example, the preceding sum-and-product example could also be
     done this way:

<programlisting>
CREATE FUNCTION sum_n_product_with_tab (x int)
RETURNS TABLE(sum int, product int) AS $$
    SELECT $1 + tab.y, $1 * tab.y FROM tab;
$$ LANGUAGE SQL;
</programlisting>

     It is not allowed to use explicit <literal>OUT</literal> or <literal>INOUT</literal>
     parameters with the <literal>RETURNS TABLE</literal> notation &mdash; you must
     put all the output columns in the <literal>TABLE</literal> list.
    </para>
   </sect2>

   <sect2 id="xfunc-sql-polymorphic-functions">
    <title>Polymorphic <acronym>SQL</acronym> Functions</title>

    <para>
     <acronym>SQL</acronym> functions can be declared to accept and
     return the polymorphic types described in <xref
     linkend="extend-types-polymorphic"/>.  Here is a polymorphic
     function <function>make_array</function> that builds up an array
     from two arbitrary data type elements:
<screen>
CREATE FUNCTION make_array(anyelement, anyelement) RETURNS anyarray AS $$
    SELECT ARRAY[$1, $2];
$$ LANGUAGE SQL;

SELECT make_array(1, 2) AS intarray, make_array('a'::text, 'b') AS textarray;
 intarray | textarray
----------+-----------
 {1,2}    | {a,b}
(1 row)
</screen>
    </para>

    <para>
     Notice the use of the typecast <literal>'a'::text</literal>
     to specify that the argument is of type <type>text</type>. This is
     required if the argument is just a string literal, since otherwise
     it would be treated as type
     <type>unknown</type>, and array of <type>unknown</type> is not a valid
     type.
     Without the typecast, you will get errors like this:
<screen>
ERROR:  could not determine polymorphic type because input has type unknown
</screen>
    </para>

    <para>
     With <function>make_array</function> declared as above, you must
     provide two arguments that are of exactly the same data type; the

Title: SQL Functions Returning TABLE and Polymorphic SQL Functions
Summary
This section discusses the evolution of set-returning functions in PostgreSQL, highlighting how conditional execution with constructs like CASE was handled in earlier versions, often leading to complexity. It recommends using the LATERAL syntax for consistent results across versions and suggests creating custom set-returning functions as a workaround for conditional logic. The section then introduces the RETURNS TABLE syntax as an alternative for declaring set-returning functions, aligning with SQL standards and offering improved portability. Finally, it explores polymorphic SQL functions, demonstrating how functions like make_array can accept and return arbitrary data types.