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 20/09/2011 17:09:20

Geo-x
Membre

mise à jour buffer table1 depuis geometrie table 2

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

#2 20/09/2011 17:16:58

gleu
Administrateur

Re : mise à jour buffer table1 depuis geometrie table 2

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

#3 21/09/2011 08:53:59

Geo-x
Membre

Re : mise à jour buffer table1 depuis geometrie table 2

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

#4 21/09/2011 09:31:22

gleu
Administrateur

Re : mise à jour buffer table1 depuis geometrie table 2

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

#5 22/09/2011 17:05:30

Geo-x
Membre

Re : mise à jour buffer table1 depuis geometrie table 2

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

#6 22/09/2011 17:18:27

gleu
Administrateur

Re : mise à jour buffer table1 depuis geometrie table 2

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

#7 22/09/2011 17:19:00

gleu
Administrateur

Re : mise à jour buffer table1 depuis geometrie table 2

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

#8 22/09/2011 17:21:19

Marc Cousin
Membre

Re : mise à jour buffer table1 depuis geometrie table 2

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

#9 23/09/2011 08:25:04

Geo-x
Membre

Re : mise à jour buffer table1 depuis geometrie table 2

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

#10 23/09/2011 09:52:32

Marc Cousin
Membre

Re : mise à jour buffer table1 depuis geometrie table 2

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

#11 26/09/2011 10:53:00

Geo-x
Membre

Re : mise à jour buffer table1 depuis geometrie table 2

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

Pied de page des forums