38.3. Un ejemplo completo de disparador de eventos #

Aquí tienes un ejemplo muy sencillo de una función de disparador de eventos escrita en C. (Se pueden encontrar ejemplos de disparadores escritos en lenguajes procedimentales en la documentación de dichos lenguajes).

La función noddl genera una excepción cada vez que se llama. La definición del disparador de eventos asoció la función con el evento ddl_command_start. El efecto es que se impide la ejecución de todos los comandos DDL (con las excepciones mencionadas en la Section 38.1).

Este es el código fuente de la función del disparador:

#include "postgres.h"

#include "commands/event_trigger.h"
#include "fmgr.h"

PG_MODULE_MAGIC;

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",
                    GetCommandTagName(trigdata->tag))));

    PG_RETURN_NULL();
}

Después de haber compilado el código fuente (ver la Section 36.10.5), declara la función y los disparadores:

CREATE FUNCTION noddl() RETURNS event_trigger
    AS 'noddl' LANGUAGE C;

CREATE EVENT TRIGGER noddl ON ddl_command_start
    EXECUTE FUNCTION noddl();

Ahora puedes probar el funcionamiento del disparador:

=# \dy
                     List of event triggers
 Name  |       Event       | Owner | Enabled | Function | Tags
-------+-------------------+-------+---------+----------+------
 noddl | ddl_command_start | dim   | enabled | noddl    |
(1 row)

=# CREATE TABLE foo(id serial);
ERROR:  command "CREATE TABLE" denied

En esta situación, para poder ejecutar algunos comandos DDL cuando necesites hacerlo, debes eliminar el disparador de eventos o desactivarlo. Puede ser conveniente desactivar el disparador únicamente durante la duración de una transacción:

BEGIN;
ALTER EVENT TRIGGER noddl DISABLE;
CREATE TABLE foo (id serial);
ALTER EVENT TRIGGER noddl ENABLE;
COMMIT;

(Recuerda que los comandos DDL sobre los propios disparadores de eventos no se ven afectados por los disparadores de eventos).