EL TEMA Disparadores Triggers SE ENCUENTRA ESPERANDO TUS CONOCIMIENTOS.

SOLO USAR BOTON EDIT ABAJO Y EMPIEZA A COLABORAR, SALUDOS Y MUCHAS GRACIAS PROF LAURO SOTO

Triggers (disparadores) Postgres tiene algunas interfaces cliente como Perl, Tcl, Python y C, así como dos Lenguajes Procedurales (PL). También es posible llamar a funciones C como acciones trigger. Notar que los eventos trigger a nivel STATEMENT no están soportados en la versión actual. Actualmente es posible especificar BEFORE o AFTER en los INSERT, DELETE o UPDATE de un registro como un evento trigger. Creación de Triggers Si un evento trigger ocurre, el administrador de triggers (llamado Ejecutor) inicializa la estructura global Trigger Data? *Current Trigger Data? (descrita más abajo) y llama a la función trigger para procesar el evento. La función trigger debe ser creada antes que el trigger, y debe hacerse como una función sin argumentos, y códigos de retorno opacos. La sintaxis para la creación de triggers es la siguiente:

   CREATE TRIGGER ‹trigger name> <BEFORE|AFTER› ‹INSERT|DELETE|UPDATE›
       ON ‹relation name> FOR EACH <ROW|STATEMENT›
       EXECUTE PROCEDURE <procedure name> (<function args>);

El nombre del trigger se usará si se desea eliminar el trigger. Se usa como argumento del comando DROP TRIGGER. La palabra siguiente determina si la función debe ser llamada antes (BEFORE) o después (AFTER) del evento. El siguiente elemento del comando determina en que evento/s será llamada la función. Es posible especificar múltiples eventos utilizado el operador OR. El nombre de la relación (relation name) determinará la tabla afectada por el evento. La instrucción FOR EACH determina si el trigger se ejecutará para cada fila afectada o bien antes (o después) de que la secuencia se haya completado. El nombre del procedimiento (procedure name) es la función C llamada. Los argumentos son pasados a la función en la estructura Current Trigger Data. El propósito de pasar los argumentos a la función es permitir a triggers diferentes con requisitos similares llamar a la misma función. Además, la función puede ser utilizada para disparar distintas relaciones (estas funciones son llamadas “general trigger funcions”). Como ejemplo de utilización de lo descrito, se puede hacer una función general que toma como argumentos dos nombres de campo e inserta el nombre del usuario y la fecha (timestamp) actuales en ellos. Esto permite, por ejemplo, utilizar los triggers en los eventos INSERT para realizar un seguimiento automático de la creación de registros en una tabla de transacciones. Se podría utilizar también para registrar actualizaciones si es utilizado en un evento UPDATE. Las funciones trigger retornan un área de tuplas (Heap Tuple?) al ejecutor. Esto es ignorado para trigger lanzados tras (AFTER) una operación INSERT, DELETE o UPDATE, pero permite lo siguiente a los triggers BEFORE: - retornar NULL e ignorar la operación para la tupla actual (y de este modo la tupla no será insertada/actualizada/borrada); - devolver un puntero a otra tupla (solo en eventos INSERT y UPDATE) que serán insertados (como la nueva versión de la tupla actualizada en caso de UPDATE) en lugar de la tupla original. Notar que no hay inicialización por parte del CREATE TRIGGER handler. Esto será cambiado en el futuro. Además, si más de un trigger es definido para el mismo evento en la misma relación, el orden de ejecución de los triggers es impredecible. Esto puede ser cambiado en el futuro. Si una función trigger ejecuta consultas SQL (utilizando SPI) entonces estas funciones pueden disparar nuevos triggers. Esto es conocido como triggers en cascada. No hay ninguna limitación explicita en cuanto al número de niveles de cascada. Si un trigger es lanzado por un INSERT e inserta una nueva tupla en la misma relación, el trigger será llamado de nuevo (por el nuevo INSERT). Actualmente, no se proporciona ningún mecanismo de sincronización (etc) para estos casos pero esto puede cambiar. Por el momento, existe una función llamada funny_dup17() en los tests de regresión que utiliza algunas técnicas para parar la recursividad (cascada) en si misma…

