postgresql/src/backend
Andres Freund 69f4b9c85f Move targetlist SRF handling from expression evaluation to new executor node.
Evaluation of set returning functions (SRFs_ in the targetlist (like SELECT
generate_series(1,5)) so far was done in the expression evaluation (i.e.
ExecEvalExpr()) and projection (i.e. ExecProject/ExecTargetList) code.

This meant that most executor nodes performing projection, and most
expression evaluation functions, had to deal with the possibility that an
evaluated expression could return a set of return values.

That's bad because it leads to repeated code in a lot of places. It also,
and that's my (Andres's) motivation, made it a lot harder to implement a
more efficient way of doing expression evaluation.

To fix this, introduce a new executor node (ProjectSet) that can evaluate
targetlists containing one or more SRFs. To avoid the complexity of the old
way of handling nested expressions returning sets (e.g. having to pass up
ExprDoneCond, and dealing with arguments to functions returning sets etc.),
those SRFs can only be at the top level of the node's targetlist.  The
planner makes sure (via split_pathtarget_at_srfs()) that SRF evaluation is
only necessary in ProjectSet nodes and that SRFs are only present at the
top level of the node's targetlist. If there are nested SRFs the planner
creates multiple stacked ProjectSet nodes.  The ProjectSet nodes always get
input from an underlying node.

We also discussed and prototyped evaluating targetlist SRFs using ROWS
FROM(), but that turned out to be more complicated than we'd hoped.

While moving SRF evaluation to ProjectSet would allow to retain the old
"least common multiple" behavior when multiple SRFs are present in one
targetlist (i.e.  continue returning rows until all SRFs are at the end of
their input at the same time), we decided to instead only return rows till
all SRFs are exhausted, returning NULL for already exhausted ones.  We
deemed the previous behavior to be too confusing, unexpected and actually
not particularly useful.

As a side effect, the previously prohibited case of multiple set returning
arguments to a function, is now allowed. Not because it's particularly
desirable, but because it ends up working and there seems to be no argument
for adding code to prohibit it.

Currently the behavior for COALESCE and CASE containing SRFs has changed,
returning multiple rows from the expression, even when the SRF containing
"arm" of the expression is not evaluated. That's because the SRFs are
evaluated in a separate ProjectSet node.  As that's quite confusing, we're
likely to instead prohibit SRFs in those places.  But that's still being
discussed, and the code would reside in places not touched here, so that's
a task for later.

There's a lot of, now superfluous, code dealing with set return expressions
around. But as the changes to get rid of those are verbose largely boring,
it seems better for readability to keep the cleanup as a separate commit.

Author: Tom Lane and Andres Freund
Discussion: https://postgr.es/m/20160822214023.aaxz5l4igypowyri@alap3.anarazel.de
2017-01-18 13:40:27 -08:00
..
access Improve comment in hashsearch.c. 2017-01-18 16:36:48 -05:00
bootstrap Remove dead code in bootstrap 2017-01-17 16:54:40 -03:00
catalog Update information_schema queries and system views for new relkind. 2017-01-18 14:29:23 -05:00
commands Move targetlist SRF handling from expression evaluation to new executor node. 2017-01-18 13:40:27 -08:00
executor Move targetlist SRF handling from expression evaluation to new executor node. 2017-01-18 13:40:27 -08:00
foreign Generate fmgr prototypes automatically 2017-01-17 14:06:07 -05:00
lib Fix overflow check in StringInfo; add missing casts 2017-01-10 11:41:13 -03:00
libpq Rename C symbols for backend lo_ functions 2017-01-17 12:35:30 -05:00
main Update copyright via script for 2017 2017-01-03 13:48:53 -05:00
nodes Move targetlist SRF handling from expression evaluation to new executor node. 2017-01-18 13:40:27 -08:00
optimizer Move targetlist SRF handling from expression evaluation to new executor node. 2017-01-18 13:40:27 -08:00
parser Make messages mentioning type names more uniform 2017-01-18 16:08:20 -03:00
po Translation updates 2016-08-08 11:08:00 -04:00
port Update copyright via script for 2017 2017-01-03 13:48:53 -05:00
postmaster Re-allow SSL passphrase prompt at server start, but not thereafter. 2017-01-04 12:44:03 -05:00
regex Update copyright via script for 2017 2017-01-03 13:48:53 -05:00
replication Update copyright via script for 2017 2017-01-03 13:48:53 -05:00
rewrite Change representation of statement lists, and add statement location info. 2017-01-14 16:02:35 -05:00
snowball Update copyright via script for 2017 2017-01-03 13:48:53 -05:00
storage Fix typo 2017-01-17 16:49:20 -03:00
tcop Change representation of statement lists, and add statement location info. 2017-01-14 16:02:35 -05:00
tsearch Generate fmgr prototypes automatically 2017-01-17 14:06:07 -05:00
utils Implement array version of jsonb_delete and operator 2017-01-18 21:37:59 +01:00
.gitignore Add .gitignore entries for AIX-specific intermediate build artifacts. 2015-07-08 20:44:22 -04:00
common.mk Remove maintainer-check target, fold into normal build 2013-10-10 20:11:56 -04:00
Makefile Generate fmgr prototypes automatically 2017-01-17 14:06:07 -05:00
nls.mk Remove trailing slashes from directories in find command 2015-09-18 22:06:54 -04:00