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 
357  table_close(sdepRel, RowExclusiveLock);
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 
409  table_close(sdepRel, RowExclusiveLock);
410 }
@ SHARED_DEPENDENCY_TABLESPACE
Definition: dependency.h:84
@ SHARED_DEPENDENCY_INVALID
Definition: dependency.h:85
#define InvalidOid
Definition: postgres_ext.h:36

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;
701  ereport(ERROR,
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  {
741  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
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 
804  table_close(sdepRel, AccessShareLock);
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++;
818  storeObjectDescription(&descs,
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:1181
bool IsPinnedObject(Oid classId, Oid objectId)
Definition: catalog.c:334
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:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
Oid MyDatabaseId
Definition: globals.c:92
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
int i
Definition: isn.c:73
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 pfree(void *pointer)
Definition: mcxt.c:1521
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
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:453
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
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:97
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
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:264
unsigned int Oid
Definition: postgres_ext.h:31

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);
984  table_close(sdepRel, RowExclusiveLock);
985 
986  /* Drop only the number of slots used */
987  for (int i = 0; i < slot_init_count; i++)
989  pfree(slot);
990 }
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1639
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1341
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:85
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1325
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 
)

Definition at line 1047 of file pg_shdepend.c.

1048 {
1049  Relation sdepRel;
1050 
1051  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1052 
1053  shdepDropDependency(sdepRel, classId, objectId, objectSubId,
1054  (objectSubId == 0),
1057 
1058  table_close(sdepRel, RowExclusiveLock);
1059 }

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

Referenced by AlterPolicy(), deleteOneObject(), DelRoleMems(), DropRole(), DropSubscription(), DropTableSpace(), GenerateTypeDependencies(), makeConfigurationDependencies(), makeOperatorDependencies(), and RemoveRoleFromObjectPolicy().

◆ 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 
155  table_close(sdepRel, RowExclusiveLock);
156 }
#define Assert(condition)
Definition: c.h:858
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:454
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:70
int a
Definition: isn.c:69

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:150
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
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:64
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static Datum CharGetDatum(char X)
Definition: postgres.h:122
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 */
270  Form_pg_shdepend shForm = (Form_pg_shdepend) GETSTRUCT(oldtup);
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:224
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
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,
1139  ObjectIdGetDatum(classIdGetDbId(classId)));
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:775

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;
1444  case SHARED_DEPENDENCY_ACL:
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  {
1456  RemoveRoleFromObjectACL(roleid,
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);
1496  RemoveRoleFromInitPriv(roleid,
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:4917
void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
Definition: aclchk.c:1465
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:332
void sort_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2761
void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1496
void ReleaseDeletionLock(const ObjectAddress *object)
Definition: dependency.c:1528
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2487
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2533
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2773
@ 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:562
#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)));
1236  pfree(tablespace);
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:3166
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1073
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:95

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;
1616  case SHARED_DEPENDENCY_ACL:
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);
1629  MemoryContextDelete(cxt);
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 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
MemoryContextSwitchTo(old_ctx)
void CommandCounterIncrement(void)
Definition: xact.c:1098

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:4808

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:916
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:14314
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3947

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:194
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 
588  table_close(sdepRel, RowExclusiveLock);
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().