mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
doc: Add event trigger C API documentation
From: Dimitri Fontaine <dimitri@2ndQuadrant.fr>
This commit is contained in:
parent
82b0102650
commit
0fe21ad8aa
@ -37,21 +37,27 @@
|
||||
<para>
|
||||
The <literal>ddl_command_start</> event occurs just before the
|
||||
execution of a <literal>CREATE</>, <literal>ALTER</>, or <literal>DROP</>
|
||||
command. As an exception, however, this event does not occur for
|
||||
command. No check whether the affected object exists or doesn't exist is
|
||||
performed before the event trigger fires.
|
||||
As an exception, however, this event does not occur for
|
||||
DDL commands targeting shared objects — databases, roles, and tablespaces
|
||||
— or for command targeting event triggers themselves. The event trigger
|
||||
— or for commands targeting event triggers themselves. The event trigger
|
||||
mechanism does not support these object types.
|
||||
<literal>ddl_command_start</> also occurs just before the execution of a
|
||||
<literal>SELECT INTO</literal> command, since this is equivalent to
|
||||
<literal>CREATE TABLE AS</literal>. The <literal>ddl_command_end</>
|
||||
event occurs just after the execution of this same set of commands.
|
||||
<literal>CREATE TABLE AS</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <literal>ddl_command_end</> event occurs just after the execution of
|
||||
this same set of commands.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <literal>sql_drop</> event occurs just before the
|
||||
<literal>ddl_command_end</> event trigger for any operation that drops
|
||||
database objects. To list the objects that have been dropped, use the set
|
||||
returning function <literal>pg_event_trigger_dropped_objects()</> from your
|
||||
database objects. To list the objects that have been dropped, use the
|
||||
set-returning function <literal>pg_event_trigger_dropped_objects()</> from the
|
||||
<literal>sql_drop</> event trigger code (see
|
||||
<xref linkend="functions-event-triggers">). Note that
|
||||
the trigger is executed after the objects have been deleted from the
|
||||
@ -76,6 +82,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Event triggers are created using the command <xref linkend="sql-createeventtrigger">.
|
||||
In order to create an event trigger, you must first create a function with
|
||||
the special return type <literal>event_trigger</literal>. This function
|
||||
need not (and may not) return a value; the return type serves merely as
|
||||
@ -607,4 +614,209 @@
|
||||
</table>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="event-trigger-interface">
|
||||
<title>Writing Event Trigger Functions in C</title>
|
||||
|
||||
<indexterm zone="event-trigger-interface">
|
||||
<primary>event trigger</primary>
|
||||
<secondary>in C</secondary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
This section describes the low-level details of the interface to an
|
||||
event trigger function. This information is only needed when writing
|
||||
event trigger functions in C. If you are using a higher-level language
|
||||
then these details are handled for you. In most cases you should
|
||||
consider using a procedural language before writing your event triggers
|
||||
in C. The documentation of each procedural language explains how to
|
||||
write an event trigger in that language.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Event trigger functions must use the <quote>version 1</> function
|
||||
manager interface.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When a function is called by the event trigger manager, it is not passed
|
||||
any normal arguments, but it is passed a <quote>context</> pointer
|
||||
pointing to a <structname>EventTriggerData</> structure. C functions can
|
||||
check whether they were called from the event trigger manager or not by
|
||||
executing the macro:
|
||||
<programlisting>
|
||||
CALLED_AS_EVENT_TRIGGER(fcinfo)
|
||||
</programlisting>
|
||||
which expands to:
|
||||
<programlisting>
|
||||
((fcinfo)->context != NULL && IsA((fcinfo)->context, EventTriggerData))
|
||||
</programlisting>
|
||||
If this returns true, then it is safe to cast
|
||||
<literal>fcinfo->context</> to type <literal>EventTriggerData
|
||||
*</literal> and make use of the pointed-to
|
||||
<structname>EventTriggerData</> structure. The function must
|
||||
<emphasis>not</emphasis> alter the <structname>EventTriggerData</>
|
||||
structure or any of the data it points to.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<structname>struct EventTriggerData</structname> is defined in
|
||||
<filename>commands/event_trigger.h</filename>:
|
||||
|
||||
<programlisting>
|
||||
typedef struct EventTriggerData
|
||||
{
|
||||
NodeTag type;
|
||||
const char *event; /* event name */
|
||||
Node *parsetree; /* parse tree */
|
||||
const char *tag; /* command tag */
|
||||
} EventTriggerData;
|
||||
</programlisting>
|
||||
|
||||
where the members are defined as follows:
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><structfield>type</></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Always <literal>T_EventTriggerData</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><structfield>tg_event</></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Describes the event for which the function is called, one of
|
||||
<literal>"ddl_command_start"</literal>, <literal>"ddl_command_end"</literal>,
|
||||
<literal>"sql_drop"</literal>.
|
||||
See <xref linkend="event-trigger-definition"> for the meaning of these
|
||||
events.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><structfield>parsetree</></term>
|
||||
<listitem>
|
||||
<para>
|
||||
A pointer to the parse tree of the command. Check the PostgreSQL
|
||||
source code for details. The parse tree structure is subject to change
|
||||
without notice.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><structfield>tag</></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The command tag associated with the event for which the event trigger
|
||||
is run, for example <literal>"CREATE FUNCTION"</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
An event trigger function must return a <symbol>NULL</> pointer
|
||||
(<emphasis>not</> an SQL null value, that is, do not
|
||||
set <parameter>isNull</parameter> true).
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="event-trigger-example">
|
||||
<title>A Complete Event Trigger Example</title>
|
||||
|
||||
<para>
|
||||
Here is a very simple example of an event trigger function written in C.
|
||||
(Examples of triggers written in procedural languages can be found in
|
||||
the documentation of the procedural languages.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The function <function>noddl</> raises an exception each time it is called.
|
||||
The event trigger definition associated the function with
|
||||
the <literal>ddl_command_start</literal> event. The effect is that all DDL
|
||||
commands (with the exceptions mentioned
|
||||
in <xref linkend="event-trigger-definition">) are prevented from running.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This is the source code of the trigger function:
|
||||
<programlisting><![CDATA[
|
||||
#include "postgres.h"
|
||||
#include "commands/event_trigger.h"
|
||||
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
Datum noddl(PG_FUNCTION_ARGS);
|
||||
|
||||
PG_FUNCTION_INFO_V1(noddl);
|
||||
|
||||
Datum
|
||||
noddl(PG_FUNCTION_ARGS)
|
||||
{
|
||||
EventTriggerData *trigdata;
|
||||
|
||||
if (!CALLED_AS_EVENT_TRIGGER(fcinfo)) /* internal error */
|
||||
elog(ERROR, "not fired by event trigger manager");
|
||||
|
||||
trigdata = (EventTriggerData *) fcinfo->context;
|
||||
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("command \"%s\" denied", trigdata->tag)));
|
||||
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
]]></programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
After you have compiled the source code (see <xref linkend="dfunc">),
|
||||
declare the function and the triggers:
|
||||
<programlisting>
|
||||
CREATE FUNCTION noddl() RETURNS event_trigger
|
||||
AS 'noddl' LANGUAGE C;
|
||||
|
||||
CREATE EVENT TRIGGER noddl ON ddl_command_start
|
||||
EXECUTE PROCEDURE noddl();
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Now you can test the operation of the trigger:
|
||||
<screen>
|
||||
=# \dy
|
||||
List of event triggers
|
||||
Name | Event | Owner | Enabled | Procedure | Tags
|
||||
-------+-------------------+-------+---------+-----------+------
|
||||
noddl | ddl_command_start | dim | enabled | noddl |
|
||||
(1 row)
|
||||
|
||||
=# CREATE TABLE foo(id serial);
|
||||
ERROR: command "CREATE TABLE" denied
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In this situation, in order to be able to run some DDL commands when you
|
||||
need to do so, you have to either drop the event trigger or disable it. It
|
||||
can be convenient to disable the trigger for only the duration of a
|
||||
transaction:
|
||||
<programlisting>
|
||||
BEGIN;
|
||||
ALTER EVENT TRIGGER noddl DISABLE;
|
||||
CREATE TABLE foo (id serial);
|
||||
ALTER EVENT TRIGGER noddl ENABLE;
|
||||
COMMIT;
|
||||
</programlisting>
|
||||
(Recall that DDL commands on event triggers themselves are not affected by
|
||||
event triggers.)
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
Loading…
Reference in New Issue
Block a user