]> granicus.if.org Git - postgresql/commitdiff
Add new catalog called pg_init_privs
authorStephen Frost <sfrost@snowman.net>
Thu, 7 Apr 2016 01:45:32 +0000 (21:45 -0400)
committerStephen Frost <sfrost@snowman.net>
Thu, 7 Apr 2016 01:45:32 +0000 (21:45 -0400)
This new catalog holds the privileges which the system was
initialized with at initdb time, along with any permissions set
by extensions at CREATE EXTENSION time.  This allows pg_dump
(and any other similar use-cases) to detect when the privileges
set on initdb-created or extension-created objects have been
changed from what they were set to at initdb/extension-creation
time and handle those changes appropriately.

Reviews by Alexander Korotkov, Jose Luis Tallon

doc/src/sgml/catalogs.sgml
src/backend/catalog/Makefile
src/backend/catalog/aclchk.c
src/backend/catalog/dependency.c
src/bin/initdb/initdb.c
src/include/catalog/indexing.h
src/include/catalog/pg_init_privs.h [new file with mode: 0644]
src/test/regress/expected/sanity_check.out

index 725bacee5dd13e8c979f15ca736eb064164154d2..d6b60db074478b20bd0c0fb3f6ddb57469f88b2a 100644 (file)
       <entry>table inheritance hierarchy</entry>
      </row>
 
+     <row>
+      <entry><link linkend="catalog-pg-init-privs"><structname>pg_init_privs</structname></link></entry>
+      <entry>object initial privileges</entry>
+     </row>
+
      <row>
       <entry><link linkend="catalog-pg-language"><structname>pg_language</structname></link></entry>
       <entry>languages for writing functions</entry>
 
  </sect1>
 
+ <sect1 id="catalog-pg-init-privs">
+  <title><structname>pg_init_privs</structname></title>
+
+  <indexterm zone="catalog-pg-init-privs">
+   <primary>pg_init_privs</primary>
+  </indexterm>
+
+  <para>
+   The catalog <structname>pg_init_privs</> records information about
+   the initial privileges of objects in the system.  There is one entry
+   for each object in the database which has a non-default (non-NULL)
+   initial set of privileges.
+  </para>
+
+  <para>
+   Objects can have initial privileges either by having those privileges set
+   when the system is initialized (by <application>initdb</>) or when the
+   object is created during a <command>CREATE EXTENSION</command> and the
+   extension script sets initial privileges using the <command>GRANT</command>
+   system.  Note that the system will automatically handle recording of the
+   privileges during the extension script and that extension authors need
+   only use the <command>GRANT</command> and <command>REVOKE</command>
+   statements in their script to have the privileges recorded.  The
+   <literal>privtype</literal> column indicates if the initial privilege was
+   set by <application>initdb</> or during a
+   <command>CREATE EXTENSION</command> command.
+  </para>
+
+  <para>
+   Objects which have initial privileges set by <application>initdb</> will
+   have entries where <literal>privtype</literal> is
+   <literal>'i'</literal>, while objects which have initial privileges set
+   by <command>CREATE EXTENSION</command> will have entries where
+   <literal>privtype</literal> is <literal>'e'</literal>.
+  </para>
+
+  <table>
+   <title><structname>pg_inherits</> Columns</title>
+
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry><structfield>objoid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry>any OID column</entry>
+      <entry>The OID of the specific object</entry>
+     </row>
+
+     <row>
+      <entry><structfield>classoid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
+      <entry>The OID of the system catalog the object is in</entry>
+     </row>
+
+     <row>
+      <entry><structfield>objsubid</structfield></entry>
+      <entry><type>int4</type></entry>
+      <entry></entry>
+      <entry>
+       For a table column, this is the column number (the
+       <structfield>objoid</> and <structfield>classoid</> refer to the
+       table itself).  For all other object types, this column is
+       zero.
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>privtype</structfield></entry>
+      <entry><type>char</type></entry>
+      <entry></entry>
+      <entry>
+       A code defining the type of initial privilege of this object; see text
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>initprivs</structfield></entry>
+      <entry><type>aclitem[]</type></entry>
+      <entry></entry>
+      <entry>
+       The initial access privileges; see
+       <xref linkend="sql-grant"> and
+       <xref linkend="sql-revoke">
+       for details
+      </entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect1>
+
 
  <sect1 id="catalog-pg-language">
   <title><structname>pg_language</structname></title>
