Vous n'êtes pas identifié(e).
Et une impasse ne venant jamais seule,
je viens vers vous parce que j'essaie de mettre en place une mise à jour automatique d'un buffer (dans table1) à partir de la géométrie d'un reseau (table2)
En clair j'aimerais lors de la mise à jour et et/ou l'insertion d'un reseau, le buffer associé se mette à jour dans l'autre table.
table1 (geom_buffer1 geometry)
table2 (wkb_geometry geometry, contrainte integer)
Voici pour le moment le code que j'ai développé :
CREATE OR REPLACE FUNCTION update_buffer1()
RETURNS trigger AS $BODY$
BEGIN
SELECT foo.contrainte,foo.wkb_geometry,geom_buffer1
FROM table1 ,dblink('hostaddr=xxx.x.x.x port=xxxx dbname=name user=xxxxx password=xxxx,
'SELECT wkb_geometry,contrainte FROM table2' )
AS foo(wkb_geometry geometry,contrainte integer);
NEW.geom_buffer1=buffer(foo.wkb_geometry,foo.contrainte);
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION update_buffer1() OWNER TO postgres;
CREATE TRIGGER update_buffer1
BEFORE INSERT OR UPDATE
ON table2
FOR EACH ROW
EXECUTE PROCEDURE update_buffer1();
Là c'est (une fois de plus) le vide absolu après avoir essayé une dizaine de choses différentes. A chaque fois j'ai l'impression de pas être loin mais je ne trouve pas le truc qu'il manque :-(
Merci de votre aide si vous avez une idée.
Hors ligne
Deux choses :
#1: dans "NEW.geom_buffer1=buffer(foo.wkb_geometry,foo.contrainte);", PostgreSQL ne sait pas ce que veut dire foo.wkb_geometry et foo.contrainte (la requête précédente serait apparemment celle qui récupère ces infos, mais elle ne les stocke pas dans une variable... voir la clause INTO en PL/pgsql)
#2: un dblink dans un trigger, certainement le meilleur moyen pour avoir les pires lenteurs
Guillaume.
Hors ligne
Bonjour Gleu,
merci pour votre piste, j'ai essayé quelque chose mai sans plus de succès :
CREATE OR REPLACE FUNCTION update_buffer1()
RETURNS trigger AS $BODY$
DECLARE
buff RECORD;
BEGIN
SELECT INTO buff foo.contrainte,foo.wkb_geometry,buffer1
FROM table1 ,dblink('hostaddr=xxx.x.x.x port=xxxx dbname=name user=xxxxx password=xxxx',
'SELECT wkb_geometry,contrainte_emprise1 FROM table2')
AS foo(wkb_geometry geometry,contraintedouble precision);
buff.buffer1=buffer(buff.wkb_geometry,buff.contrainte);
NEW.buffer1=buff.buffer1;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION update_buffer1() OWNER TO postgres;
CREATE TRIGGER update_buffer1
BEFORE INSERT OR UPDATE
ON table2
FOR EACH ROW
EXECUTE PROCEDURE update_buffer1();
En message d'erreur il me met : Record 'new' has no field 'buffer1', alors j'ai essayé entre la fin de la première requête et le return new de mettre quelque chose comme ça (j'ai essayé différentes variantes):
SELECT buffer1 FROM buffer_reseau
NEW.buffer1=buff.buffer1;
Mais ça ne marche pas plus...
concernant le dblink, y a-t-il une autre alternative à moins de modifier la structure des tables?
Merci d'avance.
Hors ligne
Concernant l'erreur sur le record, oui, c'est vrai, le record new n'a aucun champ buffer1. Si j'essaie d'avoir qqc à partir des deux fonctions, ça me donnerait qqc comme ça :
CREATE OR REPLACE FUNCTION update_buffer1()
RETURNS trigger AS $BODY$
DECLARE
buff RECORD;
BEGIN
SELECT INTO buff foo.contrainte,foo.wkb_geometry
FROM table1 ,dblink('hostaddr=xxx.x.x.x port=xxxx dbname=name user=xxxxx password=xxxx',
'SELECT wkb_geometry,contrainte_emprise1 FROM table2')
AS foo(wkb_geometry geometry,contrainte double precision);
NEW.geom_buffer1=buffer(buff.wkb_geometry,buff.contrainte);
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION update_buffer1() OWNER TO postgres;
Quant à dblink, aucune idée, étant donné que je ne sais pas du tout ce que vous cherchez à faire.
Guillaume.
Hors ligne
Bonjour gleu,
J'ai testé un truc comme ça :
CREATE OR REPLACE FUNCTION update_buffer1()
RETURNS trigger AS $BODY$
DECLARE
buff RECORD;
BEGIN
SELECT INTO buff contrainte,wkb_geometry
FROM table2;
SELECT foo.geom_buffer1
FROM dblink('hostaddr=xxx.x.x.x port=xxxx dbname=name user=xxxxx password=xxxx',
'SELECT geom_buffer1 FROM table1') AS foo(geom_buffer1 geometry);
NEW.geom_buffer1=buffer(buff.wkb_geometry,buff.contrainte);
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION update_buffer1() OWNER TO postgres;
CREATE TRIGGER update_buffer1
BEFORE INSERT OR UPDATE
ON table2
FOR EACH ROW
EXECUTE PROCEDURE update_buffer1();
Mais toujours pas de sucés...c'est désespérant
En fait le dblink est un peu obligatoire, puisque la géométrie d'un buffer et celle d'un réseau sont différentes. Du coup j'ai une table contenant le réseau et l'autre contenant le buffer associé au réseau.
A moins qu'on puisse mettre des géométries différentes dans une même table?!
Hors ligne
Mais toujours pas de sucés...c'est désespérant
Avez-vous essayé mon code ? Et si oui, quel en est le résultat ?
En fait le dblink est un peu obligatoire, puisque la géométrie d'un buffer et celle d'un réseau sont différentes. Du coup j'ai une table contenant le réseau et l'autre contenant le buffer associé au réseau.
dblink n'a un intérêt que lorsqu'il s'agit d'exécuter une requête sur un autre serveur PostgreSQL. Et je n'ai pas l'impression que ce soit le cas là.
Guillaume.
Hors ligne
Ohn et pour répondre à la dernière question, je ne vois pas pourquoi on ne pourrait pas avoir plusieurs géométries dans la même table.
Guillaume.
Hors ligne
Avez-vous essayé de créer une fonction 'normale' (pas trigger) pour voir si vous arrivez à récupérer la géométrie avec ce code ?
Sinon, oui, vous pouvez avoir autant de colonnes geometry que vous voulez dans une table. C'est d'ailleurs quelquefois fait quand par exemple on veut stocker la même information dans plusieurs projections différentes, pour éviter de recalculer les projections à tout bout de champ.
Marc.
Hors ligne
Bonjour tout le monde,
1- Gleu j'ai testé votre fonction et j'ai eu comme retour le même message d'erreur que la dernière fois : Record 'new' has no field 'buffer1'
2- Je pensais que le dblink servait à interroger d'autres tables (y compris dans la même BDD) donc dans ce cas préçis, ou les deux tables sont dans la même BDD il suffit que je fasse quelque chose du style :
SELECT INTO buff contrainte,wkb_geometry,buffer1
FROM table1,table2;
3-Par rapport aux géométries, quand je dis que je ne peux pas en avoir plusieurs dans la même table je dis ça puisqu'il s'agit de type de géométries différentes à savoir LINESTRING pour le réseau et POLYGON pour le buffer. Par conséquent ma table2 (réseau) est déclaré dans le geometry_columns en LINESTRING et la table 1 en POLYGON.
4-Marc, j'ai essayé de faire cette fonction sur une même talbe et ça fonctionne oui, c'est juste la liaison entre deux tables différentes que je n'arrive pas à faire...
Hors ligne
Pour le 2 : pourquoi table1,table2 ? Ça fait un produit cartésien entre les deux tables. Je présume que c'est juste table1 que vous voulez.
3: Je ne vois pas le problème: on peut avoir autant de géométries qu'on veut dans une table:
CREATE TABLE test (data int);
SELECT AddGeometryColumn('public', 'test', 'geom_1', 3819, 'LINESTRING', 2);
SELECT AddGeometryColumn('public', 'test', 'geom_2', 3906 , 'MULTIPOINT', 2);
4: de toutes façons, si c'est sur la même base, oubliez dblink, ça n'a aucun intérêt dans votre cas, à part compliquer le code et réduire les performances.
Marc.
Hors ligne
Bonjour à tous,
Finalement j'ai opté pour la solution : je met les buffer dans la même table, et le code donne ceci :
CREATE OR REPLACE FUNCTION update_buffer()
RETURNS trigger AS $BODY$
BEGIN
IF NEW.contrainte1 IS NOT NULL
THEN
NEW.buffer1=buffer(NEW.wkb_geometry,NEW.contrainte1);
END IF;
IF NEW.contrainte2 IS NOT NULL
THEN
NEW.buffer2=buffer(NEW.wkb_geometry,NEW.contrainte2);
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION update_buffer() OWNER TO postgres;
CREATE TRIGGER update_buffer
BEFORE INSERT OR UPDATE
ON table
FOR EACH ROW
EXECUTE PROCEDURE update_buffer();
Hors ligne