2008-11-20 17 views
19

J'ai ce déclencheur dans Postgresql que je ne peux pas simplement mettre au travail (ne fait rien). Pour comprendre, il y a la façon dont je l'ai définie:débogage postgresql trigger

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(); 

Maintenant, pour le rendre un peu plus intéressant .. Comment déboguer-vous déclencheurs?

+0

Ce n'est pas strictement lié, mais vous pourriez trouver utile dans vos aventures pgsql de toute façon: http://stackoverflow.com/questions/430123/how-do-i-enable-the-postgresql-function -profiler – Kev

Répondre

41
  1. Utilisez le code suivant dans une fonction de déclenchement, puis regarder l'onglet « messages » dans pgAdmin3 ou la sortie de psql:

    RAISE NOTICE 'myplpgsqlval is currently %', myplpgsqlval;  -- either this 
    RAISE EXCEPTION 'failed'; -- or that 
    
  2. Pour voir ce qui déclenche s'appelle en fait, combien etc fois, la déclaration suivante est la vie économiseur de choix:

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

    Notez que si votre déclencheur est pas appelé et que vous utilisez l'héritage, il peut être e Vous n'avez défini qu'un déclencheur sur la table parente, alors que les déclencheurs ne sont pas hérités automatiquement par les tables enfants.Pour parcourir cette fonction, vous pouvez utiliser le débogueur intégré à pgAdmin3, qui est activé par défaut sur Windows; tout ce que vous avez à faire est d'exécuter le code trouvé dans ... \ 8.3 \ share \ contrib \ pldbgapi.sql par rapport à la base de données que vous déboguez, redémarrez pgAdmin3, cliquez avec le bouton droit sur votre fonction de déclenchement, tapez 'Set Breakpoint', puis exécutez une instruction qui provoquerait le déclenchement du déclencheur, telle que l'instruction UPDATE ci-dessus.

+0

Vous ne savez pas si c'est comme cela sur les autres plates-formes. Aussi, j'aurais partagé la troisième méthode plus tôt (c'est * vraiment * pratique!) Mais je l'ai trouvé une semaine après que cette question ait été postée. – Kev

+1

Essayé avec Postgres 9.2 et pgAdmin d'accompagnement. Il n'y a pas de menu Set Breakpoint, même après avoir suivi les instructions mentionnées ci-dessus. Le fichier se trouve également à ... \ 9.2 \ share \ extension \ pldbgapi-1.0.sql. Système d'exploitation: Windows Server 2008 – Dojo

3

Vous pouvez utiliser les instructions 'raise notice' à l'intérieur de votre fonction de déclenchement pour le déboguer. Déboguer le déclencheur sans être appelé du tout est une autre histoire.

Si vous ajoutez une 'exception de relèvement' dans votre fonction de déclenchement, pouvez-vous toujours faire des insertions/mises à jour? De plus, si votre test de mise à jour se produit dans la même transaction que votre test d'insertion, now() sera le même (puisqu'il n'est calculé qu'une seule fois par transaction) et la mise à jour ne semblera donc rien faire. Si c'est le cas, faites-les soit dans des transactions séparées, ou s'il s'agit d'un test unitaire et que vous ne pouvez pas le faire, utilisez clock_timestamp().

J'ai un test unitaire qui dépend du temps qui passe entre les transactions, donc au début du test unitaire j'ai quelque chose comme:

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

Puis, dans la détente, utilisez « set modification_time = défaut ". Donc, normalement, cela ne fait pas le calcul supplémentaire, mais lors d'un test unitaire, cela me permet de faire des insertions avec pg_sleep entre les deux pour simuler le temps qui passe et qui se reflète dans les données.

+0

Bon indice ... donc il semble que la fonction ne soit pas appelée .. aucune idée pourquoi? –

+0

Avez-vous des autorisations d'exécution sur la fonction de déclenchement? – Kev

+0

Vous voudrez peut-être qualifier complètement (préfixer le nom du schéma) les noms des différents objets, juste pour être du bon côté. Aussi, vous pourriez probablement laisser de côté la partie "INSERT" de votre définition de déclencheur, la valeur par défaut prend soin de ce cas. –

2

Il s'avère que j'utilisais l'héritage dans le problème ci-dessus et j'ai oublié de le mentionner. Maintenant, pour tous ceux qui pourraient courir dans ce aussi bien, voici quelques conseils de débogage:

Utilisez le code suivant pour déboguer ce qu'un déclencheur fait:

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

Pour voir ce qui déclenche s'appelle en fait, combien de fois etc, la déclaration suivante est la vie économiseur de choix:

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

Ensuite, il y a une chose que je ne savais pas avant: ne se déclenche que lorsque le feu mise à jour du tableau exact qu'ils sont définis sur. Si vous utilisez l'héritage, vous DEVEZ les définir sur les tables enfants!

+0

Vous devriez faire un post-partage de cette friandise à http://www.postgresql.org/docs /8.3/interactive/ddl-inherit.html – Kev