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_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_largeobject_metadata.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opclass.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/collationcmds.h"
#include "commands/conversioncmds.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/policy.h"
#include "commands/proclang.h"
#include "commands/publicationcmds.h"
#include "commands/schemacmds.h"
#include "commands/subscriptioncmds.h"
#include "commands/tablecmds.h"
#include "commands/typecmds.h"
#include "storage/lmgr.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/fmgroids.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 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 bool isSharedObjectPinned (Oid classId, Oid objectId, Relation sdepRel)
 
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 updateAclDependencies (Oid classId, Oid objectId, int32 objsubId, Oid ownerId, 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

Referenced by checkSharedDependencies().

Enumeration Type Documentation

◆ SharedDependencyObjectType

Enumerator
LOCAL_OBJECT 
SHARED_OBJECT 
REMOTE_OBJECT 

Definition at line 70 of file pg_shdepend.c.

Function Documentation

◆ changeDependencyOnOwner()

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

Definition at line 310 of file pg_shdepend.c.

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().

311 {
312  Relation sdepRel;
313 
314  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
315 
316  /* Adjust the SHARED_DEPENDENCY_OWNER entry */
317  shdepChangeDep(sdepRel,
318  classId, objectId, 0,
319  AuthIdRelationId, newOwnerId,
321 
322  /*----------
323  * There should never be a SHARED_DEPENDENCY_ACL entry for the owner,
324  * so get rid of it if there is one. This can happen if the new owner
325  * was previously granted some rights to the object.
326  *
327  * This step is analogous to aclnewowner's removal of duplicate entries
328  * in the ACL. We have to do it to handle this scenario:
329  * A grants some rights on an object to B
330  * ALTER OWNER changes the object's owner to B
331  * ALTER OWNER changes the object's owner to C
332  * The third step would remove all mention of B from the object's ACL,
333  * but we'd still have a SHARED_DEPENDENCY_ACL for B if we did not do
334  * things this way.
335  *
336  * The rule against having a SHARED_DEPENDENCY_ACL entry for the owner
337  * allows us to fix things up in just this one place, without having
338  * to make the various ALTER OWNER routines each know about it.
339  *----------
340  */
341  shdepDropDependency(sdepRel, classId, objectId, 0, true,
342  AuthIdRelationId, newOwnerId,
344 
345  table_close(sdepRel, RowExclusiveLock);
346 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static void shdepChangeDep(Relation sdepRel, Oid classid, Oid objid, int32 objsubid, Oid refclassid, Oid refobjid, SharedDependencyType deptype)
Definition: pg_shdepend.c:200
#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:985
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ checkSharedDependencies()

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

Definition at line 578 of file pg_shdepend.c.

References AccessShareLock, appendStringInfo(), BTEqualStrategyNumber, remoteDep::count, StringInfoData::data, remoteDep::dbOid, ShDependObjectInfo::deptype, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, HeapTupleIsValid, i, initStringInfo(), InvalidOid, 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_DEPENDENCY_PIN, SHARED_OBJECT, SharedDependReferenceIndexId, storeObjectDescription(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by DropRole().

580 {
581  Relation sdepRel;
582  ScanKeyData key[2];
583  SysScanDesc scan;
584  HeapTuple tup;
585  int numReportedDeps = 0;
586  int numNotReportedDeps = 0;
587  int numNotReportedDbs = 0;
588  List *remDeps = NIL;
589  ListCell *cell;
590  ObjectAddress object;
591  ShDependObjectInfo *objects;
592  int numobjects;
593  int allocedobjects;
594  StringInfoData descs;
595  StringInfoData alldescs;
596 
597  /*
598  * We limit the number of dependencies reported to the client to
599  * MAX_REPORTED_DEPS, since client software may not deal well with
600  * enormous error strings. The server log always gets a full report.
601  *
602  * For stability of regression test results, we sort local and shared
603  * objects by OID before reporting them. We don't worry about the order
604  * in which other databases are reported, though.
605  */
606 #define MAX_REPORTED_DEPS 100
607 
608  allocedobjects = 128; /* arbitrary initial array size */
609  objects = (ShDependObjectInfo *)
610  palloc(allocedobjects * sizeof(ShDependObjectInfo));
611  numobjects = 0;
612  initStringInfo(&descs);
613  initStringInfo(&alldescs);
614 
615  sdepRel = table_open(SharedDependRelationId, AccessShareLock);
616 
617  ScanKeyInit(&key[0],
618  Anum_pg_shdepend_refclassid,
619  BTEqualStrategyNumber, F_OIDEQ,
620  ObjectIdGetDatum(classId));
621  ScanKeyInit(&key[1],
622  Anum_pg_shdepend_refobjid,
623  BTEqualStrategyNumber, F_OIDEQ,
624  ObjectIdGetDatum(objectId));
625 
626  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
627  NULL, 2, key);
628 
629  while (HeapTupleIsValid(tup = systable_getnext(scan)))
630  {
631  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
632 
633  /* This case can be dispatched quickly */
634  if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
635  {
636  object.classId = classId;
637  object.objectId = objectId;
638  object.objectSubId = 0;
639  ereport(ERROR,
640  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
641  errmsg("cannot drop %s because it is required by the database system",
642  getObjectDescription(&object))));
643  }
644 
645  object.classId = sdepForm->classid;
646  object.objectId = sdepForm->objid;
647  object.objectSubId = sdepForm->objsubid;
648 
649  /*
650  * If it's a dependency local to this database or it's a shared
651  * object, add it to the objects array.
652  *
653  * If it's a remote dependency, keep track of it so we can report the
654  * number of them later.
655  */
656  if (sdepForm->dbid == MyDatabaseId ||
657  sdepForm->dbid == InvalidOid)
658  {
659  if (numobjects >= allocedobjects)
660  {
661  allocedobjects *= 2;
662  objects = (ShDependObjectInfo *)
663  repalloc(objects,
664  allocedobjects * sizeof(ShDependObjectInfo));
665  }
666  objects[numobjects].object = object;
667  objects[numobjects].deptype = sdepForm->deptype;
668  objects[numobjects].objtype = (sdepForm->dbid == MyDatabaseId) ?
670  numobjects++;
671  }
672  else
673  {
674  /* It's not local nor shared, so it must be remote. */
675  remoteDep *dep;
676  bool stored = false;
677 
678  /*
679  * XXX this info is kept on a simple List. Maybe it's not good
680  * for performance, but using a hash table seems needlessly
681  * complex. The expected number of databases is not high anyway,
682  * I suppose.
683  */
684  foreach(cell, remDeps)
685  {
686  dep = lfirst(cell);
687  if (dep->dbOid == sdepForm->dbid)
688  {
689  dep->count++;
690  stored = true;
691  break;
692  }
693  }
694  if (!stored)
695  {
696  dep = (remoteDep *) palloc(sizeof(remoteDep));
697  dep->dbOid = sdepForm->dbid;
698  dep->count = 1;
699  remDeps = lappend(remDeps, dep);
700  }
701  }
702  }
703 
704  systable_endscan(scan);
705 
706  table_close(sdepRel, AccessShareLock);
707 
708  /*
709  * Sort and report local and shared objects.
710  */
711  if (numobjects > 1)
712  qsort((void *) objects, numobjects,
714 
715  for (int i = 0; i < numobjects; i++)
716  {
717  if (numReportedDeps < MAX_REPORTED_DEPS)
718  {
719  numReportedDeps++;
720  storeObjectDescription(&descs,
721  objects[i].objtype,
722  &objects[i].object,
723  objects[i].deptype,
724  0);
725  }
726  else
727  numNotReportedDeps++;
728  storeObjectDescription(&alldescs,
729  objects[i].objtype,
730  &objects[i].object,
731  objects[i].deptype,
732  0);
733  }
734 
735  /*
736  * Summarize dependencies in remote databases.
737  */
738  foreach(cell, remDeps)
739  {
740  remoteDep *dep = lfirst(cell);
741 
742  object.classId = DatabaseRelationId;
743  object.objectId = dep->dbOid;
744  object.objectSubId = 0;
745 
746  if (numReportedDeps < MAX_REPORTED_DEPS)
747  {
748  numReportedDeps++;
749  storeObjectDescription(&descs, REMOTE_OBJECT, &object,
751  }
752  else
753  numNotReportedDbs++;
754  storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
756  }
757 
758  pfree(objects);
759  list_free_deep(remDeps);
760 
761  if (descs.len == 0)
762  {
763  pfree(descs.data);
764  pfree(alldescs.data);
765  *detail_msg = *detail_log_msg = NULL;
766  return false;
767  }
768 
769  if (numNotReportedDeps > 0)
770  appendStringInfo(&descs, ngettext("\nand %d other object "
771  "(see server log for list)",
772  "\nand %d other objects "
773  "(see server log for list)",
774  numNotReportedDeps),
775  numNotReportedDeps);
776  if (numNotReportedDbs > 0)
777  appendStringInfo(&descs, ngettext("\nand objects in %d other database "
778  "(see server log for list)",
779  "\nand objects in %d other databases "
780  "(see server log for list)",
781  numNotReportedDbs),
782  numNotReportedDbs);
783 
784  *detail_msg = descs.data;
785  *detail_log_msg = alldescs.data;
786  return true;
787 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static int shared_dependency_comparator(const void *a, const void *b)
Definition: pg_shdepend.c:510
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
#define AccessShareLock
Definition: lockdefs.h:36
#define MAX_REPORTED_DEPS
static void storeObjectDescription(StringInfo descs, SharedDependencyObjectType type, ObjectAddress *object, SharedDependencyType deptype, int count)
Definition: pg_shdepend.c:1145
int errcode(int sqlerrcode)
Definition: elog.c:570
void list_free_deep(List *list)
Definition: list.c:1387
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
SharedDependencyObjectType objtype
Definition: pg_shdepend.c:81
char * getObjectDescription(const ObjectAddress *object)
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
void pfree(void *pointer)
Definition: mcxt.c:1031
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
List * lappend(List *list, void *datum)
Definition: list.c:321
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define ngettext(s, p, n)
Definition: c.h:1103
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:190
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define SharedDependReferenceIndexId
Definition: indexing.h:228
#define qsort(a, b, c, d)
Definition: port.h:491
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ObjectAddress object
Definition: pg_shdepend.c:79

◆ classIdGetDbId()

static Oid classIdGetDbId ( Oid  classId)
static

Definition at line 1051 of file pg_shdepend.c.

References InvalidOid, IsSharedRelation(), and MyDatabaseId.

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

1052 {
1053  Oid dbId;
1054 
1055  if (IsSharedRelation(classId))
1056  dbId = InvalidOid;
1057  else
1058  dbId = MyDatabaseId;
1059 
1060  return dbId;
1061 }
unsigned int Oid
Definition: postgres_ext.h:31
Oid MyDatabaseId
Definition: globals.c:85
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:240
#define InvalidOid
Definition: postgres_ext.h:36

◆ copyTemplateDependencies()

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)

Definition at line 796 of file pg_shdepend.c.

References BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTupleInsertWithInfo(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, sort-test::key, ObjectIdGetDatum, RelationGetDescr, RowExclusiveLock, ScanKeyInit(), SharedDependDependerIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and values.

Referenced by createdb().

797 {
798  Relation sdepRel;
799  TupleDesc sdepDesc;
800  ScanKeyData key[1];
801  SysScanDesc scan;
802  HeapTuple tup;
803  CatalogIndexState indstate;
804  Datum values[Natts_pg_shdepend];
805  bool nulls[Natts_pg_shdepend];
806  bool replace[Natts_pg_shdepend];
807 
808  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
809  sdepDesc = RelationGetDescr(sdepRel);
810 
811  indstate = CatalogOpenIndexes(sdepRel);
812 
813  /* Scan all entries with dbid = templateDbId */
814  ScanKeyInit(&key[0],
815  Anum_pg_shdepend_dbid,
816  BTEqualStrategyNumber, F_OIDEQ,
817  ObjectIdGetDatum(templateDbId));
818 
819  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
820  NULL, 1, key);
821 
822  /* Set up to copy the tuples except for inserting newDbId */
823  memset(values, 0, sizeof(values));
824  memset(nulls, false, sizeof(nulls));
825  memset(replace, false, sizeof(replace));
826 
827  replace[Anum_pg_shdepend_dbid - 1] = true;
828  values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId);
829 
830  /*
831  * Copy the entries of the original database, changing the database Id to
832  * that of the new database. Note that because we are not copying rows
833  * with dbId == 0 (ie, rows describing dependent shared objects) we won't
834  * copy the ownership dependency of the template database itself; this is
835  * what we want.
836  */
837  while (HeapTupleIsValid(tup = systable_getnext(scan)))
838  {
839  HeapTuple newtup;
840 
841  newtup = heap_modify_tuple(tup, sdepDesc, values, nulls, replace);
842  CatalogTupleInsertWithInfo(sdepRel, newtup, indstate);
843 
844  heap_freetuple(newtup);
845  }
846 
847  systable_endscan(scan);
848 
849  CatalogCloseIndexes(indstate);
850  table_close(sdepRel, RowExclusiveLock);
851 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define SharedDependDependerIndexId
Definition: indexing.h:226
#define RelationGetDescr(relation)
Definition: rel.h:442
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define RowExclusiveLock
Definition: lockdefs.h:38
uintptr_t Datum
Definition: postgres.h:367
void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:204
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:42
static Datum values[MAXATTR]
Definition: bootstrap.c:167
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:60
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ deleteSharedDependencyRecordsFor()

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

Definition at line 908 of file pg_shdepend.c.

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

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

909 {
910  Relation sdepRel;
911 
912  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
913 
914  shdepDropDependency(sdepRel, classId, objectId, objectSubId,
915  (objectSubId == 0),
918 
919  table_close(sdepRel, RowExclusiveLock);
920 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidOid
Definition: postgres_ext.h:36
static void shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, bool drop_subobjects, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:985
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 860 of file pg_shdepend.c.

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

Referenced by dropdb().

861 {
862  Relation sdepRel;
863  ScanKeyData key[1];
864  SysScanDesc scan;
865  HeapTuple tup;
866 
867  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
868 
869  /*
870  * First, delete all the entries that have the database Oid in the dbid
871  * field.
872  */
873  ScanKeyInit(&key[0],
874  Anum_pg_shdepend_dbid,
875  BTEqualStrategyNumber, F_OIDEQ,
876  ObjectIdGetDatum(databaseId));
877  /* We leave the other index fields unspecified */
878 
879  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
880  NULL, 1, key);
881 
882  while (HeapTupleIsValid(tup = systable_getnext(scan)))
883  {
884  CatalogTupleDelete(sdepRel, &tup->t_self);
885  }
886 
887  systable_endscan(scan);
888 
889  /* Now delete all entries corresponding to the database itself */
890  shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
893 
894  table_close(sdepRel, RowExclusiveLock);
895 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define SharedDependDependerIndexId
Definition: indexing.h:226
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidOid
Definition: postgres_ext.h:36
static void shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, bool drop_subobjects, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:985
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ getOidListDiff()

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

Definition at line 357 of file pg_shdepend.c.

Referenced by updateAclDependencies().

358 {
359  int in1,
360  in2,
361  out1,
362  out2;
363 
364  in1 = in2 = out1 = out2 = 0;
365  while (in1 < *nlist1 && in2 < *nlist2)
366  {
367  if (list1[in1] == list2[in2])
368  {
369  /* skip over duplicates */
370  in1++;
371  in2++;
372  }
373  else if (list1[in1] < list2[in2])
374  {
375  /* list1[in1] is not in list2 */
376  list1[out1++] = list1[in1++];
377  }
378  else
379  {
380  /* list2[in2] is not in list1 */
381  list2[out2++] = list2[in2++];
382  }
383  }
384 
385  /* any remaining list1 entries are not in list2 */
386  while (in1 < *nlist1)
387  {
388  list1[out1++] = list1[in1++];
389  }
390 
391  /* any remaining list2 entries are not in list1 */
392  while (in2 < *nlist2)
393  {
394  list2[out2++] = list2[in2++];
395  }
396 
397  *nlist1 = out1;
398  *nlist2 = out2;
399 }

◆ isSharedObjectPinned()

static bool isSharedObjectPinned ( Oid  classId,
Oid  objectId,
Relation  sdepRel 
)
static

Definition at line 1196 of file pg_shdepend.c.

References BTEqualStrategyNumber, GETSTRUCT, HeapTupleIsValid, sort-test::key, ObjectIdGetDatum, ScanKeyInit(), SHARED_DEPENDENCY_PIN, SharedDependReferenceIndexId, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by recordSharedDependencyOn(), shdepChangeDep(), shdepDropOwned(), shdepReassignOwned(), and updateAclDependencies().

1197 {
1198  bool result = false;
1199  ScanKeyData key[2];
1200  SysScanDesc scan;
1201  HeapTuple tup;
1202 
1203  ScanKeyInit(&key[0],
1204  Anum_pg_shdepend_refclassid,
1205  BTEqualStrategyNumber, F_OIDEQ,
1206  ObjectIdGetDatum(classId));
1207  ScanKeyInit(&key[1],
1208  Anum_pg_shdepend_refobjid,
1209  BTEqualStrategyNumber, F_OIDEQ,
1210  ObjectIdGetDatum(objectId));
1211 
1212  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1213  NULL, 2, key);
1214 
1215  /*
1216  * Since we won't generate additional pg_shdepend entries for pinned
1217  * objects, there can be at most one entry referencing a pinned object.
1218  * Hence, it's sufficient to look at the first returned tuple; we don't
1219  * need to loop.
1220  */
1221  tup = systable_getnext(scan);
1222  if (HeapTupleIsValid(tup))
1223  {
1224  Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1225 
1226  if (shdepForm->deptype == SHARED_DEPENDENCY_PIN)
1227  result = true;
1228  }
1229 
1230  systable_endscan(scan);
1231 
1232  return result;
1233 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define SharedDependReferenceIndexId
Definition: indexing.h:228
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ recordDependencyOnOwner()

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

Definition at line 165 of file pg_shdepend.c.

References ObjectAddress::classId, ObjectAddress::objectId, ObjectAddress::objectSubId, recordSharedDependencyOn(), and SHARED_DEPENDENCY_OWNER.

Referenced by CollationCreate(), ConversionCreate(), create_proc_lang(), createdb(), CreateForeignDataWrapper(), CreateForeignServer(), CreateOpFamily(), CreatePublication(), CreateStatistics(), CreateSubscription(), CreateTableSpace(), CreateUserMapping(), DefineOpClass(), GenerateTypeDependencies(), heap_create_with_catalog(), insert_event_trigger_tuple(), InsertExtensionTuple(), inv_create(), makeConfigurationDependencies(), makeDictionaryDependencies(), makeOperatorDependencies(), NamespaceCreate(), ProcedureCreate(), and SetDefaultACL().

166 {
167  ObjectAddress myself,
168  referenced;
169 
170  myself.classId = classId;
171  myself.objectId = objectId;
172  myself.objectSubId = 0;
173 
174  referenced.classId = AuthIdRelationId;
175  referenced.objectId = owner;
176  referenced.objectSubId = 0;
177 
178  recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_OWNER);
179 }
void recordSharedDependencyOn(ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
Definition: pg_shdepend.c:121

◆ recordSharedDependencyOn()

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

Definition at line 121 of file pg_shdepend.c.

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

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

124 {
125  Relation sdepRel;
126 
127  /*
128  * Objects in pg_shdepend can't have SubIds.
129  */
130  Assert(depender->objectSubId == 0);
131  Assert(referenced->objectSubId == 0);
132 
133  /*
134  * During bootstrap, do nothing since pg_shdepend may not exist yet.
135  * initdb will fill in appropriate pg_shdepend entries after bootstrap.
136  */
138  return;
139 
140  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
141 
142  /* If the referenced object is pinned, do nothing. */
143  if (!isSharedObjectPinned(referenced->classId, referenced->objectId,
144  sdepRel))
145  {
146  shdepAddDependency(sdepRel, depender->classId, depender->objectId,
147  depender->objectSubId,
148  referenced->classId, referenced->objectId,
149  deptype);
150  }
151 
152  table_close(sdepRel, RowExclusiveLock);
153 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1196
static void shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:930
#define RowExclusiveLock
Definition: lockdefs.h:38
#define Assert(condition)
Definition: c.h:732
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:374
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ shared_dependency_comparator()

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

Definition at line 510 of file pg_shdepend.c.

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

Referenced by checkSharedDependencies().

511 {
512  const ShDependObjectInfo *obja = (const ShDependObjectInfo *) a;
513  const ShDependObjectInfo *objb = (const ShDependObjectInfo *) b;
514 
515  /*
516  * Primary sort key is OID ascending.
517  */
518  if (obja->object.objectId < objb->object.objectId)
519  return -1;
520  if (obja->object.objectId > objb->object.objectId)
521  return 1;
522 
523  /*
524  * Next sort on catalog ID, in case identical OIDs appear in different
525  * catalogs. Sort direction is pretty arbitrary here.
526  */
527  if (obja->object.classId < objb->object.classId)
528  return -1;
529  if (obja->object.classId > objb->object.classId)
530  return 1;
531 
532  /*
533  * Sort on object subId.
534  *
535  * We sort the subId as an unsigned int so that 0 (the whole object) will
536  * come first.
537  */
538  if ((unsigned int) obja->object.objectSubId < (unsigned int) objb->object.objectSubId)
539  return -1;
540  if ((unsigned int) obja->object.objectSubId > (unsigned int) objb->object.objectSubId)
541  return 1;
542 
543  /*
544  * Last, sort on deptype, in case the same object has multiple dependency
545  * types. (Note that there's no need to consider objtype, as that's
546  * determined by the catalog OID.)
547  */
548  if (obja->deptype < objb->deptype)
549  return -1;
550  if (obja->deptype > objb->deptype)
551  return 1;
552 
553  return 0;
554 }
ObjectAddress object
Definition: pg_shdepend.c:79

◆ shdepAddDependency()

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

Definition at line 930 of file pg_shdepend.c.

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

Referenced by recordSharedDependencyOn(), and updateAclDependencies().

934 {
935  HeapTuple tup;
936  Datum values[Natts_pg_shdepend];
937  bool nulls[Natts_pg_shdepend];
938 
939  /*
940  * Make sure the object doesn't go away while we record the dependency on
941  * it. DROP routines should lock the object exclusively before they check
942  * shared dependencies.
943  */
944  shdepLockAndCheckObject(refclassId, refobjId);
945 
946  memset(nulls, false, sizeof(nulls));
947 
948  /*
949  * Form the new tuple and record the dependency.
950  */
951  values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId));
952  values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId);
953  values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId);
954  values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId);
955 
956  values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId);
957  values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId);
958  values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
959 
960  tup = heap_form_tuple(sdepRel->rd_att, values, nulls);
961 
962  CatalogTupleInsert(sdepRel, tup);
963 
964  /* clean up */
965  heap_freetuple(tup);
966 }
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1072
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:84
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1051
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define Int32GetDatum(X)
Definition: postgres.h:479
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ shdepChangeDep()

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

Definition at line 200 of file pg_shdepend.c.

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

Referenced by changeDependencyOnOwner().

204 {
205  Oid dbid = classIdGetDbId(classid);
206  HeapTuple oldtup = NULL;
207  HeapTuple scantup;
208  ScanKeyData key[4];
209  SysScanDesc scan;
210 
211  /*
212  * Make sure the new referenced object doesn't go away while we record the
213  * dependency.
214  */
215  shdepLockAndCheckObject(refclassid, refobjid);
216 
217  /*
218  * Look for a previous entry
219  */
220  ScanKeyInit(&key[0],
221  Anum_pg_shdepend_dbid,
222  BTEqualStrategyNumber, F_OIDEQ,
223  ObjectIdGetDatum(dbid));
224  ScanKeyInit(&key[1],
225  Anum_pg_shdepend_classid,
226  BTEqualStrategyNumber, F_OIDEQ,
227  ObjectIdGetDatum(classid));
228  ScanKeyInit(&key[2],
229  Anum_pg_shdepend_objid,
230  BTEqualStrategyNumber, F_OIDEQ,
231  ObjectIdGetDatum(objid));
232  ScanKeyInit(&key[3],
233  Anum_pg_shdepend_objsubid,
234  BTEqualStrategyNumber, F_INT4EQ,
235  Int32GetDatum(objsubid));
236 
237  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
238  NULL, 4, key);
239 
240  while ((scantup = systable_getnext(scan)) != NULL)
241  {
242  /* Ignore if not of the target dependency type */
243  if (((Form_pg_shdepend) GETSTRUCT(scantup))->deptype != deptype)
244  continue;
245  /* Caller screwed up if multiple matches */
246  if (oldtup)
247  elog(ERROR,
248  "multiple pg_shdepend entries for object %u/%u/%d deptype %c",
249  classid, objid, objsubid, deptype);
250  oldtup = heap_copytuple(scantup);
251  }
252 
253  systable_endscan(scan);
254 
255  if (isSharedObjectPinned(refclassid, refobjid, sdepRel))
256  {
257  /* No new entry needed, so just delete existing entry if any */
258  if (oldtup)
259  CatalogTupleDelete(sdepRel, &oldtup->t_self);
260  }
261  else if (oldtup)
262  {
263  /* Need to update existing entry */
264  Form_pg_shdepend shForm = (Form_pg_shdepend) GETSTRUCT(oldtup);
265 
266  /* Since oldtup is a copy, we can just modify it in-memory */
267  shForm->refclassid = refclassid;
268  shForm->refobjid = refobjid;
269 
270  CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup);
271  }
272  else
273  {
274  /* Need to insert new entry */
275  Datum values[Natts_pg_shdepend];
276  bool nulls[Natts_pg_shdepend];
277 
278  memset(nulls, false, sizeof(nulls));
279 
280  values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(dbid);
281  values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classid);
282  values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objid);
283  values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubid);
284 
285  values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassid);
286  values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjid);
287  values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
288 
289  /*
290  * we are reusing oldtup just to avoid declaring a new variable, but
291  * it's certainly a new tuple
292  */
293  oldtup = heap_form_tuple(RelationGetDescr(sdepRel), values, nulls);
294  CatalogTupleInsert(sdepRel, oldtup);
295  }
296 
297  if (oldtup)
298  heap_freetuple(oldtup);
299 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define SharedDependDependerIndexId
Definition: indexing.h:226
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1196
#define RelationGetDescr(relation)
Definition: rel.h:442
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1072
ItemPointerData t_self
Definition: htup.h:65
uintptr_t Datum
Definition: postgres.h:367
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1051
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define Int32GetDatum(X)
Definition: postgres.h:479
#define elog(elevel,...)
Definition: elog.h:226
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ 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 985 of file pg_shdepend.c.

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

