From 76618097a6c027ec603a3dd143f61098e3fb9794 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 14 Jun 2024 16:20:35 -0400 Subject: [PATCH] Clean out column-level pg_init_privs entries when dropping tables. 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 | 21 +++++++++++++------ .../test_pg_dump/expected/test_pg_dump.out | 7 +++++++ .../modules/test_pg_dump/sql/test_pg_dump.sql | 5 +++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index d4b5b2ade10..0489cbabcb8 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -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); diff --git a/src/test/modules/test_pg_dump/expected/test_pg_dump.out b/src/test/modules/test_pg_dump/expected/test_pg_dump.out index bda1c6b3c2a..3cd7db97aa4 100644 --- a/src/test/modules/test_pg_dump/expected/test_pg_dump.out +++ b/src/test/modules/test_pg_dump/expected/test_pg_dump.out @@ -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) + diff --git a/src/test/modules/test_pg_dump/sql/test_pg_dump.sql b/src/test/modules/test_pg_dump/sql/test_pg_dump.sql index a56a945104d..2110ac71633 100644 --- a/src/test/modules/test_pg_dump/sql/test_pg_dump.sql +++ b/src/test/modules/test_pg_dump/sql/test_pg_dump.sql @@ -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'; -- 2.39.5