Historisation sous PostgreSql

Il n’est pas rare d’avoir comme réflexion d’un utilisateur: mais ce n’est pas moi qui a changée cette donnée ... qui a changé cette donnée ou pire mias c’est toi l’informaticien qui change nos données (oui oui juste pour embêter les utilisateurs)

Quand on utilise une base de donnée il est relativement simple de créer une gestion de l’historisation des changements via l’utilisation de triggers

Nous allons voir comment nous pouvons mettre en place cette gestion sur la table CPTE sur une base PostgreSql

Le principe est de créer:

  • une table d’historisation contenant les éléments de la table à historiser plus

    • date de l’historisation
    • id de la table d’historisation
    • user: personne qui a lancé la modification
  • trigger de create sur la table à historiser

  • trigger de delete sur la table à historiser

  • trigger de update sur la table à historiser

  • les n users

Warning

notre gestion utilise comme user qui a modifié la table le user de connexion à la base il faut donc pour avoir un suivi fin avoir un user de connexion par utilisateur

ce qui donne au niveau sql

CREATE TABLE cpte (
    id        serial CONSTRAINT key_cpte PRIMARY KEY,
    lib       varchar(100) NOT NULL,
    actif     boolean DEFAULT true
);

CREATE TABLE cpte_histo (
    id_histo  serial CONSTRAINT key_cpte_histo PRIMARY KEY,
    id          integer,
    lib       varchar(100),
    actif     boolean,
    userm      varchar(100),
    action      varchar(100),
    date      varchar(100) not null default 'timeofday'
);

CREATE ROLE "UserA" LOGIN PASSWORD 'usera'
    VALID UNTIL 'infinity';

CREATE ROLE "UserB" LOGIN PASSWORD 'userb'
    VALID UNTIL 'infinity';

CREATE OR REPLACE FUNCTION  histo_cpte_insert_update() RETURNS TRIGGER AS
 $BODY$
BEGIN
    INSERT INTO cpte_histo(id, lib, actif, userm, action)
            VALUES (NEW.id, NEW.lib, NEW.actif, CURRENT_USER,'INSERT OR UPDATE');
    RETURN NEW;
END ;
 $BODY$
 LANGUAGE 'plpgsql' ;

CREATE TRIGGER histo_cpte_insert_update_trg AFTER INSERT OR UPDATE ON cpte
    FOR EACH ROW EXECUTE PROCEDURE histo_cpte_insert_update();

CREATE OR REPLACE FUNCTION  histo_cpte_delete() RETURNS TRIGGER AS
 $BODY$
BEGIN
    INSERT INTO cpte_histo(id, lib, actif, userm, action)
            VALUES (OLD.id, OLD.lib, OLD.actif, CURRENT_USER, 'DELETE');
    RETURN NEW;
END ;
 $BODY$
 LANGUAGE 'plpgsql' ;

CREATE TRIGGER histo_cpte_delete_trg AFTER DELETE ON cpte
    FOR EACH ROW EXECUTE PROCEDURE histo_cpte_delete();

Un peu d’utilisation:

  • avec le user postgres
INSERT INTO cpte(lib) VALUES ('coucou');
commit;
  • avec le userA
UPDATE cpte SET lib='coucou2' where id=1;
commit;
UPDATE cpte SET lib='coucou3' where id=1;
commit;
  • avec le userB
DELETE FROM cpte WHERE id=1;
commit;

le résultat obtenu est le suivant

SELECT * FROM cpte_histo WHERE id=1;
id_histo id lib actif userm action date
6 3 coucou t postgres INSERT OR UPDATE Mon Dec 26 11:09:36.380000 2011 CET
7 3 coucou2 t postgres INSERT OR UPDATE Mon Dec 26 11:09:38.380000 2011 CET
8 3 coucou3 t postgres INSERT OR UPDATE Mon Dec 26 11:09:42.380000 2011 CET
9 3 coucou3 t postgres DELETE Mon Dec 26 11:09:44.380000 2011 CET