index 25130ecf124805565f61c17045c9589445c10e8c..1ce761004979d2c5eb56021ed200fae5a863a22d 100644 (file)
@@ -40,7 +40,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
        pg_ts_parser.h pg_ts_template.h pg_extension.h \
        pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
        pg_foreign_table.h pg_policy.h pg_replication_origin.h \
-       pg_default_acl.h pg_seclabel.h pg_shseclabel.h \
+       pg_default_acl.h pg_init_privs.h pg_seclabel.h pg_shseclabel.h \
        pg_collation.h pg_range.h pg_transform.h \
        toasting.h indexing.h \
     )
index 0f3bc074e1f336987b55e8cfb62a74659a4c00f6..ffb6678c6a4448b503ea6cd557a3aae2cee37d1b 100644 (file)
@@ -35,6 +35,7 @@
 #include "catalog/pg_extension.h"
 #include "catalog/pg_foreign_data_wrapper.h"
 #include "catalog/pg_foreign_server.h"
+#include "catalog/pg_init_privs.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_largeobject.h"
 #include "catalog/pg_largeobject_metadata.h"
@@ -49,6 +50,7 @@
 #include "catalog/pg_ts_dict.h"
 #include "commands/dbcommands.h"
 #include "commands/event_trigger.h"
+#include "commands/extension.h"
 #include "commands/proclang.h"
 #include "commands/tablespace.h"
 #include "foreign/foreign.h"
@@ -119,6 +121,8 @@ static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
                                                 AttrNumber att_number, const char *colname);
 static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum,
                   Oid roleid, AclMode mask, AclMaskHow how);
+static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
+                                               Acl *new_acl);
 
 
 #ifdef ACLDEBUG
@@ -1678,6 +1682,10 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
                /* keep the catalog indexes up to date */
                CatalogUpdateIndexes(attRelation, newtuple);
 
