web-dev-qa-db-fra.com

Passez l'ID utilisateur aux déclencheurs postgresql

J'utilise PostgreSQL 9.1. Ma base de données est structurée de sorte qu'il y ait des tables réelles que mon application utilise. Pour chaque table, il y a une table d'histoire qui stocke uniquement l'historique de changement. Les tables d'histoire contiennent les mêmes champs que les tables réelles plus les champs forment des informations supplémentaires, par exemple. Modifier le temps. Les tables d'histoire ne sont gérées que par des déclencheurs.

J'ai 2 types de déclencheurs:

  1. Before INSERT déclenche pour ajouter des informations supplémentaires aux tables lors de leur création (par exemple. Create_time).
  2. Before UPDATE déclencheur et before DELETE déclenche de copier des valeurs anciennes de la table réelle à l'historique.

Le problème est que j'aimerais utiliser des déclencheurs pour stocker également l'ID de l'utilisateur qui a apporté ces changements. Et par ID, je veux dire ID d'application PHP, non postgreSQL ID utilisateur.

Y a-t-il une façon raisonnable de faire ça?

Avec insertion et mise à jour, il pourrait être possible d'ajouter un champ supplémentaire pour ID à des tables réelles et de transmettre l'ID utilisateur à SQL dans le cadre de la requête SQL. Autant que je sache, cela ne fonctionne pas avec Supprimer.

Tous les déclencheurs sont structurés comme suit:

CREATE OR REPLACE FUNCTION before_delete_customer() RETURNS trigger AS $BODY$
BEGIN
    INSERT INTO _customer (
        edited_by,
        edit_time,
        field1,
        field2,
        ...,
        fieldN
    ) VALUES (
        -1, // <- This should be user id.
        NOW(),
        OLD.field1,
        OLD.field2,
        ...,
        OLD.fieldN
    );
    RETURN OLD;
END; $BODY$
LANGUAGE plpgsql
38
pipo

l'ensemble a une variante session de jeu non mentionné ici. Il est fort probable que les développeurs d'applications souhaitent généralement vraiment au lieu d'un plat clair ou d'une local local.

set session trolol.userr = 'Lol';

Ma configuration de la gâchette de test était un peu plus simple, mais l'idée est la même que celle de Craig Singer's Option 2.

create table lol (
    pk varchar(3) not null primary key,
    createuser varchar(20) not null);


CREATE OR REPLACE function update_created() returns trigger as $$ 
     begin new.createuser := current_setting('trolol.userr'); return new; end; $$ language plpgsql;


create trigger lol_update before update on lol for each row execute procedure update_created();
create trigger lol_insert before insert on lol for each row execute procedure update_created();

Je trouve cela assez acceptable à ce stade. Aucune instruction DDL et l'insertion/la mise à jour ne réussira pas si la variable de session n'est pas accidentellement définie pour une raison quelconque.

À l'aide de DISCARD ALL Peut-être pas une bonne idée car il ignore tout. Par exemple, Sqlkorma n'aime pas du tout cela. Au lieu de cela, vous pourriez simplement réinitialiser la variable en utilisant

SET software.theuser TO DEFAULT

Il y avait une quatrième option que j'ai brièvement envisagée. Dans l'ensemble standard de variables, il existe "Application_Name" qui pourrait être utilisé. Cette solution a des limitations, mais également des avantages évidents selon le contexte.

Pour plus d'informations sur cette quatrième option, reportez-vous à celles-ci:

définir Application_Name via JDBC

Documentation postgre sur Application_Name

10
lokori