diff options
Diffstat (limited to 'doc/src/sgml/xfunc.sgml')
-rw-r--r-- | doc/src/sgml/xfunc.sgml | 179 |
1 files changed, 173 insertions, 6 deletions
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index be5ab0dd38a..1e79981f700 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.33 2001/08/28 14:20:26 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.34 2001/09/06 10:28:39 petere Exp $ --> <chapter id="xfunc"> @@ -337,11 +337,11 @@ SELECT clean_EMP(); </para> <para> - There are currently three procedural languages available in the standard - <productname>Postgres</productname> distribution (PLSQL, PLTCL and - PLPERL), and other languages can be defined. - Refer to <xref linkend="xplang"> for - more information. + There are currently four procedural languages available in the + standard <productname>PostgreSQL</productname> distribution: + PL/pgSQL, PL/Tcl, PL/Perl, and PL/Python. Other languages can be + defined by users. Refer to <xref linkend="xplang"> for more + information. </para> </sect1> @@ -1357,6 +1357,173 @@ LANGUAGE 'c'; </sect3> </sect2> </sect1> + + + <sect1 id="xfunc-plhandler"> + <title>Procedural Language Handlers</title> + + <para> + All calls to functions that are written in a language other than + the current <quote>version 1</quote> interface for compiled + languages, in particular in user-defined procedural languages, but + also functions written in SQL or the version 0 compiled language + interface, go through a <firstterm>call handler</firstterm> + function for the specific language. It is the responsibility of + the call handler to execute the function in a meaningful way, such + as by interpreting the supplied source text. This section + describes how a language call handler can be written. This is not + a common task, in fact, it has only been done a handful of times + in the history of <productname>PostgreSQL</productname>, but the + topic naturally belongs in this chapter, and the material might + give some insight into the extensible nature of the + <productname>PostgreSQL</productname> system. + </para> + + <para> + The call handler for a procedural language is a + <quote>normal</quote> function, which must be written in a + compiled language such as C and registered with + <productname>PostgreSQL</productname> as taking no arguments and + returning the <type>opaque</type> type, a placeholder for + unspecified or undefined types. This prevents the call handler + from being called directly as a function from queries. (However, + arguments may be supplied in the actual call to the handler when a + function in the language offered by the handler is to be + executed.) + </para> + + <note> + <para> + In <productname>PostgreSQL</productname> 7.1 and later, call + handlers must adhere to the <quote>version 1</quote> function + manager interface, not the old-style interface. + </para> + </note> + + <para> + The call handler is called in the same way as any other function: + It receives a pointer to a + <structname>FunctionCallInfoData</structname> struct containing + argument values and information about the called function, and it + is expected to return a <type>Datum</type> result (and possibly + set the <structfield>isnull</structfield> field of the + <structname>FunctionCallInfoData</structname> struct, if it wishes + to return an SQL NULL result). The difference between a call + handler and an ordinary callee function is that the + <structfield>flinfo->fn_oid</structfield> field of the + <structname>FunctionCallInfoData</structname> struct will contain + the OID of the actual function to be called, not of the call + handler itself. The call handler must use this field to determine + which function to execute. Also, the passed argument list has + been set up according to the declaration of the target function, + not of the call handler. + </para> + + <para> + It's up to the call handler to fetch the + <classname>pg_proc</classname> entry and to analyze the argument + and return types of the called procedure. The AS clause from the + <command>CREATE FUNCTION</command> of the procedure will be found + in the <literal>prosrc</literal> attribute of the + <classname>pg_proc</classname> table entry. This may be the source + text in the procedural language itself (like for PL/Tcl), a + pathname to a file, or anything else that tells the call handler + what to do in detail. + </para> + + <para> + Often, the same function is called many times per SQL statement. + A call handler can avoid repeated lookups of information about the + called function by using the + <structfield>flinfo->fn_extra</structfield> field. This will + initially be NULL, but can be set by the call handler to point at + information about the PL function. On subsequent calls, if + <structfield>flinfo->fn_extra</structfield> is already non-NULL + then it can be used and the information lookup step skipped. The + call handler must be careful that + <structfield>flinfo->fn_extra</structfield> is made to point at + memory that will live at least until the end of the current query, + since an <structname>FmgrInfo</structname> data structure could be + kept that long. One way to do this is to allocate the extra data + in the memory context specified by + <structfield>flinfo->fn_mcxt</structfield>; such data will + normally have the same lifespan as the + <structname>FmgrInfo</structname> itself. But the handler could + also choose to use a longer-lived context so that it can cache + function definition information across queries. + </para> + + <para> + When a PL function is invoked as a trigger, no explicit arguments + are passed, but the + <structname>FunctionCallInfoData</structname>'s + <structfield>context</structfield> field points at a + <structname>TriggerData</structname> node, rather than being NULL + as it is in a plain function call. A language handler should + provide mechanisms for PL functions to get at the trigger + information. + </para> + + <para> + This is a template for a PL handler written in C: +<programlisting> +#include "postgres.h" +#include "executor/spi.h" +#include "commands/trigger.h" +#include "utils/elog.h" +#include "fmgr.h" +#include "access/heapam.h" +#include "utils/syscache.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_type.h" + +PG_FUNCTION_INFO_V1(plsample_call_handler); + +Datum +plsample_call_handler(PG_FUNCTION_ARGS) +{ + Datum retval; + + if (CALLED_AS_TRIGGER(fcinfo)) + { + /* + * Called as a trigger procedure + */ + TriggerData *trigdata = (TriggerData *) fcinfo->context; + + retval = ... + } + else { + /* + * Called as a function + */ + + retval = ... + } + + return retval; +} +</programlisting> + </para> + + <para> + Only a few thousand lines of code have to be added instead of the + dots to complete the call handler. See <xref linkend="xfunc-c"> + for information on how to compile it into a loadable module. + </para> + + <para> + The following commands then register the sample procedural + language: +<programlisting> +CREATE FUNCTION plsample_call_handler () RETURNS opaque + AS '/usr/local/pgsql/lib/plsample.so' + LANGUAGE C; +CREATE LANGUAGE plsample + HANDLER plsample_call_handler; +</programlisting> + </para> + </sect1> </chapter> <!-- Keep this comment at the end of the file |