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_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/collationcmds.h"
#include "commands/conversioncmds.h"
#include "commands/dbcommands.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 "miscadmin.h"
#include "storage/lmgr.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 69 of file pg_shdepend.c.

Function Documentation

◆ changeDependencyOnOwner()

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

Definition at line 309 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().

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

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

◆ classIdGetDbId()

static Oid classIdGetDbId ( Oid  classId)
static

Definition at line 1088 of file pg_shdepend.c.

References InvalidOid, IsSharedRelation(), and MyDatabaseId.

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

1089 {
1090  Oid dbId;
1091 
1092  if (IsSharedRelation(classId))
1093  dbId = InvalidOid;
1094  else
1095  dbId = MyDatabaseId;
1096 
1097  return dbId;
1098 }
unsigned int Oid
Definition: postgres_ext.h:31
Oid MyDatabaseId
Definition: globals.c:85
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:236
#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(), 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(), SharedDependDependerIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TupleTableSlot::tts_values, and TTSOpsHeapTuple.

Referenced by createdb().

797 {
798  Relation sdepRel;
799  TupleDesc sdepDesc;
800  ScanKeyData key[1];
801  SysScanDesc scan;
802  HeapTuple tup;
803  CatalogIndexState indstate;
804  TupleTableSlot **slot;
805  int max_slots,
806  slot_init_count,
807  slot_stored_count;
808 
809  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
810  sdepDesc = RelationGetDescr(sdepRel);
811 
812  /*
813  * Allocate the slots to use, but delay costly initialization until we
814  * know that they will be used.
815  */
817  slot = palloc(sizeof(TupleTableSlot *) * max_slots);
818 
819  indstate = CatalogOpenIndexes(sdepRel);
820 
821  /* Scan all entries with dbid = templateDbId */
822  ScanKeyInit(&key[0],
823  Anum_pg_shdepend_dbid,
824  BTEqualStrategyNumber, F_OIDEQ,
825  ObjectIdGetDatum(templateDbId));
826 
827  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
828  NULL, 1, key);
829 
830  /* number of slots currently storing tuples */
831  slot_stored_count = 0;
832  /* number of slots currently initialized */
833  slot_init_count = 0;
834 
835  /*
836  * Copy the entries of the original database, changing the database Id to
837  * that of the new database. Note that because we are not copying rows
838  * with dbId == 0 (ie, rows describing dependent shared objects) we won't
839  * copy the ownership dependency of the template database itself; this is
840  * what we want.
841  */
842  while (HeapTupleIsValid(tup = systable_getnext(scan)))
843  {
844  Form_pg_shdepend shdep;
845 
846  if (slot_init_count < max_slots)
847  {
848  slot[slot_stored_count] = MakeSingleTupleTableSlot(sdepDesc, &TTSOpsHeapTuple);
849  slot_init_count++;
850  }
851 
852  ExecClearTuple(slot[slot_stored_count]);
853 
854  shdep = (Form_pg_shdepend) GETSTRUCT(tup);
855 
856  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_dbid] = ObjectIdGetDatum(newDbId);
857  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_classid] = shdep->classid;
858  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objid] = shdep->objid;
859  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objsubid] = shdep->objsubid;
860  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refclassid] = shdep->refclassid;
861  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refobjid] = shdep->refobjid;
862  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_deptype] = shdep->deptype;
863 
864  ExecStoreVirtualTuple(slot[slot_stored_count]);
865  slot_stored_count++;
866 
867  /* If slots are full, insert a batch of tuples */
868  if (slot_stored_count == max_slots)
869  {
870  CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
871  slot_stored_count = 0;
872  }
873  }
874 
875  /* Insert any tuples left in the buffer */
876  if (slot_stored_count > 0)
877  CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
878 
879  systable_endscan(scan);
880 
881  CatalogCloseIndexes(indstate);
882  table_close(sdepRel, RowExclusiveLock);
883 
884  /* Drop only the number of slots used */
885  for (int i = 0; i < slot_init_count; i++)
887  pfree(slot);
888 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
#define RelationGetDescr(relation)
Definition: rel.h:483
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1208
#define MAX_CATALOG_MULTI_INSERT_BYTES
Definition: indexing.h:33
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
Datum * tts_values
Definition: tuptable.h:126
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
Definition: indexing.c:261
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1224
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_shdepend
Definition: pg_shdepend.h:63
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:43
void * palloc(Size size)
Definition: mcxt.c:950
int i
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:61
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define SharedDependDependerIndexId
Definition: pg_shdepend.h:73
#define BTEqualStrategyNumber
Definition: stratnum.h:31
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1522

