PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 16/01/2011 20:50:32

bebert73
Membre

trigger paramétrable

Bonjour à tous,

J'essaye de faire un truc un peu biscornu...dans une fonction trigger, faire référence au nom d'une colonne mais via un paramètre (NEW.parametre)

je m'explique :

soit la table toto
create table toto (
   a text,
   b text );

et la table titi
create table titi (
   c text
   d text );

sur chaque table, je veux définir un trigger qui empêche la validation par exemple quand on essaye de saisir "pipot" dans toto(a) ou dans titi(c).
c'est simple à faire, pour chaque table une fonction trigger et son trigger

par contre je me demande si on peut ruser, et ne déclarer qu'une seule fonction trigger, qui soit appelée par chacun des deux trigger sur les tables toto et titi

la difficulté, c'est de référencer le nom des colonnes...si la fonction est appelée par le trigger de la table toto, ce sera new.a, mais si elle est appelée par le trigger de la table titi, ce sera new.c

comment faire ?

j'ai essayé en passant le nom de la colonne en argument du trigger via TG_ARGV, mais ça ne fonctionne pas

voilà ce que j'ai essayé de faire, tout d'abord ma fonction trigger :

create function verification (
begin
   if (new.TG_ARGV[0] = 'pipot') then
      raise exception ...
   end if;
end;)

puis les deux triggers
create trigger verificationToto before insert on toto for each row execute procedure verification('a');
create trigger verificationTiti before insert on titi for each row execute procedure verification('c');

mais bien sur ça plante car il n'arrive pas à interpréter TG_ARGV[0]

une idée ? c'est faisable, pas faisable ? j'ai essayé de m'en sortir avec EXECUTE, mais là aussi j'ai pas réussi pour l'instant

Hors ligne

#2 16/01/2011 21:11:54

Marc Cousin
Membre

Re : trigger paramétrable

Ce n'est pas le vrai code de la fonction trigger, la déclaration est invalide, je pense ?

Mais de toutes façons, non, vous ne pourrez pas passer un nom de colonne en argument dans new. La substitution ne sera pas faite. PL/PgSQL est assez limité de ce point de vue.

Par contre rien ne vous empêche de regarder ce que vaut TG_TABLE_NAME ou TG_ARGV[0] dans votre bout de PL, et d'avoir un simple IF, qui regarde dans l'une ou l'autre des colonnes. C'est moins dynamique, mais au moins ça marchera.

On peut peut-être aussi faire une requête dynamique avec un EXEC dans le code PL, je ne l'ai jamais tenté pour un trigger (et donc pour accéder à NEW).


Marc.

Hors ligne

#3 16/01/2011 23:17:19

bebert73
Membre

Re : trigger paramétrable

ok merci Marc...

Oui c'est ce que je vais finir par faire, je vais coder un IF dans ma fonction pour différencier selon tg_table_name...

Je pensais qu'il y avait une solution un peu plus élégante, un peu comme les fonctions eval() dans php ou javascript, mais apparemment le EXECUTE n'aime pas tellement avoir NEW dans son code... j'ai un message d'erreur qui me semble assez clair : "ERREUR: NEW utilisé dans une requête qui ne fait pas partie d'une règle - LINE 1 : SELECT NEW.name"

ci-dessous le code de ce que j'ai tenté avec EXECUTE

CREATE FUNCTION verification() RETURNS TRIGGER AS $$
DECLARE
   mon_texte VARCHAR(32);
BEGIN
   EXECUTE 'SELECT NEW.' || TG_ARGV[0] INTO mon_texte;
   IF (mon_texte = 'pipot') THEN
         RAISE EXCEPTION ...
   END IF;
END;
$$ LANGUAGE PLPGSQL

pour info, j'ai trouvé ça
http://www.developpez.net/forums/d89744 … -debutant/

Le modérateur du site confirme bien que ce n'est pas possible en PL/PGSQL, il dit :
"Dans la commande EXECUTE requete INTO resultat, la requête ne doit faire référence à aucune variable plpgsql, y compris NEW. Il faut remplacer les références à NEW.champ par leurs valeurs réelles. "

Par contre il ajoute :
"Oui le plpgsql est un langage qui ne permet pas vraiment de se référer dynamiquement à des champs, un peu comme le SQL. C'est possible en revanche dans d'autres langages comme le pl/perl. "

Donc la solution serait peut-être d'écrire ma fonction verification() en pl/perl

un jour, quand j'aurais envie d'apprendre perl...

Hors ligne

#4 17/01/2011 12:32:40

Marc Cousin
Membre

Re : trigger paramétrable

Donc, même chose pour le modérateur ou moi smile

M'étonne pas. Le PL/PgSQL n'est pas fait pour ça. L'idée est justement d'avoir autant de choses 'constantes' (les requêtes SQL comprises) que possible dans le code, afin qu'il soit très performant à l'exécution (après une compilation initiale). Pas pour avoir les noms de colonnes ou d'objets dynamiques.

plperl est un exemple. Vous pouvez aussi essayer en plpython, plsh, pltcl, pljava, ou C, par exemple smile


Marc.

Hors ligne

#5 17/01/2011 12:38:57

bebert73
Membre

Re : trigger paramétrable

ok merci...je vais tenter ma chance en plsh dès que j'ai un moment

Hors ligne

#6 17/01/2011 12:54:29

Marc Cousin
Membre

Re : trigger paramétrable

C'est un de ceux qui ne sont pas fournis directement avec le code (comme pljava). Je pense que c'est aussi le moins approprié pour ça…

Les langages supportés en standard sont là :
http://docs.postgresql.fr/9.0/server-programming.html


Pour les autres, ça veut dire les compiler soit-même, séparément.


Marc.

Hors ligne

#7 17/01/2011 15:16:41

bebert73
Membre

Re : trigger paramétrable

oui je disais plsh car je ne connais ni perl ni python ni tcl/tk, mais vous avez sans doute raison, ce sera plus simple d'apprendre les rudiments de perl plutôt que de bricoler un truc soi-même avec plsh...  je vais essayer de faire ça en perl à l'occasion

en fait, si je comprends bien, sous postgreSQL le langage pl/pgsql est à priori le langage le plus performant, sauf si on essaye de faire des trucs un peu biscornus comme ce que je voulais faire, auquel cas on peut se tourner vers un autre langage

autrement dit, pl/perl (par exemple) offre plus de souplesse que pl/pgsql, mais au prix de performances diminuées... En gros j'ai bien compris ?

(je fais mes premiers pas sur postgres, après quelques années passées sur oracle)

Hors ligne

#8 22/01/2011 11:22:15

Marc Cousin
Membre

Re : trigger paramétrable

C'est grosso modo ça: les accès aux données sont un peu plus rapides en PLPgSQL. Par contre, dès que l'algorithme va devenir complexe (entre autres, dès qu'on va vouloir jouer avec des expressions régulières, faire des opérations complexes sur des chaînes ou autres), le surcoût d'être dans Perl ou Python devient inférieur au gain apporté par utiliser un langage plus puissant.


Marc.

Hors ligne

#9 01/02/2011 12:05:53

bebert73
Membre

Re : trigger paramétrable

ok, merci Marc pour cette discussion qui m'a été très utile.

Hors ligne

Pied de page des forums