]> granicus.if.org Git - postgresql/commitdiff
Move docs about index cost estimation functions and writing a procedural
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 22 Oct 2003 22:28:10 +0000 (22:28 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 22 Oct 2003 22:28:10 +0000 (22:28 +0000)
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).

doc/src/sgml/filelist.sgml
doc/src/sgml/plhandler.sgml [new file with mode: 0644]
doc/src/sgml/postgres.sgml
doc/src/sgml/spi.sgml
doc/src/sgml/trigger.sgml
doc/src/sgml/xfunc.sgml
doc/src/sgml/xplang.sgml

index 0333aaa6d586e592da53addfa6f9d7390ab67987..be7050c5c82adde69dc7ed21cbfa5863fdfe0b4b 100644 (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">
 <!-- 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">
 <!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
diff --git a/doc/src/sgml/plhandler.sgml b/doc/src/sgml/plhandler.sgml
new file mode 100644 (file)
index 0000000..eb56028
--- /dev/null
@@ -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:
+-->
index 7247c52de7c4e83b4c36b4c2b2d1c80d2eb904f2..80cb8ecef5402f8f7c1e39f70d005216c7029d59 100644 (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;
+  &sources;
+  &nls;
+  &plhandler;
   &geqo;
+  &indexcost;
   &gist;
+  &page;
   &bki;
-  &sources;
   &compiler;
-  &nls;
 
  </part>
 
index f8c6c2cd949d04404f527baa6ee70d5f27723346..efcc086a14817fafdce12136f6a039e1ef49990b 100644 (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>
index a4eb485bf59ff1d8083bf7b2c11b2662149e5328..fcf1c1753ee454cec2d4660cac77aa4121f62c3e 100644 (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>
+
+   <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>
 
-   <indexterm zone="trigger-manager">
+  <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
index f570ce89fd42346d3585329fd499127f33601f95..dc5c3bd4c26a14fd04e22a7a662225fc2296e12b 100644 (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
index c3482909eaa0ca24be1b1172636699d77660edf8..0b849713eae28ef804ce704f89dd6d6f265623f2 100644 (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>