PostgreSQL Source Code git master
pg_shdepend.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_default_acl.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_shdepend.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
#include "commands/alter.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/policy.h"
#include "commands/publicationcmds.h"
#include "commands/schemacmds.h"
#include "commands/subscriptioncmds.h"
#include "commands/tablecmds.h"
#include "commands/tablespace.h"
#include "commands/typecmds.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "utils/acl.h"
#include "utils/fmgroids.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
Include dependency graph for pg_shdepend.c:

Go to the source code of this file.

Data Structures

struct  ShDependObjectInfo
 
struct  remoteDep
 

Macros

#define MAX_REPORTED_DEPS   100
 

Enumerations

enum  SharedDependencyObjectType { LOCAL_OBJECT , SHARED_OBJECT , REMOTE_OBJECT }
 

Functions

static void getOidListDiff (Oid *list1, int *nlist1, Oid *list2, int *nlist2)
 
static Oid classIdGetDbId (Oid classId)
 
static void shdepChangeDep (Relation sdepRel, Oid classid, Oid objid, int32 objsubid, Oid refclassid, Oid refobjid, SharedDependencyType deptype)
 
static void updateAclDependenciesWorker (Oid classId, Oid objectId, int32 objsubId, Oid ownerId, SharedDependencyType deptype, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
 
static void shdepAddDependency (Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
 
static void shdepDropDependency (Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, bool drop_subobjects, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
 
static void storeObjectDescription (StringInfo descs, SharedDependencyObjectType type, 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)
 
void recordSharedDependencyOn (ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
 
void recordDependencyOnOwner (Oid classId, Oid objectId, Oid owner)
 
void changeDependencyOnOwner (Oid classId, Oid objectId, Oid newOwnerId)
 
void recordDependencyOnTablespace (Oid classId, Oid objectId, Oid tablespace)
 
void changeDependencyOnTablespace (Oid classId, Oid objectId, Oid newTablespaceId)
 
void updateAclDependencies (Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
 
void updateInitAclDependencies (Oid classId, Oid objectId, int32 objsubId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
 
static int shared_dependency_comparator (const void *a, const void *b)
 
bool checkSharedDependencies (Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
 
void copyTemplateDependencies (Oid templateDbId, Oid newDbId)
 
void dropDatabaseDependencies (Oid databaseId)
 
void deleteSharedDependencyRecordsFor (Oid classId, Oid objectId, int32 objectSubId)
 
void shdepLockAndCheckObject (Oid classId, Oid objectId)
 
void shdepDropOwned (List *roleids, DropBehavior behavior)
 
void shdepReassignOwned (List *roleids, Oid newrole)
 

Macro Definition Documentation

◆ MAX_REPORTED_DEPS

#define MAX_REPORTED_DEPS   100

Enumeration Type Documentation

◆ SharedDependencyObjectType

Enumerator
LOCAL_OBJECT 
SHARED_OBJECT 
REMOTE_OBJECT 

Definition at line 67 of file pg_shdepend.c.

68{
SharedDependencyObjectType
Definition: pg_shdepend.c:68
@ SHARED_OBJECT
Definition: pg_shdepend.c:70
@ LOCAL_OBJECT
Definition: pg_shdepend.c:69
@ REMOTE_OBJECT
Definition: pg_shdepend.c:71

Function Documentation

◆ changeDependencyOnOwner()

void changeDependencyOnOwner ( Oid  classId,
Oid  objectId,
Oid  newOwnerId 
)

Definition at line 316 of file pg_shdepend.c.

317{
318 Relation sdepRel;
319
320 sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
321
322 /* Adjust the SHARED_DEPENDENCY_OWNER entry */
323 shdepChangeDep(sdepRel,
324 classId, objectId, 0,
325 AuthIdRelationId, newOwnerId,
327
328 /*----------
329 * There should never be a SHARED_DEPENDENCY_ACL entry for the owner,
330 * so get rid of it if there is one. This can happen if the new owner
331 * was previously granted some rights to the object.
332 *
333 * This step is analogous to aclnewowner's removal of duplicate entries
334 * in the ACL. We have to do it to handle this scenario:
335 * A grants some rights on an object to B
336 * ALTER OWNER changes the object's owner to B
337 * ALTER OWNER changes the object's owner to C
338 * The third step would remove all mention of B from the object's ACL,
339 * but we'd still have a SHARED_DEPENDENCY_ACL for B if we did not do
340 * things this way.
341 *
342 * The rule against having a SHARED_DEPENDENCY_ACL entry for the owner
343 * allows us to fix things up in just this one place, without having
344 * to make the various ALTER OWNER routines each know about it.
345 *----------
346 */
347 shdepDropDependency(sdepRel, classId, objectId, 0, true,
348 AuthIdRelationId, newOwnerId,
350
351 /*
352 * However, nothing need be done about SHARED_DEPENDENCY_INITACL entries,
353 * since those exist whether or not the role is the object's owner, and
354 * ALTER OWNER does not modify the underlying pg_init_privs entry.
355 */
356
358}
@ SHARED_DEPENDENCY_ACL
Definition: dependency.h:81
@ SHARED_DEPENDENCY_OWNER
Definition: dependency.h:80
#define RowExclusiveLock
Definition: lockdefs.h:38
static void shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, bool drop_subobjects, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:1124
static void shdepChangeDep(Relation sdepRel, Oid classid, Oid objid, int32 objsubid, Oid refclassid, Oid refobjid, SharedDependencyType deptype)
Definition: pg_shdepend.c:206
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References RowExclusiveLock, SHARED_DEPENDENCY_ACL, SHARED_DEPENDENCY_OWNER, shdepChangeDep(), shdepDropDependency(), table_close(), and table_open().

Referenced by AlterDatabaseOwner(), AlterEventTriggerOwner_internal(), AlterForeignDataWrapperOwner_internal(), AlterForeignServerOwner_internal(), AlterObjectOwner_internal(), AlterPublicationOwner_internal(), AlterSchemaOwner_internal(), AlterSubscriptionOwner_internal(), AlterTypeOwner_oid(), and ATExecChangeOwner().

◆ changeDependencyOnTablespace()

void changeDependencyOnTablespace ( Oid  classId,
Oid  objectId,
Oid  newTablespaceId 
)

Definition at line 391 of file pg_shdepend.c.

392{
393 Relation sdepRel;
394
395 sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
396
397 if (newTablespaceId != DEFAULTTABLESPACE_OID &&
398 newTablespaceId != InvalidOid)
399 shdepChangeDep(sdepRel,
400 classId, objectId, 0,
401 TableSpaceRelationId, newTablespaceId,
403 else
404 shdepDropDependency(sdepRel,
405 classId, objectId, 0, true,
408
410}
@ SHARED_DEPENDENCY_TABLESPACE
Definition: dependency.h:84
@ SHARED_DEPENDENCY_INVALID
Definition: dependency.h:85
#define InvalidOid
Definition: postgres_ext.h:37

References InvalidOid, RowExclusiveLock, SHARED_DEPENDENCY_INVALID, SHARED_DEPENDENCY_TABLESPACE, shdepChangeDep(), shdepDropDependency(), table_close(), and table_open().

Referenced by SetRelationTableSpace().

◆ checkSharedDependencies()

bool checkSharedDependencies ( Oid  classId,
Oid  objectId,
char **  detail_msg,
char **  detail_log_msg 
)

Definition at line 676 of file pg_shdepend.c.

678{
679 Relation sdepRel;
680 ScanKeyData key[2];
681 SysScanDesc scan;
682 HeapTuple tup;
683 int numReportedDeps = 0;
684 int numNotReportedDeps = 0;
685 int numNotReportedDbs = 0;
686 List *remDeps = NIL;
687 ListCell *cell;
688 ObjectAddress object;
689 ShDependObjectInfo *objects;
690 int numobjects;
691 int allocedobjects;
692 StringInfoData descs;
693 StringInfoData alldescs;
694
695 /* This case can be dispatched quickly */
696 if (IsPinnedObject(classId, objectId))
697 {
698 object.classId = classId;
699 object.objectId = objectId;
700 object.objectSubId = 0;
702 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
703 errmsg("cannot drop %s because it is required by the database system",
704 getObjectDescription(&object, false))));
705 }
706
707 /*
708 * We limit the number of dependencies reported to the client to
709 * MAX_REPORTED_DEPS, since client software may not deal well with
710 * enormous error strings. The server log always gets a full report.
711 *
712 * For stability of regression test results, we sort local and shared
713 * objects by OID before reporting them. We don't worry about the order
714 * in which other databases are reported, though.
715 */
716#define MAX_REPORTED_DEPS 100
717
718 allocedobjects = 128; /* arbitrary initial array size */
719 objects = (ShDependObjectInfo *)
720 palloc(allocedobjects * sizeof(ShDependObjectInfo));
721 numobjects = 0;
722 initStringInfo(&descs);
723 initStringInfo(&alldescs);
724
725 sdepRel = table_open(SharedDependRelationId, AccessShareLock);
726
727 ScanKeyInit(&key[0],
728 Anum_pg_shdepend_refclassid,
729 BTEqualStrategyNumber, F_OIDEQ,
730 ObjectIdGetDatum(classId));
731 ScanKeyInit(&key[1],
732 Anum_pg_shdepend_refobjid,
733 BTEqualStrategyNumber, F_OIDEQ,
734 ObjectIdGetDatum(objectId));
735
736 scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
737 NULL, 2, key);
738
739 while (HeapTupleIsValid(tup = systable_getnext(scan)))
740 {
742
743 object.classId = sdepForm->classid;
744 object.objectId = sdepForm->objid;
745 object.objectSubId = sdepForm->objsubid;
746
747 /*
748 * If it's a dependency local to this database or it's a shared
749 * object, add it to the objects array.
750 *
751 * If it's a remote dependency, keep track of it so we can report the
752 * number of them later.
753 */
754 if (sdepForm->dbid == MyDatabaseId ||
755 sdepForm->dbid == InvalidOid)
756 {
757 if (numobjects >= allocedobjects)
758 {
759 allocedobjects *= 2;
760 objects = (ShDependObjectInfo *)
761 repalloc(objects,
762 allocedobjects * sizeof(ShDependObjectInfo));
763 }
764 objects[numobjects].object = object;
765 objects[numobjects].deptype = sdepForm->deptype;
766 objects[numobjects].objtype = (sdepForm->dbid == MyDatabaseId) ?
768 numobjects++;
769 }
770 else
771 {
772 /* It's not local nor shared, so it must be remote. */
773 remoteDep *dep;
774 bool stored = false;
775
776 /*
777 * XXX this info is kept on a simple List. Maybe it's not good
778 * for performance, but using a hash table seems needlessly
779 * complex. The expected number of databases is not high anyway,
780 * I suppose.
781 */
782 foreach(cell, remDeps)
783 {
784 dep = lfirst(cell);
785 if (dep->dbOid == sdepForm->dbid)
786 {
787 dep->count++;
788 stored = true;
789 break;
790 }
791 }
792 if (!stored)
793 {
794 dep = (remoteDep *) palloc(sizeof(remoteDep));
795 dep->dbOid = sdepForm->dbid;
796 dep->count = 1;
797 remDeps = lappend(remDeps, dep);
798 }
799 }
800 }
801
802 systable_endscan(scan);
803
805
806 /*
807 * Sort and report local and shared objects.
808 */
809 if (numobjects > 1)
810 qsort(objects, numobjects,
812
813 for (int i = 0; i < numobjects; i++)
814 {
815 if (numReportedDeps < MAX_REPORTED_DEPS)
816 {
817 numReportedDeps++;
819 objects[i].objtype,
820 &objects[i].object,
821 objects[i].deptype,
822 0);
823 }
824 else
825 numNotReportedDeps++;
826 storeObjectDescription(&alldescs,
827 objects[i].objtype,
828 &objects[i].object,
829 objects[i].deptype,
830 0);
831 }
832
833 /*
834 * Summarize dependencies in remote databases.
835 */
836 foreach(cell, remDeps)
837 {
838 remoteDep *dep = lfirst(cell);
839
840 object.classId = DatabaseRelationId;
841 object.objectId = dep->dbOid;
842 object.objectSubId = 0;
843
844 if (numReportedDeps < MAX_REPORTED_DEPS)
845 {
846 numReportedDeps++;
847 storeObjectDescription(&descs, REMOTE_OBJECT, &object,
849 }
850 else
851 numNotReportedDbs++;
852 storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
854 }
855
856 pfree(objects);
857 list_free_deep(remDeps);
858
859 if (descs.len == 0)
860 {
861 pfree(descs.data);
862 pfree(alldescs.data);
863 *detail_msg = *detail_log_msg = NULL;
864 return false;
865 }
866
867 if (numNotReportedDeps > 0)
868 appendStringInfo(&descs, ngettext("\nand %d other object "
869 "(see server log for list)",
870 "\nand %d other objects "
871 "(see server log for list)",
872 numNotReportedDeps),
873 numNotReportedDeps);
874 if (numNotReportedDbs > 0)
875 appendStringInfo(&descs, ngettext("\nand objects in %d other database "
876 "(see server log for list)",
877 "\nand objects in %d other databases "
878 "(see server log for list)",
879 numNotReportedDbs),
880 numNotReportedDbs);
881
882 *detail_msg = descs.data;
883 *detail_log_msg = alldescs.data;
884 return true;
885}
#define ngettext(s, p, n)
Definition: c.h:1138
bool IsPinnedObject(Oid classId, Oid objectId)
Definition: catalog.c:341
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:606
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:513
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
Oid MyDatabaseId
Definition: globals.c:93
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
int i
Definition: isn.c:72
List * lappend(List *list, void *datum)
Definition: list.c:339
void list_free_deep(List *list)
Definition: list.c:1560
#define AccessShareLock
Definition: lockdefs.h:36
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
static int shared_dependency_comparator(const void *a, const void *b)
Definition: pg_shdepend.c:610
#define MAX_REPORTED_DEPS
static void storeObjectDescription(StringInfo descs, SharedDependencyObjectType type, ObjectAddress *object, SharedDependencyType deptype, int count)
Definition: pg_shdepend.c:1276
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:73
#define qsort(a, b, c, d)
Definition: port.h:474
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
Definition: pg_list.h:54
ObjectAddress object
Definition: pg_shdepend.c:76
SharedDependencyObjectType objtype
Definition: pg_shdepend.c:78

References AccessShareLock, appendStringInfo(), BTEqualStrategyNumber, remoteDep::count, StringInfoData::data, remoteDep::dbOid, ShDependObjectInfo::deptype, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, HeapTupleIsValid, i, initStringInfo(), InvalidOid, IsPinnedObject(), sort-test::key, lappend(), StringInfoData::len, lfirst, list_free_deep(), LOCAL_OBJECT, MAX_REPORTED_DEPS, MyDatabaseId, ngettext, NIL, ShDependObjectInfo::object, ObjectIdGetDatum(), ShDependObjectInfo::objtype, palloc(), pfree(), qsort, REMOTE_OBJECT, repalloc(), ScanKeyInit(), shared_dependency_comparator(), SHARED_DEPENDENCY_INVALID, SHARED_OBJECT, storeObjectDescription(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by DropRole(), and DropTableSpace().

◆ classIdGetDbId()

static Oid classIdGetDbId ( Oid  classId)
static

Definition at line 1190 of file pg_shdepend.c.

1191{
1192 Oid dbId;
1193
1194 if (IsSharedRelation(classId))
1195 dbId = InvalidOid;
1196 else
1197 dbId = MyDatabaseId;
1198
1199 return dbId;
1200}
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:273
unsigned int Oid
Definition: postgres_ext.h:32

References InvalidOid, IsSharedRelation(), and MyDatabaseId.

Referenced by shdepAddDependency(), shdepChangeDep(), and shdepDropDependency().

◆ copyTemplateDependencies()

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)

Definition at line 895 of file pg_shdepend.c.

896{
897 Relation sdepRel;
898 TupleDesc sdepDesc;
899 ScanKeyData key[1];
900 SysScanDesc scan;
901 HeapTuple tup;
902 CatalogIndexState indstate;
903 TupleTableSlot **slot;
904 int max_slots,
905 slot_init_count,
906 slot_stored_count;
907
908 sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
909 sdepDesc = RelationGetDescr(sdepRel);
910
911 /*
912 * Allocate the slots to use, but delay costly initialization until we
913 * know that they will be used.
914 */
916 slot = palloc(sizeof(TupleTableSlot *) * max_slots);
917
918 indstate = CatalogOpenIndexes(sdepRel);
919
920 /* Scan all entries with dbid = templateDbId */
921 ScanKeyInit(&key[0],
922 Anum_pg_shdepend_dbid,
923 BTEqualStrategyNumber, F_OIDEQ,
924 ObjectIdGetDatum(templateDbId));
925
926 scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
927 NULL, 1, key);
928
929 /* number of slots currently storing tuples */
930 slot_stored_count = 0;
931 /* number of slots currently initialized */
932 slot_init_count = 0;
933
934 /*
935 * Copy the entries of the original database, changing the database Id to
936 * that of the new database. Note that because we are not copying rows
937 * with dbId == 0 (ie, rows describing dependent shared objects) we won't
938 * copy the ownership dependency of the template database itself; this is
939 * what we want.
940 */
941 while (HeapTupleIsValid(tup = systable_getnext(scan)))
942 {
943 Form_pg_shdepend shdep;
944
945 if (slot_init_count < max_slots)
946 {
947 slot[slot_stored_count] = MakeSingleTupleTableSlot(sdepDesc, &TTSOpsHeapTuple);
948 slot_init_count++;
949 }
950
951 ExecClearTuple(slot[slot_stored_count]);
952
953 memset(slot[slot_stored_count]->tts_isnull, false,
954 slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
955
956 shdep = (Form_pg_shdepend) GETSTRUCT(tup);
957
958 slot[slot_stored_count]->tts_values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId);
959 slot[slot_stored_count]->tts_values[Anum_pg_shdepend_classid - 1] = shdep->classid;
960 slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objid - 1] = shdep->objid;
961 slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objsubid - 1] = shdep->objsubid;
962 slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refclassid - 1] = shdep->refclassid;
963 slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refobjid - 1] = shdep->refobjid;
964 slot[slot_stored_count]->tts_values[Anum_pg_shdepend_deptype - 1] = shdep->deptype;
965
966 ExecStoreVirtualTuple(slot[slot_stored_count]);
967 slot_stored_count++;
968
969 /* If slots are full, insert a batch of tuples */
970 if (slot_stored_count == max_slots)
971 {
972 CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
973 slot_stored_count = 0;
974 }
975 }
976
977 /* Insert any tuples left in the buffer */
978 if (slot_stored_count > 0)
979 CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
980
981 systable_endscan(scan);
982
983 CatalogCloseIndexes(indstate);
985
986 /* Drop only the number of slots used */
987 for (int i = 0; i < slot_init_count; i++)
989 pfree(slot);
990}
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1425
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1441
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1739
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:85
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
Definition: indexing.c:273
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:61
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:43
#define MAX_CATALOG_MULTI_INSERT_BYTES
Definition: indexing.h:33
FormData_pg_shdepend
Definition: pg_shdepend.h:66
#define RelationGetDescr(relation)
Definition: rel.h:531
Datum * tts_values
Definition: tuptable.h:125
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454

References BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTuplesMultiInsertWithInfo(), ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), FormData_pg_shdepend, GETSTRUCT, HeapTupleIsValid, i, sort-test::key, MakeSingleTupleTableSlot(), MAX_CATALOG_MULTI_INSERT_BYTES, ObjectIdGetDatum(), palloc(), pfree(), RelationGetDescr, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TupleTableSlot::tts_values, and TTSOpsHeapTuple.

Referenced by createdb().

◆ deleteSharedDependencyRecordsFor()

void deleteSharedDependencyRecordsFor ( Oid  classId,
Oid  objectId,
int32  objectSubId 
)

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 999 of file pg_shdepend.c.

1000{
1001 Relation sdepRel;
1002 ScanKeyData key[1];
1003 SysScanDesc scan;
1004 HeapTuple tup;
1005
1006 sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1007
1008 /*
1009 * First, delete all the entries that have the database Oid in the dbid
1010 * field.
1011 */
1012 ScanKeyInit(&key[0],
1013 Anum_pg_shdepend_dbid,
1014 BTEqualStrategyNumber, F_OIDEQ,
1015 ObjectIdGetDatum(databaseId));
1016 /* We leave the other index fields unspecified */
1017
1018 scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
1019 NULL, 1, key);
1020
1021 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1022 {
1023 CatalogTupleDelete(sdepRel, &tup->t_self);
1024 }
1025
1026 systable_endscan(scan);
1027
1028 /* Now delete all entries corresponding to the database itself */
1029 shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
1032
1033 table_close(sdepRel, RowExclusiveLock);
1034}
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
ItemPointerData t_self
Definition: htup.h:65

References BTEqualStrategyNumber, CatalogTupleDelete(), HeapTupleIsValid, InvalidOid, sort-test::key, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_INVALID, shdepDropDependency(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by dropdb().

◆ getOidListDiff()

static void getOidListDiff ( Oid list1,
int *  nlist1,
Oid list2,
int *  nlist2 
)
static

Definition at line 421 of file pg_shdepend.c.

422{
423 int in1,
424 in2,
425 out1,
426 out2;
427
428 in1 = in2 = out1 = out2 = 0;
429 while (in1 < *nlist1 && in2 < *nlist2)
430 {
431 if (list1[in1] == list2[in2])
432 {
433 /* skip over duplicates */
434 in1++;
435 in2++;
436 }
437 else if (list1[in1] < list2[in2])
438 {
439 /* list1[in1] is not in list2 */
440 list1[out1++] = list1[in1++];
441 }
442 else
443 {
444 /* list2[in2] is not in list1 */
445 list2[out2++] = list2[in2++];
446 }
447 }
448
449 /* any remaining list1 entries are not in list2 */
450 while (in1 < *nlist1)
451 {
452 list1[out1++] = list1[in1++];
453 }
454
455 /* any remaining list2 entries are not in list1 */
456 while (in2 < *nlist2)
457 {
458 list2[out2++] = list2[in2++];
459 }
460
461 *nlist1 = out1;
462 *nlist2 = out2;
463}

Referenced by updateAclDependenciesWorker().

◆ recordDependencyOnOwner()

void recordDependencyOnOwner ( Oid  classId,
Oid  objectId,
Oid  owner 
)

◆ recordDependencyOnTablespace()

void recordDependencyOnTablespace ( Oid  classId,
Oid  objectId,
Oid  tablespace 
)

Definition at line 370 of file pg_shdepend.c.

371{
372 ObjectAddress myself,
373 referenced;
374
375 ObjectAddressSet(myself, classId, objectId);
376 ObjectAddressSet(referenced, TableSpaceRelationId, tablespace);
377
378 recordSharedDependencyOn(&myself, &referenced,
380}
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static char * tablespace
Definition: pgbench.c:216

References ObjectAddressSet, recordSharedDependencyOn(), SHARED_DEPENDENCY_TABLESPACE, and tablespace.

Referenced by heap_create().

◆ recordSharedDependencyOn()

void recordSharedDependencyOn ( ObjectAddress depender,
ObjectAddress referenced,
SharedDependencyType  deptype 
)

Definition at line 125 of file pg_shdepend.c.

128{
129 Relation sdepRel;
130
131 /*
132 * Objects in pg_shdepend can't have SubIds.
133 */
134 Assert(depender->objectSubId == 0);
135 Assert(referenced->objectSubId == 0);
136
137 /*
138 * During bootstrap, do nothing since pg_shdepend may not exist yet.
139 * initdb will fill in appropriate pg_shdepend entries after bootstrap.
140 */
142 return;
143
144 sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
145
146 /* If the referenced object is pinned, do nothing. */
147 if (!IsPinnedObject(referenced->classId, referenced->objectId))
148 {
149 shdepAddDependency(sdepRel, depender->classId, depender->objectId,
150 depender->objectSubId,
151 referenced->classId, referenced->objectId,
152 deptype);
153 }
154
156}
#define Assert(condition)
Definition: c.h:815
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:466
static void shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:1069

References Assert, ObjectAddress::classId, IsBootstrapProcessingMode, IsPinnedObject(), ObjectAddress::objectId, ObjectAddress::objectSubId, RowExclusiveLock, shdepAddDependency(), table_close(), and table_open().

Referenced by AlterPolicy(), CreatePolicy(), recordDependencyOnOwner(), recordDependencyOnTablespace(), and RemoveRoleFromObjectPolicy().

◆ shared_dependency_comparator()

static int shared_dependency_comparator ( const void *  a,
const void *  b 
)
static

Definition at line 610 of file pg_shdepend.c.

611{
612 const ShDependObjectInfo *obja = (const ShDependObjectInfo *) a;
613 const ShDependObjectInfo *objb = (const ShDependObjectInfo *) b;
614
615 /*
616 * Primary sort key is OID ascending.
617 */
618 if (obja->object.objectId < objb->object.objectId)
619 return -1;
620 if (obja->object.objectId > objb->object.objectId)
621 return 1;
622
623 /*
624 * Next sort on catalog ID, in case identical OIDs appear in different
625 * catalogs. Sort direction is pretty arbitrary here.
626 */
627 if (obja->object.classId < objb->object.classId)
628 return -1;
629 if (obja->object.classId > objb->object.classId)
630 return 1;
631
632 /*
633 * Sort on object subId.
634 *
635 * We sort the subId as an unsigned int so that 0 (the whole object) will
636 * come first.
637 */
638 if ((unsigned int) obja->object.objectSubId < (unsigned int) objb->object.objectSubId)
639 return -1;
640 if ((unsigned int) obja->object.objectSubId > (unsigned int) objb->object.objectSubId)
641 return 1;
642
643 /*
644 * Last, sort on deptype, in case the same object has multiple dependency
645 * types. (Note that there's no need to consider objtype, as that's
646 * determined by the catalog OID.)
647 */
648 if (obja->deptype < objb->deptype)
649 return -1;
650 if (obja->deptype > objb->deptype)
651 return 1;
652
653 return 0;
654}
int b
Definition: isn.c:69
int a
Definition: isn.c:68

References a, b, ObjectAddress::classId, ShDependObjectInfo::deptype, ShDependObjectInfo::object, ObjectAddress::objectId, and ObjectAddress::objectSubId.

Referenced by checkSharedDependencies().

◆ shdepAddDependency()

static void shdepAddDependency ( Relation  sdepRel,
Oid  classId,
Oid  objectId,
int32  objsubId,
Oid  refclassId,
Oid  refobjId,
SharedDependencyType  deptype 
)
static

Definition at line 1069 of file pg_shdepend.c.

1073{
1074 HeapTuple tup;
1075 Datum values[Natts_pg_shdepend];
1076 bool nulls[Natts_pg_shdepend];
1077
1078 /*
1079 * Make sure the object doesn't go away while we record the dependency on
1080 * it. DROP routines should lock the object exclusively before they check
1081 * shared dependencies.
1082 */
1083 shdepLockAndCheckObject(refclassId, refobjId);
1084
1085 memset(nulls, false, sizeof(nulls));
1086
1087 /*
1088 * Form the new tuple and record the dependency.
1089 */
1090 values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId));
1091 values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId);
1092 values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId);
1093 values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId);
1094
1095 values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId);
1096 values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId);
1097 values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
1098
1099 tup = heap_form_tuple(sdepRel->rd_att, values, nulls);
1100
1101 CatalogTupleInsert(sdepRel, tup);
1102
1103 /* clean up */
1104 heap_freetuple(tup);
1105}
static Datum values[MAXATTR]
Definition: bootstrap.c:151
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1190
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1211
uintptr_t Datum
Definition: postgres.h:69
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
static Datum CharGetDatum(char X)
Definition: postgres.h:127
TupleDesc rd_att
Definition: rel.h:112

