Clean out column-level pg_init_privs entries when dropping tables.
authorTom Lane <[email protected]>
Fri, 14 Jun 2024 20:20:35 +0000 (16:20 -0400)
committerTom Lane <[email protected]>
Fri, 14 Jun 2024 20:20:35 +0000 (16:20 -0400)
DeleteInitPrivs did not get the memo about how, when dropping a
whole object (with subid == 0), you should drop entries relating
to its sub-objects too.  This is visible in the test_pg_dump test
case if one drops the extension at the end: the entry for
GRANT SELECT(col1) ON regress_pg_dump_table TO public;
was still present in pg_init_privs afterwards, although it was
pointing to a dangling table OID.

Noted while fooling with a fix for REASSIGN OWNED for pg_init_privs
entries.  This bug is aboriginal in the pg_init_privs feature
though, and there seems no reason not to back-patch the fix.

src/backend/catalog/dependency.c
src/test/modules/test_pg_dump/expected/test_pg_dump.out
src/test/modules/test_pg_dump/sql/test_pg_dump.sql

index d4b5b2ade10a3c3b53f51942d535d47093d7aaa5..0489cbabcb8a9a2c8b394c694308503cf1046d7b 100644 (file)
@@ -1326,7 +1326,9 @@ deleteOneObject(const ObjectAddress *object, Relation *depRel, int flags)
    /*
     * 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.)
+    * rather than having every object type know to do it.)  As above, all
+    * these functions must remove records for sub-objects too if the subid is
+    * zero.
     */
    DeleteComments(object->objectId, object->classId, object->objectSubId);
    DeleteSecurityLabel(object);
@@ -2784,6 +2786,7 @@ DeleteInitPrivs(const ObjectAddress *object)
 {
    Relation    relation;
    ScanKeyData key[3];
+   int         nkeys;
    SysScanDesc scan;
    HeapTuple   oldtuple;
 
@@ -2797,13 +2800,19 @@ DeleteInitPrivs(const ObjectAddress *object)
                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));
+   if (object->objectSubId != 0)
+   {
+       ScanKeyInit(&key[2],
+                   Anum_pg_init_privs_objsubid,
+                   BTEqualStrategyNumber, F_INT4EQ,
+                   Int32GetDatum(object->objectSubId));
+       nkeys = 3;
+   }
+   else
+       nkeys = 2;
 
    scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
-                             NULL, 3, key);
+                             NULL, nkeys, key);
 
    while (HeapTupleIsValid(oldtuple = systable_getnext(scan)))
        CatalogTupleDelete(relation, &oldtuple->t_self);
index bda1c6b3c2a3c55788d970f87a332495157172be..3cd7db97aa47e9bd7f17588681817e91e503d50b 100644 (file)
@@ -276,3 +276,10 @@ SELECT pg_describe_object(classid,objid,objsubid) COLLATE "C" AS obj,
 (0 rows)
 
 DROP ROLE regress_dump_test_role;
+DROP EXTENSION test_pg_dump;
+-- shouldn't be anything left in pg_init_privs
+SELECT * FROM pg_init_privs WHERE privtype = 'e';
+ objoid | classoid | objsubid | privtype | initprivs 
+--------+----------+----------+----------+-----------
+(0 rows)
+
index a56a945104d219086807c4e677332202ee64f86b..2110ac71633c332622be7115998d527c140844d6 100644 (file)
@@ -146,3 +146,8 @@ SELECT pg_describe_object(classid,objid,objsubid) COLLATE "C" AS obj,
   ORDER BY 1, 3;
 
 DROP ROLE regress_dump_test_role;
+
+DROP EXTENSION test_pg_dump;
+
+-- shouldn't be anything left in pg_init_privs
+SELECT * FROM pg_init_privs WHERE privtype = 'e';