1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-12 05:01:15 +03:00

PL/pgSQL functions can return sets. Neil Conway's patch, modified so

that the functionality is available to anyone via ReturnSetInfo, rather
than hard-wiring it to PL/pgSQL.
This commit is contained in:
Tom Lane
2002-08-30 00:28:41 +00:00
parent 82ccb420d5
commit e107f3a7e3
21 changed files with 957 additions and 408 deletions

View File

@@ -371,36 +371,61 @@ tuple toaster will decide whether toasting is needed.
Functions accepting or returning sets
-------------------------------------
As of 7.1, Postgres has limited support for functions returning sets;
this is presently handled only in SELECT output expressions, and the
behavior is to generate a separate output tuple for each set element.
There is no direct support for functions accepting sets; instead, the
function will be called multiple times, once for each element of the
input set. This behavior will very likely be changed in future releases,
but here is how it works now:
[ this section revised 29-Aug-2002 for 7.3 ]
If a function is marked in pg_proc as returning a set, then it is called
with fcinfo->resultinfo pointing to a node of type ReturnSetInfo. A
function that desires to return a set should raise an error "called in
context that does not accept a set result" if resultinfo is NULL or does
not point to a ReturnSetInfo node. ReturnSetInfo contains a field
not point to a ReturnSetInfo node.
There are currently two modes in which a function can return a set result:
value-per-call, or materialize. In value-per-call mode, the function returns
one value each time it is called, and finally reports "done" when it has no
more values to return. In materialize mode, the function's output set is
instantiated in a Tuplestore object; all the values are returned in one call.
Additional modes might be added in future.
ReturnSetInfo contains a field "allowedModes" which is set (by the caller)
to a bitmask that's the OR of the modes the caller can support. The actual
mode used by the function is returned in another field "returnMode". For
backwards-compatibility reasons, returnMode is initialized to value-per-call
and need only be changed if the function wants to use a different mode.
The function should elog() if it cannot use any of the modes the caller is
willing to support.
Value-per-call mode works like this: ReturnSetInfo contains a field
"isDone", which should be set to one of these values:
ExprSingleResult /* expression does not return a set */
ExprMultipleResult /* this result is an element of a set */
ExprEndResult /* there are no more elements in the set */
A function returning set returns one set element per call, setting
fcinfo->resultinfo->isDone to ExprMultipleResult for each element.
After all elements have been returned, the next call should set
isDone to ExprEndResult and return a null result. (Note it is possible
to return an empty set by doing this on the first call.)
(the caller will initialize it to ExprSingleResult). If the function simply
returns a Datum without touching ReturnSetInfo, then the call is over and a
single-item set has been returned. To return a set, the function must set
isDone to ExprMultipleResult for each set element. After all elements have
been returned, the next call should set isDone to ExprEndResult and return a
null result. (Note it is possible to return an empty set by doing this on
the first call.)
As of 7.3, the ReturnSetInfo node also contains a link to the ExprContext
within which the function is being evaluated. This is useful for functions
The ReturnSetInfo node also contains a link to the ExprContext within which
the function is being evaluated. This is useful for value-per-call functions
that need to close down internal state when they are not run to completion:
they can register a shutdown callback function in the ExprContext.
Materialize mode works like this: the function creates a Tuplestore holding
the (possibly empty) result set, and returns it. There are no multiple calls.
The function must also return a TupleDesc that indicates the tuple structure.
The Tuplestore and TupleDesc should be created in the context
econtext->ecxt_per_query_memory (note this will *not* be the context the
function is called in). The function stores pointers to the Tuplestore and
TupleDesc into ReturnSetInfo, sets returnMode to indicate materialize mode,
and returns null. isDone is not used and should be left at ExprSingleResult.
There is no support for functions accepting sets; instead, the function will
be called multiple times, once for each element of the input set.
Notes about function handlers
-----------------------------