References CatalogTupleInsert(), CharGetDatum(), classIdGetDbId(), heap_form_tuple(), heap_freetuple(), Int32GetDatum(), ObjectIdGetDatum(), RelationData::rd_att, shdepLockAndCheckObject(), and values.

Referenced by recordSharedDependencyOn(), and updateAclDependenciesWorker().

◆ shdepChangeDep()

static void shdepChangeDep ( Relation  sdepRel,
Oid  classid,
Oid  objid,
int32  objsubid,
Oid  refclassid,
Oid  refobjid,
SharedDependencyType  deptype 
)
static

Definition at line 206 of file pg_shdepend.c.

210{
211 Oid dbid = classIdGetDbId(classid);
212 HeapTuple oldtup = NULL;
213 HeapTuple scantup;
214 ScanKeyData key[4];
215 SysScanDesc scan;
216
217 /*
218 * Make sure the new referenced object doesn't go away while we record the
219 * dependency.
220 */
221 shdepLockAndCheckObject(refclassid, refobjid);
222
223 /*
224 * Look for a previous entry
225 */
226 ScanKeyInit(&key[0],
227 Anum_pg_shdepend_dbid,
228 BTEqualStrategyNumber, F_OIDEQ,
229 ObjectIdGetDatum(dbid));
230 ScanKeyInit(&key[1],
231 Anum_pg_shdepend_classid,
232 BTEqualStrategyNumber, F_OIDEQ,
233 ObjectIdGetDatum(classid));
234 ScanKeyInit(&key[2],
235 Anum_pg_shdepend_objid,
236 BTEqualStrategyNumber, F_OIDEQ,
237 ObjectIdGetDatum(objid));
238 ScanKeyInit(&key[3],
239 Anum_pg_shdepend_objsubid,
240 BTEqualStrategyNumber, F_INT4EQ,
241 Int32GetDatum(objsubid));
242
243 scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
244 NULL, 4, key);
245
246 while ((scantup = systable_getnext(scan)) != NULL)
247 {
248 /* Ignore if not of the target dependency type */
249 if (((Form_pg_shdepend) GETSTRUCT(scantup))->deptype != deptype)
250 continue;
251 /* Caller screwed up if multiple matches */
252 if (oldtup)
253 elog(ERROR,
254 "multiple pg_shdepend entries for object %u/%u/%d deptype %c",
255 classid, objid, objsubid, deptype);
256 oldtup = heap_copytuple(scantup);
257 }
258
259 systable_endscan(scan);
260
261 if (IsPinnedObject(refclassid, refobjid))
262 {
263 /* No new entry needed, so just delete existing entry if any */
264 if (oldtup)
265 CatalogTupleDelete(sdepRel, &oldtup->t_self);
266 }
267 else if (oldtup)
268 {
269 /* Need to update existing entry */
271
272 /* Since oldtup is a copy, we can just modify it in-memory */
273 shForm->refclassid = refclassid;
274 shForm->refobjid = refobjid;
275
276 CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup);
277 }
278 else
279 {
280 /* Need to insert new entry */
281 Datum values[Natts_pg_shdepend];
282 bool nulls[Natts_pg_shdepend];
283
284 memset(nulls, false, sizeof(nulls));
285
286 values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(dbid);
287 values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classid);
288 values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objid);
289 values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubid);
290
291 values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassid);
292 values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjid);
293 values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
294
295 /*
296 * we are reusing oldtup just to avoid declaring a new variable, but
297 * it's certainly a new tuple
298 */
299 oldtup = heap_form_tuple(RelationGetDescr(sdepRel), values, nulls);
300 CatalogTupleInsert(sdepRel, oldtup);
301 }
302
303 if (oldtup)
304 heap_freetuple(oldtup);
305}
#define elog(elevel,...)
Definition: elog.h:225
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:778
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313

References BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleInsert(), CatalogTupleUpdate(), CharGetDatum(), classIdGetDbId(), elog, ERROR, GETSTRUCT, heap_copytuple(), heap_form_tuple(), heap_freetuple(), Int32GetDatum(), IsPinnedObject(), sort-test::key, ObjectIdGetDatum(), RelationGetDescr, ScanKeyInit(), shdepLockAndCheckObject(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, and values.

Referenced by changeDependencyOnOwner(), and changeDependencyOnTablespace().

◆ shdepDropDependency()

static void shdepDropDependency ( Relation  sdepRel,
Oid  classId,
Oid  objectId,
int32  objsubId,
bool  drop_subobjects,
Oid  refclassId,
Oid  refobjId,
SharedDependencyType  deptype 
)
static

Definition at line 1124 of file pg_shdepend.c.

1129{
1130 ScanKeyData key[4];
1131 int nkeys;
1132 SysScanDesc scan;
1133 HeapTuple tup;
1134
1135 /* Scan for entries matching the dependent object */
1136 ScanKeyInit(&key[0],
1137 Anum_pg_shdepend_dbid,
1138 BTEqualStrategyNumber, F_OIDEQ,
1140 ScanKeyInit(&key[1],
1141 Anum_pg_shdepend_classid,
1142 BTEqualStrategyNumber, F_OIDEQ,
1143 ObjectIdGetDatum(classId));
1144 ScanKeyInit(&key[2],
1145 Anum_pg_shdepend_objid,
1146 BTEqualStrategyNumber, F_OIDEQ,
1147 ObjectIdGetDatum(objectId));
1148 if (drop_subobjects)
1149 nkeys = 3;
1150 else
1151 {
1152 ScanKeyInit(&key[3],
1153 Anum_pg_shdepend_objsubid,
1154 BTEqualStrategyNumber, F_INT4EQ,
1155 Int32GetDatum(objsubId));
1156 nkeys = 4;
1157 }
1158
1159 scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
1160 NULL, nkeys, key);
1161
1162 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1163 {
1164 Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1165
1166 /* Filter entries according to additional parameters */
1167 if (OidIsValid(refclassId) && shdepForm->refclassid != refclassId)
1168 continue;
1169 if (OidIsValid(refobjId) && shdepForm->refobjid != refobjId)
1170 continue;
1171 if (deptype != SHARED_DEPENDENCY_INVALID &&
1172 shdepForm->deptype != deptype)
1173 continue;
1174
1175 /* OK, delete it */
1176 CatalogTupleDelete(sdepRel, &tup->t_self);
1177 }
1178
1179 systable_endscan(scan);
1180}
#define OidIsValid(objectId)
Definition: c.h:732

References BTEqualStrategyNumber, CatalogTupleDelete(), classIdGetDbId(), GETSTRUCT, HeapTupleIsValid, Int32GetDatum(), sort-test::key, ObjectIdGetDatum(), OidIsValid, ScanKeyInit(), SHARED_DEPENDENCY_INVALID, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by changeDependencyOnOwner(), changeDependencyOnTablespace(), deleteSharedDependencyRecordsFor(), dropDatabaseDependencies(), and updateAclDependenciesWorker().

◆ shdepDropOwned()

void shdepDropOwned ( List roleids,
DropBehavior  behavior 
)

Definition at line 1342 of file pg_shdepend.c.

1343{
1344 Relation sdepRel;
1345 ListCell *cell;
1346 ObjectAddresses *deleteobjs;
1347
1348 deleteobjs = new_object_addresses();
1349
1350 /*
1351 * We don't need this strong a lock here, but we'll call routines that
1352 * acquire RowExclusiveLock. Better get that right now to avoid potential
1353 * deadlock failures.
1354 */
1355 sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1356
1357 /*
1358 * For each role, find the dependent objects and drop them using the
1359 * regular (non-shared) dependency management.
1360 */
1361 foreach(cell, roleids)
1362 {
1363 Oid roleid = lfirst_oid(cell);
1364 ScanKeyData key[2];
1365 SysScanDesc scan;
1366 HeapTuple tuple;
1367
1368 /* Doesn't work for pinned objects */
1369 if (IsPinnedObject(AuthIdRelationId, roleid))
1370 {
1371 ObjectAddress obj;
1372
1373 obj.classId = AuthIdRelationId;
1374 obj.objectId = roleid;
1375 obj.objectSubId = 0;
1376
1377 ereport(ERROR,
1378 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1379 errmsg("cannot drop objects owned by %s because they are "
1380 "required by the database system",
1381 getObjectDescription(&obj, false))));
1382 }
1383
1384 ScanKeyInit(&key[0],
1385 Anum_pg_shdepend_refclassid,
1386 BTEqualStrategyNumber, F_OIDEQ,
1387 ObjectIdGetDatum(AuthIdRelationId));
1388 ScanKeyInit(&key[1],
1389 Anum_pg_shdepend_refobjid,
1390 BTEqualStrategyNumber, F_OIDEQ,
1391 ObjectIdGetDatum(roleid));
1392
1393 scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1394 NULL, 2, key);
1395
1396 while ((tuple = systable_getnext(scan)) != NULL)
1397 {
1398 Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1399 ObjectAddress obj;
1400
1401 /*
1402 * We only operate on shared objects and objects in the current
1403 * database
1404 */
1405 if (sdepForm->dbid != MyDatabaseId &&
1406 sdepForm->dbid != InvalidOid)
1407 continue;
1408
1409 switch (sdepForm->deptype)
1410 {
1411 /* Shouldn't happen */
1413 elog(ERROR, "unexpected dependency type");
1414 break;
1416
1417 /*
1418 * Try to remove role from policy; if unable to, remove
1419 * policy.
1420 */
1421 if (!RemoveRoleFromObjectPolicy(roleid,
1422 sdepForm->classid,
1423 sdepForm->objid))
1424 {
1425 obj.classId = sdepForm->classid;
1426 obj.objectId = sdepForm->objid;
1427 obj.objectSubId = sdepForm->objsubid;
1428
1429 /*
1430 * Acquire lock on object, then verify this dependency
1431 * is still relevant. If not, the object might have
1432 * been dropped or the policy modified. Ignore the
1433 * object in that case.
1434 */
1435 AcquireDeletionLock(&obj, 0);
1436 if (!systable_recheck_tuple(scan, tuple))
1437 {
1438 ReleaseDeletionLock(&obj);
1439 break;
1440 }
1441 add_exact_object_address(&obj, deleteobjs);
1442 }
1443 break;
1445
1446 /*
1447 * Dependencies on role grants are recorded using
1448 * SHARED_DEPENDENCY_ACL, but unlike a regular ACL list
1449 * which stores all permissions for a particular object in
1450 * a single ACL array, there's a separate catalog row for
1451 * each grant - so removing the grant just means removing
1452 * the entire row.
1453 */
1454 if (sdepForm->classid != AuthMemRelationId)
1455 {
1457 sdepForm->classid,
1458 sdepForm->objid);
1459 break;
1460 }
1461 /* FALLTHROUGH */
1462
1464
1465 /*
1466 * Save it for deletion below, if it's a local object or a
1467 * role grant. Other shared objects, such as databases,
1468 * should not be removed here.
1469 */
1470 if (sdepForm->dbid == MyDatabaseId ||
1471 sdepForm->classid == AuthMemRelationId)
1472 {
1473 obj.classId = sdepForm->classid;
1474 obj.objectId = sdepForm->objid;
1475 obj.objectSubId = sdepForm->objsubid;
1476 /* as above */
1477 AcquireDeletionLock(&obj, 0);
1478 if (!systable_recheck_tuple(scan, tuple))
1479 {
1480 ReleaseDeletionLock(&obj);
1481 break;
1482 }
1483 add_exact_object_address(&obj, deleteobjs);
1484 }
1485 break;
1487
1488 /*
1489 * Any mentions of the role that remain in pg_init_privs
1490 * entries are just dropped. This is the same policy as
1491 * we apply to regular ACLs.
1492 */
1493
1494 /* Shouldn't see a role grant here */
1495 Assert(sdepForm->classid != AuthMemRelationId);
1497 sdepForm->classid,
1498 sdepForm->objid,
1499 sdepForm->objsubid);
1500 break;
1501 }
1502 }
1503
1504 systable_endscan(scan);
1505 }
1506
1507 /*
1508 * For stability of deletion-report ordering, sort the objects into
1509 * approximate reverse creation order before deletion. (This might also
1510 * make the deletion go a bit faster, since there's less chance of having
1511 * to rearrange the objects due to dependencies.)
1512 */
1513 sort_object_addresses(deleteobjs);
1514
1515 /* the dependency mechanism does the actual work */
1516 performMultipleDeletions(deleteobjs, behavior, 0);
1517
1518 table_close(sdepRel, RowExclusiveLock);
1519
1520 free_object_addresses(deleteobjs);
1521}
void RemoveRoleFromInitPriv(Oid roleid, Oid classid, Oid objid, int32 objsubid)
Definition: aclchk.c:4831
void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
Definition: aclchk.c:1393
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:332
void sort_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2776
void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1496
void ReleaseDeletionLock(const ObjectAddress *object)
Definition: dependency.c:1528
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2548
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2502
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2788
@ SHARED_DEPENDENCY_INITACL
Definition: dependency.h:82
@ SHARED_DEPENDENCY_POLICY
Definition: dependency.h:83
bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
Definition: genam.c:572
#define lfirst_oid(lc)
Definition: pg_list.h:174
bool RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
Definition: policy.c:416