+               /* Update initial privileges for extensions */
+               recordExtensionInitPriv(relOid, RelationRelationId, attnum,
+                                                               ACL_NUM(new_acl) > 0 ? new_acl : NULL);
+
                /* Update the shared dependency ACL info */
                updateAclDependencies(RelationRelationId, relOid, attnum,
                                                          ownerId,
@@ -1939,6 +1947,9 @@ ExecGrant_Relation(InternalGrant *istmt)
                        /* keep the catalog indexes up to date */
                        CatalogUpdateIndexes(relation, newtuple);
 
+                       /* Update initial privileges for extensions */
+                       recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
+
                        /* Update the shared dependency ACL info */
                        updateAclDependencies(RelationRelationId, relOid, 0,
                                                                  ownerId,
@@ -2254,6 +2265,10 @@ ExecGrant_Fdw(InternalGrant *istmt)
                /* keep the catalog indexes up to date */
                CatalogUpdateIndexes(relation, newtuple);
 
+               /* Update initial privileges for extensions */
+               recordExtensionInitPriv(fdwid, ForeignDataWrapperRelationId, 0,
+                                                               new_acl);
+
                /* Update the shared dependency ACL info */
                updateAclDependencies(ForeignDataWrapperRelationId,
                                                          HeapTupleGetOid(tuple), 0,
@@ -2379,6 +2394,9 @@ ExecGrant_ForeignServer(InternalGrant *istmt)
                /* keep the catalog indexes up to date */
                CatalogUpdateIndexes(relation, newtuple);
 
+               /* Update initial privileges for extensions */
+               recordExtensionInitPriv(srvid, ForeignServerRelationId, 0, new_acl);
+
                /* Update the shared dependency ACL info */
                updateAclDependencies(ForeignServerRelationId,
                                                          HeapTupleGetOid(tuple), 0,
@@ -2503,6 +2521,9 @@ ExecGrant_Function(InternalGrant *istmt)
                /* keep the catalog indexes up to date */
                CatalogUpdateIndexes(relation, newtuple);
 
+               /* Update initial privileges for extensions */
+               recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
+
                /* Update the shared dependency ACL info */
                updateAclDependencies(ProcedureRelationId, funcId, 0,
                                                          ownerId,
@@ -2633,6 +2654,9 @@ ExecGrant_Language(InternalGrant *istmt)
                /* keep the catalog indexes up to date */
                CatalogUpdateIndexes(relation, newtuple);
 
+               /* Update initial privileges for extensions */
+               recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
+
                /* Update the shared dependency ACL info */
                updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
                                                          ownerId,
@@ -2772,6 +2796,9 @@ ExecGrant_Largeobject(InternalGrant *istmt)
                /* keep the catalog indexes up to date */
                CatalogUpdateIndexes(relation, newtuple);
 
+               /* Update initial privileges for extensions */
+               recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
+
                /* Update the shared dependency ACL info */
                updateAclDependencies(LargeObjectRelationId,
                                                          HeapTupleGetOid(tuple), 0,
@@ -2897,6 +2924,9 @@ ExecGrant_Namespace(InternalGrant *istmt)
                /* keep the catalog indexes up to date */
                CatalogUpdateIndexes(relation, newtuple);
 
+               /* Update initial privileges for extensions */
+               recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
+
                /* Update the shared dependency ACL info */
                updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
                                                          ownerId,
@@ -3158,6 +3188,9 @@ ExecGrant_Type(InternalGrant *istmt)
                /* keep the catalog indexes up to date */
                CatalogUpdateIndexes(relation, newtuple);
 
+               /* Update initial privileges for extensions */
+               recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
+
                /* Update the shared dependency ACL info */
                updateAclDependencies(TypeRelationId, typId, 0,
                                                          ownerId,
@@ -5174,3 +5207,119 @@ get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
 
        return result;
 }
+
+/*
+ * Record initial ACL for an extension object
+ *
+ * This will perform a wholesale replacement of the entire ACL for the object
+ * passed in, therefore be sure to pass in the complete new ACL to use.
+ *
+ * Can be called at any time, we check if 'creating_extension' is set and, if
+ * not, exit immediately.
+ *
+ * Pass in the object OID, the OID of the class (the OID of the table which
+ * the object is defined in) and the 'sub' id of the object (objsubid), if
+ * any.  If there is no 'sub' id (they are currently only used for columns of
+ * tables) then pass in '0'.  Finally, pass in the complete ACL to store.
+ *
+ * If an ACL already exists for this object/sub-object then we will replace
+ * it with what is passed in.
+ *
+ * Passing in NULL for 'new_acl' will result in the entry for the object being
+ * removed, if one is found.
+ */
+static void
+recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
+{
+       Relation        relation;
+       ScanKeyData key[3];
+       SysScanDesc scan;
+       HeapTuple       tuple;
+       HeapTuple       oldtuple;
+
+       if (!creating_extension)
+               return;
+
+       relation = heap_open(InitPrivsRelationId, RowExclusiveLock);
+
+       ScanKeyInit(&key[0],
+                               Anum_pg_init_privs_objoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(objoid));
+       ScanKeyInit(&key[1],
+                               Anum_pg_init_privs_classoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(classoid));
+       ScanKeyInit(&key[2],
+                               Anum_pg_init_privs_objsubid,
+                               BTEqualStrategyNumber, F_INT4EQ,
+                               Int32GetDatum(objsubid));
+
+       scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
+                                                         NULL, 3, key);
+
+       /* There should exist only one entry or none. */
+       oldtuple = systable_getnext(scan);
+
+       systable_endscan(scan);
+
+       /* If we find an entry, update it with the latest ACL. */
+       if (HeapTupleIsValid(oldtuple))
+       {
+               Datum           values[Natts_pg_init_privs];
+               bool            nulls[Natts_pg_init_privs];
+               bool            replace[Natts_pg_init_privs];
+
+               /* If we have a new ACL to set, then update the row with it. */
+               if (new_acl)
+               {
+                       MemSet(values, 0, sizeof(values));
+                       MemSet(nulls, false, sizeof(nulls));
+                       MemSet(replace, false, sizeof(replace));
+
+                       values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
+                       replace[Anum_pg_init_privs_privs - 1] = true;
+
+                       oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
+                                                                                values, nulls, replace);
+
+                       simple_heap_update(relation, &oldtuple->t_self, oldtuple);
+
+                       /* keep the catalog indexes up to date */
+                       CatalogUpdateIndexes(relation, oldtuple);
+               }
+               else
+                       /* new_acl is NULL, so delete the entry we found. */
+                       simple_heap_delete(relation, &oldtuple->t_self);
+       }
+       else
+       {
+               /* No entry found, so add it. */
+               Datum           values[Natts_pg_init_privs];
+               bool            nulls[Natts_pg_init_privs];
+
+               MemSet(nulls, false, sizeof(nulls));
+
+               values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
+               values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
+               values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
+
+               /* This function only handles initial privileges of extensions */
+               values[Anum_pg_init_privs_privtype - 1] =
+                       CharGetDatum(INITPRIVS_EXTENSION);
+
+               values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
+
+               tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
+
+               simple_heap_insert(relation, tuple);
+
+               /* keep the catalog indexes up to date */
+               CatalogUpdateIndexes(relation, tuple);
+       }
+
+       /* prevent error when processing objects multiple times */
+       CommandCounterIncrement();
+
+       heap_close(relation, RowExclusiveLock);
+}
index 79595a9d230d6a0188a61512268f5b47263b658f..a6180a64f2156658195701408f9b8fbbfc4c832f 100644 (file)
@@ -39,6 +39,7 @@
 #include "catalog/pg_extension.h"
 #include "catalog/pg_foreign_data_wrapper.h"
 #include "catalog/pg_foreign_server.h"
+#include "catalog/pg_init_privs.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_largeobject.h"
 #include "catalog/pg_namespace.h"
@@ -196,6 +197,7 @@ static bool object_address_present_add_flags(const ObjectAddress *object,
 static bool stack_address_present_add_flags(const ObjectAddress *object,
                                                                int flags,
                                                                ObjectAddressStack *stack);
+static void DeleteInitPrivs(const ObjectAddress *object);
 
 
 /*
@@ -1106,12 +1108,13 @@ deleteOneObject(const ObjectAddress *object, Relation *depRel, int flags)
 
 
        /*
-        * Delete any comments or security labels associated with this object.
-        * (This is a convenient place to do these things, rather than having
-        * every object type know to do it.)
+        * Delete any comments, security labels, or initial privileges associated
+        * with this object.  (This is a convenient place to do these things,
+        * rather than having every object type know to do it.)
         */
        DeleteComments(object->objectId, object->classId, object->objectSubId);
        DeleteSecurityLabel(object);
+       DeleteInitPrivs(object);
 
        /*
         * CommandCounterIncrement here to ensure that preceding changes are all
@@ -2432,3 +2435,40 @@ getObjectClass(const ObjectAddress *object)
        elog(ERROR, "unrecognized object class: %u", object->classId);
        return OCLASS_CLASS;            /* keep compiler quiet */
 }
+
+/*
+ * delete initial ACL for extension objects
+ */
+static void
+DeleteInitPrivs(const ObjectAddress *object)
+{
+       Relation        relation;
+       ScanKeyData key[3];
+       SysScanDesc scan;
+       HeapTuple       oldtuple;
+
+       relation = heap_open(InitPrivsRelationId, RowExclusiveLock);
+
+       ScanKeyInit(&key[0],
+                               Anum_pg_init_privs_objoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->objectId));
+       ScanKeyInit(&key[1],
+                               Anum_pg_init_privs_classoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->classId));
+       ScanKeyInit(&key[2],
+                               Anum_pg_init_privs_objsubid,
+                               BTEqualStrategyNumber, F_INT4EQ,
+                               Int32GetDatum(object->objectSubId));
+
+       scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
+                                                         NULL, 3, key);
+
+       while (HeapTupleIsValid(oldtuple = systable_getnext(scan)))
+               simple_heap_delete(relation, &oldtuple->t_self);
+
+       systable_endscan(scan);
+
+       heap_close(relation, RowExclusiveLock);
+}
index ed3ba7b6248156502e701aadb2e346c00e62c4dc..858667b394155b3d5fd06942cd5e2f5fbc052c87 100644 (file)
@@ -1989,6 +1989,11 @@ setup_dictionary(FILE *cmdfd)
  * Some objects may require different permissions by default, so we
  * make sure we don't overwrite privilege sets that have already been
  * set (NOT NULL).
+ *
+ * Also populate pg_init_privs to save what the privileges are at init
+ * time.  This is used by pg_dump to allow users to change privileges
+ * on catalog objects and to have those privilege changes preserved
+ * across dump/reload and pg_upgrade.
  */
 static void
 setup_privileges(FILE *cmdfd)
@@ -2002,6 +2007,144 @@ setup_privileges(FILE *cmdfd)
                "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n\n",
                "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n\n",
                "REVOKE ALL ON pg_largeobject FROM PUBLIC;\n\n",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
+               "        0,"
+               "        relacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_class"
+               "    WHERE"
+               "        relacl IS NOT NULL"
+               "        AND relkind IN ('r', 'v', 'm', 'S');",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        pg_class.oid,"
+               "        (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
+               "        pg_attribute.attnum,"
+               "        pg_attribute.attacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_class"
+               "        JOIN pg_attribute ON (pg_class.oid = pg_attribute.attrelid)"
+               "    WHERE"
+               "        pg_attribute.attacl IS NOT NULL"
+               "        AND pg_class.relkind IN ('r', 'v', 'm', 'S');",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class WHERE relname = 'pg_proc'),"
+               "        0,"
+               "        proacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_proc"
+               "    WHERE"
+               "        proacl IS NOT NULL;",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class WHERE relname = 'pg_type'),"
+               "        0,"
+               "        typacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_type"
+               "    WHERE"
+               "        typacl IS NOT NULL;",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class WHERE relname = 'pg_language'),"
+               "        0,"
+               "        lanacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_language"
+               "    WHERE"
+               "        lanacl IS NOT NULL;",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class WHERE "
+               "                 relname = 'pg_largeobject_metadata'),"
+               "        0,"
+               "        lomacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_largeobject_metadata"
+               "    WHERE"
+               "        lomacl IS NOT NULL;",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class WHERE relname = 'pg_namespace'),"
+               "        0,"
+               "        nspacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_namespace"
+               "    WHERE"
+               "        nspacl IS NOT NULL;",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class WHERE relname = 'pg_database'),"
+               "        0,"
+               "        datacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_database"
+               "    WHERE"
+               "        datacl IS NOT NULL;",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class WHERE relname = 'pg_tablespace'),"
+               "        0,"
+               "        spcacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_tablespace"
+               "    WHERE"
+               "        spcacl IS NOT NULL;",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class WHERE "
+               "                 relname = 'pg_foreign_data_wrapper'),"
+               "        0,"
+               "        fdwacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_foreign_data_wrapper"
+               "    WHERE"
+               "        fdwacl IS NOT NULL;",
+               "INSERT INTO pg_init_privs "
+               "  (objoid, classoid, objsubid, initprivs, privtype)"
+               "    SELECT"
+               "        oid,"
+               "        (SELECT oid FROM pg_class "
+               "                 WHERE relname = 'pg_foreign_server'),"
+               "        0,"
+               "        srvacl,"
+               "        'i'"
+               "    FROM"
+               "        pg_foreign_server"
+               "    WHERE"
+               "        srvacl IS NOT NULL;",
                NULL
        };
 
