[Gfoss] Postgis, modalità di creazione di RULE on INSERT con RETURNING su viste con join spaziale: considerazioni e problemi riscontrati

francesco marucci francesco.marucci a gmail.com
Sab 16 Lug 2016 12:29:03 CEST


gentile lista,
ho notato (correggetemi se sbaglio) che dalla fiammante nuova versione di
qGis 2.16, le insert su un layer postgis vengono inviate ora con il
parametro RETURNING, e quindi nel caso di viste editabili è necessario
creare il RULE ON INSERT (che dirottino i dati, compreso il geom, sulla
tabella corrispondente) con la corretta clausola RETURNING, che fino alla
versione 2.14 non era necessaria.

immagino (e spero) che questa modifica sia stata effettuata per risolvere
l'annoso problema nelle viste editabili che in qGis non "sentono" (ad
esempio non sono snappabili) le nuove geometrie appena aggiunte (dopo
appunto l'insert relativo) finché non si ricarichi la vista o non si creino
ulteriori nuove geometrie, oppure finché non si applichi lo "splendido"
workaround di fare finta di muovere l'elemento, cliccando sulla mappa con
lo strumento "muovi".

in ogni modo, sono riuscito a creare il RULE ON INSERT che mi restituisca
correttamente i valori nel RETURNING anche nel caso in cui la vista sia
basata su una relazione spaziale.

giusto per riassumere i passi che ho fatto per arrivarci (che spero possano
essere utili anche ad altri), nel caso "geografico" abbiamo banalmente una
tabella di punti e una di poligoni (in cui i punti ricadono geometricamente)

la mia vista semplicemente assegna ad ogni punto il poligono in cui ricade:

CREATE OR REPLACE VIEW punti_edit AS
 SELECT punti.gid,
    punti.geom,
    poligoni.gid as id_poligono
   FROM punti
     LEFT JOIN poligoni ON st_intersects(poligoni.geom, punti.geom);

ho quindi creato un RULE che sia in grado di restituirmi (RETURNING) anche
l'id del poligono in cui ricade, leggo da qui:
https://www.postgresql.org/docs/current/static/rules-update.html

"If you want to support RETURNING queries on the view, you need to make the
rules include RETURNING clauses that compute the view rows. This is usually
pretty trivial for views on a single table, but it's a bit tedious for join
views such as..."

seguendo l'esempio faccio:

CREATE OR REPLACE RULE punti_edit_insert AS
    ON INSERT TO punti_edit DO INSTEAD ( INSERT INTO punti (geom)
  VALUES (new.geom)
  RETURNING punti.*,
   (
  select poligoni.gid
  from poligoni
  where st_intersects(poligoni.geom, punti.geom)
   );
);

uso il "where st_intersects" dal momento che la mia unica relazione tra le
due tabelle è puramente spaziale e non ho altre chiavi che relazionino le
due tabelle, come invece immagino lo siano nell'esempio indicato.

quando eseguo il "create rule" va tutto liscio.

se faccio il mio insert del tipo:
insert into punti_edit (geom) values ("POINT( etc...") returning
id_poligono;

mi fa l'insert e mi restituisce subito anche il valore del poligono in cui
il punto ricade.
bellissimo.

quello che quindi io mi aspettavo è che nel RULE io potessi raccogliere
quello stesso valore in un oggetto del tipo "NEW.id_poligono", da usare per
lanciare la mia procedura successiva direttamente da dentro il RULE
passandogli come parametro appunto l'id del poligono.

invece sembra proprio dalle mille prove che ho fatto che NEW.id_poligono
all'interno del RULE non contenga nulla.

avete qualche suggerimento ?
sto interpretando male il concetto dei valori RETURNING di un insert?
non hanno nulla a che vedere con l'oggetto NEW di un RULE?
oppure è forse sbagliato come ho creato i valori RETURNING nel RULE?

attendo vostro prezioso contributo.

grazie.

saluti,
francesco


Maggiori informazioni sulla lista Gfoss