diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 2f52e70b48e..a63cc71efa2 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -7182,9 +7182,6 @@ SCRAM-SHA-256$<iteration count>:&l
The referenced object (which must be a role) is mentioned in a
pg_init_privs
entry for the dependent object.
- (A SHARED_DEPENDENCY_INITACL entry is not made for
- the owner of the object, since the owner will have
- a SHARED_DEPENDENCY_OWNER entry anyway.)
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 143876b77ff..fe90102e6eb 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -4771,19 +4771,16 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
/* Update pg_shdepend for roles mentioned in the old/new ACLs. */
oldAclDatum = heap_getattr(oldtuple, Anum_pg_init_privs_initprivs,
RelationGetDescr(relation), &isNull);
- if (!isNull)
- old_acl = DatumGetAclP(oldAclDatum);
- else
- old_acl = NULL; /* this case shouldn't happen, probably */
+ Assert(!isNull);
+ old_acl = DatumGetAclP(oldAclDatum);
noldmembers = aclmembers(old_acl, &oldmembers);
updateInitAclDependencies(classoid, objoid, objsubid,
- ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
/* If we have a new ACL to set, then update the row with it. */
- if (new_acl)
+ if (new_acl && ACL_NUM(new_acl) != 0)
{
values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
replace[Anum_pg_init_privs_initprivs - 1] = true;
@@ -4795,7 +4792,7 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
}
else
{
- /* new_acl is NULL, so delete the entry we found. */
+ /* new_acl is NULL/empty, so delete the entry we found. */
CatalogTupleDelete(relation, &oldtuple->t_self);
}
}
@@ -4810,7 +4807,7 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
* If we are passed in a NULL ACL and no entry exists, we can just
* fall through and do nothing.
*/
- if (new_acl)
+ if (new_acl && ACL_NUM(new_acl) != 0)
{
/* No entry found, so add it. */
values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
@@ -4832,7 +4829,6 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
oldmembers = NULL;
updateInitAclDependencies(classoid, objoid, objsubid,
- ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
}
@@ -4846,6 +4842,115 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
table_close(relation, RowExclusiveLock);
}
+/*
+ * ReplaceRoleInInitPriv
+ *
+ * Used by shdepReassignOwned to replace mentions of a role in pg_init_privs.
+ */
+void
+ReplaceRoleInInitPriv(Oid oldroleid, Oid newroleid,
+ Oid classid, Oid objid, int32 objsubid)
+{
+ Relation rel;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple oldtuple;
+ Datum oldAclDatum;
+ bool isNull;
+ Acl *old_acl;
+ Acl *new_acl;
+ HeapTuple newtuple;
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+
+ /* Search for existing pg_init_privs entry for the target object. */
+ rel = table_open(InitPrivsRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_init_privs_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objid));
+ ScanKeyInit(&key[1],
+ Anum_pg_init_privs_classoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classid));
+ ScanKeyInit(&key[2],
+ Anum_pg_init_privs_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(objsubid));
+
+ scan = systable_beginscan(rel, InitPrivsObjIndexId, true,
+ NULL, 3, key);
+
+ /* There should exist only one entry or none. */
+ oldtuple = systable_getnext(scan);
+
+ if (!HeapTupleIsValid(oldtuple))
+ {
+ /*
+ * Hmm, why are we here if there's no entry? But pack up and go away
+ * quietly.
+ */
+ systable_endscan(scan);
+ table_close(rel, RowExclusiveLock);
+ return;
+ }
+
+ /* Get a writable copy of the existing ACL. */
+ oldAclDatum = heap_getattr(oldtuple, Anum_pg_init_privs_initprivs,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ old_acl = DatumGetAclPCopy(oldAclDatum);
+
+ /*
+ * Generate new ACL. This usage of aclnewowner is a bit off-label when
+ * oldroleid isn't the owner; but it does the job fine.
+ */
+ new_acl = aclnewowner(old_acl, oldroleid, newroleid);
+
+ /*
+ * If we end with an empty ACL, delete the pg_init_privs entry. (That
+ * probably can't happen here, but we may as well cover the case.)
+ */
+ if (new_acl == NULL || ACL_NUM(new_acl) == 0)
+ {
+ CatalogTupleDelete(rel, &oldtuple->t_self);
+ }
+ else
+ {
+ Datum values[Natts_pg_init_privs] = {0};
+ bool nulls[Natts_pg_init_privs] = {0};
+ bool replaces[Natts_pg_init_privs] = {0};
+
+ /* Update existing entry. */
+ values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
+ replaces[Anum_pg_init_privs_initprivs - 1] = true;
+
+ newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel),
+ values, nulls, replaces);
+ CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
+ }
+
+ /*
+ * Update the shared dependency ACL info.
+ */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ updateInitAclDependencies(classid, objid, objsubid,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ systable_endscan(scan);
+
+ /* prevent error when processing objects multiple times */
+ CommandCounterIncrement();
+
+ table_close(rel, RowExclusiveLock);
+}
+
/*
* RemoveRoleFromInitPriv
*
@@ -4907,10 +5012,8 @@ RemoveRoleFromInitPriv(Oid roleid, Oid classid, Oid objid, int32 objsubid)
/* Get a writable copy of the existing ACL. */
oldAclDatum = heap_getattr(oldtuple, Anum_pg_init_privs_initprivs,
RelationGetDescr(rel), &isNull);
- if (!isNull)
- old_acl = DatumGetAclPCopy(oldAclDatum);
- else
- old_acl = NULL; /* this case shouldn't happen, probably */
+ Assert(!isNull);
+ old_acl = DatumGetAclPCopy(oldAclDatum);
/*
* We need the members of both old and new ACLs so we can correct the
@@ -4972,7 +5075,6 @@ RemoveRoleFromInitPriv(Oid roleid, Oid classid, Oid objid, int32 objsubid)
nnewmembers = aclmembers(new_acl, &newmembers);
updateInitAclDependencies(classid, objid, objsubid,
- ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index 20bcfd779b9..753afb88453 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -103,6 +103,9 @@ static void storeObjectDescription(StringInfo descs,
ObjectAddress *object,
SharedDependencyType deptype,
int count);
+static void shdepReassignOwned_Owner(Form_pg_shdepend sdepForm, Oid newrole);
+static void shdepReassignOwned_InitAcl(Form_pg_shdepend sdepForm,
+ Oid oldrole, Oid newrole);
/*
@@ -345,10 +348,11 @@ changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
AuthIdRelationId, newOwnerId,
SHARED_DEPENDENCY_ACL);
- /* The same applies to SHARED_DEPENDENCY_INITACL */
- shdepDropDependency(sdepRel, classId, objectId, 0, true,
- AuthIdRelationId, newOwnerId,
- SHARED_DEPENDENCY_INITACL);
+ /*
+ * However, nothing need be done about SHARED_DEPENDENCY_INITACL entries,
+ * since those exist whether or not the role is the object's owner, and
+ * ALTER OWNER does not modify the underlying pg_init_privs entry.
+ */
table_close(sdepRel, RowExclusiveLock);
}
@@ -500,16 +504,18 @@ updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
* Update the pg_shdepend info for a pg_init_privs entry.
*
* Exactly like updateAclDependencies, except we are considering a
- * pg_init_privs ACL for the specified object.
+ * pg_init_privs ACL for the specified object. Since recording of
+ * pg_init_privs role dependencies is the same for owners and non-owners,
+ * we do not need an ownerId argument.
*/
void
updateInitAclDependencies(Oid classId, Oid objectId, int32 objsubId,
- Oid ownerId,
int noldmembers, Oid *oldmembers,
int nnewmembers, Oid *newmembers)
{
updateAclDependenciesWorker(classId, objectId, objsubId,
- ownerId, SHARED_DEPENDENCY_INITACL,
+ InvalidOid, /* ownerId will not be consulted */
+ SHARED_DEPENDENCY_INITACL,
noldmembers, oldmembers,
nnewmembers, newmembers);
}
@@ -542,11 +548,13 @@ updateAclDependenciesWorker(Oid classId, Oid objectId, int32 objsubId,
Oid roleid = newmembers[i];
/*
- * Skip the owner: he has an OWNER shdep entry instead. (This is
- * not just a space optimization; it makes ALTER OWNER easier. See
- * notes in changeDependencyOnOwner.)
+ * For SHARED_DEPENDENCY_ACL entries, skip the owner: she has an
+ * OWNER shdep entry instead. (This is not just a space
+ * optimization; it makes ALTER OWNER easier. See notes in
+ * changeDependencyOnOwner.) But for INITACL entries, we record
+ * the owner too.
*/
- if (roleid == ownerId)
+ if (deptype == SHARED_DEPENDENCY_ACL && roleid == ownerId)
continue;
/* Skip pinned roles; they don't need dependency entries */
@@ -563,8 +571,8 @@ updateAclDependenciesWorker(Oid classId, Oid objectId, int32 objsubId,
{
Oid roleid = oldmembers[i];
- /* Skip the owner, same as above */
- if (roleid == ownerId)
+ /* Skip the owner for ACL entries, same as above */
+ if (deptype == SHARED_DEPENDENCY_ACL && roleid == ownerId)
continue;
/* Skip pinned roles */
@@ -1476,6 +1484,13 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
}
break;
case SHARED_DEPENDENCY_INITACL:
+
+ /*
+ * Any mentions of the role that remain in pg_init_privs
+ * entries are just dropped. This is the same policy as
+ * we apply to regular ACLs.
+ */
+
/* Shouldn't see a role grant here */
Assert(sdepForm->classid != AuthMemRelationId);
RemoveRoleFromInitPriv(roleid,
@@ -1577,12 +1592,8 @@ shdepReassignOwned(List *roleids, Oid newrole)
sdepForm->dbid != InvalidOid)
continue;
- /* We leave non-owner dependencies alone */
- if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
- continue;
-
/*
- * The various ALTER OWNER routines tend to leak memory in
+ * The various DDL routines called here tend to leak memory in
* CurrentMemoryContext. That's not a problem when they're only
* called once per command; but in this usage where we might be
* touching many objects, it can amount to a serious memory leak.
@@ -1593,81 +1604,23 @@ shdepReassignOwned(List *roleids, Oid newrole)
ALLOCSET_DEFAULT_SIZES);
oldcxt = MemoryContextSwitchTo(cxt);
- /* Issue the appropriate ALTER OWNER call */
- switch (sdepForm->classid)
+ /* Perform the appropriate processing */
+ switch (sdepForm->deptype)
{
- case TypeRelationId:
- AlterTypeOwner_oid(sdepForm->objid, newrole, true);
+ case SHARED_DEPENDENCY_OWNER:
+ shdepReassignOwned_Owner(sdepForm, newrole);
break;
-
- case NamespaceRelationId:
- AlterSchemaOwner_oid(sdepForm->objid, newrole);
+ case SHARED_DEPENDENCY_INITACL:
+ shdepReassignOwned_InitAcl(sdepForm, roleid, newrole);
break;
-
- case RelationRelationId:
-
- /*
- * Pass recursing = true so that we don't fail on indexes,
- * owned sequences, etc when we happen to visit them
- * before their parent table.
- */
- ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
+ case SHARED_DEPENDENCY_ACL:
+ case SHARED_DEPENDENCY_POLICY:
+ case SHARED_DEPENDENCY_TABLESPACE:
+ /* Nothing to do for these entry types */
break;
-
- case DefaultAclRelationId:
-
- /*
- * Ignore default ACLs; they should be handled by DROP
- * OWNED, not REASSIGN OWNED.
- */
- break;
-
- case UserMappingRelationId:
- /* ditto */
- break;
-
- case ForeignServerRelationId:
- AlterForeignServerOwner_oid(sdepForm->objid, newrole);
- break;
-
- case ForeignDataWrapperRelationId:
- AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
- break;
-
- case EventTriggerRelationId:
- AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
- break;
-
- case PublicationRelationId:
- AlterPublicationOwner_oid(sdepForm->objid, newrole);
- break;
-
- case SubscriptionRelationId:
- AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
- break;
-
- /* Generic alter owner cases */
- case CollationRelationId:
- case ConversionRelationId:
- case OperatorRelationId:
- case ProcedureRelationId:
- case LanguageRelationId:
- case LargeObjectRelationId:
- case OperatorFamilyRelationId:
- case OperatorClassRelationId:
- case ExtensionRelationId:
- case StatisticExtRelationId:
- case TableSpaceRelationId:
- case DatabaseRelationId:
- case TSConfigRelationId:
- case TSDictionaryRelationId:
- AlterObjectOwner_internal(sdepForm->classid,
- sdepForm->objid,
- newrole);
- break;
-
default:
- elog(ERROR, "unexpected classid %u", sdepForm->classid);
+ elog(ERROR, "unrecognized dependency type: %d",
+ (int) sdepForm->deptype);
break;
}
@@ -1684,3 +1637,123 @@ shdepReassignOwned(List *roleids, Oid newrole)
table_close(sdepRel, RowExclusiveLock);
}
+
+/*
+ * shdepReassignOwned_Owner
+ *
+ * shdepReassignOwned's processing of SHARED_DEPENDENCY_OWNER entries
+ */
+static void
+shdepReassignOwned_Owner(Form_pg_shdepend sdepForm, Oid newrole)
+{
+ /* Issue the appropriate ALTER OWNER call */
+ switch (sdepForm->classid)
+ {
+ case TypeRelationId:
+ AlterTypeOwner_oid(sdepForm->objid, newrole, true);
+ break;
+
+ case NamespaceRelationId:
+ AlterSchemaOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case RelationRelationId:
+
+ /*
+ * Pass recursing = true so that we don't fail on indexes, owned
+ * sequences, etc when we happen to visit them before their parent
+ * table.
+ */
+ ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
+ break;
+
+ case DefaultAclRelationId:
+
+ /*
+ * Ignore default ACLs; they should be handled by DROP OWNED, not
+ * REASSIGN OWNED.
+ */
+ break;
+
+ case UserMappingRelationId:
+ /* ditto */
+ break;
+
+ case ForeignServerRelationId:
+ AlterForeignServerOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case ForeignDataWrapperRelationId:
+ AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case EventTriggerRelationId:
+ AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case PublicationRelationId:
+ AlterPublicationOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case SubscriptionRelationId:
+ AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ /* Generic alter owner cases */
+ case CollationRelationId:
+ case ConversionRelationId:
+ case OperatorRelationId:
+ case ProcedureRelationId:
+ case LanguageRelationId:
+ case LargeObjectRelationId:
+ case OperatorFamilyRelationId:
+ case OperatorClassRelationId:
+ case ExtensionRelationId:
+ case StatisticExtRelationId:
+ case TableSpaceRelationId:
+ case DatabaseRelationId:
+ case TSConfigRelationId:
+ case TSDictionaryRelationId:
+ AlterObjectOwner_internal(sdepForm->classid,
+ sdepForm->objid,
+ newrole);
+ break;
+
+ default:
+ elog(ERROR, "unexpected classid %u", sdepForm->classid);
+ break;
+ }
+}
+
+/*
+ * shdepReassignOwned_InitAcl
+ *
+ * shdepReassignOwned's processing of SHARED_DEPENDENCY_INITACL entries
+ */
+static void
+shdepReassignOwned_InitAcl(Form_pg_shdepend sdepForm, Oid oldrole, Oid newrole)
+{
+ /*
+ * Currently, REASSIGN OWNED replaces mentions of oldrole with newrole in
+ * pg_init_privs entries, just as it does in the object's regular ACL.
+ * This is less than ideal, since pg_init_privs ought to retain a
+ * historical record of the situation at the end of CREATE EXTENSION.
+ * However, there are two big stumbling blocks to doing something
+ * different:
+ *
+ * 1. If we don't replace the references, what is to happen if the old
+ * role gets dropped? (DROP OWNED's current answer is to just delete the
+ * pg_init_privs entry, which is surely ahistorical.)
+ *
+ * 2. It's unlikely that pg_dump will cope nicely with pg_init_privs
+ * entries that are based on a different owner than the object now has ---
+ * the more so given that pg_init_privs doesn't record the original owner
+ * explicitly. (This problem actually exists anyway given that a bare
+ * ALTER OWNER won't update pg_init_privs, but we don't need REASSIGN
+ * OWNED making it worse.)
+ */
+ ReplaceRoleInInitPriv(oldrole, newrole,
+ sdepForm->classid,
+ sdepForm->objid,
+ sdepForm->objsubid);
+}
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index dc10b4a4839..d7b39140b3d 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -1091,6 +1091,12 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
* The result is a modified copy; the input object is not changed.
*
* NB: caller is responsible for having detoasted the input ACL, if needed.
+ *
+ * Note: the name of this function is a bit of a misnomer, since it will
+ * happily make the specified role substitution whether the old role is
+ * really the owner of the parent object or merely mentioned in its ACL.
+ * But the vast majority of callers use it in connection with ALTER OWNER
+ * operations, so we'll keep the name.
*/
Acl *
aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 542213db380..b3322e8d675 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202406141
+#define CATALOG_VERSION_NO 202406171
#endif
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 7eee66f8106..6908ca7180a 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -57,10 +57,10 @@ typedef enum DependencyType
* one or the other, but not both, of these dependency types.)
*
* (c) a SHARED_DEPENDENCY_INITACL entry means that the referenced object is
- * a role mentioned in a pg_init_privs entry for the dependent object. The
- * referenced object must be a pg_authid entry. (SHARED_DEPENDENCY_INITACL
- * entries are not created for the owner of an object; hence two objects may
- * be linked by one or the other, but not both, of these dependency types.)
+ * a role mentioned in a pg_init_privs entry for the dependent object.
+ * The referenced object must be a pg_authid entry. (Unlike the case for
+ * SHARED_DEPENDENCY_ACL, we make an entry for such a role whether or not
+ * it is the object's owner.)
*
* (d) a SHARED_DEPENDENCY_POLICY entry means that the referenced object is
* a role mentioned in a policy object. The referenced object must be a
@@ -209,7 +209,6 @@ extern void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
int nnewmembers, Oid *newmembers);
extern void updateInitAclDependencies(Oid classId, Oid objectId, int32 objsubId,
- Oid ownerId,
int noldmembers, Oid *oldmembers,
int nnewmembers, Oid *newmembers);
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 1a554c66997..731d84b2a93 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -276,6 +276,8 @@ extern void aclcheck_error_type(AclResult aclerr, Oid typeOid);
extern void recordExtObjInitPriv(Oid objoid, Oid classoid);
extern void removeExtObjInitPriv(Oid objoid, Oid classoid);
+extern void ReplaceRoleInInitPriv(Oid oldroleid, Oid newroleid,
+ Oid classid, Oid objid, int32 objsubid);
extern void RemoveRoleFromInitPriv(Oid roleid,
Oid classid, Oid objid, int32 objsubid);
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 3cd7db97aa4..3536d636d8e 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
@@ -283,3 +283,308 @@ SELECT * FROM pg_init_privs WHERE privtype = 'e';
--------+----------+----------+----------+-----------
(0 rows)
+CREATE ROLE regress_dump_test_role;
+CREATE ROLE regress_dump_test_super SUPERUSER;
+SET ROLE regress_dump_test_super;
+CREATE EXTENSION test_pg_dump;
+RESET ROLE;
+-- Substitute for current user's name to keep test output consistent
+SELECT s.obj,
+ CASE WHEN a.grantor::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantor::regrole::name END,
+ CASE WHEN a.grantee::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantee::regrole::name END,
+ a.privilege_type, a.is_grantable
+FROM
+ (SELECT pg_describe_object(classoid,objoid,objsubid) COLLATE "C" AS obj, initprivs
+ FROM pg_init_privs WHERE privtype = 'e' ORDER BY 1) s,
+ aclexplode(s.initprivs) a;
+ obj | grantor | grantee | privilege_type | is_grantable
+----------------------------------------------------+-------------------------+-------------------------+----------------+--------------
+ column col1 of table regress_pg_dump_table | regress_dump_test_super | - | SELECT | f
+ function regress_pg_dump_schema.test_agg(smallint) | regress_dump_test_super | - | EXECUTE | f
+ function regress_pg_dump_schema.test_agg(smallint) | regress_dump_test_super | regress_dump_test_super | EXECUTE | f
+ function regress_pg_dump_schema.test_agg(smallint) | regress_dump_test_super | regress_dump_test_role | EXECUTE | f
+ function regress_pg_dump_schema.test_func() | regress_dump_test_super | - | EXECUTE | f
+ function regress_pg_dump_schema.test_func() | regress_dump_test_super | regress_dump_test_super | EXECUTE | f
+ function regress_pg_dump_schema.test_func() | regress_dump_test_super | regress_dump_test_role | EXECUTE | f
+ function wgo_then_no_access() | regress_dump_test_super | - | EXECUTE | f
+ function wgo_then_no_access() | regress_dump_test_super | regress_dump_test_super | EXECUTE | f
+ function wgo_then_no_access() | regress_dump_test_super | pg_signal_backend | EXECUTE | t
+ sequence regress_pg_dump_schema.test_seq | regress_dump_test_super | regress_dump_test_super | SELECT | f
+ sequence regress_pg_dump_schema.test_seq | regress_dump_test_super | regress_dump_test_super | UPDATE | f
+ sequence regress_pg_dump_schema.test_seq | regress_dump_test_super | regress_dump_test_super | USAGE | f
+ sequence regress_pg_dump_schema.test_seq | regress_dump_test_super | regress_dump_test_role | USAGE | f
+ sequence regress_pg_dump_seq | regress_dump_test_super | regress_dump_test_super | SELECT | f
+ sequence regress_pg_dump_seq | regress_dump_test_super | regress_dump_test_super | UPDATE | f
+ sequence regress_pg_dump_seq | regress_dump_test_super | regress_dump_test_super | USAGE | f
+ sequence regress_pg_dump_seq | regress_dump_test_super | regress_dump_test_role | USAGE | f
+ sequence regress_seq_dumpable | regress_dump_test_super | regress_dump_test_super | SELECT | f
+ sequence regress_seq_dumpable | regress_dump_test_super | regress_dump_test_super | UPDATE | f
+ sequence regress_seq_dumpable | regress_dump_test_super | regress_dump_test_super | USAGE | f
+ sequence regress_seq_dumpable | regress_dump_test_super | - | SELECT | f
+ sequence wgo_then_regular | regress_dump_test_super | regress_dump_test_super | SELECT | f
+ sequence wgo_then_regular | regress_dump_test_super | regress_dump_test_super | UPDATE | f
+ sequence wgo_then_regular | regress_dump_test_super | regress_dump_test_super | USAGE | f
+ sequence wgo_then_regular | regress_dump_test_super | pg_signal_backend | SELECT | f
+ sequence wgo_then_regular | regress_dump_test_super | pg_signal_backend | UPDATE | t
+ sequence wgo_then_regular | regress_dump_test_super | pg_signal_backend | USAGE | t
+ table regress_pg_dump_schema.test_table | regress_dump_test_super | regress_dump_test_super | INSERT | f
+ table regress_pg_dump_schema.test_table | regress_dump_test_super | regress_dump_test_super | SELECT | f
+ table regress_pg_dump_schema.test_table | regress_dump_test_super | regress_dump_test_super | UPDATE | f
+ table regress_pg_dump_schema.test_table | regress_dump_test_super | regress_dump_test_super | DELETE | f
+ table regress_pg_dump_schema.test_table | regress_dump_test_super | regress_dump_test_super | TRUNCATE | f
+ table regress_pg_dump_schema.test_table | regress_dump_test_super | regress_dump_test_super | REFERENCES | f
+ table regress_pg_dump_schema.test_table | regress_dump_test_super | regress_dump_test_super | TRIGGER | f
+ table regress_pg_dump_schema.test_table | regress_dump_test_super | regress_dump_test_super | MAINTAIN | f
+ table regress_pg_dump_schema.test_table | regress_dump_test_super | regress_dump_test_role | SELECT | f
+ table regress_pg_dump_table | regress_dump_test_super | regress_dump_test_super | INSERT | f
+ table regress_pg_dump_table | regress_dump_test_super | regress_dump_test_super | SELECT | f
+ table regress_pg_dump_table | regress_dump_test_super | regress_dump_test_super | UPDATE | f
+ table regress_pg_dump_table | regress_dump_test_super | regress_dump_test_super | DELETE | f
+ table regress_pg_dump_table | regress_dump_test_super | regress_dump_test_super | TRUNCATE | f
+ table regress_pg_dump_table | regress_dump_test_super | regress_dump_test_super | REFERENCES | f
+ table regress_pg_dump_table | regress_dump_test_super | regress_dump_test_super | TRIGGER | f
+ table regress_pg_dump_table | regress_dump_test_super | regress_dump_test_super | MAINTAIN | f
+ table regress_pg_dump_table | regress_dump_test_super | regress_dump_test_role | SELECT | f
+ table regress_table_dumpable | regress_dump_test_super | regress_dump_test_super | INSERT | f
+ table regress_table_dumpable | regress_dump_test_super | regress_dump_test_super | SELECT | f
+ table regress_table_dumpable | regress_dump_test_super | regress_dump_test_super | UPDATE | f
+ table regress_table_dumpable | regress_dump_test_super | regress_dump_test_super | DELETE | f
+ table regress_table_dumpable | regress_dump_test_super | regress_dump_test_super | TRUNCATE | f
+ table regress_table_dumpable | regress_dump_test_super | regress_dump_test_super | REFERENCES | f
+ table regress_table_dumpable | regress_dump_test_super | regress_dump_test_super | TRIGGER | f
+ table regress_table_dumpable | regress_dump_test_super | regress_dump_test_super | MAINTAIN | f
+ table regress_table_dumpable | regress_dump_test_super | - | SELECT | f
+ type regress_pg_dump_schema.test_type | regress_dump_test_super | - | USAGE | f
+ type regress_pg_dump_schema.test_type | regress_dump_test_super | regress_dump_test_super | USAGE | f
+ type regress_pg_dump_schema.test_type | regress_dump_test_super | regress_dump_test_role | USAGE | f
+(58 rows)
+
+SELECT pg_describe_object(classid,objid,objsubid) COLLATE "C" AS obj,
+ pg_describe_object(refclassid,refobjid,0) AS refobj,
+ deptype
+ FROM pg_shdepend JOIN pg_database d ON dbid = d.oid
+ WHERE d.datname = current_database()
+ ORDER BY 1, 2, 3;
+ obj | refobj | deptype
+----------------------------------------------------+------------------------------+---------
+ column col1 of table regress_pg_dump_table | role regress_dump_test_super | i
+ extension test_pg_dump | role regress_dump_test_super | o
+ function regress_pg_dump_schema.test_agg(smallint) | role regress_dump_test_role | a
+ function regress_pg_dump_schema.test_agg(smallint) | role regress_dump_test_role | i
+ function regress_pg_dump_schema.test_agg(smallint) | role regress_dump_test_super | i
+ function regress_pg_dump_schema.test_agg(smallint) | role regress_dump_test_super | o
+ function regress_pg_dump_schema.test_func() | role regress_dump_test_role | a
+ function regress_pg_dump_schema.test_func() | role regress_dump_test_role | i
+ function regress_pg_dump_schema.test_func() | role regress_dump_test_super | i
+ function regress_pg_dump_schema.test_func() | role regress_dump_test_super | o
+ function wgo_then_no_access() | role regress_dump_test_super | i
+ function wgo_then_no_access() | role regress_dump_test_super | o
+ schema regress_pg_dump_schema | role regress_dump_test_super | o
+ sequence regress_pg_dump_schema.test_seq | role regress_dump_test_role | a
+ sequence regress_pg_dump_schema.test_seq | role regress_dump_test_role | i
+ sequence regress_pg_dump_schema.test_seq | role regress_dump_test_super | i
+ sequence regress_pg_dump_schema.test_seq | role regress_dump_test_super | o
+ sequence regress_pg_dump_seq | role regress_dump_test_role | a
+ sequence regress_pg_dump_seq | role regress_dump_test_role | i
+ sequence regress_pg_dump_seq | role regress_dump_test_super | i
+ sequence regress_pg_dump_seq | role regress_dump_test_super | o
+ sequence regress_pg_dump_table_col1_seq | role regress_dump_test_super | o
+ sequence regress_seq_dumpable | role regress_dump_test_super | i
+ sequence regress_seq_dumpable | role regress_dump_test_super | o
+ sequence wgo_then_regular | role regress_dump_test_super | i
+ sequence wgo_then_regular | role regress_dump_test_super | o
+ table regress_pg_dump_schema.test_table | role regress_dump_test_role | a
+ table regress_pg_dump_schema.test_table | role regress_dump_test_role | i
+ table regress_pg_dump_schema.test_table | role regress_dump_test_super | i
+ table regress_pg_dump_schema.test_table | role regress_dump_test_super | o
+ table regress_pg_dump_table | role regress_dump_test_role | a
+ table regress_pg_dump_table | role regress_dump_test_role | i
+ table regress_pg_dump_table | role regress_dump_test_super | i
+ table regress_pg_dump_table | role regress_dump_test_super | o
+ table regress_table_dumpable | role regress_dump_test_super | i
+ table regress_table_dumpable | role regress_dump_test_super | o
+ type regress_pg_dump_schema.test_type | role regress_dump_test_role | a
+ type regress_pg_dump_schema.test_type | role regress_dump_test_role | i
+ type regress_pg_dump_schema.test_type | role regress_dump_test_super | i
+ type regress_pg_dump_schema.test_type | role regress_dump_test_super | o
+(40 rows)
+
+REASSIGN OWNED BY regress_dump_test_super TO CURRENT_ROLE;
+-- Substitute for current user's name to keep test output consistent
+SELECT s.obj,
+ CASE WHEN a.grantor::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantor::regrole::name END,
+ CASE WHEN a.grantee::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantee::regrole::name END,
+ a.privilege_type, a.is_grantable
+FROM
+ (SELECT pg_describe_object(classoid,objoid,objsubid) COLLATE "C" AS obj, initprivs
+ FROM pg_init_privs WHERE privtype = 'e' ORDER BY 1) s,
+ aclexplode(s.initprivs) a;
+ obj | grantor | grantee | privilege_type | is_grantable
+----------------------------------------------------+----------+------------------------+----------------+--------------
+ column col1 of table regress_pg_dump_table | postgres | - | SELECT | f
+ function regress_pg_dump_schema.test_agg(smallint) | postgres | - | EXECUTE | f
+ function regress_pg_dump_schema.test_agg(smallint) | postgres | postgres | EXECUTE | f
+ function regress_pg_dump_schema.test_agg(smallint) | postgres | regress_dump_test_role | EXECUTE | f
+ function regress_pg_dump_schema.test_func() | postgres | - | EXECUTE | f
+ function regress_pg_dump_schema.test_func() | postgres | postgres | EXECUTE | f
+ function regress_pg_dump_schema.test_func() | postgres | regress_dump_test_role | EXECUTE | f
+ function wgo_then_no_access() | postgres | - | EXECUTE | f
+ function wgo_then_no_access() | postgres | postgres | EXECUTE | f
+ function wgo_then_no_access() | postgres | pg_signal_backend | EXECUTE | t
+ sequence regress_pg_dump_schema.test_seq | postgres | postgres | SELECT | f
+ sequence regress_pg_dump_schema.test_seq | postgres | postgres | UPDATE | f
+ sequence regress_pg_dump_schema.test_seq | postgres | postgres | USAGE | f
+ sequence regress_pg_dump_schema.test_seq | postgres | regress_dump_test_role | USAGE | f
+ sequence regress_pg_dump_seq | postgres | postgres | SELECT | f
+ sequence regress_pg_dump_seq | postgres | postgres | UPDATE | f
+ sequence regress_pg_dump_seq | postgres | postgres | USAGE | f
+ sequence regress_pg_dump_seq | postgres | regress_dump_test_role | USAGE | f
+ sequence regress_seq_dumpable | postgres | postgres | SELECT | f
+ sequence regress_seq_dumpable | postgres | postgres | UPDATE | f
+ sequence regress_seq_dumpable | postgres | postgres | USAGE | f
+ sequence regress_seq_dumpable | postgres | - | SELECT | f
+ sequence wgo_then_regular | postgres | postgres | SELECT | f
+ sequence wgo_then_regular | postgres | postgres | UPDATE | f
+ sequence wgo_then_regular | postgres | postgres | USAGE | f
+ sequence wgo_then_regular | postgres | pg_signal_backend | SELECT | f
+ sequence wgo_then_regular | postgres | pg_signal_backend | UPDATE | t
+ sequence wgo_then_regular | postgres | pg_signal_backend | USAGE | t
+ table regress_pg_dump_schema.test_table | postgres | postgres | INSERT | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | SELECT | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | UPDATE | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | DELETE | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | TRUNCATE | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | REFERENCES | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | TRIGGER | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | MAINTAIN | f
+ table regress_pg_dump_schema.test_table | postgres | regress_dump_test_role | SELECT | f
+ table regress_pg_dump_table | postgres | postgres | INSERT | f
+ table regress_pg_dump_table | postgres | postgres | SELECT | f
+ table regress_pg_dump_table | postgres | postgres | UPDATE | f
+ table regress_pg_dump_table | postgres | postgres | DELETE | f
+ table regress_pg_dump_table | postgres | postgres | TRUNCATE | f
+ table regress_pg_dump_table | postgres | postgres | REFERENCES | f
+ table regress_pg_dump_table | postgres | postgres | TRIGGER | f
+ table regress_pg_dump_table | postgres | postgres | MAINTAIN | f
+ table regress_pg_dump_table | postgres | regress_dump_test_role | SELECT | f
+ table regress_table_dumpable | postgres | postgres | INSERT | f
+ table regress_table_dumpable | postgres | postgres | SELECT | f
+ table regress_table_dumpable | postgres | postgres | UPDATE | f
+ table regress_table_dumpable | postgres | postgres | DELETE | f
+ table regress_table_dumpable | postgres | postgres | TRUNCATE | f
+ table regress_table_dumpable | postgres | postgres | REFERENCES | f
+ table regress_table_dumpable | postgres | postgres | TRIGGER | f
+ table regress_table_dumpable | postgres | postgres | MAINTAIN | f
+ table regress_table_dumpable | postgres | - | SELECT | f
+ type regress_pg_dump_schema.test_type | postgres | - | USAGE | f
+ type regress_pg_dump_schema.test_type | postgres | postgres | USAGE | f
+ type regress_pg_dump_schema.test_type | postgres | regress_dump_test_role | USAGE | f
+(58 rows)
+
+SELECT pg_describe_object(classid,objid,objsubid) COLLATE "C" AS obj,
+ pg_describe_object(refclassid,refobjid,0) AS refobj,
+ deptype
+ FROM pg_shdepend JOIN pg_database d ON dbid = d.oid
+ WHERE d.datname = current_database()
+ ORDER BY 1, 2, 3;
+ obj | refobj | deptype
+----------------------------------------------------+-----------------------------+---------
+ function regress_pg_dump_schema.test_agg(smallint) | role regress_dump_test_role | a
+ function regress_pg_dump_schema.test_agg(smallint) | role regress_dump_test_role | i
+ function regress_pg_dump_schema.test_func() | role regress_dump_test_role | a
+ function regress_pg_dump_schema.test_func() | role regress_dump_test_role | i
+ sequence regress_pg_dump_schema.test_seq | role regress_dump_test_role | a
+ sequence regress_pg_dump_schema.test_seq | role regress_dump_test_role | i
+ sequence regress_pg_dump_seq | role regress_dump_test_role | a
+ sequence regress_pg_dump_seq | role regress_dump_test_role | i
+ table regress_pg_dump_schema.test_table | role regress_dump_test_role | a
+ table regress_pg_dump_schema.test_table | role regress_dump_test_role | i
+ table regress_pg_dump_table | role regress_dump_test_role | a
+ table regress_pg_dump_table | role regress_dump_test_role | i
+ type regress_pg_dump_schema.test_type | role regress_dump_test_role | a
+ type regress_pg_dump_schema.test_type | role regress_dump_test_role | i
+(14 rows)
+
+DROP OWNED BY regress_dump_test_role RESTRICT;
+-- Substitute for current user's name to keep test output consistent
+SELECT s.obj,
+ CASE WHEN a.grantor::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantor::regrole::name END,
+ CASE WHEN a.grantee::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantee::regrole::name END,
+ a.privilege_type, a.is_grantable
+FROM
+ (SELECT pg_describe_object(classoid,objoid,objsubid) COLLATE "C" AS obj, initprivs
+ FROM pg_init_privs WHERE privtype = 'e' ORDER BY 1) s,
+ aclexplode(s.initprivs) a;
+ obj | grantor | grantee | privilege_type | is_grantable
+----------------------------------------------------+----------+-------------------+----------------+--------------
+ column col1 of table regress_pg_dump_table | postgres | - | SELECT | f
+ function regress_pg_dump_schema.test_agg(smallint) | postgres | - | EXECUTE | f
+ function regress_pg_dump_schema.test_agg(smallint) | postgres | postgres | EXECUTE | f
+ function regress_pg_dump_schema.test_func() | postgres | - | EXECUTE | f
+ function regress_pg_dump_schema.test_func() | postgres | postgres | EXECUTE | f
+ function wgo_then_no_access() | postgres | - | EXECUTE | f
+ function wgo_then_no_access() | postgres | postgres | EXECUTE | f
+ function wgo_then_no_access() | postgres | pg_signal_backend | EXECUTE | t
+ sequence regress_pg_dump_schema.test_seq | postgres | postgres | SELECT | f
+ sequence regress_pg_dump_schema.test_seq | postgres | postgres | UPDATE | f
+ sequence regress_pg_dump_schema.test_seq | postgres | postgres | USAGE | f
+ sequence regress_pg_dump_seq | postgres | postgres | SELECT | f
+ sequence regress_pg_dump_seq | postgres | postgres | UPDATE | f
+ sequence regress_pg_dump_seq | postgres | postgres | USAGE | f
+ sequence regress_seq_dumpable | postgres | postgres | SELECT | f
+ sequence regress_seq_dumpable | postgres | postgres | UPDATE | f
+ sequence regress_seq_dumpable | postgres | postgres | USAGE | f
+ sequence regress_seq_dumpable | postgres | - | SELECT | f
+ sequence wgo_then_regular | postgres | postgres | SELECT | f
+ sequence wgo_then_regular | postgres | postgres | UPDATE | f
+ sequence wgo_then_regular | postgres | postgres | USAGE | f
+ sequence wgo_then_regular | postgres | pg_signal_backend | SELECT | f
+ sequence wgo_then_regular | postgres | pg_signal_backend | UPDATE | t
+ sequence wgo_then_regular | postgres | pg_signal_backend | USAGE | t
+ table regress_pg_dump_schema.test_table | postgres | postgres | INSERT | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | SELECT | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | UPDATE | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | DELETE | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | TRUNCATE | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | REFERENCES | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | TRIGGER | f
+ table regress_pg_dump_schema.test_table | postgres | postgres | MAINTAIN | f
+ table regress_pg_dump_table | postgres | postgres | INSERT | f
+ table regress_pg_dump_table | postgres | postgres | SELECT | f
+ table regress_pg_dump_table | postgres | postgres | UPDATE | f
+ table regress_pg_dump_table | postgres | postgres | DELETE | f
+ table regress_pg_dump_table | postgres | postgres | TRUNCATE | f
+ table regress_pg_dump_table | postgres | postgres | REFERENCES | f
+ table regress_pg_dump_table | postgres | postgres | TRIGGER | f
+ table regress_pg_dump_table | postgres | postgres | MAINTAIN | f
+ table regress_table_dumpable | postgres | postgres | INSERT | f
+ table regress_table_dumpable | postgres | postgres | SELECT | f
+ table regress_table_dumpable | postgres | postgres | UPDATE | f
+ table regress_table_dumpable | postgres | postgres | DELETE | f
+ table regress_table_dumpable | postgres | postgres | TRUNCATE | f
+ table regress_table_dumpable | postgres | postgres | REFERENCES | f
+ table regress_table_dumpable | postgres | postgres | TRIGGER | f
+ table regress_table_dumpable | postgres | postgres | MAINTAIN | f
+ table regress_table_dumpable | postgres | - | SELECT | f
+ type regress_pg_dump_schema.test_type | postgres | - | USAGE | f
+ type regress_pg_dump_schema.test_type | postgres | postgres | USAGE | f
+(51 rows)
+
+SELECT pg_describe_object(classid,objid,objsubid) COLLATE "C" AS obj,
+ pg_describe_object(refclassid,refobjid,0) AS refobj,
+ deptype
+ FROM pg_shdepend JOIN pg_database d ON dbid = d.oid
+ WHERE d.datname = current_database()
+ ORDER BY 1, 2, 3;
+ obj | refobj | deptype
+-----+--------+---------
+(0 rows)
+
+DROP ROLE regress_dump_test_super;
+DROP ROLE regress_dump_test_role;
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 2110ac71633..87e66cae6e3 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
@@ -151,3 +151,74 @@ DROP EXTENSION test_pg_dump;
-- shouldn't be anything left in pg_init_privs
SELECT * FROM pg_init_privs WHERE privtype = 'e';
+
+CREATE ROLE regress_dump_test_role;
+CREATE ROLE regress_dump_test_super SUPERUSER;
+
+SET ROLE regress_dump_test_super;
+
+CREATE EXTENSION test_pg_dump;
+
+RESET ROLE;
+
+-- Substitute for current user's name to keep test output consistent
+SELECT s.obj,
+ CASE WHEN a.grantor::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantor::regrole::name END,
+ CASE WHEN a.grantee::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantee::regrole::name END,
+ a.privilege_type, a.is_grantable
+FROM
+ (SELECT pg_describe_object(classoid,objoid,objsubid) COLLATE "C" AS obj, initprivs
+ FROM pg_init_privs WHERE privtype = 'e' ORDER BY 1) s,
+ aclexplode(s.initprivs) a;
+SELECT pg_describe_object(classid,objid,objsubid) COLLATE "C" AS obj,
+ pg_describe_object(refclassid,refobjid,0) AS refobj,
+ deptype
+ FROM pg_shdepend JOIN pg_database d ON dbid = d.oid
+ WHERE d.datname = current_database()
+ ORDER BY 1, 2, 3;
+
+REASSIGN OWNED BY regress_dump_test_super TO CURRENT_ROLE;
+
+-- Substitute for current user's name to keep test output consistent
+SELECT s.obj,
+ CASE WHEN a.grantor::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantor::regrole::name END,
+ CASE WHEN a.grantee::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantee::regrole::name END,
+ a.privilege_type, a.is_grantable
+FROM
+ (SELECT pg_describe_object(classoid,objoid,objsubid) COLLATE "C" AS obj, initprivs
+ FROM pg_init_privs WHERE privtype = 'e' ORDER BY 1) s,
+ aclexplode(s.initprivs) a;
+SELECT pg_describe_object(classid,objid,objsubid) COLLATE "C" AS obj,
+ pg_describe_object(refclassid,refobjid,0) AS refobj,
+ deptype
+ FROM pg_shdepend JOIN pg_database d ON dbid = d.oid
+ WHERE d.datname = current_database()
+ ORDER BY 1, 2, 3;
+
+DROP OWNED BY regress_dump_test_role RESTRICT;
+
+-- Substitute for current user's name to keep test output consistent
+SELECT s.obj,
+ CASE WHEN a.grantor::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantor::regrole::name END,
+ CASE WHEN a.grantee::regrole::name = quote_ident(current_user) THEN 'postgres'
+ ELSE a.grantee::regrole::name END,
+ a.privilege_type, a.is_grantable
+FROM
+ (SELECT pg_describe_object(classoid,objoid,objsubid) COLLATE "C" AS obj, initprivs
+ FROM pg_init_privs WHERE privtype = 'e' ORDER BY 1) s,
+ aclexplode(s.initprivs) a;
+SELECT pg_describe_object(classid,objid,objsubid) COLLATE "C" AS obj,
+ pg_describe_object(refclassid,refobjid,0) AS refobj,
+ deptype
+ FROM pg_shdepend JOIN pg_database d ON dbid = d.oid
+ WHERE d.datname = current_database()
+ ORDER BY 1, 2, 3;
+
+DROP ROLE regress_dump_test_super;
+
+DROP ROLE regress_dump_test_role;