diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-03-16 21:05:29 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-03-16 21:05:55 -0400 |
commit | 5e4a0b7194b9b53eeedc718fde1430eb649b8b62 (patch) | |
tree | 2881bb254c79749a3ae256c74225e85330a421f0 /doc/src | |
parent | c6b75b3f14fd4ff973ad3d2e2cfe42b5639bd101 (diff) |
Avoid holding a directory FD open across assorted SRF calls.
This extends the fixes made in commit 085b6b667 to other SRFs with the
same bug, namely pg_logdir_ls(), pgrowlocks(), pg_timezone_names(),
pg_ls_dir(), and pg_tablespace_databases().
Also adjust various comments and documentation to warn against
expecting to clean up resources during a ValuePerCall SRF's final
call.
Back-patch to all supported branches, since these functions were
all born broken.
Justin Pryzby, with cosmetic tweaks by me
Discussion: https://postgr.es/m/20200308173103.GC1357@telsasoft.com
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/xfunc.sgml | 98 |
1 files changed, 62 insertions, 36 deletions
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 7856e39e3fa..e7612135a92 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -2779,22 +2779,50 @@ HeapTupleGetDatum(HeapTuple tuple) <title>Returning Sets</title> <para> - There is also a special API that provides support for returning - sets (multiple rows) from a C-language function. A set-returning - function must follow the version-1 calling conventions. Also, - source files must include <filename>funcapi.h</filename>, as - above. - </para> - - <para> - A set-returning function (<acronym>SRF</>) is called - once for each item it returns. The <acronym>SRF</> must - therefore save enough state to remember what it was doing and - return the next item on each call. - The structure <structname>FuncCallContext</> is provided to help - control this process. Within a function, <literal>fcinfo->flinfo->fn_extra</> - is used to hold a pointer to <structname>FuncCallContext</> - across calls. + C-language functions have two options for returning sets (multiple + rows). In one method, called <firstterm>ValuePerCall</firstterm> + mode, a set-returning function is called repeatedly (passing the same + arguments each time) and it returns one new row on each call, until + it has no more rows to return and signals that by returning NULL. + The set-returning function (<acronym>SRF</acronym>) must therefore + save enough state across calls to remember what it was doing and + return the correct next item on each call. + In the other method, called <firstterm>Materialize</firstterm> mode, + a SRF fills and returns a tuplestore object containing its + entire result; then only one call occurs for the whole result, and + no inter-call state is needed. + </para> + + <para> + When using ValuePerCall mode, it is important to remember that the + query is not guaranteed to be run to completion; that is, due to + options such as <literal>LIMIT</literal>, the executor might stop + making calls to the set-returning function before all rows have been + fetched. This means it is not safe to perform cleanup activities in + the last call, because that might not ever happen. It's recommended + to use Materialize mode for functions that need access to external + resources, such as file descriptors. + </para> + + <para> + The remainder of this section documents a set of helper macros that + are commonly used (though not required to be used) for SRFs using + ValuePerCall mode. Additional details about Materialize mode can be + found in <filename>src/backend/utils/fmgr/README</filename>. Also, + the <filename>contrib</filename> modules in + the <productname>PostgreSQL</productname> source distribution contain + many examples of SRFs using both ValuePerCall and Materialize mode. + </para> + + <para> + To use the ValuePerCall support macros described here, + include <filename>funcapi.h</filename>. These macros work with a + structure <structname>FuncCallContext</structname> that contains the + state that needs to be saved across calls. Within the calling + SRF, <literal>fcinfo->flinfo->fn_extra</literal> is used to + hold a pointer to <structname>FuncCallContext</structname> across + calls. The macros automatically fill that field on first use, + and expect to find the same pointer there on subsequent uses. <programlisting> typedef struct FuncCallContext { @@ -2867,29 +2895,26 @@ typedef struct FuncCallContext </para> <para> - An <acronym>SRF</> uses several functions and macros that - automatically manipulate the <structname>FuncCallContext</> - structure (and expect to find it via <literal>fn_extra</>). Use: + The macros to be used by an <acronym>SRF</acronym> using this + infrastructure are: <programlisting> SRF_IS_FIRSTCALL() </programlisting> - to determine if your function is being called for the first or a - subsequent time. On the first call (only) use: + Use this to determine if your function is being called for the first or a + subsequent time. On the first call (only), call: <programlisting> SRF_FIRSTCALL_INIT() </programlisting> - to initialize the <structname>FuncCallContext</>. On every function call, - including the first, use: + to initialize the <structname>FuncCallContext</structname>. On every function call, + including the first, call: <programlisting> SRF_PERCALL_SETUP() </programlisting> - to properly set up for using the <structname>FuncCallContext</> - and clearing any previously returned data left over from the - previous pass. + to set up for using the <structname>FuncCallContext</structname>. </para> <para> - If your function has data to return, use: + If your function has data to return in the current call, use: <programlisting> SRF_RETURN_NEXT(funcctx, result) </programlisting> @@ -2913,7 +2938,14 @@ SRF_RETURN_DONE(funcctx) <structfield>multi_call_memory_ctx</> is a suitable location for any data that needs to survive until the <acronym>SRF</> is finished running. In most cases, this means that you should switch into - <structfield>multi_call_memory_ctx</> while doing the first-call setup. + <structfield>multi_call_memory_ctx</structfield> while doing the + first-call setup. + Use <literal>funcctx->user_fctx</literal> to hold a pointer to + any such cross-call data structures. + (Data you allocate + in <structfield>multi_call_memory_ctx</structfield> will go away + automatically when the query ends, so it is not necessary to free + that data manually, either.) </para> <warning> @@ -2970,8 +3002,8 @@ my_set_returning_function(PG_FUNCTION_ARGS) } else { - /* Here we are done returning items and just need to clean up: */ - <replaceable>user code</replaceable> + /* Here we are done returning items, so just report that fact. */ + /* (Resist the temptation to put cleanup code here.) */ SRF_RETURN_DONE(funcctx); } } @@ -3093,12 +3125,6 @@ CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer, Notice that in this method the output type of the function is formally an anonymous <structname>record</> type. </para> - - <para> - The directory <link linkend="tablefunc"><filename>contrib/tablefunc</filename></> - module in the source distribution contains more examples of - set-returning functions. - </para> </sect2> <sect2> |