Referenced by changeDependencyOnOwner(), deleteSharedDependencyRecordsFor(), dropDatabaseDependencies(), and updateAclDependencies().

990 {
991  ScanKeyData key[4];
992  int nkeys;
993  SysScanDesc scan;
994  HeapTuple tup;
995 
996  /* Scan for entries matching the dependent object */
997  ScanKeyInit(&key[0],
998  Anum_pg_shdepend_dbid,
999  BTEqualStrategyNumber, F_OIDEQ,
1000  ObjectIdGetDatum(classIdGetDbId(classId)));
1001  ScanKeyInit(&key[1],
1002  Anum_pg_shdepend_classid,
1003  BTEqualStrategyNumber, F_OIDEQ,
1004  ObjectIdGetDatum(classId));
1005  ScanKeyInit(&key[2],
1006  Anum_pg_shdepend_objid,
1007  BTEqualStrategyNumber, F_OIDEQ,
1008  ObjectIdGetDatum(objectId));
1009  if (drop_subobjects)
1010  nkeys = 3;
1011  else
1012  {
1013  ScanKeyInit(&key[3],
1014  Anum_pg_shdepend_objsubid,
1015  BTEqualStrategyNumber, F_INT4EQ,
1016  Int32GetDatum(objsubId));
1017  nkeys = 4;
1018  }
1019 
1020  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
1021  NULL, nkeys, key);
1022 
1023  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1024  {
1025  Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1026 
1027  /* Filter entries according to additional parameters */
1028  if (OidIsValid(refclassId) && shdepForm->refclassid != refclassId)
1029  continue;
1030  if (OidIsValid(refobjId) && shdepForm->refobjid != refobjId)
1031  continue;
1032  if (deptype != SHARED_DEPENDENCY_INVALID &&
1033  shdepForm->deptype != deptype)
1034  continue;
1035 
1036  /* OK, delete it */
1037  CatalogTupleDelete(sdepRel, &tup->t_self);
1038  }
1039 
1040  systable_endscan(scan);
1041 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define SharedDependDependerIndexId
Definition: indexing.h:226
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define OidIsValid(objectId)
Definition: c.h:638
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1051
#define Int32GetDatum(X)
Definition: postgres.h:479
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ shdepDropOwned()

