37.10. Proc�dures D�clencheur

PL/pgSQL peut �tre utilis� pour d�finir des proc�dures d�clencheur. Une proc�dure d�clencheur est cr��e gr�ce � la commande CREATE FUNCTION utilis�e comme fonction sans arguments ayant un type de retour trigger. Notez que la fonction doit �tre d�clar�e avec aucun argument m�me si elle s'attend � recevoir les arguments sp�cifi�s dans CREATE TRIGGER --- les arguments trigger sont pass�s via TG_ARGV, comme d�crit plus loin.

Quand une fonction PL/pgSQL est appel�e en tant que trigger, plusieurs variables sp�ciales sont cr��es automatiquement dans le bloc de plus haut niveau. Ce sont :

NEW

Type de donn�es RECORD; variable contenant la nouvelle ligne de base de donn�es pour les op�rations INSERT/UPDATE dans les d�clencheurs de niveau ligne. Cette variable est NULL dans un trigger de niveau instruction.

OLD

Type de donn�es RECORD; variable contenant l'ancienne ligne de base de donn�es pour les op�rations UPDATE/DELETE dans les triggers de niveau ligne. Cette variable est NULL dans les triggers de niveau instruction.

TG_NAME

Type de donn�es nom ; variable qui contient le nom du d�clencheur r�ellement lanc�.

TG_WHEN

Type de donn�es text ; une cha�ne, soit BEFORE soit AFTER selon la d�finition du d�clencheur.

TG_LEVEL

Type de donn�es text ; une cha�ne, soit ROW soit STATEMENT selon la d�finition du d�clencheur.

TG_OP

Type de donn�es text ; une cha�ne, INSERT, UPDATE ou DELETE, indiquant pour quelle op�ration le d�clencheur a �t� lanc�.

TG_RELID

Type de donn�es oid ; l'ID de l'objet de la table qui a caus� le d�clenchement.

TG_RELNAME

Type de donn�es nom ; le nom de la table qui a caus� le d�clenchement.

TG_NARGS

Type de donn�es integer ; le nombre d'arguments donn�s � la proc�dure d�clencheur dans l'instruction CREATE TRIGGER.

TG_ARGV[]

Type de donn�e text ; les arguments de l'instruction CREATE TRIGGER. L'index d�bute � 0. Les indices invalides (inf�rieurs � 0 ou sup�rieurs ou �gaux � tg_nargs) auront une valeur nulle.

Une fonction d�clencheur doit renvoyer soit NULL soit une valeur record/ligne ayant exactement la structure de la table pour laquelle le d�clencheur a �t� lanc�.

Les d�clencheurs de niveau ligne lanc�s BEFORE peuvent renvoyer NULL pour indiquer au gestionnaire de d�clencheur de sauter le reste de l'op�ration pour cette ligne (les d�clencheurs suivants ne sont pas lanc�s, et les INSERT/UPDATE/DELETE ne se font pas pour cette ligne). Si une valeur non NULL est renvoy�e alors l'op�ration se d�roule avec cette valeur ligne. Renvoyer une valeur ligne diff�rente de la valeur originale de NEW modifie la ligne qui sera ins�r�e ou mise � jour (mais n'a pas d'effet sur le cas DELETE). Pour modifier la ligne � stocker, il est possible de remplacer des valeurs seules directement dans NEW et de renvoyer NEW, ou de construire un nouveau record/ligne � renvoyer.

La valeur de retour d'un d�clencheur de niveau ligne BEFORE ou AFTER ou un d�clencheur de niveau ligne AFTER est toujours ignor� ; il pourrait aussi bien �tre NULL. N�anmoins, tous les types de d�clencheurs peuvent toujours annuler l'op�ration compl�te en envoyant une erreur.

L'Exemple 37-1 montre un exemple d'une proc�dure d�clencheur dans PL/pgSQL.

Exemple 37-1. Une proc�dure d�clencheur PL/pgSQL

Cet exemple de d�clencheur assure qu'� chaque moment o� une ligne est ins�r�e ou mise � jour dans la table, le nom de l'utilisateur courant et l'heure sont estampill�s dans la ligne. Et cela vous assure qu'un nom d'employ� est donn� et que le salaire est une valeur positive.

CREATE TABLE emp (
    empname text,
    salary integer,
    last_date timestamp,
    last_user text
);

CREATE FUNCTION emp_stamp() RETURNS trigger AS '
    BEGIN
        -- Verifie que empname et salary sont donn�s
        IF NEW.empname IS NULL THEN
            RAISE EXCEPTION ''empname cannot be NULL'';
        END IF;
        IF NEW.salary IS NULL THEN
            RAISE EXCEPTION ''% cannot have NULL salary'', NEW.empname;
        END IF;

        -- Qui travaille pour nous quand elle doit payer pour cela ?
        IF NEW.salary < 0 THEN
            RAISE EXCEPTION ''% cannot have a negative salary'', NEW.empname;
        END IF;

        -- Rappelons nous qui a chang� le payroll quand 
        NEW.last_date := ''now'';
        NEW.last_user := current_user;
        RETURN NEW;
    END;
' LANGUAGE plpgsql;

CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
    FOR EACH ROW EXECUTE PROCEDURE emp_stamp();