>From c84133168628f0eb919d2a607542a6ad804cf445 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 16 Mar 2015 14:41:13 -0300 Subject: [PATCH 28/29] deparse: support ALTER DEFAULT PRIVILEGES --- src/backend/commands/event_trigger.c | 67 +++++++++++++++++++ src/backend/tcop/deparse_utility.c | 124 ++++++++++++++++++++++++++++++++++- src/backend/tcop/utility.c | 3 +- src/include/commands/event_trigger.h | 1 + src/include/tcop/deparse_utility.h | 8 ++- 5 files changed, 200 insertions(+), 3 deletions(-) diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index c19a6a5..002f999 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -1870,6 +1870,52 @@ EventTriggerStashAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid, MemoryContextSwitchTo(oldcxt); } +/* + * EventTriggerStashAlterDefPrivs + * Save data about an ALTER DEFAULT PRIVILEGES command being + * executed + */ +void +EventTriggerStashAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt) +{ + MemoryContext oldcxt; + StashedCommand *stashed; + + if (currentEventTriggerState->commandCollectionInhibited) + return; + + oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt); + + stashed = palloc0(sizeof(StashedCommand)); + stashed->type = SCT_AlterDefaultPrivileges; + + switch (stmt->action->objtype) + { + case ACL_OBJECT_RELATION: + stashed->d.defprivs.objtype = "TABLES"; + break; + case ACL_OBJECT_FUNCTION: + stashed->d.defprivs.objtype = "FUNCTIONS"; + break; + case ACL_OBJECT_SEQUENCE: + stashed->d.defprivs.objtype = "SEQUENCES"; + break; + case ACL_OBJECT_TYPE: + stashed->d.defprivs.objtype = "TYPES"; + break; + default: + elog(ERROR, "unexpected object type %d", stmt->action->objtype); + } + + + stashed->in_extension = creating_extension; + stashed->parsetree = copyObject(stmt); + + currentEventTriggerState->stash = lappend(currentEventTriggerState->stash, + stashed); + MemoryContextSwitchTo(oldcxt); +} + Datum pg_event_trigger_get_creation_commands(PG_FUNCTION_ARGS) { @@ -2034,6 +2080,27 @@ pg_event_trigger_get_creation_commands(PG_FUNCTION_ARGS) /* command */ values[i++] = CStringGetTextDatum(command); } + else if (cmd->type == SCT_AlterDefaultPrivileges) + { + /* classid */ + nulls[i++] = true; + /* objid */ + nulls[i++] = true; + /* objsubid */ + nulls[i++] = true; + /* command tag */ + values[i++] = CStringGetTextDatum(CreateCommandTag(cmd->parsetree)); + /* object_type */ + values[i++] = CStringGetTextDatum(cmd->d.defprivs.objtype); + /* schema */ + nulls[i++] = true; + /* identity */ + nulls[i++] = true; + /* in_extension */ + values[i++] = BoolGetDatum(cmd->in_extension); + /* command */ + values[i++] = CStringGetTextDatum(command); + } else { Assert(cmd->type == SCT_Grant); diff --git a/src/backend/tcop/deparse_utility.c b/src/backend/tcop/deparse_utility.c index 4a00479..a0f5849 100644 --- a/src/backend/tcop/deparse_utility.c +++ b/src/backend/tcop/deparse_utility.c @@ -5650,6 +5650,124 @@ deparse_AlterOpFamily(StashedCommand *cmd) } static ObjTree * +deparse_AlterDefaultPrivilegesStmt(StashedCommand *cmd) +{ + ObjTree *alterStmt; + AlterDefaultPrivilegesStmt *stmt = (AlterDefaultPrivilegesStmt *) cmd->parsetree; + List *roles = NIL; + List *schemas = NIL; + List *grantees; + List *privs; + ListCell *cell; + ObjTree *tmp; + ObjTree *grant; + + alterStmt = new_objtree_VA("ALTER DEFAULT PRIVILEGES %{in_schema}s " + "%{for_roles}s %{grant}s", 0); + + /* Scan the parse node to dig out the FOR ROLE and IN SCHEMA clauses */ + foreach(cell, stmt->options) + { + DefElem *opt = (DefElem *) lfirst(cell); + ListCell *cell2; + + Assert(IsA(opt, DefElem)); + Assert(IsA(opt->arg, List)); + if (strcmp(opt->defname, "roles") == 0) + { + foreach(cell2, (List *) opt->arg) + { + Value *val = lfirst(cell2); + + roles = lappend(roles, + new_string_object(strVal(val))); + } + } + else if (strcmp(opt->defname, "schemas") == 0) + { + foreach(cell2, (List *) opt->arg) + { + Value *val = lfirst(cell2); + + schemas = lappend(schemas, + new_string_object(strVal(val))); + } + } + } + + /* Add the FOR ROLE clause, if any */ + tmp = new_objtree_VA("FOR ROLE %{roles:, }I", 0); + append_array_object(tmp, "roles", roles); + if (roles == NIL) + append_bool_object(tmp, "present", false); + append_object_object(alterStmt, "for_roles", tmp); + + /* Add the IN SCHEMA clause, if any */ + tmp = new_objtree_VA("IN SCHEMA %{schemas:, }I", 0); + append_array_object(tmp, "schemas", schemas); + if (schemas == NIL) + append_bool_object(tmp, "present", false); + append_object_object(alterStmt, "in_schema", tmp); + + /* Add the GRANT subcommand */ + if (stmt->action->is_grant) + grant = new_objtree_VA("GRANT %{privileges:, }s ON %{target}s " + "TO %{grantees:, }I %{grant_option}s", 0); + else + grant = new_objtree_VA("REVOKE %{grant_option}s %{privileges:, }s " + "ON %{target}s FROM %{grantees:, }I", 0); + + /* add the GRANT OPTION clause */ + tmp = new_objtree_VA(stmt->action->is_grant ? + "WITH GRANT OPTION" : "GRANT OPTION FOR", + 1, "present", ObjTypeBool, + stmt->action->grant_option); + append_object_object(grant, "grant_option", tmp); + + /* add the target object type */ + append_string_object(grant, "target", cmd->d.defprivs.objtype); + + /* add the grantee list */ + grantees = NIL; + foreach(cell, stmt->action->grantees) + { + RoleSpec *spec = (RoleSpec *) lfirst(cell); + char *role = spec->roletype == ROLESPEC_PUBLIC ? "PUBLIC" : + get_rolespec_name((Node *) spec); + + grantees = lappend(grantees, new_string_object(role)); + } + append_array_object(grant, "grantees", grantees); + + /* + * Add the privileges list. This uses the parser struct, as opposed to the + * InternalGrant format used by GRANT. There are enough other differences + * that this doesn't seem worth improving. + */ + if (stmt->action->privileges == NIL) + privs = list_make1(new_string_object("ALL PRIVILEGES")); + else + { + privs = NIL; + + foreach(cell, stmt->action->privileges) + { + AccessPriv *priv = lfirst(cell); + + Assert(priv->cols == NIL); + privs = lappend(privs, + new_string_object(priv->priv_name)); + } + } + + append_array_object(grant, "privileges", privs); + + append_object_object(alterStmt, "grant", grant); + + return alterStmt; +} + +static ObjTree * deparse_AlterTableStmt(StashedCommand *cmd) { ObjTree *alterTableStmt; @@ -6419,7 +6537,8 @@ deparse_simple_command(StashedCommand *cmd) break; case T_AlterDefaultPrivilegesStmt: - elog(ERROR, "unimplemented deparse of %s", CreateCommandTag(parsetree)); + /* handled elsewhere */ + elog(ERROR, "unexpected command type %s", CreateCommandTag(parsetree)); break; case T_CreatePolicyStmt: /* CREATE POLICY */ @@ -6501,6 +6620,9 @@ deparse_utility_command(StashedCommand *cmd) case SCT_AlterOpFamily: tree = deparse_AlterOpFamily(cmd); break; + case SCT_AlterDefaultPrivileges: + tree = deparse_AlterDefaultPrivilegesStmt(cmd); + break; default: elog(ERROR, "unexpected deparse node type %d", cmd->type); } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 3bc2387..868ae13 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1462,7 +1462,8 @@ ProcessUtilitySlow(Node *parsetree, case T_AlterDefaultPrivilegesStmt: ExecAlterDefaultPrivilegesStmt((AlterDefaultPrivilegesStmt *) parsetree); - /* XXX FIXME WTF? */ + EventTriggerStashAlterDefPrivs(parsetree); + commandStashed = true; break; case T_CreatePolicyStmt: /* CREATE POLICY */ diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h index fd34001..b8b39f9 100644 --- a/src/include/commands/event_trigger.h +++ b/src/include/commands/event_trigger.h @@ -75,5 +75,6 @@ extern void EventTriggerAlterTableEnd(void); extern void EventTriggerStashGrant(InternalGrant *istmt); extern void EventTriggerStashAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid, List *operators, List *procedures); +extern void EventTriggerStashAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt); #endif /* EVENT_TRIGGER_H */ diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h index b663ba2..a0ed8e4 100644 --- a/src/include/tcop/deparse_utility.h +++ b/src/include/tcop/deparse_utility.h @@ -30,7 +30,8 @@ typedef enum StashedCommandType SCT_Simple, SCT_AlterTable, SCT_Grant, - SCT_AlterOpFamily + SCT_AlterOpFamily, + SCT_AlterDefaultPrivileges } StashedCommandType; /* @@ -77,6 +78,11 @@ typedef struct StashedCommand List *operators; List *procedures; } opfam; + + struct + { + char *objtype; + } defprivs; } d; } StashedCommand; -- 2.1.4