PSQL SET
variabelen worden niet geïnterpoleerd in strings tussen aanhalingstekens in dollars. Ik weet dit niet zeker, maar ik denk dat er geen ontsnapping of ander bedrog is om SET
in te schakelen variabele interpolatie daarin.
Je zou kunnen denken dat je een niet-geciteerde :user
tussen twee in dollars genoteerde stukken PL/pgSQL om het gewenste effect te krijgen. Maar dit lijkt niet te werken... Ik denk dat de syntaxis een enkele string vereist en geen expressie die strings aaneenvoegt. Misschien vergis je je daarin.
Hoe dan ook, dat maakt niet uit. Er is een andere benadering (zoals Pasco opmerkte):schrijf de opgeslagen procedure om een PL/pgSQL-argument te accepteren. Zo zou dat eruit zien.
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;
Opmerkingen over deze functie:
EXECUTE
genereert een geschikteGRANT
op elke aanroep met behulp van ons procedure-argument. De PG handleiding sectie genaamd "Dynamische commando's uitvoeren " legt uitEXECUTE
in detail.- Het declaratie van procedure argument
user
moet dubbel geciteerd worden. Dubbele aanhalingstekens dwingen het te interpreteren als een identifier.
Nadat u de functie op deze manier hebt gedefinieerd, kunt u deze aanroepen met behulp van geïnterpoleerde PSQL-variabelen. Hier is een overzicht.
- Voer
psql --variable user="'whoever'" --file=myscript.sql
uit . Enkele aanhalingstekens zijn vereist rond de gebruikersnaam! - Definieer in myscript.sql de functie zoals hierboven.
- Plaats in myscript.sql
select foo(:user);
. Dit is waar we vertrouwen op die enkele aanhalingstekens die we in de waarde vanuser
plaatsen .
Hoewel dit lijkt te werken, lijkt het me nogal eekhoornachtig. Ik dacht SET
variabelen waren bedoeld voor runtime-configuratie. Gegevens meenemen in SET
lijkt vreemd.
Bewerken :hier is een concrete reden om niet gebruik SET
variabelen. Van de manpage:"Deze toewijzingen worden gedaan tijdens een zeer vroege fase van het opstarten, dus variabelen die zijn gereserveerd voor interne doeleinden kunnen later worden overschreven." Als Postgres besloot een variabele te gebruiken met de naam user
(of wat je ook kiest), het zou je scriptargument kunnen overschrijven met iets dat je nooit van plan was. In feite neemt psql al USER
voor zichzelf -- dit werkt alleen omdat SET
is hoofdlettergevoelig. Dit brak bijna alles vanaf het begin!