References AcquireDeletionLock(), add_exact_object_address(), Assert, BTEqualStrategyNumber, ObjectAddress::classId, elog, ereport, errcode(), errmsg(), ERROR, free_object_addresses(), getObjectDescription(), GETSTRUCT, InvalidOid, IsPinnedObject(), sort-test::key, lfirst_oid, MyDatabaseId, new_object_addresses(), ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, performMultipleDeletions(), ReleaseDeletionLock(), RemoveRoleFromInitPriv(), RemoveRoleFromObjectACL(), RemoveRoleFromObjectPolicy(), RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_ACL, SHARED_DEPENDENCY_INITACL, SHARED_DEPENDENCY_INVALID, SHARED_DEPENDENCY_OWNER, SHARED_DEPENDENCY_POLICY, sort_object_addresses(), systable_beginscan(), systable_endscan(), systable_getnext(), systable_recheck_tuple(), table_close(), and table_open().

Referenced by DropOwnedObjects().

◆ shdepLockAndCheckObject()

void shdepLockAndCheckObject ( Oid  classId,
Oid  objectId 
)

Definition at line 1211 of file pg_shdepend.c.

1212{
1213 /* AccessShareLock should be OK, since we are not modifying the object */
1214 LockSharedObject(classId, objectId, 0, AccessShareLock);
1215
1216 switch (classId)
1217 {
1218 case AuthIdRelationId:
1219 if (!SearchSysCacheExists1(AUTHOID, ObjectIdGetDatum(objectId)))
1220 ereport(ERROR,
1221 (errcode(ERRCODE_UNDEFINED_OBJECT),
1222 errmsg("role %u was concurrently dropped",
1223 objectId)));
1224 break;
1225
1226 case TableSpaceRelationId:
1227 {
1228 /* For lack of a syscache on pg_tablespace, do this: */
1229 char *tablespace = get_tablespace_name(objectId);
1230
1231 if (tablespace == NULL)
1232 ereport(ERROR,
1233 (errcode(ERRCODE_UNDEFINED_OBJECT),
1234 errmsg("tablespace %u was concurrently dropped",
1235 objectId)));
1237 break;
1238 }
1239
1240 case DatabaseRelationId:
1241 {
1242 /* For lack of a syscache on pg_database, do this: */
1243 char *database = get_database_name(objectId);
1244
1245 if (database == NULL)
1246 ereport(ERROR,
1247 (errcode(ERRCODE_UNDEFINED_OBJECT),
1248 errmsg("database %u was concurrently dropped",
1249 objectId)));
1250 pfree(database);
1251 break;
1252 }
1253
1254
1255 default:
1256 elog(ERROR, "unrecognized shared classId: %u", classId);
1257 }
1258}
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1472
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3187
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1072
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:100