void shdepDropOwned ( List roleids,
DropBehavior  behavior 
)

Definition at line 1248 of file pg_shdepend.c.

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

Referenced by DropOwnedObjects().

1249 {
1250  Relation sdepRel;
1251  ListCell *cell;
1252  ObjectAddresses *deleteobjs;
1253 
1254  deleteobjs = new_object_addresses();
1255 
1256  /*
1257  * We don't need this strong a lock here, but we'll call routines that
1258  * acquire RowExclusiveLock. Better get that right now to avoid potential
1259  * deadlock failures.
1260  */
1261  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1262 
1263  /*
1264  * For each role, find the dependent objects and drop them using the
1265  * regular (non-shared) dependency management.
1266  */
1267  foreach(cell, roleids)
1268  {
1269  Oid roleid = lfirst_oid(cell);
1270  ScanKeyData key[2];
1271  SysScanDesc scan;
1272  HeapTuple tuple;
1273 
1274  /* Doesn't work for pinned objects */
1275  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
1276  {
1277  ObjectAddress obj;
1278 
1279  obj.classId = AuthIdRelationId;
1280  obj.objectId = roleid;
1281  obj.objectSubId = 0;
1282 
1283  ereport(ERROR,
1284  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1285  errmsg("cannot drop objects owned by %s because they are "
1286  "required by the database system",
1287  getObjectDescription(&obj))));
1288  }
1289 
1290  ScanKeyInit(&key[0],
1291  Anum_pg_shdepend_refclassid,
1292  BTEqualStrategyNumber, F_OIDEQ,
1293  ObjectIdGetDatum(AuthIdRelationId));
1294  ScanKeyInit(&key[1],
1295  Anum_pg_shdepend_refobjid,
1296  BTEqualStrategyNumber, F_OIDEQ,
1297  ObjectIdGetDatum(roleid));
1298 
1299  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1300  NULL, 2, key);
1301 
1302  while ((tuple = systable_getnext(scan)) != NULL)
1303  {
1304  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1305  ObjectAddress obj;
1306 
1307  /*
1308  * We only operate on shared objects and objects in the current
1309  * database
1310  */
1311  if (sdepForm->dbid != MyDatabaseId &&
1312  sdepForm->dbid != InvalidOid)
1313  continue;
1314 
1315  switch (sdepForm->deptype)
1316  {
1317  /* Shouldn't happen */
1318  case SHARED_DEPENDENCY_PIN:
1320  elog(ERROR, "unexpected dependency type");
1321  break;
1322  case SHARED_DEPENDENCY_ACL:
1323  RemoveRoleFromObjectACL(roleid,
1324  sdepForm->classid,
1325  sdepForm->objid);
1326  break;
1328  /* If unable to remove role from policy, remove policy. */
1329  if (!RemoveRoleFromObjectPolicy(roleid,
1330  sdepForm->classid,
1331  sdepForm->objid))
1332  {
1333  obj.classId = sdepForm->classid;
1334  obj.objectId = sdepForm->objid;
1335  obj.objectSubId = sdepForm->objsubid;
1336  add_exact_object_address(&obj, deleteobjs);
1337  }
1338  break;
1340  /* If a local object, save it for deletion below */
1341  if (sdepForm->dbid == MyDatabaseId)
1342  {
1343  obj.classId = sdepForm->classid;
1344  obj.objectId = sdepForm->objid;
1345  obj.objectSubId = sdepForm->objsubid;
1346  add_exact_object_address(&obj, deleteobjs);
1347  }
1348  break;
1349  }
1350  }
1351 
1352  systable_endscan(scan);
1353  }
1354 
1355  /*
1356  * For stability of deletion-report ordering, sort the objects into
1357  * approximate reverse creation order before deletion. (This might also
1358  * make the deletion go a bit faster, since there's less chance of having
1359  * to rearrange the objects due to dependencies.)
1360  */
1361  sort_object_addresses(deleteobjs);
1362 
1363  /* the dependency mechanism does the actual work */
1364  performMultipleDeletions(deleteobjs, behavior, 0);
1365 
1366  table_close(sdepRel, RowExclusiveLock);
1367 
1368  free_object_addresses(deleteobjs);
1369 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1196
void sort_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2668
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
int errcode(int sqlerrcode)
Definition: elog.c:570
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2440
void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
Definition: aclchk.c:1403
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2385
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2680
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
char * getObjectDescription(const ObjectAddress *object)
bool RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
Definition: policy.c:439
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:374
#define SharedDependReferenceIndexId
Definition: indexing.h:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ shdepLockAndCheckObject()

