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).
This commit is contained in:
Tom Lane 2003-10-22 22:28:10 +00:00
parent b8400c7f52
commit cdbf9b328e
7 changed files with 341 additions and 288 deletions

View File

@ -1,4 +1,4 @@
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/filelist.sgml,v 1.31 2003/10/17 18:57:01 tgl Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/filelist.sgml,v 1.32 2003/10/22 22:28:10 tgl Exp $ -->
<!entity history SYSTEM "history.sgml">
<!entity info SYSTEM "info.sgml">
@ -7,8 +7,6 @@
<!entity notation SYSTEM "notation.sgml">
<!entity problems SYSTEM "problems.sgml">
<!entity bookindex SYSTEM "bookindex.sgml">
<!-- tutorial -->
<!entity advanced SYSTEM "advanced.sgml">
<!entity query SYSTEM "query.sgml">
@ -20,27 +18,16 @@
<!-- user's guide -->
<!entity array SYSTEM "array.sgml">
<!entity datatype SYSTEM "datatype.sgml">
<!entity datetime SYSTEM "datetime.sgml">
<!entity ddl SYSTEM "ddl.sgml">
<!entity dml SYSTEM "dml.sgml">
<!entity errcodes SYSTEM "errcodes.sgml">
<!entity features SYSTEM "features.sgml">
<!entity func SYSTEM "func.sgml">
<!entity indices SYSTEM "indices.sgml">
<!entity keywords SYSTEM "keywords.sgml">
<!entity mvcc SYSTEM "mvcc.sgml">
<!entity perform SYSTEM "perform.sgml">
<!entity queries SYSTEM "queries.sgml">
<!entity syntax SYSTEM "syntax.sgml">
<!entity typeconv SYSTEM "typeconv.sgml">
<!entity features-supported SYSTEM "features-supported.sgml">
<!entity features-unsupported SYSTEM "features-unsupported.sgml">
<!-- reference pages -->
<!entity % allfiles SYSTEM "ref/allfiles.sgml">
%allfiles;
<!-- administrator's guide -->
<!entity backup SYSTEM "backup.sgml">
<!entity charset SYSTEM "charset.sgml">
@ -52,7 +39,6 @@
<!entity manage-ag SYSTEM "manage-ag.sgml">
<!entity monitoring SYSTEM "monitoring.sgml">
<!entity regress SYSTEM "regress.sgml">
<!entity release SYSTEM "release.sgml">
<!entity runtime SYSTEM "runtime.sgml">
<!entity user-manag SYSTEM "user-manag.sgml">
<!entity wal SYSTEM "wal.sgml">
@ -62,8 +48,6 @@
<!entity ecpg SYSTEM "ecpg.sgml">
<!entity extend SYSTEM "extend.sgml">
<!entity func-ref SYSTEM "func-ref.sgml">
<!entity gist SYSTEM "gist.sgml">
<!entity indexcost SYSTEM "indexcost.sgml">
<!entity infoschema SYSTEM "information_schema.sgml">
<!entity jdbc SYSTEM "jdbc.sgml">
<!entity libpgeasy SYSTEM "libpgeasy.sgml">
@ -85,21 +69,40 @@
<!entity plsql SYSTEM "plpgsql.sgml">
<!entity pltcl SYSTEM "pltcl.sgml">
<!-- reference pages -->
<!entity % allfiles SYSTEM "ref/allfiles.sgml">
%allfiles;
<!-- developer's guide -->
<!entity arch-dev SYSTEM "arch-dev.sgml">
<!entity biblio SYSTEM "biblio.sgml">
<!entity bki SYSTEM "bki.sgml">
<!entity catalogs SYSTEM "catalogs.sgml">
<!entity compiler SYSTEM "compiler.sgml">
<!entity contacts SYSTEM "contacts.sgml">
<!entity cvs SYSTEM "cvs.sgml">
<!entity docguide SYSTEM "docguide.sgml">
<!entity geqo SYSTEM "geqo.sgml">
<!entity index SYSTEM "index.sgml">
<!entity gist SYSTEM "gist.sgml">
<!entity indexcost SYSTEM "indexcost.sgml">
<!entity nls SYSTEM "nls.sgml">
<!entity page SYSTEM "page.sgml">
<!entity plhandler SYSTEM "plhandler.sgml">
<!entity protocol SYSTEM "protocol.sgml">
<!entity sources SYSTEM "sources.sgml">
<!entity nls SYSTEM "nls.sgml">
<!-- appendixes -->
<!entity contacts SYSTEM "contacts.sgml">
<!entity cvs SYSTEM "cvs.sgml">
<!entity datetime SYSTEM "datetime.sgml">
<!entity docguide SYSTEM "docguide.sgml">
<!entity errcodes SYSTEM "errcodes.sgml">
<!entity features SYSTEM "features.sgml">
<!entity keywords SYSTEM "keywords.sgml">
<!entity release SYSTEM "release.sgml">
<!entity features-supported SYSTEM "features-supported.sgml">
<!entity features-unsupported SYSTEM "features-unsupported.sgml">
<!-- back matter -->
<!entity biblio SYSTEM "biblio.sgml">
<!entity bookindex SYSTEM "bookindex.sgml">
<!--
Some parts of the documentation are also source for some plain-text

