PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Esistono sintassi di escape per la variabile psql all'interno delle funzioni PostgreSQL?

PSQL SET le variabili non sono interpolate all'interno di stringhe tra virgolette. Non lo so per certo, ma penso che non ci sia via di scampo o altri trucchi per attivare SET interpolazione variabile lì dentro.

Si potrebbe pensare che potresti inserire un :user senza virgolette tra due tratti di PL/pgSQL quotati in dollari per ottenere l'effetto desiderato. Ma questo non sembra funzionare ... Penso che la sintassi richieda una singola stringa e non un'espressione che concatena le stringhe. Potrebbe essere sbagliato.

Comunque, non importa. C'è un altro approccio (come ha notato Pasco):scrivere la procedura memorizzata per accettare un argomento PL/pgSQL. Ecco come sarebbe.

CREATE OR REPLACE FUNCTION foo("user" TEXT) RETURNS void AS
$$
BEGIN
        EXECUTE 'GRANT SELECT ON my_table TO GROUP ' || quote_ident(user);
END;    
$$ LANGUAGE plpgsql;

Note su questa funzione:

  1. EXECUTE genera un GRANT appropriato su ogni invocazione usando sul nostro argomento di procedura. La sezione del manuale PG denominata "Esecuzione di comandi dinamici " spiega EXECUTE in dettaglio.
  2. La dichiarazione dell'argomento della procedura user deve essere doppiato. Le virgolette doppie ne obbligano a essere interpretate come un identificatore.

Una volta definita la funzione in questo modo, è possibile chiamarla utilizzando variabili PSQL interpolate. Ecco uno schema.

  1. Esegui psql --variable user="'whoever'" --file=myscript.sql . Sono necessarie virgolette singole attorno al nome utente!
  2. In myscript.sql, definisci la funzione come sopra.
  3. In myscript.sql, inserisci select foo(:user); . È qui che ci affidiamo a quelle virgolette singole che mettiamo nel valore di user .

Anche se questo sembra funzionare, mi sembra piuttosto scoiattolo. Ho pensato SET le variabili erano destinate alla configurazione di runtime. Portare i dati in giro in SET sembra strano.

Modifica :ecco un motivo concreto per non usa SET variabili. Dalla manpage:"Questi compiti vengono eseguiti durante una fase iniziale dell'avvio, quindi le variabili riservate per scopi interni potrebbero essere sovrascritte in seguito." Se Postgres ha deciso di utilizzare una variabile denominata user (o qualunque cosa tu scelga), potrebbe sovrascrivere l'argomento dello script con qualcosa che non avresti mai voluto. In effetti, psql accetta già USER per sé -- funziona solo perché SET fa distinzione tra maiuscole e minuscole. Questo ha quasi rotto le cose dall'inizio!