PSQL SET
les variables ne sont pas interpolées à l'intérieur des chaînes entre guillemets en dollars. Je ne le sais pas avec certitude, mais je pense qu'il n'y a pas d'échappatoire ou autre tromperie pour activer SET
interpolation variable là-dedans.
On pourrait penser que vous pourriez coincer un :user
sans guillemets entre deux portions de PL/pgSQL cotées en dollars pour obtenir l'effet désiré. Mais cela ne semble pas fonctionner ... Je pense que la syntaxe nécessite une seule chaîne et non une expression concaténant des chaînes. Peut-être se trompe-t-il.
Quoi qu'il en soit, cela n'a pas d'importance. Il existe une autre approche (comme Pasco l'a noté):écrivez la procédure stockée pour accepter un argument PL/pgSQL. Voici à quoi cela ressemblerait.
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;
Remarques sur cette fonction :
EXECUTE
génère unGRANT
approprié sur chaque invocation en utilisant sur notre argument de procédure. La section du manuel PG appelée "Exécuter des commandes dynamiques " expliqueEXECUTE
en détail.- La déclaration de l'argument de la procédure
user
doit être entre guillemets. Les guillemets doubles l'obligent à être interprété comme un identifiant.
Une fois que vous avez défini la fonction comme celle-ci, vous pouvez l'appeler en utilisant des variables PSQL interpolées. Voici un aperçu.
- Exécutez
psql --variable user="'whoever'" --file=myscript.sql
. Des guillemets simples sont requis autour du nom d'utilisateur ! - Dans myscript.sql, définissez la fonction comme ci-dessus.
- Dans myscript.sql, mettez
select foo(:user);
. C'est là que nous nous appuyons sur ces guillemets simples que nous mettons dans la valeur deuser
.
Bien que cela semble fonctionner, cela me semble plutôt étrange. Je pensais SET
les variables étaient destinées à la configuration d'exécution. Transporter des données dans SET
semble étrange.
Modifier :voici une raison concrète pour ne pas utilisez SET
variables. D'après la page de manuel :"Ces affectations sont effectuées à un stade très précoce du démarrage, de sorte que les variables réservées à des fins internes peuvent être écrasées ultérieurement." Si Postgres décide d'utiliser une variable nommée user
(ou quoi que vous choisissiez), cela pourrait écraser votre argument de script avec quelque chose que vous n'aviez jamais prévu. En fait, psql prend déjà USER
pour lui-même - cela ne fonctionne que parce que SET
est sensible à la casse. Cela a failli casser les choses dès le départ !