◆ deleteSharedDependencyRecordsFor()

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

Definition at line 945 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().

946 {
947  Relation sdepRel;
948 
949  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
950 
951  shdepDropDependency(sdepRel, classId, objectId, objectSubId,
952  (objectSubId == 0),
955 
956  table_close(sdepRel, RowExclusiveLock);
957 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#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:1022
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 897 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().

898 {
899  Relation sdepRel;
900  ScanKeyData key[1];
901  SysScanDesc scan;
902  HeapTuple tup;
903 
904  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
905 
906  /*
907  * First, delete all the entries that have the database Oid in the dbid
908  * field.
909  */
910  ScanKeyInit(&key[0],
911  Anum_pg_shdepend_dbid,
912  BTEqualStrategyNumber, F_OIDEQ,
913  ObjectIdGetDatum(databaseId));
914  /* We leave the other index fields unspecified */
915 
916  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
917  NULL, 1, key);
918 
919  while (HeapTupleIsValid(tup = systable_getnext(scan)))
920  {
921  CatalogTupleDelete(sdepRel, &tup->t_self);
922  }
923 
924  systable_endscan(scan);
925 
926  /* Now delete all entries corresponding to the database itself */
927  shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
930 
931  table_close(sdepRel, RowExclusiveLock);
932 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#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:1022
#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 SharedDependDependerIndexId
Definition: pg_shdepend.h:73
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ getOidListDiff()

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

Definition at line 356 of file pg_shdepend.c.

Referenced by updateAclDependencies().

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

◆ isSharedObjectPinned()

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

Definition at line 1233 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().

1234 {
1235  bool result = false;
1236  ScanKeyData key[2];
1237  SysScanDesc scan;
1238  HeapTuple tup;
1239 
1240  ScanKeyInit(&key[0],
1241  Anum_pg_shdepend_refclassid,
1242  BTEqualStrategyNumber, F_OIDEQ,
1243  ObjectIdGetDatum(classId));
1244  ScanKeyInit(&key[1],
1245  Anum_pg_shdepend_refobjid,
1246  BTEqualStrategyNumber, F_OIDEQ,
1247  ObjectIdGetDatum(objectId));
1248 
1249  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1250  NULL, 2, key);
1251 
1252  /*
1253  * Since we won't generate additional pg_shdepend entries for pinned
1254  * objects, there can be at most one entry referencing a pinned object.
1255  * Hence, it's sufficient to look at the first returned tuple; we don't
1256  * need to loop.
1257  */
1258  tup = systable_getnext(scan);
1259  if (HeapTupleIsValid(tup))
1260  {
1261  Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1262 
1263  if (shdepForm->deptype == SHARED_DEPENDENCY_PIN)
1264  result = true;
1265  }
1266 
1267  systable_endscan(scan);
1268 
1269  return result;
1270 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#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:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define SharedDependReferenceIndexId
Definition: pg_shdepend.h:75
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ recordDependencyOnOwner()

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

Definition at line 164 of file pg_shdepend.c.

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

Referenced by CollationCreate(), ConversionCreate(), createdb(), CreateForeignDataWrapper(), CreateForeignServer(), CreateOpFamily(), CreateProceduralLanguage(), 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().

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

◆ recordSharedDependencyOn()

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

Definition at line 120 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().

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

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

Referenced by checkSharedDependencies().

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

◆ shdepAddDependency()

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

Definition at line 967 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().

971 {
972  HeapTuple tup;
973  Datum values[Natts_pg_shdepend];
974  bool nulls[Natts_pg_shdepend];
975 
976  /*
977  * Make sure the object doesn't go away while we record the dependency on
978  * it. DROP routines should lock the object exclusively before they check
979  * shared dependencies.
980  */
981  shdepLockAndCheckObject(refclassId, refobjId);
982 
983  memset(nulls, false, sizeof(nulls));
984 
985  /*
986  * Form the new tuple and record the dependency.
987  */
988  values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId));
989  values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId);
990  values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId);
991  values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId);
992 
993  values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId);
994  values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId);
995  values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
996 
997  tup = heap_form_tuple(sdepRel->rd_att, values, nulls);
998 
999  CatalogTupleInsert(sdepRel, tup);
1000 
1001  /* clean up */
1002  heap_freetuple(tup);
1003 }
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:1109
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:111
static Oid classIdGetDbId(Oid classId)
Definition: pg_shdepend.c:1088
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define Int32GetDatum(X)
Definition: postgres.h:479
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ shdepChangeDep()

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

