1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Second round of fmgr changes: triggers are now invoked in new style,

CurrentTriggerData is history.
This commit is contained in:
Tom Lane
2000-05-29 01:59:17 +00:00
parent 147ccf5c80
commit 18952f6744
41 changed files with 666 additions and 674 deletions

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.9 2000/03/26 18:32:27 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.10 2000/05/29 01:59:06 tgl Exp $
Postgres documentation
-->
@ -160,44 +160,42 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
<title>
Writing PL handlers
</title>
<note>
<para>
In <productname>Postgres</productname> 7.1 and later, call handlers
must adhere to the "new style" function manager interface.
</para>
</note>
<para>
The call handler for a procedural language must be written
in a compiler language such as 'C' and registered with
in a compiled language such as 'C' and registered with
<productname>Postgres</productname> as a function taking
no arguments and returning the
<type>opaque</type> type, a placeholder for unspecified or undefined types..
<type>opaque</type> type, a placeholder for unspecified or undefined types.
This prevents the call handler from being
called directly as a function from queries.
(However, arguments may be supplied in the actual call when a
PL function in the language offered by the handler is to be executed.)
</para>
<para>
However, arguments must be supplied on the actual call when a
PL function or trigger
procedure in the language offered by the handler is to be
executed.
<itemizedlist>
<listitem>
<para>
When called from the trigger manager, the only argument is
the object ID from the procedure's <filename>pg_proc</filename>
entry. All other
information from the trigger manager is found in the
global <structname>CurrentTriggerData</structname> pointer.
</para>
</listitem>
<listitem>
<para>
When called from the function manager, the arguments are
the object ID of the procedure's <filename>pg_proc</filename>
entry, the number
of arguments given to the PL function, the arguments in a
<structname>FmgrValues</structname> structure and a pointer
to a boolean where the
function tells the caller if the return value is the SQL
NULL value.
</para>
</listitem>
</itemizedlist>
The call handler is called in the same way as any other new-style
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
<literal>isnull</literal> field of the FunctionCallInfoData struct,
if it wishes to return an SQL NULL result). The difference between
a call handler and an ordinary callee function is that the
<literal>flinfo-&gt;fn_oid</literal> field of the FunctionCallInfoData
struct will contain the OID of the PL 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 PL function,
not of the call handler.
</para>
<para>
It's up to the call handler to fetch the
<filename>pg_proc</filename> entry and
@ -212,6 +210,28 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
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 <literal>flinfo-&gt;fn_extra</literal> field.
This will initially be NULL, but can be set by the call handler to
point at information about the PL function. On subsequent calls,
if <literal>flinfo-&gt;fn_extra</literal> is already non-NULL then it
can be used and the information lookup step skipped. The call handler
must be careful that <literal>flinfo-&gt;fn_extra</literal> 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.
</para>
<para>
When a PL function is invoked as a trigger, no explicit arguments
are passed, but the FunctionCallInfoData's
<literal>context</literal> field points at a TriggerData node,
rather than being NULL as it is in a plain function call.
A PL handler should provide mechanisms for PL functions to get
at the trigger information.
</para>
</refsect2>
<refsect2 id="R2-SQL-CREATELANGUAGE-4">
@ -275,39 +295,33 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
#include "executor/spi.h"
#include "commands/trigger.h"
#include "utils/elog.h"
#include "fmgr.h" /* for FmgrValues struct */
#include "fmgr.h"
#include "access/heapam.h"
#include "utils/syscache.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
Datum
plsample_call_handler(
Oid prooid,
int pronargs,
FmgrValues *proargs,
bool *isNull)
plsample_call_handler(PG_FUNCTION_ARGS)
{
Datum retval;
TriggerData *trigdata;
if (CurrentTriggerData == NULL) {
if (CALLED_AS_TRIGGER(fcinfo))
{
/*
* Called as a trigger procedure
*/
TriggerData *trigdata = (TriggerData *) fcinfo->context;
retval = ...
} else {
/*
* Called as a function
*/
retval = ...
} else {
/*
* Called as a trigger procedure
*/
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
retval = ...
}
*isNull = false;
return retval;
}
</programlisting>
@ -325,7 +339,7 @@ plsample_call_handler(
<programlisting>
CREATE FUNCTION plsample_call_handler () RETURNS opaque
AS '/usr/local/pgsql/lib/plsample.so'
LANGUAGE 'C';
LANGUAGE 'newC';
CREATE PROCEDURAL LANGUAGE 'plsample'
HANDLER plsample_call_handler
LANCOMPILER 'PL/Sample';