References AccessShareLock, elog, ereport, errcode(), errmsg(), ERROR, get_database_name(), get_tablespace_name(), LockSharedObject(), ObjectIdGetDatum(), pfree(), SearchSysCacheExists1, and tablespace.

Referenced by AlterDatabaseSet(), AlterRoleSet(), shdepAddDependency(), and shdepChangeDep().

◆ shdepReassignOwned()

void shdepReassignOwned ( List roleids,
Oid  newrole 
)

Definition at line 1530 of file pg_shdepend.c.

1531{
1532 Relation sdepRel;
1533 ListCell *cell;
1534
1535 /*
1536 * We don't need this strong a lock here, but we'll call routines that
1537 * acquire RowExclusiveLock. Better get that right now to avoid potential
1538 * deadlock problems.
1539 */
1540 sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1541
1542 foreach(cell, roleids)
1543 {
1544 SysScanDesc scan;
1545 ScanKeyData key[2];
1546 HeapTuple tuple;
1547 Oid roleid = lfirst_oid(cell);
1548
1549 /* Refuse to work on pinned roles */
1550 if (IsPinnedObject(AuthIdRelationId, roleid))
1551 {
1552 ObjectAddress obj;
1553
1554 obj.classId = AuthIdRelationId;
1555 obj.objectId = roleid;
1556 obj.objectSubId = 0;
1557
1558 ereport(ERROR,
1559 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1560 errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system",
1561 getObjectDescription(&obj, false))));
1562
1563 /*
1564 * There's no need to tell the whole truth, which is that we
1565 * didn't track these dependencies at all ...
1566 */
1567 }
1568
1569 ScanKeyInit(&key[0],
1570 Anum_pg_shdepend_refclassid,
1571 BTEqualStrategyNumber, F_OIDEQ,
1572 ObjectIdGetDatum(AuthIdRelationId));
1573 ScanKeyInit(&key[1],
1574 Anum_pg_shdepend_refobjid,
1575 BTEqualStrategyNumber, F_OIDEQ,
1576 ObjectIdGetDatum(roleid));
1577
1578 scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1579 NULL, 2, key);
1580
1581 while ((tuple = systable_getnext(scan)) != NULL)
1582 {
1583 Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1584 MemoryContext cxt,
1585 oldcxt;
1586
1587 /*
1588 * We only operate on shared objects and objects in the current
1589 * database
1590 */
1591 if (sdepForm->dbid != MyDatabaseId &&
1592 sdepForm->dbid != InvalidOid)
1593 continue;
1594
1595 /*
1596 * The various DDL routines called here tend to leak memory in
1597 * CurrentMemoryContext. That's not a problem when they're only
1598 * called once per command; but in this usage where we might be
1599 * touching many objects, it can amount to a serious memory leak.
1600 * Fix that by running each call in a short-lived context.
1601 */
1603 "shdepReassignOwned",
1605 oldcxt = MemoryContextSwitchTo(cxt);
1606
1607 /* Perform the appropriate processing */
1608 switch (sdepForm->deptype)
1609 {
1611 shdepReassignOwned_Owner(sdepForm, newrole);
1612 break;
1614 shdepReassignOwned_InitAcl(sdepForm, roleid, newrole);
1615 break;
1619 /* Nothing to do for these entry types */
1620 break;
1621 default:
1622 elog(ERROR, "unrecognized dependency type: %d",
1623 (int) sdepForm->deptype);
1624 break;
1625 }
1626
1627 /* Clean up */
1628 MemoryContextSwitchTo(oldcxt);
1630
1631 /* Make sure the next iteration will see my changes */
1633 }
1634
1635 systable_endscan(scan);
1636 }
1637
1638 table_close(sdepRel, RowExclusiveLock);
1639}
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static void shdepReassignOwned_InitAcl(Form_pg_shdepend sdepForm, Oid oldrole, Oid newrole)
Definition: pg_shdepend.c:1734
static void shdepReassignOwned_Owner(Form_pg_shdepend sdepForm, Oid newrole)
Definition: pg_shdepend.c:1647
void CommandCounterIncrement(void)
Definition: xact.c:1099

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, BTEqualStrategyNumber, ObjectAddress::classId, CommandCounterIncrement(), CurrentMemoryContext, elog, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, InvalidOid, IsPinnedObject(), sort-test::key, lfirst_oid, MemoryContextDelete(), MemoryContextSwitchTo(), MyDatabaseId, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_ACL, SHARED_DEPENDENCY_INITACL, SHARED_DEPENDENCY_OWNER, SHARED_DEPENDENCY_POLICY, SHARED_DEPENDENCY_TABLESPACE, shdepReassignOwned_InitAcl(), shdepReassignOwned_Owner(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ReassignOwnedObjects().

◆ shdepReassignOwned_InitAcl()

static void shdepReassignOwned_InitAcl ( Form_pg_shdepend  sdepForm,
Oid  oldrole,
Oid  newrole 
)
static

Definition at line 1734 of file pg_shdepend.c.

1735{
1736 /*
1737 * Currently, REASSIGN OWNED replaces mentions of oldrole with newrole in
1738 * pg_init_privs entries, just as it does in the object's regular ACL.
1739 * This is less than ideal, since pg_init_privs ought to retain a
1740 * historical record of the situation at the end of CREATE EXTENSION.
1741 * However, there are two big stumbling blocks to doing something
1742 * different:
1743 *
1744 * 1. If we don't replace the references, what is to happen if the old
1745 * role gets dropped? (DROP OWNED's current answer is to just delete the
1746 * pg_init_privs entry, which is surely ahistorical.)
1747 *
1748 * 2. It's unlikely that pg_dump will cope nicely with pg_init_privs
1749 * entries that are based on a different owner than the object now has ---
1750 * the more so given that pg_init_privs doesn't record the original owner
1751 * explicitly. (This problem actually exists anyway given that a bare
1752 * ALTER OWNER won't update pg_init_privs, but we don't need REASSIGN
1753 * OWNED making it worse.)
1754 */
1755 ReplaceRoleInInitPriv(oldrole, newrole,
1756 sdepForm->classid,
1757 sdepForm->objid,
1758 sdepForm->objsubid);
1759}
void ReplaceRoleInInitPriv(Oid oldroleid, Oid newroleid, Oid classid, Oid objid, int32 objsubid)
Definition: aclchk.c:4722

References ReplaceRoleInInitPriv().

Referenced by shdepReassignOwned().

◆ shdepReassignOwned_Owner()

static void shdepReassignOwned_Owner ( Form_pg_shdepend  sdepForm,
Oid  newrole 
)
static

Definition at line 1647 of file pg_shdepend.c.

1648{
1649 /* Issue the appropriate ALTER OWNER call */
1650 switch (sdepForm->classid)
1651 {
1652 case TypeRelationId:
1653 AlterTypeOwner_oid(sdepForm->objid, newrole, true);
1654 break;
1655
1656 case NamespaceRelationId:
1657 AlterSchemaOwner_oid(sdepForm->objid, newrole);
1658 break;
1659
1660 case RelationRelationId:
1661
1662 /*
1663 * Pass recursing = true so that we don't fail on indexes, owned
1664 * sequences, etc when we happen to visit them before their parent
1665 * table.
1666 */
1667 ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
1668 break;
1669
1670 case DefaultAclRelationId:
1671
1672 /*
1673 * Ignore default ACLs; they should be handled by DROP OWNED, not
1674 * REASSIGN OWNED.
1675 */
1676 break;
1677
1678 case UserMappingRelationId:
1679 /* ditto */
1680 break;
1681
1682 case ForeignServerRelationId:
1683 AlterForeignServerOwner_oid(sdepForm->objid, newrole);
1684 break;
1685
1686 case ForeignDataWrapperRelationId:
1687 AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
1688 break;
1689
1690 case EventTriggerRelationId:
1691 AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
1692 break;
1693
1694 case PublicationRelationId:
1695 AlterPublicationOwner_oid(sdepForm->objid, newrole);
1696 break;
1697
1698 case SubscriptionRelationId:
1699 AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
1700 break;
1701
1702 /* Generic alter owner cases */
1703 case CollationRelationId:
1704 case ConversionRelationId:
1705 case OperatorRelationId:
1706 case ProcedureRelationId:
1707 case LanguageRelationId:
1708 case LargeObjectRelationId:
1709 case OperatorFamilyRelationId:
1710 case OperatorClassRelationId:
1711 case ExtensionRelationId:
1712 case StatisticExtRelationId:
1713 case TableSpaceRelationId:
1714 case DatabaseRelationId:
1715 case TSConfigRelationId:
1716 case TSDictionaryRelationId:
1717 AlterObjectOwner_internal(sdepForm->classid,
1718 sdepForm->objid,
1719 newrole);
1720 break;
1721
1722 default:
1723 elog(ERROR, "unexpected classid %u", sdepForm->classid);
1724 break;
1725 }
1726}
void AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
Definition: alter.c:910
void AlterEventTriggerOwner_oid(Oid trigOid, Oid newOwnerId)
void AlterForeignServerOwner_oid(Oid srvId, Oid newOwnerId)
Definition: foreigncmds.c:450
void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId)
Definition: foreigncmds.c:313
#define AccessExclusiveLock
Definition: lockdefs.h:43
void AlterPublicationOwner_oid(Oid subid, Oid newOwnerId)
void AlterSchemaOwner_oid(Oid schemaoid, Oid newOwnerId)
Definition: schemacmds.c:307
void AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
Definition: tablecmds.c:14994
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3934