Definition at line 199 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().

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

1027 {
1028  ScanKeyData key[4];
1029  int nkeys;
1030  SysScanDesc scan;
1031  HeapTuple tup;
1032 
1033  /* Scan for entries matching the dependent object */
1034  ScanKeyInit(&key[0],
1035  Anum_pg_shdepend_dbid,
1036  BTEqualStrategyNumber, F_OIDEQ,
1037  ObjectIdGetDatum(classIdGetDbId(classId)));
1038  ScanKeyInit(&key[1],
1039  Anum_pg_shdepend_classid,
1040  BTEqualStrategyNumber, F_OIDEQ,
1041  ObjectIdGetDatum(classId));
1042  ScanKeyInit(&key[2],
1043  Anum_pg_shdepend_objid,
1044  BTEqualStrategyNumber, F_OIDEQ,
1045  ObjectIdGetDatum(objectId));
1046  if (drop_subobjects)
1047  nkeys = 3;
1048  else
1049  {
1050  ScanKeyInit(&key[3],
1051  Anum_pg_shdepend_objsubid,
1052  BTEqualStrategyNumber, F_INT4EQ,
1053  Int32GetDatum(objsubId));
1054  nkeys = 4;
1055  }
1056 
1057  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
1058  NULL, nkeys, key);
1059 
1060  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1061  {
1062  Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
1063 
1064  /* Filter entries according to additional parameters */
1065  if (OidIsValid(refclassId) && shdepForm->refclassid != refclassId)
1066  continue;
1067  if (OidIsValid(refobjId) && shdepForm->refobjid != refobjId)
1068  continue;
1069  if (deptype != SHARED_DEPENDENCY_INVALID &&
1070  shdepForm->deptype != deptype)
1071  continue;
1072 
1073  /* OK, delete it */
1074  CatalogTupleDelete(sdepRel, &tup->t_self);
1075  }
1076 
1077  systable_endscan(scan);
1078 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define OidIsValid(objectId)
Definition: c.h:706
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#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:1088
#define Int32GetDatum(X)
Definition: postgres.h:479
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define SharedDependDependerIndexId
Definition: pg_shdepend.h:73
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ shdepDropOwned()

void shdepDropOwned ( List roleids,
DropBehavior  behavior 
)

Definition at line 1285 of file pg_shdepend.c.

References AcquireDeletionLock(), 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(), ReleaseDeletionLock(), 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(), systable_recheck_tuple(), table_close(), and table_open().

Referenced by DropOwnedObjects().

