returning sets can also be called in the select list
of a query. For each row that the query
generates by itself, the set-returning function is invoked, and an output
row is generated for each element of the function's result set.
The previous example could also be done with queries like
these:
<screen>
SELECT listchildren('Top');
listchildren
--------------
Child1
Child2
Child3
(3 rows)
SELECT name, listchildren(name) FROM nodes;
name | listchildren
--------+--------------
Top | Child1
Top | Child2
Top | Child3
Child1 | SubChild1
Child1 | SubChild2
(5 rows)
</screen>
In the last <command>SELECT</command>,
notice that no output row appears for <literal>Child2</literal>, <literal>Child3</literal>, etc.
This happens because <function>listchildren</function> returns an empty set
for those arguments, so no result rows are generated. This is the same
behavior as we got from an inner join to the function result when using
the <literal>LATERAL</literal> syntax.
</para>
<para>
<productname>PostgreSQL</productname>'s behavior for a set-returning function in a
query's select list is almost exactly the same as if the set-returning
function had been written in a <literal>LATERAL FROM</literal>-clause item
instead. For example,
<programlisting>
SELECT x, generate_series(1,5) AS g FROM tab;
</programlisting>
is almost equivalent to
<programlisting>
SELECT x, g FROM tab, LATERAL generate_series(1,5) AS g;
</programlisting>
It would be exactly the same, except that in this specific example,
the planner could choose to put <structname>g</structname> on the outside of the
nested-loop join, since <structname>g</structname> has no actual lateral dependency
on <structname>tab</structname>. That would result in a different output row
order. Set-returning functions in the select list are always evaluated
as though they are on the inside of a nested-loop join with the rest of
the <literal>FROM</literal> clause, so that the function(s) are run to
completion before the next row from the <literal>FROM</literal> clause is
considered.
</para>
<para>
If there is more than one set-returning function in the query's select
list, the behavior is similar to what you get from putting the functions
into a single <literal>LATERAL ROWS FROM( ... )</literal> <literal>FROM</literal>-clause
item. For each row from the underlying query, there is an output row
using the first result from each function, then an output row using the
second result, and so on. If some of the set-returning functions
produce fewer outputs than others, null values are substituted for the
missing data, so that the total number of rows emitted for one
underlying row is the same as for the set-returning function that
produced the most outputs. Thus the set-returning functions
run <quote>in lockstep</quote> until they are all exhausted, and then
execution continues with the next underlying row.
</para>
<para>
Set-returning functions can be nested in a select list, although that is
not allowed in <literal>FROM</literal>-clause items. In such cases, each level
of nesting is treated separately, as though it were
a separate <literal>LATERAL ROWS FROM( ... )</literal> item. For example, in
<programlisting>
SELECT srf1(srf2(x), srf3(y)), srf4(srf5(z)) FROM tab;
</programlisting>
the set-returning functions <function>srf2</function>, <function>srf3</function>,
and <function>srf5</function> would be run in lockstep for each row
of <structname>tab</structname>, and then <function>srf1</function> and <function>srf4</function>
would be applied in lockstep to each row produced by the lower
functions.
</para>
<para>
Set-returning functions cannot be used within conditional-evaluation
constructs, such as <literal>CASE</literal>