void shdepLockAndCheckObject ( Oid  classId,
Oid  objectId 
)

Definition at line 1072 of file pg_shdepend.c.

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

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

1073 {
1074  /* AccessShareLock should be OK, since we are not modifying the object */
1075  LockSharedObject(classId, objectId, 0, AccessShareLock);
1076 
1077  switch (classId)
1078  {
1079  case AuthIdRelationId:
1081  ereport(ERROR,
1082  (errcode(ERRCODE_UNDEFINED_OBJECT),
1083  errmsg("role %u was concurrently dropped",
1084  objectId)));
1085  break;
1086 
1087  /*
1088  * Currently, this routine need not support any other shared
1089  * object types besides roles. If we wanted to record explicit
1090  * dependencies on databases or tablespaces, we'd need code along
1091  * these lines:
1092  */
1093 #ifdef NOT_USED
1094  case TableSpaceRelationId:
1095  {
1096  /* For lack of a syscache on pg_tablespace, do this: */
1097  char *tablespace = get_tablespace_name(objectId);
1098 
1099  if (tablespace == NULL)
1100  ereport(ERROR,
1101  (errcode(ERRCODE_UNDEFINED_OBJECT),
1102  errmsg("tablespace %u was concurrently dropped",
1103  objectId)));
1104  pfree(tablespace);
1105  break;
1106  }
1107 #endif
1108 
1109  case DatabaseRelationId:
1110  {
1111  /* For lack of a syscache on pg_database, do this: */
1112  char *database = get_database_name(objectId);
1113 
1114  if (database == NULL)
1115  ereport(ERROR,
1116  (errcode(ERRCODE_UNDEFINED_OBJECT),
1117  errmsg("database %u was concurrently dropped",
1118  objectId)));
1119  pfree(database);
1120  break;
1121  }
1122 
1123 
1124  default:
1125  elog(ERROR, "unrecognized shared classId: %u", classId);
1126  }
1127 }
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:570
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:183
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2099
char * tablespace
Definition: pgbench.c:186
#define ereport(elevel, rest)
Definition: elog.h:141
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1004
int errmsg(const char *fmt,...)
Definition: elog.c:784
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1463
#define elog(elevel,...)
Definition: elog.h:226

