2008-11-20 16 views
19

Tengo este desencadenador en Postgresql que no puedo simplemente ir a trabajar (no hace nada). Para la comprensión, no es como la he definido:depuración postgresql desencadenador

CREATE TABLE documents (
    ... 
    modification_time timestamp with time zone DEFAULT now() 
); 

CREATE FUNCTION documents_update_mod_time() RETURNS trigger 
AS $$ 
    begin 
    new.modification_time := now(); 
    return new; 
    end 
$$ 
    LANGUAGE plpgsql; 

CREATE TRIGGER documents_modification_time 
    BEFORE INSERT OR UPDATE ON documents 
    FOR EACH ROW 
    EXECUTE PROCEDURE documents_update_mod_time(); 

Ahora para que sea un poco más interesante .. ¿Cómo se depura desencadenantes?

+0

Esto no es estrictamente relacionados, pero puede que le resulte útil en sus aventuras pgsql todos modos: http://stackoverflow.com/questions/430123/how-do-i-enable-the-postgresql-function -profiler – Kev

Respuesta

41
  1. utilizar el siguiente código dentro de una función de disparo, y luego ver la pestaña 'Mensajes' en pgadmin3 o la salida de psql:

    RAISE NOTICE 'myplpgsqlval is currently %', myplpgsqlval;  -- either this 
    RAISE EXCEPTION 'failed'; -- or that 
    
  2. Para ver lo que desencadena consiguen realmente llama, cuántos tiempos, etc., la siguiente declaración es el salvavidas de elección:

    EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers 
    

    Tenga en cuenta que si su activación no está recibiendo llamadas y utilizar la herencia, puede ser º solo ha definido un desencadenador en la tabla primaria, mientras que las tablas secundarias no heredan los desencadenantes automáticamente.

  3. Para recorrer la función, puede usar el depurador integrado en pgAdmin3, que en Windows está habilitado de forma predeterminada; todo lo que tiene que hacer es ejecutar el código encontrado en ... \ 8.3 \ share \ contrib \ pldbgapi.sql contra la base de datos que está depurando, reiniciar pgAdmin3, hacer clic con el botón derecho en su función de activación, presionar 'Establecer punto de interrupción', y luego ejecute una declaración que provocaría que el desencadenador se dispare, como la instrucción UPDATE anterior.

+0

No estoy seguro si esto es cómo hacerlo en otras plataformas. También habría compartido el tercer método antes (¡es * realmente * útil!) Pero descubrí esto una semana después de que esta pregunta se publicara originalmente. – Kev

+1

Probado con Postgres 9.2 y pgAdmin que lo acompaña. No hay menú Establecer punto de interrupción en cualquier lugar, incluso después de seguir las instrucciones mencionadas anteriormente. Además, el archivo se encuentra en ... \ 9.2 \ share \ extension \ pldbgapi-1.0.sql. Sistema operativo: Windows Server 2008 – Dojo

3

Puede usar declaraciones de 'aviso' dentro de su función de desencadenador para depurarlo. Para depurar el gatillo no se llama en absoluto es otra historia.

Si agrega una 'excepción de aumento' dentro de la función de desencadenante, ¿aún puede hacer inserciones/actualizaciones?

Además, si su prueba de actualización ocurre en la misma transacción que su prueba de inserción, ahora() será la misma (ya que solo se calcula una vez por transacción) y por lo tanto la actualización no parece hacer nada. Si ese es el caso, hágalo en transacciones separadas, o si esta es una prueba unitaria y no puede hacer eso, use clock_timestamp().

tengo una prueba de unidad que depende de algún tiempo pasando por entre las transacciones, por lo que al comienzo de la prueba unitaria tengo algo como:

ALTER TABLE documents 
    ALTER COLUMN modification_time SET DEFAULT clock_timestamp(); 

Luego, en el gatillo, el uso "set modification_time = por defecto ".

Normalmente no hace el cálculo extra, pero durante una prueba unitaria esto me permite hacer inserciones con pg_sleep en el medio para simular el paso del tiempo y realmente tener eso reflejado en los datos.

+0

Buena pista ... por lo que parece que la función no se llama ... alguna idea ¿por qué? –

+0

¿Tiene permisos de ejecución en la función de disparo? – Kev

+0

Es posible que desee calificar completamente (anteponer el nombre del esquema) los nombres de los diversos objetos, solo para estar seguros. También es probable que pueda omitir la parte "INSERTAR" de su definición de desencadenante; el valor predeterminado se ocupa de este caso. –

2

Resulta que estaba usando la herencia en el problema anterior y olvidé mencionarlo. Ahora, para todos los que podría encontrarse con esto también, aquí hay algunos consejos de depuración:

utilizar el siguiente código para depurar lo que un disparador está haciendo:

RAISE NOTICE 'test';  -- either this 
RAISE EXCEPTION 'failed'; -- or that 

Para ver lo que desencadena consiguen realmente llama, ¿cuántas veces etc, la siguiente declaración es la vida de ahorro de elección:

EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers 

Luego está la única cosa que no sabía antes: se dispara sólo cuando el fuego actualizar la tabla exacta que están definidos en. Si usa herencia, ¡DEBE definirlos en las tablas secundarias también!

+0

Debería publicar el tidbit de manera cruzada en http://www.postgresql.org/docs /8.3/interactive/ddl-inherit.html – Kev

Cuestiones relacionadas