References AccessExclusiveLock, AlterEventTriggerOwner_oid(), AlterForeignDataWrapperOwner_oid(), AlterForeignServerOwner_oid(), AlterObjectOwner_internal(), AlterPublicationOwner_oid(), AlterSchemaOwner_oid(), AlterSubscriptionOwner_oid(), AlterTypeOwner_oid(), ATExecChangeOwner(), elog, and ERROR.

Referenced by shdepReassignOwned().

◆ storeObjectDescription()

static void storeObjectDescription ( StringInfo  descs,
SharedDependencyObjectType  type,
ObjectAddress object,
SharedDependencyType  deptype,
int  count 
)
static

Definition at line 1276 of file pg_shdepend.c.

1281{
1282 char *objdesc = getObjectDescription(object, false);
1283
1284 /*
1285 * An object being dropped concurrently doesn't need to be reported.
1286 */
1287 if (objdesc == NULL)
1288 return;
1289
1290 /* separate entries with a newline */
1291 if (descs->len != 0)
1292 appendStringInfoChar(descs, '\n');
1293
1294 switch (type)
1295 {
1296 case LOCAL_OBJECT:
1297 case SHARED_OBJECT:
1298 if (deptype == SHARED_DEPENDENCY_OWNER)
1299 appendStringInfo(descs, _("owner of %s"), objdesc);
1300 else if (deptype == SHARED_DEPENDENCY_ACL)
1301 appendStringInfo(descs, _("privileges for %s"), objdesc);
1302 else if (deptype == SHARED_DEPENDENCY_INITACL)
1303 appendStringInfo(descs, _("initial privileges for %s"), objdesc);
1304 else if (deptype == SHARED_DEPENDENCY_POLICY)
1305 appendStringInfo(descs, _("target of %s"), objdesc);
1306 else if (deptype == SHARED_DEPENDENCY_TABLESPACE)
1307 appendStringInfo(descs, _("tablespace for %s"), objdesc);
1308 else
1309 elog(ERROR, "unrecognized dependency type: %d",
1310 (int) deptype);
1311 break;
1312
1313 case REMOTE_OBJECT:
1314 /* translator: %s will always be "database %s" */
1315 appendStringInfo(descs, ngettext("%d object in %s",
1316 "%d objects in %s",
1317 count),
1318 count, objdesc);
1319 break;
1320
1321 default:
1322 elog(ERROR, "unrecognized object type: %d", type);
1323 }
1324
1325 pfree(objdesc);
1326}
#define _(x)
Definition: elog.c:90
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
const char * type