◆ shdepReassignOwned()

void shdepReassignOwned ( List roleids,
Oid  newrole 
)

Definition at line 1378 of file pg_shdepend.c.

References AccessExclusiveLock, AlterEventTriggerOwner_oid(), AlterForeignDataWrapperOwner_oid(), AlterForeignServerOwner_oid(), AlterObjectOwner_internal(), AlterPublicationOwner_oid(), AlterSchemaOwner_oid(), AlterSubscriptionOwner_oid(), AlterTypeOwner_oid(), ATExecChangeOwner(), BTEqualStrategyNumber, ObjectAddress::classId, CommandCounterIncrement(), elog, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, InvalidOid, isSharedObjectPinned(), sort-test::key, lfirst_oid, MyDatabaseId, NoLock, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_OWNER, SHARED_DEPENDENCY_PIN, SharedDependReferenceIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ReassignOwnedObjects().

1379 {
1380  Relation sdepRel;
1381  ListCell *cell;
1382 
1383  /*
1384  * We don't need this strong a lock here, but we'll call routines that
1385  * acquire RowExclusiveLock. Better get that right now to avoid potential
1386  * deadlock problems.
1387  */
1388  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1389 
1390  foreach(cell, roleids)
1391  {
1392  SysScanDesc scan;
1393  ScanKeyData key[2];
1394  HeapTuple tuple;
1395  Oid roleid = lfirst_oid(cell);
1396 
1397  /* Refuse to work on pinned roles */
1398  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
1399  {
1400  ObjectAddress obj;
1401 
1402  obj.classId = AuthIdRelationId;
1403  obj.objectId = roleid;
1404  obj.objectSubId = 0;
1405 
1406  ereport(ERROR,
1407  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1408  errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system",
1409  getObjectDescription(&obj))));
1410 
1411  /*
1412  * There's no need to tell the whole truth, which is that we
1413  * didn't track these dependencies at all ...
1414  */
1415  }
1416 
1417  ScanKeyInit(&key[0],
1418  Anum_pg_shdepend_refclassid,
1419  BTEqualStrategyNumber, F_OIDEQ,
1420  ObjectIdGetDatum(AuthIdRelationId));
1421  ScanKeyInit(&key[1],
1422  Anum_pg_shdepend_refobjid,
1423  BTEqualStrategyNumber, F_OIDEQ,
1424  ObjectIdGetDatum(roleid));
1425 
1426  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1427  NULL, 2, key);
1428 
1429  while ((tuple = systable_getnext(scan)) != NULL)
1430  {
1431  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1432 
1433  /*
1434  * We only operate on shared objects and objects in the current
1435  * database
1436  */
1437  if (sdepForm->dbid != MyDatabaseId &&
1438  sdepForm->dbid != InvalidOid)
1439  continue;
1440 
1441  /* Unexpected because we checked for pins above */
1442  if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
1443  elog(ERROR, "unexpected shared pin");
1444 
1445  /* We leave non-owner dependencies alone */
1446  if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
1447  continue;
1448 
1449  /* Issue the appropriate ALTER OWNER call */
1450  switch (sdepForm->classid)
1451  {
1452  case TypeRelationId:
1453  AlterTypeOwner_oid(sdepForm->objid, newrole, true);
1454  break;
1455 
1456  case NamespaceRelationId:
1457  AlterSchemaOwner_oid(sdepForm->objid, newrole);
1458  break;
1459 
1460  case RelationRelationId:
1461 
1462  /*
1463  * Pass recursing = true so that we don't fail on indexes,
1464  * owned sequences, etc when we happen to visit them
1465  * before their parent table.
1466  */
1467  ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
1468  break;
1469 
1470  case DefaultAclRelationId:
1471 
1472  /*
1473  * Ignore default ACLs; they should be handled by DROP
1474  * OWNED, not REASSIGN OWNED.
1475  */
1476  break;
1477 
1478  case UserMappingRelationId:
1479  /* ditto */
1480  break;
1481 
1482  case ForeignServerRelationId:
1483  AlterForeignServerOwner_oid(sdepForm->objid, newrole);
1484  break;
1485 
1486  case ForeignDataWrapperRelationId:
1487  AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
1488  break;
1489 
1490  case EventTriggerRelationId:
1491  AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
1492  break;
1493 
1494  case PublicationRelationId:
1495  AlterPublicationOwner_oid(sdepForm->objid, newrole);
1496  break;
1497 
1498  case SubscriptionRelationId:
1499  AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
1500  break;
1501 
1502  /* Generic alter owner cases */
1503  case CollationRelationId:
1504  case ConversionRelationId:
1505  case OperatorRelationId:
1506  case ProcedureRelationId:
1507  case LanguageRelationId:
1508  case LargeObjectRelationId:
1509  case OperatorFamilyRelationId:
1510  case OperatorClassRelationId:
1511  case ExtensionRelationId:
1512  case StatisticExtRelationId:
1513  case TableSpaceRelationId:
1514  case DatabaseRelationId:
1515  case TSConfigRelationId:
1516  case TSDictionaryRelationId:
1517  {
1518  Oid classId = sdepForm->classid;
1519  Relation catalog;
1520 
1521  if (classId == LargeObjectRelationId)
1522  classId = LargeObjectMetadataRelationId;
1523 
1524  catalog = table_open(classId, RowExclusiveLock);
1525 
1526  AlterObjectOwner_internal(catalog, sdepForm->objid,
1527  newrole);
1528 
1529  table_close(catalog, NoLock);
1530  }
1531  break;
1532 
1533  default:
1534  elog(ERROR, "unexpected classid %u", sdepForm->classid);
1535  break;
1536  }
1537  /* Make sure the next iteration will see my changes */
1539  }
1540 
1541  systable_endscan(scan);
1542  }
1543 
1544  table_close(sdepRel, RowExclusiveLock);
1545 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId)
Definition: foreigncmds.c:313
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1196
void AlterSchemaOwner_oid(Oid oid, Oid newOwnerId)
Definition: schemacmds.c:300
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
void AlterForeignServerOwner_oid(Oid srvId, Oid newOwnerId)
Definition: foreigncmds.c:450
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
char * getObjectDescription(const ObjectAddress *object)
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3409
void AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
Definition: alter.c:910
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
Definition: tablecmds.c:11637
void CommandCounterIncrement(void)
Definition: xact.c:1003
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
void AlterEventTriggerOwner_oid(Oid trigOid, Oid newOwnerId)
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
void AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void AlterPublicationOwner_oid(Oid subid, Oid newOwnerId)
#define SharedDependReferenceIndexId
Definition: indexing.h:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ storeObjectDescription()

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

