diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index 0f1ec4da5..be3a27cbc 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -878,8 +878,10 @@ GenerateGrantRoleStmtsOfRole(Oid roleid) #if PG_VERSION_NUM >= PG_VERSION_16 if (membership->admin_option) { - DefElem *opt = makeDefElem("admin", (Node *) makeBoolean(true), -1); - grantRoleStmt->opt = list_make1(opt); + DefElem *opt = makeDefElem("admin", (Node *) makeBoolean(true), -1); + DefElem *inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(true), -1); + DefElem *set_opt = makeDefElem("set", (Node *) makeBoolean(true), -1); + grantRoleStmt->opt = list_make3(opt, inherit_opt, set_opt); } if (membership->inherit_option) diff --git a/src/backend/distributed/deparser/deparse_role_stmts.c b/src/backend/distributed/deparser/deparse_role_stmts.c index 42a73f231..49756bde4 100644 --- a/src/backend/distributed/deparser/deparse_role_stmts.c +++ b/src/backend/distributed/deparser/deparse_role_stmts.c @@ -403,21 +403,33 @@ AppendRevokeAdminOptionFor(StringInfo buf, GrantRoleStmt *stmt) if (!stmt->is_grant) { DefElem *opt = NULL; + int opt_count = 0 ; foreach_ptr(opt, stmt->opt) { - - switch (opt->defname) + switch (opt->defname) { - appendStringInfo(buf, "ADMIN OPTION FOR "); - } - else if (strcmp(opt->defname, "inherit") == 0); - { - appendStringInfo(buf, "INHERIT TRUE"); - appendStringInfo(buf, "GRANT x TO y WITH INHERIT TRUE, SET TRUE;"); - } - else if (strcmp(opt->defname, "set") == 0) - { - appendStringInfo(buf, "SET TRUE"); + case "admin": + appendStringInfo(buf, "ADMIN OPTION FOR "); + opt_count++; + break; + + case "inherit": + if (opt_count > 0) + { + appendStringInfo(buf, ", "); + } + appendStringInfo(buf, "INHERIT OPTION FOR "); + opt_count++; + break; + + case "set": + if (opt_count > 0) + { + appendStringInfo(buf, ", "); + } + appendStringInfo(buf, "SET OPTION FOR "); + opt_count++; + break; } } } @@ -440,13 +452,32 @@ AppendGrantWithAdminOption(StringInfo buf, GrantRoleStmt *stmt) int opt_count = 0; foreach_ptr(opt, stmt->opt) { - bool admin_option = false; - char *optval = defGetString(opt); - if (strcmp(opt->defname, "admin") == 0 && - parse_bool(optval, &admin_option) && admin_option) - { - appendStringInfo(buf, " WITH ADMIN OPTION"); + switch (opt->defname) + { + case "admin": + appendStringInfo(buf, " WITH ADMIN OPTION"); + opt_count++; + break; + + case "inherit": + if (opt_count > 0) + { + appendStringInfo(buf, ", "); + } + appendStringInfo(buf, "INHERIT OPTION "); + opt_count++; break; + + + case "set": + if (opt_count > 0) + { + appendStringInfo(buf, ", "); + } + appendStringInfo(buf, "SET OPTION "); + opt_count++; + break; + } } } #else diff --git a/src/test/regress/sql/pg16.sql b/src/test/regress/sql/pg16.sql index 82e9edf1e..c216e5d55 100644 --- a/src/test/regress/sql/pg16.sql +++ b/src/test/regress/sql/pg16.sql @@ -658,3 +658,38 @@ DROP ROLE role3, role4, role5; SET client_min_messages TO ERROR; DROP EXTENSION postgres_fdw CASCADE; DROP SCHEMA pg16 CASCADE; + +-- +-- PG16 allows GRANT WITH ADMIN | INHERIT | SET +-- +-- GRANT privileges to a role or roles +\c - - - :master_port +CREATE ROLE create_role; +CREATE ROLE create_role_2; +CREATE ROLE create_role_3; +CREATE ROLE create_role_4; +CREATE USER create_user; +CREATE USER create_user_2; +CREATE GROUP create_group; +CREATE GROUP create_group_2; + +--test grant role +GRANT create_group TO create_role; +GRANT create_group TO create_role_2 WITH ADMIN OPTION; +GRANT create_group TO create_role_3 WITH INHERIT; +GRANT create_group TO create_role_4 WITH SET; + +-- ADMIN role can perfom administrative tasks +-- role can now access the data and permissions of the table (owner of table) +-- role can change current user to any other user/role that has access +GRANT ADMIN TO joe; +GRANT INHERIT ON ROLE joe TO james; + +GRANT SELECT ON companies TO joe WITH GRANT OPTION; +GRANT SET (SELECT) ON companies TO james; + + +\set VERBOSITY terse +SET client_min_messages TO ERROR; +DROP SCHEMA pg16 CASCADE; +