0

I have been trying to create a script that detects that a role already excists and if it does it should revoke all privileges. This works fine doing it like this:

DO $$DECLARE count int;
BEGIN
SELECT count(*) INTO count FROM pg_roles WHERE rolname = 'superman';
IF count > 0 THEN
    REVOKE ALL PRIVILEGES ON TABLE FROM superman;
END IF;
END$$;

But now I want this to be dynamic per environment since I will be using different role names per environment. So I tried to use the \set mechanism but that doesn't seem to work when using pl/sql so if I would do something like the following Postgresql is complaining with syntax errors:

/set environment _int

DO $$DECLARE count int;
BEGIN
SELECT count(*) INTO count FROM pg_roles WHERE rolname = 'superman';
IF count > 0 THEN
    REVOKE ALL PRIVILEGES ON TABLE FROM superman:environment;
END IF;
END$$;

Although if I would not do it in pl/sql the revoke statment works just fine. So my question is how can I make my script dynamic by passing parameters to it so they will be replaced?

Jon Heller
  • 34,999
  • 6
  • 74
  • 132
Tranquilized
  • 721
  • 2
  • 6
  • 23

1 Answers1

4

You have to use EXECUTE for dynamic SQL. Also, a DO statement cannot take parameters. Create a plpgsql function:

CREATE OR REPLACE FUNCTION f_revoke_all_from_role(_role text)
  RETURNS void AS
$BODY$
BEGIN

IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = _role) THEN
    EXECUTE 'REVOKE ALL PRIVILEGES ON TABLE x FROM ' || quote_ident(_role);
END IF;

END;
$BODY$ LANGUAGE plpgsql;

Call:

SELECT f_revoke_all_from_role('superman');
  • IF block is simpler with EXISTS.

  • I use quote_ident() to avoid SQLi.

  • The table name could be the second parameter of the function ...

Milen A. Radev
  • 60,241
  • 22
  • 105
  • 110
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • Ah ok.. Thnx!! I will try this out. I was already afraid to have to do it like this. I find it weird though since in Oracle it is possible to pass variables from the outside to a plsql script without having to write a function. I just want this logic in there so I can do a deployment of my database. Why do I have to create a function for this? Isn't there any other way of doing it like in Oracle? – Tranquilized Jul 10 '12 at 22:12
  • @user1515731: I wouldn't know of any. The plpgsql function doesn't seem to complicated, though, or does it? – Erwin Brandstetter Jul 10 '12 at 22:17
  • No it's not indeed but I don't like the fact that I have to create a function just to detect if a role exists and basically drop it afterwords since I won't be using it in my application. But I will try it out thnx for your help :-) – Tranquilized Jul 11 '12 at 07:56