1286 {
1287  Relation sdepRel;
1288  ListCell *cell;
1289  ObjectAddresses *deleteobjs;
1290 
1291  deleteobjs = new_object_addresses();
1292 
1293  /*
1294  * We don't need this strong a lock here, but we'll call routines that
1295  * acquire RowExclusiveLock. Better get that right now to avoid potential
1296  * deadlock failures.
1297  */
1298  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1299 
1300  /*
1301  * For each role, find the dependent objects and drop them using the
1302  * regular (non-shared) dependency management.
1303  */
1304  foreach(cell, roleids)
1305  {
1306  Oid roleid = lfirst_oid(cell);
1307  ScanKeyData key[2];
1308  SysScanDesc scan;
1309  HeapTuple tuple;
1310 
1311  /* Doesn't work for pinned objects */
1312  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
1313  {
1314  ObjectAddress obj;
1315 
1316  obj.classId = AuthIdRelationId;
1317  obj.objectId = roleid;
1318  obj.objectSubId = 0;
1319 
1320  ereport(ERROR,
1321  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1322  errmsg("cannot drop objects owned by %s because they are "
1323  "required by the database system",
1324  getObjectDescription(&obj, false))));
1325  }
1326 
1327  ScanKeyInit(&key[0],
1328  Anum_pg_shdepend_refclassid,
1329  BTEqualStrategyNumber, F_OIDEQ,
1330  ObjectIdGetDatum(AuthIdRelationId));
1331  ScanKeyInit(&key[1],
1332  Anum_pg_shdepend_refobjid,
1333  BTEqualStrategyNumber, F_OIDEQ,
1334  ObjectIdGetDatum(roleid));
1335 
1336  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1337  NULL, 2, key);
1338 
1339  while ((tuple = systable_getnext(scan)) != NULL)
1340  {
1341  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1342  ObjectAddress obj;
1343 
1344  /*
1345  * We only operate on shared objects and objects in the current
1346  * database
1347  */
1348  if (sdepForm->dbid != MyDatabaseId &&
1349  sdepForm->dbid != InvalidOid)
1350  continue;
1351 
1352  switch (sdepForm->deptype)
1353  {
1354  /* Shouldn't happen */
1355  case SHARED_DEPENDENCY_PIN:
1357  elog(ERROR, "unexpected dependency type");
1358  break;
1359  case SHARED_DEPENDENCY_ACL:
1360  RemoveRoleFromObjectACL(roleid,
1361  sdepForm->classid,
1362  sdepForm->objid);
1363  break;
1365 
1366  /*
1367  * Try to remove role from policy; if unable to, remove
1368  * policy.
1369  */
1370  if (!RemoveRoleFromObjectPolicy(roleid,
1371  sdepForm->classid,
1372  sdepForm->objid))
1373  {
1374  obj.classId = sdepForm->classid;
1375  obj.objectId = sdepForm->objid;
1376  obj.objectSubId = sdepForm->objsubid;
1377 
1378  /*
1379  * Acquire lock on object, then verify this dependency
1380  * is still relevant. If not, the object might have
1381  * been dropped or the policy modified. Ignore the
1382  * object in that case.
1383  */
1384  AcquireDeletionLock(&obj, 0);
1385  if (!systable_recheck_tuple(scan, tuple))
1386  {
1387  ReleaseDeletionLock(&obj);
1388  break;
1389  }
1390  add_exact_object_address(&obj, deleteobjs);
1391  }
1392  break;
1394  /* If a local object, save it for deletion below */
1395  if (sdepForm->dbid == MyDatabaseId)
1396  {
1397  obj.classId = sdepForm->classid;
1398  obj.objectId = sdepForm->objid;
1399  obj.objectSubId = sdepForm->objsubid;
1400  /* as above */
1401  AcquireDeletionLock(&obj, 0);
1402  if (!systable_recheck_tuple(scan, tuple))
1403  {
1404  ReleaseDeletionLock(&obj);
1405  break;
1406  }
1407  add_exact_object_address(&obj, deleteobjs);
1408  }
1409  break;
1410  }
1411  }
1412 
1413  systable_endscan(scan);
1414  }
1415 
1416  /*
1417  * For stability of deletion-report ordering, sort the objects into
1418  * approximate reverse creation order before deletion. (This might also
1419  * make the deletion go a bit faster, since there's less chance of having
1420  * to rearrange the objects due to dependencies.)
1421  */
1422  sort_object_addresses(deleteobjs);
1423 
1424  /* the dependency mechanism does the actual work */
1425  performMultipleDeletions(deleteobjs, behavior, 0);
1426 
1427  table_close(sdepRel, RowExclusiveLock);
1428 
1429  free_object_addresses(deleteobjs);
1430 }
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
Definition: pg_shdepend.c:1233
void sort_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2823
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:70
void ReleaseDeletionLock(const ObjectAddress *object)
Definition: dependency.c:1632
int errcode(int sqlerrcode)
Definition: elog.c:691
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2594
void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
Definition: aclchk.c:1377
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2539
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2835
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:357
bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
Definition: genam.c:535
bool RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
Definition: policy.c:419
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define SharedDependReferenceIndexId
Definition: pg_shdepend.h:75
#define RowExclusiveLock
Definition: lockdefs.h:38
void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1603
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define elog(elevel,...)
Definition: elog.h:228
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:372
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:171

◆ shdepLockAndCheckObject()

void shdepLockAndCheckObject ( Oid  classId,
Oid  objectId 
)

Definition at line 1109 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().

