deparse: support ALTER DEFAULT PRIVILEGES
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 16 Mar 2015 17:41:13 +0000 (14:41 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 7 Apr 2015 17:09:40 +0000 (14:09 -0300)
src/backend/commands/event_trigger.c
src/backend/tcop/deparse_utility.c
src/backend/tcop/utility.c
src/include/commands/event_trigger.h
src/include/tcop/deparse_utility.h

index 1fa0d95962d68302cf9f444e319223eccb750ede..488ca20398e353acbf76baf6ef3ca188364a5d36 100644 (file)
@@ -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);
index 9d083dbc418cdfcecf72ffe3422249d761fca2e7..860eb0f22ca508c2de130fd5e13a97db4d00e911 100644 (file)
@@ -5690,6 +5690,123 @@ deparse_AlterOpFamily(StashedCommand *cmd)
    return alterOpFam;
 }
 
+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)
 {
@@ -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);
    }
index 0bd239c6aa7f5ff31c88b8391f143a0dce80f406..eaa057f2858dc362ad81c3feccd15af4f9b3c220 100644 (file)
@@ -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 */
index a8435e323cbc84f778c4a960b569fb6c539e621e..35fbfd153b00b20bc27e9cdb29dd608fce5df468 100644 (file)
@@ -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 */
index 6aa5fa56524193bf65cb68d3e2336d87dd565787..3a51b2489b7ac60b7712b41d3b9f5394c79d534e 100644 (file)
@@ -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;