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.) + +