References _, appendStringInfo(), appendStringInfoChar(), elog, ERROR, getObjectDescription(), StringInfoData::len, LOCAL_OBJECT, ngettext, pfree(), REMOTE_OBJECT, SHARED_DEPENDENCY_ACL, SHARED_DEPENDENCY_INITACL, SHARED_DEPENDENCY_OWNER, SHARED_DEPENDENCY_POLICY, SHARED_DEPENDENCY_TABLESPACE, SHARED_OBJECT, and type.

Referenced by checkSharedDependencies().

◆ updateAclDependencies()

void updateAclDependencies ( Oid  classId,
Oid  objectId,
int32  objsubId,
Oid  ownerId,
int  noldmembers,
Oid oldmembers,
int  nnewmembers,
Oid newmembers 
)

Definition at line 491 of file pg_shdepend.c.

495{
496 updateAclDependenciesWorker(classId, objectId, objsubId,
497 ownerId, SHARED_DEPENDENCY_ACL,
498 noldmembers, oldmembers,
499 nnewmembers, newmembers);
500}
static void updateAclDependenciesWorker(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, SharedDependencyType deptype, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:525

References SHARED_DEPENDENCY_ACL, and updateAclDependenciesWorker().

Referenced by AddRoleMems(), ExecGrant_Attribute(), ExecGrant_common(), ExecGrant_Largeobject(), ExecGrant_Parameter(), ExecGrant_Relation(), recordDependencyOnNewAcl(), and SetDefaultACL().

◆ updateAclDependenciesWorker()

static void updateAclDependenciesWorker ( Oid  classId,
Oid  objectId,
int32  objsubId,
Oid  ownerId,
SharedDependencyType  deptype,
int  noldmembers,
Oid oldmembers,
int  nnewmembers,
Oid newmembers 
)
static

Definition at line 525 of file pg_shdepend.c.

529{
530 Relation sdepRel;
531 int i;
532
533 /*
534 * Remove entries that are common to both lists; those represent existing
535 * dependencies we don't need to change.
536 *
537 * OK to overwrite the inputs since we'll pfree them anyway.
538 */
539 getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers);
540
541 if (noldmembers > 0 || nnewmembers > 0)
542 {
543 sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
544
545 /* Add new dependencies that weren't already present */
546 for (i = 0; i < nnewmembers; i++)
547 {
548 Oid roleid = newmembers[i];
549
550 /*
551 * For SHARED_DEPENDENCY_ACL entries, skip the owner: she has an
552 * OWNER shdep entry instead. (This is not just a space
553 * optimization; it makes ALTER OWNER easier. See notes in
554 * changeDependencyOnOwner.) But for INITACL entries, we record
555 * the owner too.
556 */
557 if (deptype == SHARED_DEPENDENCY_ACL && roleid == ownerId)
558 continue;
559
560 /* Skip pinned roles; they don't need dependency entries */
561 if (IsPinnedObject(AuthIdRelationId, roleid))
562 continue;
563
564 shdepAddDependency(sdepRel, classId, objectId, objsubId,
565 AuthIdRelationId, roleid,
566 deptype);
567 }
568
569 /* Drop no-longer-used old dependencies */
570 for (i = 0; i < noldmembers; i++)
571 {
572 Oid roleid = oldmembers[i];
573
574 /* Skip the owner for ACL entries, same as above */
575 if (deptype == SHARED_DEPENDENCY_ACL && roleid == ownerId)
576 continue;
577
578 /* Skip pinned roles */
579 if (IsPinnedObject(AuthIdRelationId, roleid))
580 continue;
581
582 shdepDropDependency(sdepRel, classId, objectId, objsubId,
583 false, /* exact match on objsubId */
584 AuthIdRelationId, roleid,
585 deptype);
586 }
587
589 }
590
591 if (oldmembers)
592 pfree(oldmembers);
593 if (newmembers)
594 pfree(newmembers);
595}
static void getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2)
Definition: pg_shdepend.c:421

References getOidListDiff(), i, IsPinnedObject(), pfree(), RowExclusiveLock, SHARED_DEPENDENCY_ACL, shdepAddDependency(), shdepDropDependency(), table_close(), and table_open().

Referenced by updateAclDependencies(), and updateInitAclDependencies().

◆ updateInitAclDependencies()

void updateInitAclDependencies ( Oid  classId,
Oid  objectId,
int32  objsubId,
int  noldmembers,
Oid oldmembers,
int  nnewmembers,
Oid newmembers 
)

Definition at line 512 of file pg_shdepend.c.

515{
516 updateAclDependenciesWorker(classId, objectId, objsubId,
517 InvalidOid, /* ownerId will not be consulted */
519 noldmembers, oldmembers,
520 nnewmembers, newmembers);
521}

References InvalidOid, SHARED_DEPENDENCY_INITACL, and updateAclDependenciesWorker().

Referenced by recordExtensionInitPrivWorker(), RemoveRoleFromInitPriv(), and ReplaceRoleInInitPriv().