Richiamare procedure o funzioni PostgreSQL da Query Builder di QGIS

Oct 18 2020

Sto cercando di chiamare una procedura memorizzata o una funzione definita nel database PostgreSQL / PostGIS e di utilizzarla da QGIS Query Builder. Nessuno dei due funziona:

  • la funzione restituisce una tabella che non può essere interpretata dal Query Builder
  • la procedura, che restituisce una selezione, fallisce quando la chiamo usando l' callistruzione

Entrambi funzionano bene in DataGrip e interrogano un tag da una tagcolonna di matrice di testo nella waypointstabella.

Ecco la funzione:

create or replace function gwd(t text)
RETURNS TABLE (f_ogc_fid int, f_name text)
LANGUAGE plpgsql
AS $$ BEGIN return query SELECT ogc_fid,name::text FROM gis.gps.waypoints where tag @> STRING_TO_ARRAY(t, ','); end; $$

Ecco la procedura che fallisce CALLnel Query Builder di QGIS:

create or replace procedure grw(T text)
LANGUAGE plpgsql
AS $$ BEGIN SELECT * FROM gis.gps.waypoints where tag @> STRING_TO_ARRAY(T, ','); end; $$

Ecco l'errore riportato da QGis quando eseguo call grw('iron')nel Query Builder:

An error occurred when executing the query.
The data provider said:
ERROR:  syntax error at or near "grw"
LINE 1: SELECT * FROM "gps"."waypoints" WHERE call grw('iron') LIMIT...

Quando lo chiamo senza CALL, non funziona neanche:

An error occurred when executing the query.
The data provider said:
ERROR:  grw(unknown) is a procedure
LINE 1: SELECT * FROM "gps"."waypoints" WHERE grw('iron') LIMIT 0
HINT:  To call a procedure, use CALL.

Risposte

1 geozelot Oct 19 2020 at 09:56

Tre cose:

  • A PRODECUREè un'istruzione procedurale consapevole della transazione , introdotta in PG 11, per accogliere il controllo della transazione mancante in un FUNCTIONblocco normale .

    Tuttavia , a PROCEDURE non può restituire valori e nient'altro che chiamarlo direttamente con ( nient'altro ma )

    CALL <procedure>;
    

    non può funzionare. Si desidera utilizzare PROCEDUREogni volta che si desidera eseguire istruzioni DDL sulle relazioni con il controllo delle transazioni , gestendo gli errori durante l'esecuzione in modo più elegante. Semanticamente, quello che stai cercando è un fileFUNCTION

  • La finestra di dialogo Generatore di query consente di aggiungere rapidamente espressioni di filtro sull'origine dati.

    Tuttavia , QGIS traduce questi filtri nella sintassi specifica del provider , il che significa che, in caso di un livello sorgente PostgreSQL / PostGIS, aggiungerà queste istruzioni a una query di base sotto forma di

    SELECT * FROM "<schema>"."<table>" WHERE <FILTER>;
    

    dove <FILTER>è l'espressione precisa inserita nel campo di dialogo

  • In ogni caso, i tuoi tentativi sono inutili (senza offesa) per il modo in cui intendi usarli:

    • non ha senso filtrare una tabella per un tag per utilizzare le righe / valori restituiti come lo stesso filtro per la stessa tabella
    • e se si desidera farlo, è necessario definire nuovamente un'espressione di filtro per utilizzare le righe / i valori restituiti

La soluzione più semplice sarebbe solo ( e solo ) entrare

'iron' = ANY(tag)

nel campo Espressione del generatore di query ; questo si traduce in

SELECT * FROM "gps"."waypoints" WHERE 'iron' = ANY(tag);

che è possibile utilizzare direttamente in SQL se necessario.