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:
parent
b8400c7f52
commit
cdbf9b328e
@ -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
174
doc/src/sgml/plhandler.sgml
Normal 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->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:
|
||||
-->
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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->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>
|
||||
</sect1>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode:sgml
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user