doc: Add event trigger C API documentation
authorPeter Eisentraut
Thu, 4 Jul 2013 01:06:20 +0000 (21:06 -0400)
committerPeter Eisentraut
Thu, 4 Jul 2013 01:06:20 +0000 (21:06 -0400)
From: Dimitri Fontaine 

doc/src/sgml/event-trigger.sgml

index 7343227d28f6075ad3c11f00a0e2d0639b8451ec..8950bfde2fcb0b13b80c28027ebb76d672dfdccd 100644 (file)
    
      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
    
   
 
+  
+   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:
+
+#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();
+}
+]]>
+   
+
+   
+    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.)
+   
+