From 1f1eedd3fa696f41ba426ebcd5de4fe08b5005cf 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 3cca1074490..24f1e0184a7 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1374,7 +1374,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); @@ -2985,6 +2987,7 @@ DeleteInitPrivs(const ObjectAddress *object) { Relation relation; ScanKeyData key[3]; + int nkeys; SysScanDesc scan; HeapTuple oldtuple; @@ -2998,13 +3001,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 f14f3a66646..8df7f090544 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 @@ -91,3 +91,10 @@ ALTER EXTENSION test_pg_dump DROP SERVER s0; ALTER EXTENSION test_pg_dump DROP TABLE test_pg_dump_t1; ALTER EXTENSION test_pg_dump DROP TYPE test_pg_dump_e1; ALTER EXTENSION test_pg_dump DROP VIEW test_pg_dump_v1; +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 a61a7c8c4ce..7f2e7d32f6d 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 @@ -106,3 +106,8 @@ ALTER EXTENSION test_pg_dump DROP SERVER s0; ALTER EXTENSION test_pg_dump DROP TABLE test_pg_dump_t1; ALTER EXTENSION test_pg_dump DROP TYPE test_pg_dump_e1; ALTER EXTENSION test_pg_dump DROP VIEW test_pg_dump_v1; + +DROP EXTENSION test_pg_dump; + +-- shouldn't be anything left in pg_init_privs +SELECT * FROM pg_init_privs WHERE privtype = 'e';