>From e81824deb10dcee547ea4216842f050ec6bb0882 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 16 Mar 2015 14:41:13 -0300 Subject: [PATCH 30/37] deparse: support ALTER DEFAULT PRIVILEGES --- src/backend/commands/event_trigger.c | 67 +++++++++++++++++++ src/backend/tcop/deparse_utility.c | 123 ++++++++++++++++++++++++++++++++++- src/backend/tcop/utility.c | 3 +- src/include/commands/event_trigger.h | 1 + src/include/tcop/deparse_utility.h | 9 ++- 5 files changed, 200 insertions(+), 3 deletions(-) diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 9b51bf3..95491a1 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -1887,6 +1887,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) { @@ -2050,6 +2096,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 9d083db..860eb0f 100644 --- a/src/backend/tcop/deparse_utility.c +++ b/src/backend/tcop/deparse_utility.c @@ -5691,6 +5691,123 @@ 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); + ObjTree *obj = new_objtree_for_role(strVal(val)); + + roles = lappend(roles, new_object_object(obj)); + } + } + 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:, }R", 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:, }R %{grant_option}s", 0); + else + grant = new_objtree_VA("REVOKE %{grant_option}s %{privileges:, }s " + "ON %{target}s FROM %{grantees:, }R", 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); + ObjTree *obj = new_objtree_for_rolespec(spec); + + grantees = lappend(grantees, new_object_object(obj)); + } + 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; @@ -6478,7 +6595,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 */ @@ -6559,6 +6677,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 0bd239c..eaa057f 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1465,7 +1465,8 @@ ProcessUtilitySlow(Node *parsetree, case T_AlterDefaultPrivilegesStmt: ExecAlterDefaultPrivilegesStmt((AlterDefaultPrivilegesStmt *) parsetree); - /* XXX FIXME WTF? */ + EventTriggerStashAlterDefPrivs((AlterDefaultPrivilegesStmt *) 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 a8435e3..35fbfd1 100644 --- a/src/include/commands/event_trigger.h +++ b/src/include/commands/event_trigger.h @@ -76,5 +76,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 6aa5fa5..3a51b24 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; /* @@ -80,6 +81,12 @@ typedef struct StashedCommand List *operators; List *procedures; } opfam; + + /* ALTER DEFAULT PRIVILEGES */ + struct + { + char *objtype; + } defprivs; } d; } StashedCommand; -- 2.1.4