Vous n'êtes pas identifié(e).
Bonjour à tous et tous,
J'essaie sous Postgresql de créer une contrainte de vérification de la topologie d'objets insérés sur une table test.topo1 (pour empêcher la saisie sous QGIS d'objets se chevauchant).
Pour faire cela, j'ajoute un trigger sur cette table et je créé une fonction déclencheur. Ce qui donne ceci :
CREATE OR REPLACE FUNCTION admingeo.overlapping_parcel_trigger()
RETURNS trigger AS
$$
DECLARE
c bigint;
BEGIN
SELECT count(*)
INTO c
FROM test.topo1 t1
WHERE ST_Intersects(t1.geom, NEW.geom)
AND t1.id != NEW.id
AND ST_Relate(t1.geom, NEW.geom, '2********');
IF c > 0 THEN
RAISE EXCEPTION 'l''objet % empiète sur un autre objet', NEW.id;
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';
CREATE CONSTRAINT TRIGGER verif_topo
AFTER INSERT OR UPDATE ON test.topo1
FOR EACH ROW EXECUTE FUNCTION admingeo.overlapping_parcel_trigger();
Cette procédure fonctionne parfaitement mais je dois rentrer en dur le nom de la table sur lequel est posé mon trigger, ce qui n'est pas du tout optimal.
J'ai donc essayé d'introduire TG_TABLE_SCHEMA et TG_TABLE_NAME mais sans aucun succès après des dizaines de tentatives.
L'un de vous aurait-il une solution à mon problème svp ?
Merci d'avance pour votre aide.
Voici le code de ma dernière tentative :
CREATE or replace FUNCTION admingeo.overlapping_parcel_trigger()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
c bigint;
t1 text;
BEGIN
EXECUTE format('select (schemaname::text||''.''||tablename::text)::regclass t from pg_tables where schemaname=%I and tablename=%I',TG_TABLE_SCHEMA,TG_TABLE_NAME) INTO t1;
SELECT Count(*)
INTO c
FROM t1
WHERE ST_Intersects(t1.geom, NEW.geom)
AND t1.id != NEW.id
AND ST_overlaps(t1.geom, NEW.geom);
IF c > 0 THEN
RAISE EXCEPTION 'l''objet % empiète sur un autre objet', NEW.id;
END IF;
RETURN NEW;
END;
$BODY$;
Merci.
Hors ligne
Vous ne pouvez pas utiliser une chaine de texte pour remplacer un identifiant de table (ou autre), vous devez utiliser une requête dynamique pour ça.
Quelquechose comme
EXECUTE format('SELECT count(*) FROM %I.%I WHERE ST_Intersects...', TG_TABLE_SCHEMA, TG_TABLE_NAME) INTO c;
Julien.
https://rjuju.github.io/
Hors ligne
Merci beaucoup pour votre aide
Je ne maîtrise pas du tout les requêtes dynamiques, désolé.
J'ai modifié ma requête ainsi :
(...)
EXECUTE format('SELECT count(*) FROM %I.%I as x
WHERE ST_Intersects(x.geom, NEW.geom)
AND x.id != NEW.id AND ST_overlaps(x.geom, NEW.geom)',
TG_TABLE_SCHEMA, TG_TABLE_NAME) INTO c;
(...)
et j'obtiens ce message d'erreur dans QGIS :
" ERREUR: entrée manquante de la clause FROM pour la table « new » "
Je suppose qu'il ne reconnait plus cette syntaxe à l'intérieur de la requête dynamique mais je ne sais pas comment désigner autrement la géométrie et l'id du dernier objet saisi...
Auriez-vous une idée ?
Merci d'avance pour votre aide.
Hors ligne
Vous devez fournir les valeurs NEW.id et autre explicitement :
EXECUTE format('SELECT count(*) FROM %I.%I WHERE ST_Intersects... AND x.id != $1 AND ...', TG_TABLE_SCHEMA, TG_TABLE_NAME) USING NEW.id INTO c;
(idem pour geom, et tout autre valeur de NEW)
Voir https://www.postgresql.org/docs/current … CUTING-DYN pour plus de détails.
Julien.
https://rjuju.github.io/
Hors ligne
Super, ca fonctionne parfaitement ! Merci beaucoup (je vous dois une fière chandelle).
Je vais enfin pouvoir créer des fonctions plus intelligentes et optimisées !
Bon week-end à vous
Hors ligne
Très bonne nouvelle, bon weekend également
Julien.
https://rjuju.github.io/
Hors ligne