diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2003-10-22 22:28:10 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2003-10-22 22:28:10 +0000 |
| commit | cdbf9b328ef3a917b1bd065c74db1f4015b1c822 (patch) | |
| tree | 40249d481b35d664ce15196b12e5e4f721b79bc1 /doc/src/sgml/plhandler.sgml | |
| parent | b8400c7f528a341b7745fa7f048bd559ba9f59a4 (diff) | |
| download | postgresql-cdbf9b328ef3a917b1bd065c74db1f4015b1c822.tar.gz | |
Move docs about index cost estimation functions and writing a procedural
language handler to the 'Internals' area, per my proposal of yesterday.
Clean up the trigger documentation a bit. Push SPI chapter to the end
of its part, and reorder the Internals chapters into what seems a more
sensible order (at the moment anyway).
Diffstat (limited to 'doc/src/sgml/plhandler.sgml')
| -rw-r--r-- | doc/src/sgml/plhandler.sgml | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/doc/src/sgml/plhandler.sgml b/doc/src/sgml/plhandler.sgml new file mode 100644 index 0000000000..eb5602864c --- /dev/null +++ b/doc/src/sgml/plhandler.sgml @@ -0,0 +1,174 @@ +<!-- +$Header: /cvsroot/pgsql/doc/src/sgml/plhandler.sgml,v 1.1 2003/10/22 22:28:10 tgl Exp $ +--> + + <chapter id="plhandler"> + <title>Writing A Procedural Language Handler</title> + + <indexterm zone="plhandler"> + <primary>procedural language</primary> + <secondary>handler for</secondary> + </indexterm> + + <para> + All calls to functions that are written in a language other than + the current <quote>version 1</quote> interface for compiled + languages (this includes functions in user-defined procedural languages, + functions written in SQL, and functions using 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 chapter outlines + how a new procedural language's call handler can be written. + </para> + + <para> + The call handler for a procedural language is a + <quote>normal</quote> function that must be written in a compiled + language such as C, using the version-1 interface, and registered + with <productname>PostgreSQL</productname> as taking no arguments + and returning the type <type>language_handler</type>. This + special pseudotype identifies the function as a call handler and + prevents it from being called directly in SQL commands. + </para> + + <para> + The call handler is called in the same way as any other function: + It receives a pointer to a + <structname>FunctionCallInfoData</structname> <type>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> structure, 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> structure 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 entry of the function from the + system table + <classname>pg_proc</classname> and to analyze the argument + and return types of the called function. The <literal>AS</> clause from the + <command>CREATE FUNCTION</command> of the function will be found + in the <literal>prosrc</literal> column of the + <classname>pg_proc</classname> row. This may be the source + text in the procedural language itself (like for PL/Tcl), a + path name 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 <symbol>NULL</>, but can be set by the call handler to point at + information about the called function. On subsequent calls, if + <structfield>flinfo->fn_extra</structfield> is already non-<symbol>NULL</> + then it can be used and the information lookup step skipped. The + call handler must make sure 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 memory context so that it can cache + function definition information across queries. + </para> + + <para> + When a procedural-language function is invoked as a trigger, no arguments + are passed in the usual way, but the + <structname>FunctionCallInfoData</structname>'s + <structfield>context</structfield> field points at a + <structname>TriggerData</structname> structure, rather than being <symbol>NULL</> + as it is in a plain function call. A language handler should + provide mechanisms for procedural-language functions to get at the trigger + information. + </para> + + <para> + This is a template for a procedural-language handler written in C: +<programlisting> +#include "postgres.h" +#include "executor/spi.h" +#include "commands/trigger.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> + Only a few thousand lines of code have to be added instead of the + dots to complete the call handler. + </para> + + <para> + After having compiled the handler function into a loadable module + (see <xref linkend="dfunc">), the following commands then + register the sample procedural language: +<programlisting> +CREATE FUNCTION plsample_call_handler() RETURNS language_handler + AS '<replaceable>filename</replaceable>' + LANGUAGE C; +CREATE LANGUAGE plsample + HANDLER plsample_call_handler; +</programlisting> + </para> + + </chapter> + +<!-- Keep this comment at the end of the file +Local variables: +mode:sgml +sgml-omittag:nil +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +sgml-parent-document:nil +sgml-default-dtd-file:"./reference.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:("/usr/lib/sgml/catalog") +sgml-local-ecat-files:nil +End: +--> |
