skip to Main Content

I’m using a client library that only accepts SQL strings that are compile-time constant, in order to prevent SQL injection attacks. And I wanted to execute some GRANT statements for a set of tables and a user.

I tried

GRANT SELECT ON $1 TO $2

and passing the table and user names as bound parameters. But that fails with

syntax error at or near "$1"

Not being able to pass in a tablename as a bound parameter is understandable (you can’t use SELECT columns FROM $1 for instance), and with a bit of work, I can make the tablenames compile-time constants. But changing the command to

GRANT SELECT ON MyTable to $1

and passing just the username as a bound parameter also fails. Which is more of an issue: whereas the tablenames can be hard-coded with a bit of work, the username is only known at runtime.

Is there a way to pass the username as a bound parameter, or do I need to bypass my client library in order to GRANT permissions to a run-time-defined username?

2

Answers


  1. The only statements that can use parameters are INSERT, UPDATE, DELETE and SELECT. GRANT cannot use parameters; you will have to build a statement dynamically.

    Login or Signup to reply.
  2. CREATE OR REPLACE FUNCTION test_grant (_role text)
        RETURNS void
        AS $$
    DECLARE
        _sql text := '';
    BEGIN
        _sql := 'GRANT SELECT ON a to ' || quote_ident(_role) || ' GRANTED BY current_user ';
        RAISE NOTICE '%', _sql;
        EXECUTE _sql;
        RAISE NOTICE '% granted table a to %', CURRENT_USER, _role;
    END
    $$
    LANGUAGE plpgsql
    STRICT.
    

    You can also make the table as function input argument. quote_ident is used for identifiers quoting. In GRANT SELECT ON MyTable to $1 you hope to make sure $1 is a identifiers rather than some string. Because if $1 string then the whole command can be:
    GRANT SELECT ON MyTable to public;
    GRANT SELECT ON MyTable to role_a WITH GRANT OPTION;
    So the above function can solve these problem.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search