Definition at line 1145 of file pg_shdepend.c.

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

Referenced by checkSharedDependencies().

1150 {
1151  char *objdesc = getObjectDescription(object);
1152 
1153  /* separate entries with a newline */
1154  if (descs->len != 0)
1155  appendStringInfoChar(descs, '\n');
1156 
1157  switch (type)
1158  {
1159  case LOCAL_OBJECT:
1160  case SHARED_OBJECT:
1161  if (deptype == SHARED_DEPENDENCY_OWNER)
1162  appendStringInfo(descs, _("owner of %s"), objdesc);
1163  else if (deptype == SHARED_DEPENDENCY_ACL)
1164  appendStringInfo(descs, _("privileges for %s"), objdesc);
1165  else if (deptype == SHARED_DEPENDENCY_POLICY)
1166  appendStringInfo(descs, _("target of %s"), objdesc);
1167  else
1168  elog(ERROR, "unrecognized dependency type: %d",
1169  (int) deptype);
1170  break;
1171 
1172  case REMOTE_OBJECT:
1173  /* translator: %s will always be "database %s" */
1174  appendStringInfo(descs, ngettext("%d object in %s",
1175  "%d objects in %s",
1176  count),
1177  count, objdesc);
1178  break;
1179 
1180  default:
1181  elog(ERROR, "unrecognized object type: %d", type);
1182  }
1183 
1184  pfree(objdesc);
1185 }
char * getObjectDescription(const ObjectAddress *object)
void pfree(void *pointer)
Definition: mcxt.c:1031
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ERROR
Definition: elog.h:43
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
#define ngettext(s, p, n)
Definition: c.h:1103
#define elog(elevel,...)
Definition: elog.h:226
#define _(x)
Definition: elog.c:84