1110 {
1111  /* AccessShareLock should be OK, since we are not modifying the object */
1112  LockSharedObject(classId, objectId, 0, AccessShareLock);
1113 
1114  switch (classId)
1115  {
1116  case AuthIdRelationId:
1118  ereport(ERROR,
1119  (errcode(ERRCODE_UNDEFINED_OBJECT),
1120  errmsg("role %u was concurrently dropped",
1121  objectId)));
1122  break;
1123 
1124  /*
1125  * Currently, this routine need not support any other shared
1126  * object types besides roles. If we wanted to record explicit
1127  * dependencies on databases or tablespaces, we'd need code along
1128  * these lines:
1129  */
1130 #ifdef NOT_USED
1131  case TableSpaceRelationId:
1132  {
1133  /* For lack of a syscache on pg_tablespace, do this: */
1134  char *tablespace = get_tablespace_name(objectId);
1135 
1136  if (tablespace == NULL)
1137  ereport(ERROR,
1138  (errcode(ERRCODE_UNDEFINED_OBJECT),
1139  errmsg("tablespace %u was concurrently dropped",
1140  objectId)));
1141  pfree(tablespace);
1142  break;
1143  }
1144 #endif
1145 
1146  case DatabaseRelationId:
1147  {
1148  /* For lack of a syscache on pg_database, do this: */
1149  char *database = get_database_name(objectId);
1150 
1151  if (database == NULL)
1152  ereport(ERROR,
1153  (errcode(ERRCODE_UNDEFINED_OBJECT),
1154  errmsg("database %u was concurrently dropped",
1155  objectId)));
1156  pfree(database);
1157  break;
1158  }
1159 
1160 
1161  default:
1162  elog(ERROR, "unrecognized shared classId: %u", classId);
1163  }
1164 }
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:691
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:183
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
char * tablespace
Definition: pgbench.c:189
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1017
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:902
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1467
#define elog(elevel,...)
Definition: elog.h:228

◆ shdepReassignOwned()

void shdepReassignOwned ( List roleids,
Oid  newrole 
)

Definition at line 1439 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().

1440 {
1441  Relation sdepRel;
1442  ListCell *cell;
1443 
1444  /*
1445  * We don't need this strong a lock here, but we'll call routines that
1446  * acquire RowExclusiveLock. Better get that right now to avoid potential
1447  * deadlock problems.
1448  */
1449  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1450 
1451  foreach(cell, roleids)
1452  {
1453  SysScanDesc scan;
1454  ScanKeyData key[2];
1455  HeapTuple tuple;
1456  Oid roleid = lfirst_oid(cell);
1457 
1458  /* Refuse to work on pinned roles */
1459  if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
1460  {
1461  ObjectAddress obj;
1462 
1463  obj.classId = AuthIdRelationId;
1464  obj.objectId = roleid;
1465  obj.objectSubId = 0;
1466 
1467  ereport(ERROR,
1468  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1469  errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system",
1470  getObjectDescription(&obj, false))));
1471 
1472  /*
1473  * There's no need to tell the whole truth, which is that we
1474  * didn't track these dependencies at all ...
1475  */
1476  }
1477 
1478  ScanKeyInit(&key[0],
1479  Anum_pg_shdepend_refclassid,
1480  BTEqualStrategyNumber, F_OIDEQ,
1481  ObjectIdGetDatum(AuthIdRelationId));
1482  ScanKeyInit(&key[1],
1483  Anum_pg_shdepend_refobjid,
1484  BTEqualStrategyNumber, F_OIDEQ,
1485  ObjectIdGetDatum(roleid));
1486 
1487  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1488  NULL, 2, key);
1489 
1490  while ((tuple = systable_getnext(scan)) != NULL)
1491  {
1492  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1493 
1494  /*
1495  * We only operate on shared objects and objects in the current
1496  * database
1497  */
1498  if (sdepForm->dbid != MyDatabaseId &&
1499  sdepForm->dbid != InvalidOid)
1500  continue;
1501 
1502  /* Unexpected because we checked for pins above */
1503  if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
1504  elog(ERROR, "unexpected shared pin");
1505 
1506  /* We leave non-owner dependencies alone */
1507  if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
1508  continue;
1509 
1510  /* Issue the appropriate ALTER OWNER call */
1511  switch (sdepForm->classid)
1512  {
1513  case TypeRelationId:
1514  AlterTypeOwner_oid(sdepForm->objid, newrole, true);
1515  break;
1516 
1517  case NamespaceRelationId:
1518  AlterSchemaOwner_oid(sdepForm->objid, newrole);
1519  break;
1520 
1521  case RelationRelationId:
1522 
1523  /*
1524  * Pass recursing = true so that we don't fail on indexes,
1525  * owned sequences, etc when we happen to visit them
1526  * before their parent table.
1527  */
1528  ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
1529  break;
1530 
1531  case DefaultAclRelationId:
1532 
1533  /*
1534  * Ignore default ACLs; they should be handled by DROP
1535  * OWNED, not REASSIGN OWNED.
1536  */
1537  break;
1538 
1539  case UserMappingRelationId:
1540  /* ditto */
1541  break;
1542 
1543  case ForeignServerRelationId:
1544  AlterForeignServerOwner_oid(sdepForm->objid, newrole);
1545  break;
1546 
1547  case ForeignDataWrapperRelationId:
1548  AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
1549  break;
1550 
1551  case EventTriggerRelationId:
1552  AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
1553  break;
1554 
1555  case PublicationRelationId:
1556  AlterPublicationOwner_oid(sdepForm->objid, newrole);
1557  break;
1558 
1559  case SubscriptionRelationId:
1560  AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
1561  break;
1562 
1563  /* Generic alter owner cases */
1564  case CollationRelationId:
1565  case ConversionRelationId:
1566  case OperatorRelationId:
1567  case ProcedureRelationId:
1568  case LanguageRelationId:
1569  case LargeObjectRelationId:
1570  case OperatorFamilyRelationId:
1571  case OperatorClassRelationId:
1572  case ExtensionRelationId:
1573  case StatisticExtRelationId:
1574  case TableSpaceRelationId:
1575  case DatabaseRelationId:
1576  case TSConfigRelationId:
1577  case TSDictionaryRelationId:
1578  {
1579  Oid classId = sdepForm->classid;
1580  Relation catalog;
1581 
1582  if (classId == LargeObjectRelationId)
1583  classId = LargeObjectMetadataRelationId;
1584 
1585  catalog = table_open(classId, RowExclusiveLock);
1586 
1587  AlterObjectOwner_internal(catalog, sdepForm->objid,
1588  newrole);
1589 
1590  table_close(catalog, NoLock);
1591  }
1592  break;
1593 
1594  default:
1595  elog(ERROR, "unexpected classid %u", sdepForm->classid);
1596  break;
1597  }
1598  /* Make sure the next iteration will see my changes */
1600  }
1601 
1602  systable_endscan(scan);
1603  }
1604 
1605  table_close(sdepRel, RowExclusiveLock);
1606 }
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#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:1233
void AlterSchemaOwner_oid(Oid oid, Oid newOwnerId)
Definition: schemacmds.c:276
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:691
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:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define SharedDependReferenceIndexId
Definition: pg_shdepend.h:75
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3363
void AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
Definition: alter.c:934
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
Definition: tablecmds.c:12514
void CommandCounterIncrement(void)
Definition: xact.c:1021
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
void AlterEventTriggerOwner_oid(Oid trigOid, Oid newOwnerId)
#define ereport(elevel,...)
Definition: elog.h:155
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define elog(elevel,...)
Definition: elog.h:228
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)
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:171