174
doc/src/sgml/plhandler.sgml Normal file
View File

@ -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-&gt;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-&gt;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-&gt;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-&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 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:
-->

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.57 2003/10/17 18:57:01 tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.58 2003/10/22 22:28:10 tgl Exp $
-->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
@ -203,10 +203,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.57 2003/10/17 18:57:01 tg
</partintro>
&extend;
&indexcost;
&rules;
&trigger;
&spi;
&xplang;
&plsql;
@ -214,6 +212,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.57 2003/10/17 18:57:01 tg
&plperl;
&plpython;
&spi;
</part>
&reference;
@ -231,13 +231,15 @@ $Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.57 2003/10/17 18:57:01 tg
&arch-dev;
&catalogs;
&protocol;
&page;
&geqo;
&gist;
&bki;
&sources;
&compiler;
&nls;
&plhandler;
&geqo;
&indexcost;
&gist;
&page;
&bki;
&compiler;
</part>

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/spi.sgml,v 1.27 2003/08/31 17:32:20 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/spi.sgml,v 1.28 2003/10/22 22:28:10 tgl Exp $
-->
<chapter id="spi">
@ -11,18 +11,28 @@ $Header: /cvsroot/pgsql/doc/src/sgml/spi.sgml,v 1.27 2003/08/31 17:32:20 petere
<para>
The <firstterm>Server Programming Interface</firstterm>
(<acronym>SPI</acronym>) gives users the ability to run
<acronym>SQL</acronym> commands inside user-defined
<acronym>C</acronym> functions. <acronym>SPI</acronym> is a set of
(<acronym>SPI</acronym>) gives writers of user-defined
<acronym>C</acronym> functions the ability to run
<acronym>SQL</acronym> commands inside their functions.
<acronym>SPI</acronym> is a set of
interface functions to simplify access to the parser, planner,
optimizer, and executor. <acronym>SPI</acronym> also does some
memory management.
</para>
<note>
<para>
The available procedural languages provide various means to
execute SQL commands from procedures. Some of these are based on or
modelled after SPI, so this documentation might be of use for users
of those languages as well.
</para>
</note>
<para>
To avoid misunderstanding we'll use the term <quote>function</quote>
when we speak of <acronym>SPI</acronym> interface functions and
<quote>procedure</quote> for user-defined C-functions, which may be
<quote>procedure</quote> for a user-defined C-function that is
using <acronym>SPI</acronym>.
</para>
@ -50,15 +60,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/spi.sgml,v 1.27 2003/08/31 17:32:20 petere
<filename>executor/spi.h</filename>.
</para>
<note>
<para>
The available procedural languages provide different means to
execute SQL commands from procedures. Some of these are modelled
after SPI, so this documentation might be of use for those users as
well.
</para>
</note>
<sect1 id="spi-interface">
<title>Interface Functions</title>

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.30 2003/08/31 17:32:20 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.31 2003/10/22 22:28:10 tgl Exp $
-->
<chapter id="triggers">
@ -10,49 +10,44 @@ $Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.30 2003/08/31 17:32:20 pet
</indexterm>
<para>
This chapter describes how to write trigger functions. In
particular, it describes the C-language interface for trigger
functions. The trigger interfaces in most procedural languages
work analogously. (Trigger functions cannot be written in SQL.)
</para>
<para>
A trigger function can execute before or after a
<command>INSERT</command>, <command>UPDATE</command>, or
<command>DELETE</command>, either once per modified row, or once
per <acronym>SQL</acronym> statement.
This chapter describes how to write trigger functions. Trigger
functions can be written in C or in some of the available procedural
languages. It is not currently possible to write a SQL-language
trigger function.
</para>
<sect1 id="trigger-definition">
<title>Trigger Definition</title>
<title>Overview of Trigger Behavior</title>
<para>
If a trigger event occurs, the trigger manager is called by the
executor. It sets up an information structure of type
<structname>TriggerData</> (described below) and calls the trigger
function to handle the event.
A trigger can be defined to execute before or after an
<command>INSERT</command>, <command>UPDATE</command>, or
<command>DELETE</command> operation, either once per modified row,
or once per <acronym>SQL</acronym> statement.
If a trigger event occurs, the trigger's function is called
at the appropriate time to handle the event.
</para>
<para>
The trigger function must be defined before the trigger itself can be
created. The trigger function must be declared as a
function taking no arguments and returning type <literal>trigger</>.
(The trigger function receives its input through a <structname>TriggerData</>
structure, not in the form of ordinary function arguments.)
If the function is written in C, it must use the <quote>version 1</>
function manager interface.
(The trigger function receives its input through a specially-passed
<structname>TriggerData</> structure, not in the form of ordinary function
arguments.)
</para>
<para>
The syntax for creating triggers is described in
Once a suitable trigger function has been created, the trigger is
established with
<xref linkend="sql-createtrigger" endterm="sql-createtrigger-title">.
The same trigger function can be used for multiple triggers.
</para>
<para>
Trigger functions return a value of type <structname>HeapTuple</>,
which represents a table row, to the calling executor. The return
value is ignored for triggers fired after an operation, but a
triggers fired before an operation has the following choices:
Trigger functions return a table row (a value of type
<structname>HeapTuple</>) to the calling executor.
A trigger fired before an operation has the following choices:
<itemizedlist>
<listitem>
@ -75,13 +70,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.30 2003/08/31 17:32:20 pet
</itemizedlist>
A before trigger that does not intend to cause either of these
behaviors must be careful to return the same row that was passed
in as the new row (see below).
behaviors must be careful to return as its result the same row that was
passed in.
</para>
<para>
The return
value is ignored for triggers fired after an operation, and so
they may as well return <symbol>NULL</>.
</para>
<para>
If more than one trigger is defined for the same event on the same
relation, the triggers will be fired in alphabetical order by
relation, the triggers will be fired in alphabetical order by trigger
name. In the case of before triggers, the possibly-modified row
returned by each trigger becomes the input to the next trigger.
If any before trigger returns a <symbol>NULL</> pointer, the
@ -89,7 +90,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.30 2003/08/31 17:32:20 pet
</para>
<para>
If a trigger function executes SQL commands (using SPI) then these
If a trigger function executes SQL commands then these
commands may fire triggers again. This is known as cascading
triggers. There is no direct limitation on the number of cascade
levels. It is possible for cascades to cause a recursive invocation
@ -120,10 +121,57 @@ $Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.30 2003/08/31 17:32:20 pet
</sect1>
<sect1 id="trigger-manager">
<title>Interaction with the Trigger Manager</title>
<sect1 id="trigger-datachanges">
<title>Visibility of Data Changes</title>
<indexterm zone="trigger-manager">
<para>
If you execute SQL commands in your trigger function, and these
commands access the table that the trigger is for, then
you need to be aware of the data visibility rules, because they determine
whether these SQL commands will see the data change that the trigger
is fired for. Briefly:
<itemizedlist>
<listitem>
<para>
The data change (insertion, update, or deletion) causing the trigger
to fire is naturally
<emphasis>not</emphasis> visible to SQL commands executed in a
before trigger, because it hasn't happened yet.
</para>
</listitem>
<listitem>
<para>
However, SQL commands executed in a before trigger
<emphasis>will</emphasis> see the effects of data changes
for rows previously processed in the same outer command. This
requires caution, since the ordering of these change events
is not in general predictable; a SQL command that affects
multiple rows may visit the rows in any order.
</para>
</listitem>
<listitem>
<para>
When an after trigger is fired, all data changes made by the outer
command are already complete, and are visible to executed SQL commands.
</para>
</listitem>
</itemizedlist>
</para>
<para>
Further information about data visibility rules can be found in
<xref linkend="spi-visibility">. The example in <xref
linkend="trigger-example"> contains a demonstration of these rules.
</para>
</sect1>
<sect1 id="trigger-interface">
<title>Writing Trigger Functions in C</title>
<indexterm zone="trigger-interface">
<primary>trigger</primary>
<secondary>in C</secondary>
</indexterm>
@ -132,7 +180,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.30 2003/08/31 17:32:20 pet
This section describes the low-level details of the interface to a
trigger function. This information is only needed when writing a
trigger function in C. If you are using a higher-level
language then these details are handled for you.
language then these details are handled for you. The documentation
of each procedural language explains how to write a trigger in that
language.
</para>
<para>
Trigger functions must use the <quote>version 1</> function manager
interface.
</para>
<para>
@ -342,49 +397,12 @@ typedef struct Trigger
</varlistentry>
</variablelist>
</para>
</sect1>
<sect1 id="trigger-datachanges">
<title>Visibility of Data Changes</title>
<para>
If you are using the SPI interface to execute SQL commands in your
trigger functions written in C (or you are using a different
language and execute SQL commands in some way, which internally
goes through SPI as well), be sure to read <xref
linkend="spi-visibility"> so that you know which data is visible
at which point during the execution of a trigger. For triggers,
the most important consequences of the data visibility rules are:
<itemizedlist>
<listitem>
<para>
The row being inserted (<structfield>tg_trigtuple</>) is
<emphasis>not</emphasis> visible to SQL commands executed in a
before trigger.
</para>
</listitem>
<listitem>
<para>
The row being inserted (<structfield>tg_trigtuple</>)
<emphasis>is</emphasis> visible to SQL commands executed in an
after trigger (because it was just inserted).
</para>
</listitem>
<listitem>
<para>
A just-inserted row is visible to all SQL commands executed
within any trigger that is fired later in the execution of the
outer command (e.g., for the next row).
</para>
</listitem>
</itemizedlist>
</para>
<para>
The next section contains a demonstration of these rules applied.
A trigger function must return either <symbol>NULL</> or a
<structname>HeapTuple</> pointer. Be careful to return either
<structfield>tg_trigtuple</> or <structfield>tg_newtuple</>,
as appropriate, if you don't want to modify the row being operated on.
</para>
</sect1>
@ -393,6 +411,11 @@ typedef struct Trigger
<para>
Here is a very simple example of a trigger function written in C.
(Examples of triggers written in procedural languages may be found
in the documentation of the procedural languages.)
</para>
<para>
The function <function>trigf</> reports the number of rows in the
table <literal>ttest</> and skips the actual operation if the
command attempts to insert a null value into the column

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.75 2003/09/12 22:17:24 tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.76 2003/10/22 22:28:10 tgl Exp $
-->
<sect1 id="xfunc">
@ -58,6 +58,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.75 2003/09/12 22:17:24 tgl E
<para>
It's easiest to define <acronym>SQL</acronym>
functions, so we'll start by discussing those.
Most of the concepts presented for <acronym>SQL</acronym> functions
will carry over to the other types of functions.
</para>
<para>
@ -66,7 +68,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.75 2003/09/12 22:17:24 tgl E
understand the examples better.
Some examples from this chapter
can be found in <filename>funcs.sql</filename>
and <filename>funcs.c</filename> in the tutorial directory.
and <filename>funcs.c</filename> in the <filename>src/tutorial</>
directory in the <productname>PostgreSQL</productname> source distribution.
</para>
</sect1>
@ -597,19 +600,23 @@ DETAIL: A function returning ANYARRAY or ANYELEMENT must have at least one argu
<title>Procedural Language Functions</title>
<para>
Procedural languages aren't built into the <productname>PostgreSQL</productname> server; they are offered
Procedural languages aren't built into the
<productname>PostgreSQL</productname> server; they are offered
by loadable modules. Please refer to the documentation of the
procedural language in question for details about the syntax and how the function body
is interpreted for each language.
procedural language in question for details about the syntax and how the
function body is interpreted for each language.
</para>
<para>
There are currently four procedural languages available in the
standard <productname>PostgreSQL</productname> distribution:
<application>PL/pgSQL</application>, <application>PL/Tcl</application>,
<application>PL/Perl</application>, and <application>PL/Python</application>. Other languages can be
defined by users. Refer to <xref linkend="xplang"> for more
information. The basics of developing a new procedural language are covered in <xref linkend="xfunc-plhandler">.
<application>PL/Perl</application>, and
<application>PL/Python</application>.
Refer to <xref linkend="xplang"> for more information.
Other languages can be defined by users.
The basics of developing a new procedural language are covered in <xref
linkend="plhandler">.
</para>
</sect1>
@ -1478,7 +1485,7 @@ concat_text(PG_FUNCTION_ARGS)
to return set results (<xref linkend="xfunc-c-return-set">) and
implement trigger functions (<xref linkend="triggers">) and
procedural-language call handlers (<xref
linkend="xfunc-plhandler">). Version-1 code is also more
linkend="plhandler">). Version-1 code is also more
portable than version-0, because it does not break restrictions
on function call protocol in the C standard. For more details
see <filename>src/backend/utils/fmgr/README</filename> in the
@ -2247,163 +2254,6 @@ CREATE FUNCTION test(int, int) RETURNS int
</para>
</sect1>
<sect1 id="xfunc-plhandler">
<title>Procedural Language Handlers</title>
<indexterm zone="xfunc-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 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 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-&gt;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-&gt;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-&gt;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-&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 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>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
mode:sgml

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.24 2003/09/20 20:12:05 tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.25 2003/10/22 22:28:10 tgl Exp $
-->
<chapter id="xplang">
@ -28,7 +28,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.24 2003/09/20 20:12:05 tgl
<para>
Writing a handler for a new procedural language is described in
<xref linkend="xfunc-plhandler">. Several procedural languages are
<xref linkend="plhandler">. Several procedural languages are
available in the standard <productname>PostgreSQL</productname>
distribution, which can serve as examples.
</para>