diff --git a/doc/src/sgml/event-trigger.sgml b/doc/src/sgml/event-trigger.sgml
index 7343227d28..8950bfde2f 100644
--- a/doc/src/sgml/event-trigger.sgml
+++ b/doc/src/sgml/event-trigger.sgml
@@ -37,21 +37,27 @@
The ddl_command_start> event occurs just before the
execution of a CREATE>, ALTER>, or 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.
ddl_command_start> also occurs just before the execution of a
SELECT INTO command, since this is equivalent to
- CREATE TABLE AS. The ddl_command_end>
- event occurs just after the execution of this same set of commands.
+ CREATE TABLE AS.
+
+
+
+ The ddl_command_end> event occurs just after the execution of
+ this same set of commands.
The sql_drop> event occurs just before the
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 pg_event_trigger_dropped_objects()> from your
+ database objects. To list the objects that have been dropped, use the
+ set-returning function pg_event_trigger_dropped_objects()> from the
sql_drop> event trigger code (see
). Note that
the trigger is executed after the objects have been deleted from the
@@ -76,6 +82,7 @@
+ Event triggers are created using the command .
In order to create an event trigger, you must first create a function with
the special return type event_trigger. This function
need not (and may not) return a value; the return type serves merely as
@@ -607,4 +614,209 @@
+
+ Writing Event Trigger Functions in C
+
+
+ event trigger
+ in C
+
+
+
+ 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.
+
+
+
+ Event trigger functions must use the version 1> function
+ manager interface.
+
+
+
+ When a function is called by the event trigger manager, it is not passed
+ any normal arguments, but it is passed a context> pointer
+ pointing to a EventTriggerData> structure. C functions can
+ check whether they were called from the event trigger manager or not by
+ executing the macro:
+
+CALLED_AS_EVENT_TRIGGER(fcinfo)
+
+ which expands to:
+
+((fcinfo)->context != NULL && IsA((fcinfo)->context, EventTriggerData))
+
+ If this returns true, then it is safe to cast
+ fcinfo->context> to type EventTriggerData
+ * and make use of the pointed-to
+ EventTriggerData> structure. The function must
+ not alter the EventTriggerData>
+ structure or any of the data it points to.
+
+
+
+ struct EventTriggerData is defined in
+ commands/event_trigger.h:
+
+
+typedef struct EventTriggerData
+{
+ NodeTag type;
+ const char *event; /* event name */
+ Node *parsetree; /* parse tree */
+ const char *tag; /* command tag */
+} EventTriggerData;
+
+
+ where the members are defined as follows:
+
+
+
+ type>
+
+
+ Always T_EventTriggerData.
+
+
+
+
+
+ tg_event>
+
+
+ Describes the event for which the function is called, one of
+ "ddl_command_start", "ddl_command_end",
+ "sql_drop".
+ See for the meaning of these
+ events.
+
+
+
+
+
+ parsetree>
+
+
+ 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.
+
+
+
+
+
+ tag>
+
+
+ The command tag associated with the event for which the event trigger
+ is run, for example "CREATE FUNCTION".
+
+
+
+
+
+
+
+ An event trigger function must return a NULL> pointer
+ (not> an SQL null value, that is, do not
+ set isNull true).
+
+
+
+
+ A Complete Event Trigger Example
+
+
+ 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.)
+
+
+
+ The function noddl> raises an exception each time it is called.
+ The event trigger definition associated the function with
+ the ddl_command_start event. The effect is that all DDL
+ commands (with the exceptions mentioned
+ in ) are prevented from running.
+
+
+
+ This is the source code of the trigger function:
+context;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("command \"%s\" denied", trigdata->tag)));
+
+ PG_RETURN_NULL();
+}
+]]>
+
+
+
+ After you have compiled the source code (see ),
+ declare the function and the triggers:
+
+CREATE FUNCTION noddl() RETURNS event_trigger
+ AS 'noddl' LANGUAGE C;
+
+CREATE EVENT TRIGGER noddl ON ddl_command_start
+ EXECUTE PROCEDURE noddl();
+
+
+
+
+ Now you can test the operation of the trigger:
+
+=# \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
+
+
+
+
+ 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:
+
+BEGIN;
+ALTER EVENT TRIGGER noddl DISABLE;
+CREATE TABLE foo (id serial);
+ALTER EVENT TRIGGER noddl ENABLE;
+COMMIT;
+
+ (Recall that DDL commands on event triggers themselves are not affected by
+ event triggers.)
+
+