Hola amigos de la lista,

Tengo un problema con la ejecucion de un Trigger, explico: Busco con un
trigger registrar todos los movimientos de ciertas tablas (auditoria de
movimientos)

Tengo la sig. funcion que es llamada por el trigger:
CREATE OR REPLACE FUNCTION procesa_usuario_audit() RETURNS trigger AS
$$
    DECLARE
    BEGIN
    -- Crea un registro en usuario_audit para reflejar las operaciones
    -- realizadas en usuario utiliza las variables especiales TG_OP
    -- para efectuar la operacion
        IF (TG_OP = 'DELETE') THEN
            INSERT INTO usuario_audit SELECT
nextval('usuario_audit_id_usuario_audit_seq'::regclass), 'D', now(), user,
OLD.id_usuario;
            RETURN OLD;
         ELSIF (TG_OP = 'UPDATE') THEN
            INSERT INTO usuario_audit SELECT
nextval('usuario_audit_id_usuario_audit_seq'::regclass), 'U', now(), user,
NEW.id_usuario;
            RETURN NEW;
         ELSIF (TG_OP = 'INSERT') THEN
            INSERT INTO usuario_audit SELECT
nextval('usuario_audit_id_usuario_audit_seq'::regclass), 'I', now(), user,
NEW.id_usuario;
            RETURN NEW;
         END IF;
    RETURN NULL; -- el resultado es ignorado puesto que este es un trigger
AFTER
    END;
$$
LANGUAGE plpgsql;

Esta es la tabla original principal a donde amarro el trigger: tabla usuario

     Columna     |              Tipo              |
Modificadores
-----------------+--------------------------------+---------------------------------------------------------------
 id              | integer                        | not null valor por
omisin nextval('usuario_id_seq'::regclass)
 id_usuario      | integer                        | not null
 nombre          | character varying              |
 apellido        | character varying              |
 puesto          | character varying              |
 depto           | character varying              |
 num_serv_sol    | integer                        |
 ultimo_ticket   | integer                        |
 usuario_windows | character varying              |
 clave_windows   | character varying              |
 email           | character varying              |
 usuario_correo  | character varying              |
 clave_correo    | character varying              |
 ext             | integer                        |
 tipo_linea      | character varying              |
 tel_libre       | boolean                        |
 celular         | numeric(14,0)                  |
 plan_celular    | character varying              |
 foto            | bytea                          |
 userbd          | name                           | not null valor por
omisin getpgusername()
 timeupdate      | timestamp(0) without time zone | not null valor por
omisin now()
-ndices:
    "usuario_celular_key" UNIQUE, btree (celular)
    "usuario_id_key" UNIQUE, btree (id)
    "usuario_id_usuario_key" UNIQUE, btree (id_usuario)
    "usuario_usuario" UNIQUE, btree (id_usuario, nombre, apellido, email)
Referenciada por:
    TABLE "carpetas" CONSTRAINT "carpetas_usuario" FOREIGN KEY (id_usuario)
REFERENCES usuario(id_usuario) ON UPDATE CASCADE
    TABLE "equipo" CONSTRAINT "equipo_usuario" FOREIGN KEY (id_usuario)
REFERENCES usuario(id_usuario) ON UPDATE CASCADE
    TABLE "internet" CONSTRAINT "internet_fk" FOREIGN KEY (id_usuario)
REFERENCES usuario(id_usuario) ON UPDATE CASCADE
Triggers:
    grabar_usuario AFTER INSERT OR DELETE OR UPDATE ON usuario FOR EACH
STATEMENT EXECUTE PROCEDURE procesa_usuario_audit()

Este es el trigger:
CREATE TRIGGER grabar_usuario AFTER INSERT OR DELETE OR UPDATE ON usuario
FOR EACH STATEMENT EXECUTE PROCEDURE procesa_usuario_audit();

Esta es la tabla donde ingresa los datos el trigger: tabla usuario_audit

  Columna   |            Tipo
|                                   Modificadores
------------+-----------------------------+-----------------------------------------------------------------------------------
 id_audit   | integer                     | not null valor por omisin
nextval('usuario_audit_id_usuario_audit_seq'::regclass)
 operacion  | character(1)                | not null
 timeupdate | timestamp without time zone | not null
 userbd     | text                        | not null
 id_usuario | integer                     | not null
-ndices:
    "usuario_audit_pkey" PRIMARY KEY, btree (id_audit)


------------------------------------------------------------------------------------------------------------------------
Este es el mensaje de error:
Ejecuto un update o insert en la tabla usuario:

soporte=# update usuario set depto = 'Administracion' where id_usuario =
514;
ERROR:  el registro «new» no ha sido asignado aún
DETALLE:  La estructura de fila de un registro aún no asignado no está
determinado.
CONTEXTO:  función PL/pgSQL «procesa_usuario_audit» en la línea 10 en
sentencia SQL
soporte=#


Ejecuto la instruccion de manera directa del trigger (ver funcion):
soporte=# INSERT INTO usuario_audit SELECT
nextval('usuario_audit_id_usuario_audit_seq'::regclass),'I', now(), user, 8;
INSERT 92551 1
soporte=# INSERT INTO usuario_audit SELECT
nextval('usuario_audit_id_usuario_audit_seq'::regclass),'U', now(), user, 8;
INSERT 92552 1
(resultado OK)

reviso la tabla afectada:
soporte=# select * from usuario_audit;
 id_audit | operacion |       timeupdate        | userbd | id_usuario
----------+-----------+-------------------------+--------+------------
       10 | I         | 2011-04-18 15:05:05.917 | miguel |          8
       11 | I         | 2011-04-18 15:05:11.839 | miguel |          8
       12 | U         | 2011-04-18 15:10:57.464 | miguel |          8
(3 filas)

No entiendo que pasa, ya realize pruebas con BEFORE y no funciona, en teoria
funciona con AFTER segun ejemplos tomados en la red (Yo practique con los
ejemplos y funcionan con AFTER)
Alguna sugerencia?

Desde ya, muchas gracias.

soporte=# select * from version();
                           version
-------------------------------------------------------------
 PostgreSQL 8.4.4, compiled by Visual C++ build 1400, 32-bit
(1 fila)
desde Win XP Pro
-- 
Miguel Angel Torres
Culiacan, Sin.

Responder a