Il va être trop tard pour abandonner l'héritage dans mon cas 
Voilà ou j'en suis. (pour ceux qui auraient le même problème)
J'ai créé une procédure stockée qui permet de palier en partie au problème que j'ai
il faut déjà installer le module hstore qui va permettre d’accéder aux attributs de l'objet NEW.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| CREATE OR REPLACE FUNCTION master_foreign_key() RETURNS TRIGGER AS $$
DECLARE
curs refcursor;
id int;
idchild integer;
BEGIN
IF TG_NARGS <> 3 THEN
RAISE EXCEPTION 'master_foreign_key need to receive 3 parameters';
END IF;
IF TG_WHEN = 'AFTER' THEN
idchild := (hstore(new)->TG_ARGV[0])::bigint;
OPEN curs FOR EXECUTE 'SELECT * FROM ' || quote_ident(TG_ARGV[1]) || ' WHERE ' || quote_ident(TG_ARGV[2]) || ' = $1' USING idchild;
FETCH curs INTO id;
IF NOT FOUND THEN
RAISE EXCEPTION '% on table "%" violates master_foreign_key
DETAIL: Key (idobject)=(%) is not present in table "%"', TG_OP, TG_RELNAME, idchild, TG_ARGV[1];
END IF;
CLOSE curs;
RETURN NEW;
ELSE
idchild := (hstore(old)->TG_ARGV[0])::bigint;
OPEN curs FOR EXECUTE 'SELECT * FROM ' || quote_ident(TG_ARGV[1]) || ' WHERE ' || quote_ident(TG_ARGV[2]) || ' = $1' USING idchild;
FETCH curs INTO id;
IF FOUND THEN
RAISE EXCEPTION '% on table "%" violates master_foreign_key
DETAIL: Key (idobject)=(%) is still referenced from table "%"', TG_OP, TG_RELNAME, idchild, TG_ARGV[1];
END IF;
CLOSE curs;
RETURN OLD;
END IF;
END;
$$ LANGUAGE plpgsql; |
puis on remplace le foreign key (qui ne marche pas) par:
CREATE constraint TRIGGER ctc_group_link_idcontact AFTER INSERT OR UPDATE ON ctc_group_link FOR EACH ROW EXECUTE PROCEDURE master_foreign_key('idcontact', 'contact', 'idcontact');
Les 3 paramètres sont:
- l'idcontact de la table ctc_group_link
- la table dans laquelle il faut faire la verification
- la clé dans la table dans laquelle il faut faire la verification
Du coup le trigger est suffisamment générique pour être ré-utilisé dans d'autres cas puisque toutes les tables et colonnes sont envoyées en paramètres.
Lors de la création d'un enregistrement dans ctc_group_link le trigger va vérifier qu'il existe bien un contact avec idcontact fournit.
L'idéal serait à présent que j'arrive a placer le même TRIGGER sur la table contact
Un truc genre
CREATE TRIGGER contact_panel_check BEFORE UPDATE OR DELETE ON contact FOR EACH ROW EXECUTE PROCEDURE master_foreign_key('idcontact', 'ctc_group_link ', 'idcontact');
Pour faire ça il faut 2 codes distinct que l'on appelle en fonction du moment (BEFORE ou AFTER) de l'invocation du TRIGGER
Mais cela ne fonctionne pas car malheureusement,
n’exécute le TRIGGER que sur les entrées crées dans la table "contact".
Il faut donc appliquer le TRIGGER sur toutes les tables que héritent de "contact".
1 2 3 4 5
| CREATE TRIGGER contact_panel_check BEFORE UPDATE OR DELETE ON contact FOR EACH ROW EXECUTE PROCEDURE master_foreign_key('idcontact', 'ctc_group_link ', 'idcontact');
CREATE TRIGGER contact_panel_check BEFORE UPDATE OR DELETE ON membre FOR EACH ROW EXECUTE PROCEDURE master_foreign_key('idcontact', 'ctc_group_link ', 'idcontact');
CREATE TRIGGER contact_panel_check BEFORE UPDATE OR DELETE ON client FOR EACH ROW EXECUTE PROCEDURE master_foreign_key('idcontact', 'ctc_group_link ', 'idcontact');
CREATE TRIGGER contact_panel_check BEFORE UPDATE OR DELETE ON ami FOR EACH ROW EXECUTE PROCEDURE master_foreign_key('idcontact', 'ctc_group_link ', 'idcontact');
CREATE TRIGGER contact_panel_check BEFORE UPDATE OR DELETE ON utilisateur FOR EACH ROW EXECUTE PROCEDURE master_foreign_key('idcontact', 'ctc_group_link ', 'idcontact'); |
Bon voilà.
C'est pas le top, mais ça fonctionne. C'est un peu meilleur que ce que j'avait avant puisque à présent le TRIGGER est générique.
Si quelqu'un a une meilleure solution, je prends !
Merci.
Partager