From cdbf9b328ef3a917b1bd065c74db1f4015b1c822 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 22 Oct 2003 22:28:10 +0000 Subject: [PATCH] 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). --- doc/src/sgml/filelist.sgml | 49 +++++----- doc/src/sgml/plhandler.sgml | 174 ++++++++++++++++++++++++++++++++++ doc/src/sgml/postgres.sgml | 14 +-- doc/src/sgml/spi.sgml | 29 +++--- doc/src/sgml/trigger.sgml | 173 +++++++++++++++++++--------------- doc/src/sgml/xfunc.sgml | 182 ++++-------------------------------- doc/src/sgml/xplang.sgml | 4 +- 7 files changed, 339 insertions(+), 286 deletions(-) create mode 100644 doc/src/sgml/plhandler.sgml diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index 0333aaa6d5..be7050c5c8 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -1,4 +1,4 @@ - + @@ -7,8 +7,6 @@ - - @@ -20,27 +18,16 @@ - - - - - - - - - -%allfiles; - @@ -52,7 +39,6 @@ - @@ -62,8 +48,6 @@ - - @@ -85,21 +69,40 @@ + + +%allfiles; + - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + Writing A Procedural Language Handler + + + procedural language + handler for + + + + All calls to functions that are written in a language other than + the current version 1 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 call handler + 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. + + + + The call handler for a procedural language is a + normal function that must be written in a compiled + language such as C, using the version-1 interface, and registered + with PostgreSQL as taking no arguments + and returning the type language_handler. This + special pseudotype identifies the function as a call handler and + prevents it from being called directly in SQL commands. + + + + The call handler is called in the same way as any other function: + It receives a pointer to a + FunctionCallInfoData struct containing + argument values and information about the called function, and it + is expected to return a Datum result (and possibly + set the isnull field of the + FunctionCallInfoData structure, if it wishes + to return an SQL null result). The difference between a call + handler and an ordinary callee function is that the + flinfo->fn_oid field of the + FunctionCallInfoData 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. + + + + It's up to the call handler to fetch the entry of the function from the + system table + pg_proc and to analyze the argument + and return types of the called function. The AS clause from the + CREATE FUNCTION of the function will be found + in the prosrc column of the + pg_proc 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. + + + + 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 + flinfo->fn_extra field. This will + initially be NULL, but can be set by the call handler to point at + information about the called function. On subsequent calls, if + flinfo->fn_extra is already non-NULL + then it can be used and the information lookup step skipped. The + call handler must make sure that + flinfo->fn_extra is made to point at + memory that will live at least until the end of the current query, + since an FmgrInfo data structure could be + kept that long. One way to do this is to allocate the extra data + in the memory context specified by + flinfo->fn_mcxt; such data will + normally have the same lifespan as the + FmgrInfo itself. But the handler could + also choose to use a longer-lived memory context so that it can cache + function definition information across queries. + + + + When a procedural-language function is invoked as a trigger, no arguments + are passed in the usual way, but the + FunctionCallInfoData's + context field points at a + TriggerData structure, rather than being 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. + + + + This is a template for a procedural-language handler written in C: + +#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; +} + + Only a few thousand lines of code have to be added instead of the + dots to complete the call handler. + + + + After having compiled the handler function into a loadable module + (see ), the following commands then + register the sample procedural language: + +CREATE FUNCTION plsample_call_handler() RETURNS language_handler + AS 'filename' + LANGUAGE C; +CREATE LANGUAGE plsample + HANDLER plsample_call_handler; + + + + + + diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index 7247c52de7..80cb8ecef5 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -1,5 +1,5 @@ &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; + &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; diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml index f8c6c2cd94..efcc086a14 100644 --- a/doc/src/sgml/spi.sgml +++ b/doc/src/sgml/spi.sgml @@ -1,5 +1,5 @@ @@ -11,18 +11,28 @@ $Header: /cvsroot/pgsql/doc/src/sgml/spi.sgml,v 1.27 2003/08/31 17:32:20 petere The Server Programming Interface - (SPI) gives users the ability to run - SQL commands inside user-defined - C functions. SPI is a set of + (SPI) gives writers of user-defined + C functions the ability to run + SQL commands inside their functions. + SPI is a set of interface functions to simplify access to the parser, planner, optimizer, and executor. SPI also does some memory management. + + + 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. + + + To avoid misunderstanding we'll use the term function when we speak of SPI interface functions and - procedure for user-defined C-functions, which may be + procedure for a user-defined C-function that is using SPI. @@ -50,15 +60,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/spi.sgml,v 1.27 2003/08/31 17:32:20 petere executor/spi.h. - - - 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. - - - Interface Functions diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml index a4eb485bf5..fcf1c1753e 100644 --- a/doc/src/sgml/trigger.sgml +++ b/doc/src/sgml/trigger.sgml @@ -1,5 +1,5 @@ @@ -10,49 +10,44 @@ $Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.30 2003/08/31 17:32:20 pet - 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.) - - - - A trigger function can execute before or after a - INSERT, UPDATE, or - DELETE, either once per modified row, or once - per SQL 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. - Trigger Definition + Overview of Trigger Behavior - If a trigger event occurs, the trigger manager is called by the - executor. It sets up an information structure of type - TriggerData (described below) and calls the trigger - function to handle the event. + A trigger can be defined to execute before or after an + INSERT, UPDATE, or + DELETE operation, either once per modified row, + or once per SQL statement. + If a trigger event occurs, the trigger's function is called + at the appropriate time to handle the event. 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 trigger. - (The trigger function receives its input through a TriggerData - structure, not in the form of ordinary function arguments.) - If the function is written in C, it must use the version 1 - function manager interface. + (The trigger function receives its input through a specially-passed + TriggerData structure, not in the form of ordinary function + arguments.) - The syntax for creating triggers is described in + Once a suitable trigger function has been created, the trigger is + established with . + The same trigger function can be used for multiple triggers. - Trigger functions return a value of type 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 + HeapTuple) to the calling executor. + A trigger fired before an operation has the following choices: @@ -75,13 +70,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/trigger.sgml,v 1.30 2003/08/31 17:32:20 pet 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. + + + + The return + value is ignored for triggers fired after an operation, and so + they may as well return NULL. 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 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 - 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 - - Interaction with the Trigger Manager + + Visibility of Data Changes + + + 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: + + + + + The data change (insertion, update, or deletion) causing the trigger + to fire is naturally + not visible to SQL commands executed in a + before trigger, because it hasn't happened yet. + + + + + + However, SQL commands executed in a before trigger + will 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. + + + + + + When an after trigger is fired, all data changes made by the outer + command are already complete, and are visible to executed SQL commands. + + + + + + + Further information about data visibility rules can be found in + . The example in contains a demonstration of these rules. + + - + + Writing Trigger Functions in C + + trigger in C @@ -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. + + + + Trigger functions must use the version 1 function manager + interface. @@ -342,49 +397,12 @@ typedef struct Trigger - - - - Visibility of Data Changes - - - 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 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: - - - - - The row being inserted (tg_trigtuple) is - not visible to SQL commands executed in a - before trigger. - - - - - - The row being inserted (tg_trigtuple) - is visible to SQL commands executed in an - after trigger (because it was just inserted). - - - - - - 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). - - - - - The next section contains a demonstration of these rules applied. + A trigger function must return either NULL or a + HeapTuple pointer. Be careful to return either + tg_trigtuple or tg_newtuple, + as appropriate, if you don't want to modify the row being operated on. @@ -393,6 +411,11 @@ typedef struct Trigger 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.) + + + The function trigf reports the number of rows in the table ttest and skips the actual operation if the command attempts to insert a null value into the column diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index f570ce89fd..dc5c3bd4c2 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,5 +1,5 @@ @@ -58,6 +58,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.75 2003/09/12 22:17:24 tgl E It's easiest to define SQL functions, so we'll start by discussing those. + Most of the concepts presented for SQL functions + will carry over to the other types of functions. @@ -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 funcs.sql - and funcs.c in the tutorial directory. + and funcs.c in the src/tutorial + directory in the PostgreSQL source distribution. @@ -597,19 +600,23 @@ DETAIL: A function returning ANYARRAY or ANYELEMENT must have at least one argu Procedural Language Functions - Procedural languages aren't built into the PostgreSQL server; they are offered + Procedural languages aren't built into the + PostgreSQL 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. There are currently four procedural languages available in the standard PostgreSQL distribution: PL/pgSQL, PL/Tcl, - PL/Perl, and PL/Python. Other languages can be - defined by users. Refer to for more - information. The basics of developing a new procedural language are covered in . + PL/Perl, and + PL/Python. + Refer to for more information. + Other languages can be defined by users. + The basics of developing a new procedural language are covered in . @@ -1478,7 +1485,7 @@ concat_text(PG_FUNCTION_ARGS) to return set results () and implement trigger functions () and procedural-language call handlers (). 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 src/backend/utils/fmgr/README in the @@ -2247,163 +2254,6 @@ CREATE FUNCTION test(int, int) RETURNS int - - Procedural Language Handlers - - - procedural language - handler for - - - - All calls to functions that are written in a language other than - the current version 1 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 call handler - 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 PostgreSQL, but the - topic naturally belongs in this chapter, and the material might - give some insight into the extensible nature of the - PostgreSQL system. - - - - The call handler for a procedural language is a - normal function that must be written in a compiled - language such as C, using the version-1 interface, and registered - with PostgreSQL as taking no arguments - and returning the type language_handler. This - special pseudotype identifies the function as a call handler and - prevents it from being called directly in SQL commands. - - - - The call handler is called in the same way as any other function: - It receives a pointer to a - FunctionCallInfoData struct containing - argument values and information about the called function, and it - is expected to return a Datum result (and possibly - set the isnull field of the - FunctionCallInfoData structure, if it wishes - to return an SQL null result). The difference between a call - handler and an ordinary callee function is that the - flinfo->fn_oid field of the - FunctionCallInfoData 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. - - - - It's up to the call handler to fetch the entry of the function from the system table - pg_proc and to analyze the argument - and return types of the called function. The AS clause from the - CREATE FUNCTION of the function will be found - in the prosrc column of the - pg_proc 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. - - - - 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 - flinfo->fn_extra field. This will - initially be NULL, but can be set by the call handler to point at - information about the called function. On subsequent calls, if - flinfo->fn_extra is already non-NULL - then it can be used and the information lookup step skipped. The - call handler must make sure that - flinfo->fn_extra is made to point at - memory that will live at least until the end of the current query, - since an FmgrInfo data structure could be - kept that long. One way to do this is to allocate the extra data - in the memory context specified by - flinfo->fn_mcxt; such data will - normally have the same lifespan as the - FmgrInfo itself. But the handler could - also choose to use a longer-lived memory context so that it can cache - function definition information across queries. - - - - When a procedural-language function is invoked as a trigger, no arguments - are passed in the usual way, but the - FunctionCallInfoData's - context field points at a - TriggerData structure, rather than being 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. - - - - This is a template for a procedural-language handler written in C: - -#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; -} - - Only a few thousand lines of code have to be added instead of the - dots to complete the call handler. - - - - After having compiled the handler function into a loadable module - (see ), the following commands then - register the sample procedural language: - -CREATE FUNCTION plsample_call_handler() RETURNS language_handler - AS 'filename' - LANGUAGE C; -CREATE LANGUAGE plsample - HANDLER plsample_call_handler; - - - - @@ -28,7 +28,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.24 2003/09/20 20:12:05 tgl Writing a handler for a new procedural language is described in - . Several procedural languages are + . Several procedural languages are available in the standard PostgreSQL distribution, which can serve as examples. -- GitLab