index ab2c1a8e68c90a045b5bbed01f66008b468f0541..ca5eb3d417882ea6bd616dd0c645207cc373afc1 100644 (file)
@@ -162,6 +162,9 @@ DECLARE_UNIQUE_INDEX(pg_inherits_relid_seqno_index, 2680, on pg_inherits using b
 DECLARE_INDEX(pg_inherits_parent_index, 2187, on pg_inherits using btree(inhparent oid_ops));
 #define InheritsParentIndexId  2187
 
+DECLARE_UNIQUE_INDEX(pg_init_privs_o_c_o_index, 3395, on pg_init_privs using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
+#define InitPrivsObjIndexId  3395
+
 DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, on pg_language using btree(lanname name_ops));
 #define LanguageNameIndexId  2681
 DECLARE_UNIQUE_INDEX(pg_language_oid_index, 2682, on pg_language using btree(oid oid_ops));
diff --git a/src/include/catalog/pg_init_privs.h b/src/include/catalog/pg_init_privs.h
new file mode 100644 (file)
index 0000000..e13edd3
--- /dev/null
@@ -0,0 +1,101 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_init_privs.h
+ *       definition of the system "initial privileges" relation (pg_init_privs)
+ *
+ * NOTE: an object is identified by the OID of the row that primarily
+ * defines the object, plus the OID of the table that that row appears in.
+ * For example, a function is identified by the OID of its pg_proc row
+ * plus the pg_class OID of table pg_proc.  This allows unique identification
+ * of objects without assuming that OIDs are unique across tables.
+ *
+ * Since attributes don't have OIDs of their own, we identify an attribute
+ * privilege by the objoid+classoid of its parent table, plus an "objsubid"
+ * giving the attribute column number.  "objsubid" must be zero in a privilege
+ * for a table itself, so that it is distinct from any column privilege.
+ * Currently, objsubid is unused and zero for all other kinds of objects.
+ *
+ * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_init_privs.h
+ *
+ * NOTES
+ *             the genbki.pl script reads this file and generates .bki
+ *             information from the DATA() statements.
+ *
+ *             XXX do NOT break up DATA() statements into multiple lines!
+ *                     the scripts are not as smart as you might think...
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_INIT_PRIVS_H
+#define PG_INIT_PRIVS_H
+
+#include "catalog/genbki.h"
+
+/* ----------------
+ *             pg_init_privs definition.  cpp turns this into
+ *             typedef struct FormData_pg_init_privs
+ * ----------------
+ */
+#define InitPrivsRelationId  3394
+
+CATALOG(pg_init_privs,3394) BKI_WITHOUT_OIDS
+{
+       Oid                     objoid;                 /* OID of object itself */
+       Oid                     classoid;               /* OID of table containing object */
+       int32           objsubid;               /* column number, or 0 if not used */
+       char            privtype;               /* from initdb or extension? */
+
+#ifdef CATALOG_VARLEN                  /* variable-length fields start here */
+       aclitem         initprivs[1] BKI_FORCE_NOT_NULL;                /* initial privs on
+                                                                                                                * object */
+#endif
+} FormData_pg_init_privs;
+
+/* ----------------
+ *             Form_pg_init_privs corresponds to a pointer to a tuple with
+ *             the format of pg_init_privs relation.
+ * ----------------
+ */
+typedef FormData_pg_init_privs *Form_pg_init_privs;
+
+/* ----------------
+ *             compiler constants for pg_init_privs
+ * ----------------
+ */
+#define Natts_pg_init_privs                            5
+#define Anum_pg_init_privs_objoid              1
+#define Anum_pg_init_privs_classoid            2
+#define Anum_pg_init_privs_objsubid            3
+#define Anum_pg_init_privs_privtype            4
+#define Anum_pg_init_privs_privs               5
+
+/*
+ * It is important to know if the initial privileges are from initdb or from an
+ * extension.  This enum is used to provide that differentiation and the two
+ * places which populate this table (initdb and during CREATE EXTENSION, see
+ * recordExtensionInitPriv()) know to use the correct values.
+ */
+
+typedef enum InitPrivsType
+{
+       INITPRIVS_INITDB = 'i',
+       INITPRIVS_EXTENSION = 'e'
+} InitPrivsType;
+
+/* ----------------
+ *             initial contents of pg_init_privs
+ * ----------------
+ */
+
+/*
+ *     Because the contents of this table depend on what is done with the other
+ *     objects in the system (and, in particular, may change due to changes is
+ *     system_views.sql), there is no initialization here.
+ *
+ *     The initial contents are loaded near the end of initdb.
+ */
+
+#endif   /* PG_INIT_PRIVS_H */
index 2c5be4bae4bb0fa80db1b7d151e647023aa5a7f8..4d81ba7dac2c9dac0739b3ff945f22984d231178 100644 (file)
@@ -110,6 +110,7 @@ pg_foreign_server|t
 pg_foreign_table|t
 pg_index|t
 pg_inherits|t
+pg_init_privs|t
 pg_language|t
 pg_largeobject|t
 pg_largeobject_metadata|t