aboutsummaryrefslogtreecommitdiff
path: root/doc/src/sgml/xfunc.sgml
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/sgml/xfunc.sgml')
-rw-r--r--doc/src/sgml/xfunc.sgml179
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-&gt;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-&gt;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-&gt;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-&gt;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-&gt;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