◆ storeObjectDescription()

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

Definition at line 1182 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().

1187 {
1188  char *objdesc = getObjectDescription(object, false);
1189 
1190  /* separate entries with a newline */
1191  if (descs->len != 0)
1192  appendStringInfoChar(descs, '\n');
1193 
1194  switch (type)
1195  {
1196  case LOCAL_OBJECT:
1197  case SHARED_OBJECT:
1198  if (deptype == SHARED_DEPENDENCY_OWNER)
1199  appendStringInfo(descs, _("owner of %s"), objdesc);
1200  else if (deptype == SHARED_DEPENDENCY_ACL)
1201  appendStringInfo(descs, _("privileges for %s"), objdesc);
1202  else if (deptype == SHARED_DEPENDENCY_POLICY)
1203  appendStringInfo(descs, _("target of %s"), objdesc);
1204  else
1205  elog(ERROR, "unrecognized dependency type: %d",
1206  (int) deptype);
1207  break;
1208 
1209  case REMOTE_OBJECT:
1210  /* translator: %s will always be "database %s" */
1211  appendStringInfo(descs, ngettext("%d object in %s",
1212  "%d objects in %s",
1213  count),
1214  count, objdesc);
1215  break;
1216 
1217  default:
1218  elog(ERROR, "unrecognized object type: %d", type);
1219  }
1220 
1221  pfree(objdesc);
1222 }
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ERROR
Definition: elog.h:43
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define ngettext(s, p, n)
Definition: c.h:1178
#define elog(elevel,...)
Definition: elog.h:228
#define _(x)
Definition: elog.c:88

◆ updateAclDependencies()

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

Definition at line 426 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().

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