PSQL SET
variabler interpoleres ikke inde i strenge med citerede dollars. Jeg ved det ikke med sikkerhed, men jeg tror, der ikke er nogen flugt eller andet trick for at slå SET
til variabel interpolation derinde.
Man kunne tro, at du kunne kile en uciteret :user
mellem to dollar-noterede strækninger af PL/pgSQL for at få den ønskede effekt. Men dette ser ikke ud til at virke... Jeg tror, at syntaksen kræver en enkelt streng og ikke et udtryk, der sammenkæder strenge. Kan tage fejl af det.
Det betyder i hvert fald ikke noget. Der er en anden tilgang (som Pasco bemærkede):skriv den lagrede procedure for at acceptere et PL/pgSQL-argument. Sådan ser det ud.
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;
Bemærkninger om denne funktion:
EXECUTE
genererer en passendeGRANT
på hver påkaldelse ved hjælp af vores procedureargument. PG-manualafsnittet kaldet "Udførelse af dynamiske kommandoer " forklarerEXECUTE
i detaljer.- Procedureerklæringsargumentet
user
skal citeres dobbelt. Dobbelte anførselstegn tvinger det til at blive fortolket som en identifikator.
Når du har defineret funktionen som denne, kan du kalde den ved hjælp af interpolerede PSQL-variabler. Her er en oversigt.
- Kør
psql --variable user="'whoever'" --file=myscript.sql
. Enkelte citater er påkrævet omkring brugernavnet! - I myscript.sql skal du definere funktion som ovenfor.
- Indsæt
select foo(:user);
i myscript.sql . Det er her, vi stoler på de enkelte citater, vi sætter i værdien af user
.
Selvom det ser ud til at virke, virker det temmelig skurrende. Jeg tænkte SET
variabler var beregnet til runtime-konfiguration. Transporterer data rundt i SET
virker underligt.
Rediger :her er en konkret grund til at ikke brug SET
variabler. Fra manpage:"Disse opgaver udføres i et meget tidligt trin af opstarten, så variabler reserveret til interne formål kan blive overskrevet senere." Hvis Postgres besluttede at bruge en variabel ved navn user
(eller hvad du end vælger), kan det overskrive dit script-argument med noget, du aldrig havde tænkt dig. Faktisk tager psql allerede USER
for sig selv -- dette virker kun fordi SET
er store og små bogstaver. Dette gik næsten i stykker fra starten!