◆ updateAclDependencies()

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

Definition at line 427 of file pg_shdepend.c.

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

Referenced by ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), recordDependencyOnNewAcl(), and SetDefaultACL().

431 {
432  Relation sdepRel;
433  int i;
434 
435  /*
436  * Remove entries that are common to both lists; those represent existing
437  * dependencies we don't need to change.
438  *
439  * OK to overwrite the inputs since we'll pfree them anyway.
440  */
441  getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers);
442 
443  if (noldmembers > 0 || nnewmembers > 0)
444  {
445  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
446 
447  /* Add new dependencies that weren't already present */
448  for (i = 0; i < nnewmembers; i++)
449  {
450  Oid roleid = newmembers[i];
451 
452  /*
453  * Skip the owner: he has an OWNER shdep entry instead. (This is
454  * not just a space optimization; it makes ALTER OWNER easier. See
455  * notes in changeDependencyOnOwner.)
456  */
457  if (roleid == ownerId)
458  continue;
459 
460  /* Skip pinned roles; they don't need dependency entries */
461  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
462  continue;
463 
464  shdepAddDependency(sdepRel, classId, objectId, objsubId,
465  AuthIdRelationId, roleid,
467  }
468 
469  /* Drop no-longer-used old dependencies */
470  for (i = 0; i < noldmembers; i++)
471  {
472  Oid roleid = oldmembers[i];
473 
474  /* Skip the owner, same as above */
475  if (roleid == ownerId)
476  continue;
477 
478  /* Skip pinned roles */
479  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
480  continue;
481 
482  shdepDropDependency(sdepRel, classId, objectId, objsubId,
483  false, /* exact match on objsubId */
484  AuthIdRelationId, roleid,
486  }
487 
488  table_close(sdepRel, RowExclusiveLock);
489  }
490 
491  if (oldmembers)
492  pfree(oldmembers);
493  if (newmembers)
494  pfree(newmembers);
495 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1196
static void getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2)
Definition: pg_shdepend.c:357
static void shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId, int32 objsubId, Oid refclassId, Oid refobjId, SharedDependencyType deptype)
Definition: pg_shdepend.c:930
unsigned int Oid
Definition: postgres_ext.h:31
void pfree(void *pointer)
Definition: mcxt.c:1031
#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:985
int i
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39