Interacción con el Trigger Manager Como se ha mencionado, cuando una función es llamada por el administrador de triggers (trigger manager), la estructura Trigger Data *Current Trigger Data no es NULL y se inicializa. Por lo cual es mejor verificar que Current Trigger Data no sea NULL al principio y asignar el valor NULL justo después de obtener la información para evitar llamadas a la función trigger que no procedan del administrador de triggers. La estructura Trigger Data se define en src/include/commands/trigger.h: typedef struct Trigger Data {

	Trigger Event?	tg_event;
	Relation	tg_relation;
	Heap Tuple	tg_trigtuple;
	Heap Tuple	tg_newtuple;
	Trigger		*tg_trigger;

} Trigger Data; tg_event

   describe los eventos para los que la función es llamada. Puede utilizar
   las siguientes macros para examinar tg_event:

   TRIGGER_FIRED_BEFORE(event) devuelve TRUE si el trigger se disparó antes;
   TRIGGER_FIRED_AFTER(event) devuelve TRUE si se disparó después;
   TRIGGER_FIRED_FOR_ROW(event) devuelve TRUE si el trigger se disparó para un 
                                evento a nivel de fila;
   TRIGGER_FIRED_FOR_STATEMENT(event) devuelve TRUE si el trigger se disparó
                                para un evento a nivel de sentencia. 
   TRIGGER_FIRED_BY_INSERT(event) devuelve TRUE si fue disparado por un INSERT;
   TRIGGER_FIRED_BY_DELETE(event) devuelve TRUE si fue disparado por un DELETE;
   TRIGGER_FIRED_BY_UPDATE(event) devuelve TRUE si fue disparado por un UPDATE.

tg_relation

   es un puntero a una estructura que describe la relación disparadora. Mirar
   en src/include/utils/rel.h para ver detalles sobre esta estructura. Lo más
   interesante es tg_relation→rd_att (descriptor de las tuplas de la relación)
   y tg_relation→rd_rel→relname (nombre de la relación. No es un char*, sino
   Name Data?. Utilizar SPI_getrelname(tg_relation) para obtener char* si se
   necesita una copia del nombre).

tg_trigtuple

   es un puntero a la tupla por la que es disparado el trigger, esto es, la
   tupla que se está insertando (en un INSERT), borrando (DELETE) o 
   actualizando (UPDATE).
   En caso de un INSERT/DELETE esto es lo que se debe devolver al Ejecutor si 
   no se desea reemplazar la tupla con otra (INSERT) o ignorar la operación. 

tg_newtuple

   es un puntero a la nueva tupla en caso de UPDATE y NULL si es para un INSERT
   o un DELETE. Esto es lo que debe devolverse al Ejecutor en el caso de un 
   UPDATE si no se desea reemplazar la tupla por otra o ignorar la operación. 

tg_trigger

   es un puntero a la estructura Trigger definida en src/include/utils/rel.h:

typedef struct Trigger {

    Oid         tgoid;
    char       *tgname;
    Oid         tgfoid;
    Fmgr Info?    tgfunc;
    int16       tgtype;
    bool        tgenabled;
    bool        tgisconstraint;
    bool        tgdeferrable;
    bool        tginitdeferred;
    int16       tgnargs;
    int16       tgattr[FUNC_MAX_ARGS];
    char      **tgargs;

} Trigger;

   tgname es el nombre del trigger, tgnargs es el número de argumentos en 
   tgargs,
   tgargs es un array de punteros a los argumentos especificados en el CREATE
   TRIGGER. Otros miembros son exclusivamente para uso interno.

Búsqueda personalizada