I am running the following procedure to obtain the SQL for grants to roles on a database:
CREATE OR REPLACE PROCEDURE DBMGT.REFRESHES.GET_DB_GRANTS(dbname VARCHAR)
RETURNS TABLE ()
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
qry VARCHAR;
v_sql varchar;
DB_SCHEMA_PATH varchar default '';
C1 CURSOR FOR SELECT PRIVILEGE, GRANTED_ON, TABLE_CATALOG, TABLE_SCHEMA, NAME, GRANTED_TO, GRANTEE_NAME
FROM SNOWFLAKE.ACCOUNT_USAGE.GRANTS_TO_ROLES
WHERE TABLE_CATALOG = ?;
BEGIN
IF (NOT EXISTS (
SELECT 1
FROM "SNOWFLAKE"."INFORMATION_SCHEMA"."DATABASES"
WHERE DATABASE_NAME = upper(:dbname)
) )THEN
LET rs RESULTSET := (select 'Source database does not exist');
RETURN table(rs);
END IF;
CREATE or REPLACE TEMPORARY TABLE DBMGT.REFRESHES.GRANT_STORE(SQL_QRY VARCHAR);
OPEN C1 USING(:DBNAME);
FOR obj IN C1 DO
IF (obj.GRANTED_ON = 'DATABASE') THEN
qry := 'GRANT ' || obj.PRIVILEGE || ' ON ' || obj.GRANTED_ON || ' ' || dbname || ' TO ' || obj.GRANTED_TO || ' ' || obj.GRANTEE_NAME ;
elseif (obj.GRANTED_ON = 'SCHEMA') then
qry := 'GRANT ' || obj.PRIVILEGE || ' ON ' || obj.GRANTED_ON || ' ' || dbname || '.' || obj.TABLE_SCHEMA ||' TO ' || obj.GRANTED_TO || ' ' || obj.GRANTEE_NAME ;
ELSEIF (obj.GRANTED_ON IN ('PROCEDURE', 'FUNCTION')) THEN
qry := 'GRANT ' || obj.PRIVILEGE || ' ON ' || obj.GRANTED_ON || ' ' || dbname || '.' || obj.TABLE_SCHEMA || '.' || obj.NAME || ' TO ' || obj.GRANTED_TO || ' ' || obj.GRANTEE_NAME ;
else
qry := 'GRANT ' || obj.PRIVILEGE || ' ON ' || obj.GRANTED_ON || ' ' || dbname || '.' || obj.TABLE_SCHEMA || '.' || obj.NAME || ' TO ' || obj.GRANTED_TO || ' ' || obj.GRANTEE_NAME ;
END IF;
if (obj.PRIVILEGE = 'OWNERSHIP') THEN
qry := qry || ' COPY CURRENT GRANTS' ;
end if;
qry := qry || ' ;';
insert into DBMGT.REFRESHES.GRANT_STORE values (:qry);
END FOR;
CLOSE C1;
LET rs RESULTSET := (select * from DBMGT.REFRESHES.GRANT_STORE);
RETURN table(rs);
END;
$$;
It is working fine for most objects but it is having problems for functions and procedures, for example, if I run this script on TESTDB
CALL DBMGT.REFRESHES.GET_DB_GRANTS('TESTDB');
It procedures the following result for the procedure
LOG_ETL_STATS(JOB_NAME VARCHAR, SOURCE_TABLE VARCHAR, TARGET_TABLE VARCHAR, APPLICATION_NAME VARCHAR):
GRANT OWNERSHIP ON PROCEDURE
TESTDB.OPERATIONS.LOG_ETL_STATS(JOB_NAME VARCHAR, SOURCE_TABLE VARCHAR, TARGET_TABLE VARCHAR, APPLICATION_NAME VARCHAR):VARCHAR(16777216)
TO ROLE SNF_ADMIN_ROLE COPY CURRENT GRANTS ;
Running this line returns an error because Snowflake expects the above SQL command to look like this:
GRANT OWNERSHIP ON PROCEDURE TESTDB.OPERATIONS.LOG_ETL_STATS( VARCHAR, VARCHAR, VARCHAR, VARCHAR) TO ROLE SNF_ADMIN_ROLE COPY CURRENT GRANTS ;
I have tried a couple of things to try and manipulate the obj.GRANTED_ON
string to try and get it into the above format, but nothing has been successful so far, was wondering if anyone else experienced this and has a good solution to returning the procedure/function in a form that snowflake likes?