PostgreSQL Source Code  git master
dependency.h File Reference
Include dependency graph for dependency.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define PERFORM_DELETION_INTERNAL   0x0001 /* internal action */
 
#define PERFORM_DELETION_CONCURRENTLY   0x0002 /* concurrent drop */
 
#define PERFORM_DELETION_QUIETLY   0x0004 /* suppress notices */
 
#define PERFORM_DELETION_SKIP_ORIGINAL   0x0008 /* keep original obj */
 
#define PERFORM_DELETION_SKIP_EXTENSIONS   0x0010 /* keep extensions */
 
#define PERFORM_DELETION_CONCURRENT_LOCK
 

Typedefs

typedef enum DependencyType DependencyType
 
typedef enum SharedDependencyType SharedDependencyType
 
typedef struct ObjectAddresses ObjectAddresses
 

Enumerations

enum  DependencyType {
  DEPENDENCY_NORMAL = 'n' , DEPENDENCY_AUTO = 'a' , DEPENDENCY_INTERNAL = 'i' , DEPENDENCY_PARTITION_PRI = 'P' ,
  DEPENDENCY_PARTITION_SEC = 'S' , DEPENDENCY_EXTENSION = 'e' , DEPENDENCY_AUTO_EXTENSION = 'x'
}
 
enum  SharedDependencyType {
  SHARED_DEPENDENCY_OWNER = 'o' , SHARED_DEPENDENCY_ACL = 'a' , SHARED_DEPENDENCY_INITACL = 'i' , SHARED_DEPENDENCY_POLICY = 'r' ,
  SHARED_DEPENDENCY_TABLESPACE = 't' , SHARED_DEPENDENCY_INVALID = 0
}
 

Functions

void AcquireDeletionLock (const ObjectAddress *object, int flags)
 
void ReleaseDeletionLock (const ObjectAddress *object)
 
void performDeletion (const ObjectAddress *object, DropBehavior behavior, int flags)
 
void performMultipleDeletions (const ObjectAddresses *objects, DropBehavior behavior, int flags)
 
void recordDependencyOnExpr (const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
 
void recordDependencyOnSingleRelExpr (const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
 
ObjectAddressesnew_object_addresses (void)
 
void add_exact_object_address (const ObjectAddress *object, ObjectAddresses *addrs)
 
bool object_address_present (const ObjectAddress *object, const ObjectAddresses *addrs)
 
void record_object_address_dependencies (const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
 
void sort_object_addresses (ObjectAddresses *addrs)
 
void free_object_addresses (ObjectAddresses *addrs)
 
void recordDependencyOn (const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
 
void recordMultipleDependencies (const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
 
void recordDependencyOnCurrentExtension (const ObjectAddress *object, bool isReplace)
 
void checkMembershipInCurrentExtension (const ObjectAddress *object)
 
long deleteDependencyRecordsFor (Oid classId, Oid objectId, bool skipExtensionDeps)
 
long deleteDependencyRecordsForClass (Oid classId, Oid objectId, Oid refclassId, char deptype)
 
long deleteDependencyRecordsForSpecific (Oid classId, Oid objectId, char deptype, Oid refclassId, Oid refobjectId)
 
long changeDependencyFor (Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
 
long changeDependenciesOf (Oid classId, Oid oldObjectId, Oid newObjectId)
 
long changeDependenciesOn (Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
 
Oid getExtensionOfObject (Oid classId, Oid objectId)
 
ListgetAutoExtensionsOfObject (Oid classId, Oid objectId)
 
bool sequenceIsOwned (Oid seqId, char deptype, Oid *tableId, int32 *colId)
 
ListgetOwnedSequences (Oid relid)
 
Oid getIdentitySequence (Relation rel, AttrNumber attnum, bool missing_ok)
 
Oid get_index_constraint (Oid indexId)
 
Listget_index_ref_constraints (Oid indexId)
 
void recordSharedDependencyOn (ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
 
void deleteSharedDependencyRecordsFor (Oid classId, Oid objectId, int32 objectSubId)
 
void recordDependencyOnOwner (Oid classId, Oid objectId, Oid owner)
 
void changeDependencyOnOwner (Oid classId, Oid objectId, Oid newOwnerId)
 
void recordDependencyOnTablespace (Oid classId, Oid objectId, Oid tablespace)
 
void changeDependencyOnTablespace (Oid classId, Oid objectId, Oid newTablespaceId)
 
void updateAclDependencies (Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
 
void updateInitAclDependencies (Oid classId, Oid objectId, int32 objsubId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
 
bool checkSharedDependencies (Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
 
void shdepLockAndCheckObject (Oid classId, Oid objectId)
 
void copyTemplateDependencies (Oid templateDbId, Oid newDbId)
 
void dropDatabaseDependencies (Oid databaseId)
 
void shdepDropOwned (List *roleids, DropBehavior behavior)
 
void shdepReassignOwned (List *roleids, Oid newrole)
 

Macro Definition Documentation

◆ PERFORM_DELETION_CONCURRENT_LOCK

#define PERFORM_DELETION_CONCURRENT_LOCK
Value:
0x0020 /* normal drop with
* concurrent lock mode */

Definition at line 97 of file dependency.h.

◆ PERFORM_DELETION_CONCURRENTLY

#define PERFORM_DELETION_CONCURRENTLY   0x0002 /* concurrent drop */

Definition at line 93 of file dependency.h.

◆ PERFORM_DELETION_INTERNAL

#define PERFORM_DELETION_INTERNAL   0x0001 /* internal action */

Definition at line 92 of file dependency.h.

◆ PERFORM_DELETION_QUIETLY

#define PERFORM_DELETION_QUIETLY   0x0004 /* suppress notices */

Definition at line 94 of file dependency.h.

◆ PERFORM_DELETION_SKIP_EXTENSIONS

#define PERFORM_DELETION_SKIP_EXTENSIONS   0x0010 /* keep extensions */

Definition at line 96 of file dependency.h.

◆ PERFORM_DELETION_SKIP_ORIGINAL

#define PERFORM_DELETION_SKIP_ORIGINAL   0x0008 /* keep original obj */

Definition at line 95 of file dependency.h.

Typedef Documentation

◆ DependencyType

◆ ObjectAddresses

Definition at line 1 of file dependency.h.

◆ SharedDependencyType

Enumeration Type Documentation

◆ DependencyType

Enumerator
DEPENDENCY_NORMAL 
DEPENDENCY_AUTO 
DEPENDENCY_INTERNAL 
DEPENDENCY_PARTITION_PRI 
DEPENDENCY_PARTITION_SEC 
DEPENDENCY_EXTENSION 
DEPENDENCY_AUTO_EXTENSION 

Definition at line 31 of file dependency.h.

32 {
33  DEPENDENCY_NORMAL = 'n',
34  DEPENDENCY_AUTO = 'a',
35  DEPENDENCY_INTERNAL = 'i',
DependencyType
Definition: dependency.h:32
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_AUTO_EXTENSION
Definition: dependency.h:39
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
@ DEPENDENCY_EXTENSION
Definition: dependency.h:38
@ DEPENDENCY_NORMAL
Definition: dependency.h:33

◆ SharedDependencyType

Enumerator
SHARED_DEPENDENCY_OWNER 
SHARED_DEPENDENCY_ACL 
SHARED_DEPENDENCY_INITACL 
SHARED_DEPENDENCY_POLICY 
SHARED_DEPENDENCY_TABLESPACE 
SHARED_DEPENDENCY_INVALID 

Definition at line 78 of file dependency.h.

79 {
SharedDependencyType
Definition: dependency.h:79
@ SHARED_DEPENDENCY_INITACL
Definition: dependency.h:82
@ SHARED_DEPENDENCY_TABLESPACE
Definition: dependency.h:84
@ SHARED_DEPENDENCY_INVALID
Definition: dependency.h:85
@ SHARED_DEPENDENCY_POLICY
Definition: dependency.h:83
@ SHARED_DEPENDENCY_ACL
Definition: dependency.h:81
@ SHARED_DEPENDENCY_OWNER
Definition: dependency.h:80

Function Documentation

◆ AcquireDeletionLock()

void AcquireDeletionLock ( const ObjectAddress object,
int  flags 
)

Definition at line 1496 of file dependency.c.

1497 {
1498  if (object->classId == RelationRelationId)
1499  {
1500  /*
1501  * In DROP INDEX CONCURRENTLY, take only ShareUpdateExclusiveLock on
1502  * the index for the moment. index_drop() will promote the lock once
1503  * it's safe to do so. In all other cases we need full exclusive
1504  * lock.
1505  */
1506  if (flags & PERFORM_DELETION_CONCURRENTLY)
1508  else
1510  }
1511  else if (object->classId == AuthMemRelationId)
1512  LockSharedObject(object->classId, object->objectId, 0,
1514  else
1515  {
1516  /* assume we should lock the whole object not a sub-object */
1517  LockDatabaseObject(object->classId, object->objectId, 0,
1519  }
1520 }
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:93
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1073
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:994
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108
#define AccessExclusiveLock
Definition: lockdefs.h:43
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39

References AccessExclusiveLock, ObjectAddress::classId, ObjectAddressStack::flags, LockDatabaseObject(), LockRelationOid(), LockSharedObject(), ObjectAddressStack::object, ObjectAddress::objectId, PERFORM_DELETION_CONCURRENTLY, and ShareUpdateExclusiveLock.

Referenced by findDependentObjects(), performDeletion(), performMultipleDeletions(), and shdepDropOwned().

◆ add_exact_object_address()

void add_exact_object_address ( const ObjectAddress object,
ObjectAddresses addrs 
)

Definition at line 2533 of file dependency.c.

2535 {
2536  ObjectAddress *item;
2537 
2538  /* enlarge array if needed */
2539  if (addrs->numrefs >= addrs->maxrefs)
2540  {
2541  addrs->maxrefs *= 2;
2542  addrs->refs = (ObjectAddress *)
2543  repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2544  Assert(!addrs->extras);
2545  }
2546  /* record this item */
2547  item = addrs->refs + addrs->numrefs;
2548  *item = *object;
2549  addrs->numrefs++;
2550 }
#define Assert(condition)
Definition: c.h:858
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
ObjectAddressExtra * extras
Definition: dependency.c:116
ObjectAddress * refs
Definition: dependency.c:115

References Assert, ObjectAddresses::extras, ObjectAddresses::maxrefs, ObjectAddresses::numrefs, ObjectAddressStack::object, ObjectAddresses::refs, and repalloc().

Referenced by AggregateCreate(), AlterConstraintNamespaces(), AlterIndexNamespaces(), AlterRelationNamespaceInternal(), AlterTypeNamespaceInternal(), ATExecDropColumn(), ATPostAlterTypeCleanup(), CastCreate(), CreateConstraintEntry(), CreateProceduralLanguage(), CreateTransform(), DropClonedTriggersFromPartition(), GenerateTypeDependencies(), heap_create_with_catalog(), index_create(), InsertExtensionTuple(), makeConfigurationDependencies(), makeDictionaryDependencies(), makeOperatorDependencies(), makeParserDependencies(), makeTSTemplateDependencies(), PreCommit_on_commit_actions(), ProcedureCreate(), RangeCreate(), recordDependencyOnSingleRelExpr(), ReindexRelationConcurrently(), RemoveObjects(), RemoveRelations(), shdepDropOwned(), and StorePartitionKey().

◆ changeDependenciesOf()

long changeDependenciesOf ( Oid  classId,
Oid  oldObjectId,
Oid  newObjectId 
)

Definition at line 566 of file pg_depend.c.

568 {
569  long count = 0;
570  Relation depRel;
571  ScanKeyData key[2];
572  SysScanDesc scan;
573  HeapTuple tup;
574 
575  depRel = table_open(DependRelationId, RowExclusiveLock);
576 
577  ScanKeyInit(&key[0],
578  Anum_pg_depend_classid,
579  BTEqualStrategyNumber, F_OIDEQ,
580  ObjectIdGetDatum(classId));
581  ScanKeyInit(&key[1],
582  Anum_pg_depend_objid,
583  BTEqualStrategyNumber, F_OIDEQ,
584  ObjectIdGetDatum(oldObjectId));
585 
586  scan = systable_beginscan(depRel, DependDependerIndexId, true,
587  NULL, 2, key);
588 
589  while (HeapTupleIsValid((tup = systable_getnext(scan))))
590  {
591  Form_pg_depend depform;
592 
593  /* make a modifiable copy */
594  tup = heap_copytuple(tup);
595  depform = (Form_pg_depend) GETSTRUCT(tup);
596 
597  depform->objid = newObjectId;
598 
599  CatalogTupleUpdate(depRel, &tup->t_self, tup);
600 
601  heap_freetuple(tup);
602 
603  count++;
604  }
605 
606  systable_endscan(scan);
607 
608  table_close(depRel, RowExclusiveLock);
609 
610  return count;
611 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:72
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References BTEqualStrategyNumber, CatalogTupleUpdate(), GETSTRUCT, heap_copytuple(), heap_freetuple(), HeapTupleIsValid, sort-test::key, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by index_concurrently_swap().

◆ changeDependenciesOn()

long changeDependenciesOn ( Oid  refClassId,
Oid  oldRefObjectId,
Oid  newRefObjectId 
)

Definition at line 622 of file pg_depend.c.

624 {
625  long count = 0;
626  Relation depRel;
627  ScanKeyData key[2];
628  SysScanDesc scan;
629  HeapTuple tup;
630  ObjectAddress objAddr;
631  bool newIsPinned;
632 
633  depRel = table_open(DependRelationId, RowExclusiveLock);
634 
635  /*
636  * If oldRefObjectId is pinned, there won't be any dependency entries on
637  * it --- we can't cope in that case. (This isn't really worth expending
638  * code to fix, in current usage; it just means you can't rename stuff out
639  * of pg_catalog, which would likely be a bad move anyway.)
640  */
641  objAddr.classId = refClassId;
642  objAddr.objectId = oldRefObjectId;
643  objAddr.objectSubId = 0;
644 
645  if (isObjectPinned(&objAddr))
646  ereport(ERROR,
647  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
648  errmsg("cannot remove dependency on %s because it is a system object",
649  getObjectDescription(&objAddr, false))));
650 
651  /*
652  * We can handle adding a dependency on something pinned, though, since
653  * that just means deleting the dependency entry.
654  */
655  objAddr.objectId = newRefObjectId;
656 
657  newIsPinned = isObjectPinned(&objAddr);
658 
659  /* Now search for dependency records */
660  ScanKeyInit(&key[0],
661  Anum_pg_depend_refclassid,
662  BTEqualStrategyNumber, F_OIDEQ,
663  ObjectIdGetDatum(refClassId));
664  ScanKeyInit(&key[1],
665  Anum_pg_depend_refobjid,
666  BTEqualStrategyNumber, F_OIDEQ,
667  ObjectIdGetDatum(oldRefObjectId));
668 
669  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
670  NULL, 2, key);
671 
672  while (HeapTupleIsValid((tup = systable_getnext(scan))))
673  {
674  if (newIsPinned)
675  CatalogTupleDelete(depRel, &tup->t_self);
676  else
677  {
678  Form_pg_depend depform;
679 
680  /* make a modifiable copy */
681  tup = heap_copytuple(tup);
682  depform = (Form_pg_depend) GETSTRUCT(tup);
683 
684  depform->refobjid = newRefObjectId;
685 
686  CatalogTupleUpdate(depRel, &tup->t_self, tup);
687 
688  heap_freetuple(tup);
689  }
690 
691  count++;
692  }
693 
694  systable_endscan(scan);
695 
696  table_close(depRel, RowExclusiveLock);
697 
698  return count;
699 }
int errcode(int sqlerrcode)
Definition: elog.c:855
int errmsg(const char *fmt,...)
Definition: elog.c:1068
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
static bool isObjectPinned(const ObjectAddress *object)
Definition: pg_depend.c:710

References BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), ObjectAddress::classId, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, heap_copytuple(), heap_freetuple(), HeapTupleIsValid, isObjectPinned(), sort-test::key, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by index_concurrently_swap().

◆ changeDependencyFor()

long changeDependencyFor ( Oid  classId,
Oid  objectId,
Oid  refClassId,
Oid  oldRefObjectId,
Oid  newRefObjectId 
)

Definition at line 458 of file pg_depend.c.

461 {
462  long count = 0;
463  Relation depRel;
464  ScanKeyData key[2];
465  SysScanDesc scan;
466  HeapTuple tup;
467  ObjectAddress objAddr;
468  ObjectAddress depAddr;
469  bool oldIsPinned;
470  bool newIsPinned;
471 
472  /*
473  * Check to see if either oldRefObjectId or newRefObjectId is pinned.
474  * Pinned objects should not have any dependency entries pointing to them,
475  * so in these cases we should add or remove a pg_depend entry, or do
476  * nothing at all, rather than update an entry as in the normal case.
477  */
478  objAddr.classId = refClassId;
479  objAddr.objectId = oldRefObjectId;
480  objAddr.objectSubId = 0;
481 
482  oldIsPinned = isObjectPinned(&objAddr);
483 
484  objAddr.objectId = newRefObjectId;
485 
486  newIsPinned = isObjectPinned(&objAddr);
487 
488  if (oldIsPinned)
489  {
490  /*
491  * If both are pinned, we need do nothing. However, return 1 not 0,
492  * else callers will think this is an error case.
493  */
494  if (newIsPinned)
495  return 1;
496 
497  /*
498  * There is no old dependency record, but we should insert a new one.
499  * Assume a normal dependency is wanted.
500  */
501  depAddr.classId = classId;
502  depAddr.objectId = objectId;
503  depAddr.objectSubId = 0;
504  recordDependencyOn(&depAddr, &objAddr, DEPENDENCY_NORMAL);
505 
506  return 1;
507  }
508 
509  depRel = table_open(DependRelationId, RowExclusiveLock);
510 
511  /* There should be existing dependency record(s), so search. */
512  ScanKeyInit(&key[0],
513  Anum_pg_depend_classid,
514  BTEqualStrategyNumber, F_OIDEQ,
515  ObjectIdGetDatum(classId));
516  ScanKeyInit(&key[1],
517  Anum_pg_depend_objid,
518  BTEqualStrategyNumber, F_OIDEQ,
519  ObjectIdGetDatum(objectId));
520 
521  scan = systable_beginscan(depRel, DependDependerIndexId, true,
522  NULL, 2, key);
523 
524  while (HeapTupleIsValid((tup = systable_getnext(scan))))
525  {
526  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
527 
528  if (depform->refclassid == refClassId &&
529  depform->refobjid == oldRefObjectId)
530  {
531  if (newIsPinned)
532  CatalogTupleDelete(depRel, &tup->t_self);
533  else
534  {
535  /* make a modifiable copy */
536  tup = heap_copytuple(tup);
537  depform = (Form_pg_depend) GETSTRUCT(tup);
538 
539  depform->refobjid = newRefObjectId;
540 
541  CatalogTupleUpdate(depRel, &tup->t_self, tup);
542 
543  heap_freetuple(tup);
544  }
545 
546  count++;
547  }
548  }
549 
550  systable_endscan(scan);
551 
552  table_close(depRel, RowExclusiveLock);
553 
554  return count;
555 }
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46

References BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), ObjectAddress::classId, DEPENDENCY_NORMAL, GETSTRUCT, heap_copytuple(), heap_freetuple(), HeapTupleIsValid, isObjectPinned(), sort-test::key, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, recordDependencyOn(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by AlterExtensionNamespace(), AlterFunction(), AlterObjectNamespace_internal(), AlterRelationNamespaceInternal(), AlterTypeNamespaceInternal(), ATExecSetAccessMethodNoStorage(), and swap_relation_files().

◆ changeDependencyOnOwner()

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

Definition at line 316 of file pg_shdepend.c.

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

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

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

◆ changeDependencyOnTablespace()

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

Definition at line 391 of file pg_shdepend.c.

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

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

Referenced by SetRelationTableSpace().

◆ checkMembershipInCurrentExtension()

void checkMembershipInCurrentExtension ( const ObjectAddress object)

Definition at line 259 of file pg_depend.c.

260 {
261  /*
262  * This is actually the same condition tested in
263  * recordDependencyOnCurrentExtension; but we want to issue a
264  * differently-worded error, and anyway it would be pretty confusing to
265  * call recordDependencyOnCurrentExtension in these circumstances.
266  */
267 
268  /* Only whole objects can be extension members */
269  Assert(object->objectSubId == 0);
270 
271  if (creating_extension)
272  {
273  Oid oldext;
274 
275  oldext = getExtensionOfObject(object->classId, object->objectId);
276  /* If already a member of this extension, OK */
277  if (oldext == CurrentExtensionObject)
278  return;
279  /* Else complain */
280  ereport(ERROR,
281  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
282  errmsg("%s is not a member of extension \"%s\"",
283  getObjectDescription(object, false),
285  errdetail("An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.")));
286  }
287 }
int errdetail(const char *fmt,...)
Definition: elog.c:1201
bool creating_extension
Definition: extension.c:71
Oid CurrentExtensionObject
Definition: extension.c:72
char * get_extension_name(Oid ext_oid)
Definition: extension.c:190
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:733
unsigned int Oid
Definition: postgres_ext.h:31

References Assert, ObjectAddress::classId, creating_extension, CurrentExtensionObject, ereport, errcode(), errdetail(), errmsg(), ERROR, get_extension_name(), getExtensionOfObject(), getObjectDescription(), ObjectAddress::objectId, and ObjectAddress::objectSubId.

Referenced by CollationCreate(), CreateForeignServer(), CreateSchemaCommand(), CreateTableAsRelExists(), DefineSequence(), and transformCreateStmt().

◆ checkSharedDependencies()

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

Definition at line 676 of file pg_shdepend.c.

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

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

Referenced by DropRole(), and DropTableSpace().

◆ copyTemplateDependencies()

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)

Definition at line 895 of file pg_shdepend.c.

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

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

Referenced by createdb().

◆ deleteDependencyRecordsFor()

long deleteDependencyRecordsFor ( Oid  classId,
Oid  objectId,
bool  skipExtensionDeps 
)

Definition at line 302 of file pg_depend.c.

304 {
305  long count = 0;
306  Relation depRel;
307  ScanKeyData key[2];
308  SysScanDesc scan;
309  HeapTuple tup;
310 
311  depRel = table_open(DependRelationId, RowExclusiveLock);
312 
313  ScanKeyInit(&key[0],
314  Anum_pg_depend_classid,
315  BTEqualStrategyNumber, F_OIDEQ,
316  ObjectIdGetDatum(classId));
317  ScanKeyInit(&key[1],
318  Anum_pg_depend_objid,
319  BTEqualStrategyNumber, F_OIDEQ,
320  ObjectIdGetDatum(objectId));
321 
322  scan = systable_beginscan(depRel, DependDependerIndexId, true,
323  NULL, 2, key);
324 
325  while (HeapTupleIsValid(tup = systable_getnext(scan)))
326  {
327  if (skipExtensionDeps &&
328  ((Form_pg_depend) GETSTRUCT(tup))->deptype == DEPENDENCY_EXTENSION)
329  continue;
330 
331  CatalogTupleDelete(depRel, &tup->t_self);
332  count++;
333  }
334 
335  systable_endscan(scan);
336 
337  table_close(depRel, RowExclusiveLock);
338 
339  return count;
340 }

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

Referenced by AlterPolicy(), ATExecAlterColumnType(), ATExecDropExpression(), ATExecSetExpression(), CreateProceduralLanguage(), CreateTransform(), CreateTriggerFiringOn(), GenerateTypeDependencies(), InsertRule(), makeConfigurationDependencies(), makeOperatorDependencies(), ProcedureCreate(), swap_relation_files(), and tryAttachPartitionForeignKey().

◆ deleteDependencyRecordsForClass()

long deleteDependencyRecordsForClass ( Oid  classId,
Oid  objectId,
Oid  refclassId,
char  deptype 
)

Definition at line 352 of file pg_depend.c.

354 {
355  long count = 0;
356  Relation depRel;
357  ScanKeyData key[2];
358  SysScanDesc scan;
359  HeapTuple tup;
360 
361  depRel = table_open(DependRelationId, RowExclusiveLock);
362 
363  ScanKeyInit(&key[0],
364  Anum_pg_depend_classid,
365  BTEqualStrategyNumber, F_OIDEQ,
366  ObjectIdGetDatum(classId));
367  ScanKeyInit(&key[1],
368  Anum_pg_depend_objid,
369  BTEqualStrategyNumber, F_OIDEQ,
370  ObjectIdGetDatum(objectId));
371 
372  scan = systable_beginscan(depRel, DependDependerIndexId, true,
373  NULL, 2, key);
374 
375  while (HeapTupleIsValid(tup = systable_getnext(scan)))
376  {
377  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
378 
379  if (depform->refclassid == refclassId && depform->deptype == deptype)
380  {
381  CatalogTupleDelete(depRel, &tup->t_self);
382  count++;
383  }
384  }
385 
386  systable_endscan(scan);
387 
388  table_close(depRel, RowExclusiveLock);
389 
390  return count;
391 }

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

Referenced by AlterForeignDataWrapper(), ApplyExtensionUpdates(), ATExecDropIdentity(), ATExecSetAccessMethodNoStorage(), ConstraintSetParentConstraint(), DetachPartitionFinalize(), DropClonedTriggersFromPartition(), ExecAlterExtensionContentsRecurse(), index_constraint_create(), IndexSetParentIndex(), process_owned_by(), and TriggerSetParentTrigger().

◆ deleteDependencyRecordsForSpecific()

long deleteDependencyRecordsForSpecific ( Oid  classId,
Oid  objectId,
char  deptype,
Oid  refclassId,
Oid  refobjectId 
)

Definition at line 399 of file pg_depend.c.

401 {
402  long count = 0;
403  Relation depRel;
404  ScanKeyData key[2];
405  SysScanDesc scan;
406  HeapTuple tup;
407 
408  depRel = table_open(DependRelationId, RowExclusiveLock);
409 
410  ScanKeyInit(&key[0],
411  Anum_pg_depend_classid,
412  BTEqualStrategyNumber, F_OIDEQ,
413  ObjectIdGetDatum(classId));
414  ScanKeyInit(&key[1],
415  Anum_pg_depend_objid,
416  BTEqualStrategyNumber, F_OIDEQ,
417  ObjectIdGetDatum(objectId));
418 
419  scan = systable_beginscan(depRel, DependDependerIndexId, true,
420  NULL, 2, key);
421 
422  while (HeapTupleIsValid(tup = systable_getnext(scan)))
423  {
424  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
425 
426  if (depform->refclassid == refclassId &&
427  depform->refobjid == refobjectId &&
428  depform->deptype == deptype)
429  {
430  CatalogTupleDelete(depRel, &tup->t_self);
431  count++;
432  }
433  }
434 
435  systable_endscan(scan);
436 
437  table_close(depRel, RowExclusiveLock);
438 
439  return count;
440 }

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

Referenced by ExecAlterObjectDependsStmt().

◆ deleteSharedDependencyRecordsFor()

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

Definition at line 1047 of file pg_shdepend.c.

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

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

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

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 999 of file pg_shdepend.c.

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

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

Referenced by dropdb().

◆ free_object_addresses()

◆ get_index_constraint()

Oid get_index_constraint ( Oid  indexId)

Definition at line 989 of file pg_depend.c.

990 {
991  Oid constraintId = InvalidOid;
992  Relation depRel;
993  ScanKeyData key[3];
994  SysScanDesc scan;
995  HeapTuple tup;
996 
997  /* Search the dependency table for the index */
998  depRel = table_open(DependRelationId, AccessShareLock);
999 
1000  ScanKeyInit(&key[0],
1001  Anum_pg_depend_classid,
1002  BTEqualStrategyNumber, F_OIDEQ,
1003  ObjectIdGetDatum(RelationRelationId));
1004  ScanKeyInit(&key[1],
1005  Anum_pg_depend_objid,
1006  BTEqualStrategyNumber, F_OIDEQ,
1007  ObjectIdGetDatum(indexId));
1008  ScanKeyInit(&key[2],
1009  Anum_pg_depend_objsubid,
1010  BTEqualStrategyNumber, F_INT4EQ,
1011  Int32GetDatum(0));
1012 
1013  scan = systable_beginscan(depRel, DependDependerIndexId, true,
1014  NULL, 3, key);
1015 
1016  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1017  {
1018  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1019 
1020  /*
1021  * We assume any internal dependency on a constraint must be what we
1022  * are looking for.
1023  */
1024  if (deprec->refclassid == ConstraintRelationId &&
1025  deprec->refobjsubid == 0 &&
1026  deprec->deptype == DEPENDENCY_INTERNAL)
1027  {
1028  constraintId = deprec->refobjid;
1029  break;
1030  }
1031  }
1032 
1033  systable_endscan(scan);
1034  table_close(depRel, AccessShareLock);
1035 
1036  return constraintId;
1037 }
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212

References AccessShareLock, BTEqualStrategyNumber, DEPENDENCY_INTERNAL, GETSTRUCT, HeapTupleIsValid, Int32GetDatum(), InvalidOid, sort-test::key, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by generateClonedIndexStmt(), index_concurrently_swap(), RememberIndexForRebuilding(), RenameRelationInternal(), and transformIndexConstraint().

◆ get_index_ref_constraints()

List* get_index_ref_constraints ( Oid  indexId)

Definition at line 1045 of file pg_depend.c.

1046 {
1047  List *result = NIL;
1048  Relation depRel;
1049  ScanKeyData key[3];
1050  SysScanDesc scan;
1051  HeapTuple tup;
1052 
1053  /* Search the dependency table for the index */
1054  depRel = table_open(DependRelationId, AccessShareLock);
1055 
1056  ScanKeyInit(&key[0],
1057  Anum_pg_depend_refclassid,
1058  BTEqualStrategyNumber, F_OIDEQ,
1059  ObjectIdGetDatum(RelationRelationId));
1060  ScanKeyInit(&key[1],
1061  Anum_pg_depend_refobjid,
1062  BTEqualStrategyNumber, F_OIDEQ,
1063  ObjectIdGetDatum(indexId));
1064  ScanKeyInit(&key[2],
1065  Anum_pg_depend_refobjsubid,
1066  BTEqualStrategyNumber, F_INT4EQ,
1067  Int32GetDatum(0));
1068 
1069  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1070  NULL, 3, key);
1071 
1072  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1073  {
1074  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1075 
1076  /*
1077  * We assume any normal dependency from a constraint must be what we
1078  * are looking for.
1079  */
1080  if (deprec->classid == ConstraintRelationId &&
1081  deprec->objsubid == 0 &&
1082  deprec->deptype == DEPENDENCY_NORMAL)
1083  {
1084  result = lappend_oid(result, deprec->objid);
1085  }
1086  }
1087 
1088  systable_endscan(scan);
1089  table_close(depRel, AccessShareLock);
1090 
1091  return result;
1092 }
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375

References AccessShareLock, BTEqualStrategyNumber, DEPENDENCY_NORMAL, GETSTRUCT, HeapTupleIsValid, Int32GetDatum(), sort-test::key, lappend_oid(), NIL, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by index_concurrently_swap().

◆ getAutoExtensionsOfObject()

List* getAutoExtensionsOfObject ( Oid  classId,
Oid  objectId 
)

Definition at line 779 of file pg_depend.c.

780 {
781  List *result = NIL;
782  Relation depRel;
783  ScanKeyData key[2];
784  SysScanDesc scan;
785  HeapTuple tup;
786 
787  depRel = table_open(DependRelationId, AccessShareLock);
788 
789  ScanKeyInit(&key[0],
790  Anum_pg_depend_classid,
791  BTEqualStrategyNumber, F_OIDEQ,
792  ObjectIdGetDatum(classId));
793  ScanKeyInit(&key[1],
794  Anum_pg_depend_objid,
795  BTEqualStrategyNumber, F_OIDEQ,
796  ObjectIdGetDatum(objectId));
797 
798  scan = systable_beginscan(depRel, DependDependerIndexId, true,
799  NULL, 2, key);
800 
801  while (HeapTupleIsValid((tup = systable_getnext(scan))))
802  {
803  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
804 
805  if (depform->refclassid == ExtensionRelationId &&
806  depform->deptype == DEPENDENCY_AUTO_EXTENSION)
807  result = lappend_oid(result, depform->refobjid);
808  }
809 
810  systable_endscan(scan);
811 
812  table_close(depRel, AccessShareLock);
813 
814  return result;
815 }

References AccessShareLock, BTEqualStrategyNumber, DEPENDENCY_AUTO_EXTENSION, GETSTRUCT, HeapTupleIsValid, sort-test::key, lappend_oid(), NIL, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ExecAlterObjectDependsStmt().

◆ getExtensionOfObject()

Oid getExtensionOfObject ( Oid  classId,
Oid  objectId 
)

Definition at line 733 of file pg_depend.c.

734 {
735  Oid result = InvalidOid;
736  Relation depRel;
737  ScanKeyData key[2];
738  SysScanDesc scan;
739  HeapTuple tup;
740 
741  depRel = table_open(DependRelationId, AccessShareLock);
742 
743  ScanKeyInit(&key[0],
744  Anum_pg_depend_classid,
745  BTEqualStrategyNumber, F_OIDEQ,
746  ObjectIdGetDatum(classId));
747  ScanKeyInit(&key[1],
748  Anum_pg_depend_objid,
749  BTEqualStrategyNumber, F_OIDEQ,
750  ObjectIdGetDatum(objectId));
751 
752  scan = systable_beginscan(depRel, DependDependerIndexId, true,
753  NULL, 2, key);
754 
755  while (HeapTupleIsValid((tup = systable_getnext(scan))))
756  {
757  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
758 
759  if (depform->refclassid == ExtensionRelationId &&
760  depform->deptype == DEPENDENCY_EXTENSION)
761  {
762  result = depform->refobjid;
763  break; /* no need to keep scanning */
764  }
765  }
766 
767  systable_endscan(scan);
768 
769  table_close(depRel, AccessShareLock);
770 
771  return result;
772 }

References AccessShareLock, BTEqualStrategyNumber, DEPENDENCY_EXTENSION, GETSTRUCT, HeapTupleIsValid, InvalidOid, sort-test::key, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterExtensionNamespace(), checkMembershipInCurrentExtension(), ExecAlterExtensionContentsRecurse(), lookup_shippable(), pg_extension_config_dump(), and recordDependencyOnCurrentExtension().

◆ getIdentitySequence()

Oid getIdentitySequence ( Relation  rel,
AttrNumber  attnum,
bool  missing_ok 
)

Definition at line 946 of file pg_depend.c.

947 {
948  Oid relid = RelationGetRelid(rel);
949  List *seqlist;
950 
951  /*
952  * The identity sequence is associated with the topmost partitioned table,
953  * which might have column order different than the given partition.
954  */
955  if (RelationGetForm(rel)->relispartition)
956  {
957  List *ancestors = get_partition_ancestors(relid);
958  const char *attname = get_attname(relid, attnum, false);
959 
960  relid = llast_oid(ancestors);
961  attnum = get_attnum(relid, attname);
962  if (attnum == InvalidAttrNumber)
963  elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u",
964  attname, relid);
965  list_free(ancestors);
966  }
967 
969  if (list_length(seqlist) > 1)
970  elog(ERROR, "more than one owned sequence found");
971  else if (seqlist == NIL)
972  {
973  if (missing_ok)
974  return InvalidOid;
975  else
976  elog(ERROR, "no owned sequence found");
977  }
978 
979  return linitial_oid(seqlist);
980 }
#define InvalidAttrNumber
Definition: attnum.h:23
#define elog(elevel,...)
Definition: elog.h:224
void list_free(List *list)
Definition: list.c:1546
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:858
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:827
List * get_partition_ancestors(Oid relid)
Definition: partition.c:134
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
static List * getOwnedSequences_internal(Oid relid, AttrNumber attnum, char deptype)
Definition: pg_depend.c:878
static int list_length(const List *l)
Definition: pg_list.h:152
#define llast_oid(l)
Definition: pg_list.h:200
#define linitial_oid(l)
Definition: pg_list.h:180
#define RelationGetForm(relation)
Definition: rel.h:499
#define RelationGetRelid(relation)
Definition: rel.h:505

References attname, attnum, DEPENDENCY_INTERNAL, elog, ERROR, get_attname(), get_attnum(), get_partition_ancestors(), getOwnedSequences_internal(), InvalidAttrNumber, InvalidOid, linitial_oid, list_free(), list_length(), llast_oid, NIL, RelationGetForm, and RelationGetRelid.

Referenced by ATExecDropIdentity(), build_column_default(), transformAlterTableStmt(), and transformTableLikeClause().

◆ getOwnedSequences()

List* getOwnedSequences ( Oid  relid)

Definition at line 937 of file pg_depend.c.

938 {
939  return getOwnedSequences_internal(relid, 0, 0);
940 }

References getOwnedSequences_internal().

Referenced by ATRewriteTables(), and ExecuteTruncateGuts().

◆ new_object_addresses()

◆ object_address_present()

bool object_address_present ( const ObjectAddress object,
const ObjectAddresses addrs 
)

Definition at line 2593 of file dependency.c.

2595 {
2596  int i;
2597 
2598  for (i = addrs->numrefs - 1; i >= 0; i--)
2599  {
2600  const ObjectAddress *thisobj = addrs->refs + i;
2601 
2602  if (object->classId == thisobj->classId &&
2603  object->objectId == thisobj->objectId)
2604  {
2605  if (object->objectSubId == thisobj->objectSubId ||
2606  thisobj->objectSubId == 0)
2607  return true;
2608  }
2609  }
2610 
2611  return false;
2612 }

References ObjectAddress::classId, i, ObjectAddresses::numrefs, ObjectAddressStack::object, ObjectAddress::objectId, ObjectAddress::objectSubId, and ObjectAddresses::refs.

Referenced by AlterConstraintNamespaces(), AlterIndexNamespaces(), AlterRelationNamespaceInternal(), AlterTypeNamespaceInternal(), findDependentObjects(), and PreCommit_on_commit_actions().

◆ performDeletion()

void performDeletion ( const ObjectAddress object,
DropBehavior  behavior,
int  flags 
)

Definition at line 273 of file dependency.c.

275 {
276  Relation depRel;
277  ObjectAddresses *targetObjects;
278 
279  /*
280  * We save some cycles by opening pg_depend just once and passing the
281  * Relation pointer down to all the recursive deletion steps.
282  */
283  depRel = table_open(DependRelationId, RowExclusiveLock);
284 
285  /*
286  * Acquire deletion lock on the target object. (Ideally the caller has
287  * done this already, but many places are sloppy about it.)
288  */
289  AcquireDeletionLock(object, 0);
290 
291  /*
292  * Construct a list of objects to delete (ie, the given object plus
293  * everything directly or indirectly dependent on it).
294  */
295  targetObjects = new_object_addresses();
296 
297  findDependentObjects(object,
299  flags,
300  NULL, /* empty stack */
301  targetObjects,
302  NULL, /* no pendingObjects */
303  &depRel);
304 
305  /*
306  * Check if deletion is allowed, and report about cascaded deletes.
307  */
308  reportDependentObjects(targetObjects,
309  behavior,
310  flags,
311  object);
312 
313  /* do the deed */
314  deleteObjectsInList(targetObjects, &depRel, flags);
315 
316  /* And clean up */
317  free_object_addresses(targetObjects);
318 
319  table_close(depRel, RowExclusiveLock);
320 }
void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1496
#define DEPFLAG_ORIGINAL
Definition: dependency.c:101
static void reportDependentObjects(const ObjectAddresses *targetObjects, DropBehavior behavior, int flags, const ObjectAddress *origObject)
Definition: dependency.c:980
static void findDependentObjects(const ObjectAddress *object, int objflags, int flags, ObjectAddressStack *stack, ObjectAddresses *targetObjects, const ObjectAddresses *pendingObjects, Relation *depRel)
Definition: dependency.c:432
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2487
static void deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, int flags)
Definition: dependency.c:185
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2773

References AcquireDeletionLock(), deleteObjectsInList(), DEPFLAG_ORIGINAL, findDependentObjects(), ObjectAddressStack::flags, free_object_addresses(), new_object_addresses(), reportDependentObjects(), RowExclusiveLock, table_close(), and table_open().

Referenced by AlterDomainDropConstraint(), AlterDomainNotNull(), ATExecDropConstraint(), ATExecDropIdentity(), ATExecMergePartitions(), ATExecSplitPartition(), DetachPartitionFinalize(), do_autovacuum(), dropOperators(), dropProcedures(), finish_heap_swap(), inv_drop(), PublicationDropSchemas(), PublicationDropTables(), RemoveAttrDefault(), RemoveTempRelations(), RemoveUserMapping(), SetDefaultACL(), and tryAttachPartitionForeignKey().

◆ performMultipleDeletions()

void performMultipleDeletions ( const ObjectAddresses objects,
DropBehavior  behavior,
int  flags 
)

Definition at line 332 of file dependency.c.

334 {
335  Relation depRel;
336  ObjectAddresses *targetObjects;
337  int i;
338 
339  /* No work if no objects... */
340  if (objects->numrefs <= 0)
341  return;
342 
343  /*
344  * We save some cycles by opening pg_depend just once and passing the
345  * Relation pointer down to all the recursive deletion steps.
346  */
347  depRel = table_open(DependRelationId, RowExclusiveLock);
348 
349  /*
350  * Construct a list of objects to delete (ie, the given objects plus
351  * everything directly or indirectly dependent on them). Note that
352  * because we pass the whole objects list as pendingObjects context, we
353  * won't get a failure from trying to delete an object that is internally
354  * dependent on another one in the list; we'll just skip that object and
355  * delete it when we reach its owner.
356  */
357  targetObjects = new_object_addresses();
358 
359  for (i = 0; i < objects->numrefs; i++)
360  {
361  const ObjectAddress *thisobj = objects->refs + i;
362 
363  /*
364  * Acquire deletion lock on each target object. (Ideally the caller
365  * has done this already, but many places are sloppy about it.)
366  */
367  AcquireDeletionLock(thisobj, flags);
368 
369  findDependentObjects(thisobj,
371  flags,
372  NULL, /* empty stack */
373  targetObjects,
374  objects,
375  &depRel);
376  }
377 
378  /*
379  * Check if deletion is allowed, and report about cascaded deletes.
380  *
381  * If there's exactly one object being deleted, report it the same way as
382  * in performDeletion(), else we have to be vaguer.
383  */
384  reportDependentObjects(targetObjects,
385  behavior,
386  flags,
387  (objects->numrefs == 1 ? objects->refs : NULL));
388 
389  /* do the deed */
390  deleteObjectsInList(targetObjects, &depRel, flags);
391 
392  /* And clean up */
393  free_object_addresses(targetObjects);
394 
395  table_close(depRel, RowExclusiveLock);
396 }

References AcquireDeletionLock(), deleteObjectsInList(), DEPFLAG_ORIGINAL, findDependentObjects(), ObjectAddressStack::flags, free_object_addresses(), i, new_object_addresses(), ObjectAddresses::numrefs, ObjectAddresses::refs, reportDependentObjects(), RowExclusiveLock, table_close(), and table_open().

Referenced by ATExecDropColumn(), DropClonedTriggersFromPartition(), PreCommit_on_commit_actions(), ReindexRelationConcurrently(), RemoveObjects(), RemoveRelations(), and shdepDropOwned().

◆ record_object_address_dependencies()

void record_object_address_dependencies ( const ObjectAddress depender,
ObjectAddresses referenced,
DependencyType  behavior 
)

Definition at line 2742 of file dependency.c.

2745 {
2747  recordMultipleDependencies(depender,
2748  referenced->refs, referenced->numrefs,
2749  behavior);
2750 }
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs)
Definition: dependency.c:2383
void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
Definition: pg_depend.c:58

References eliminate_duplicate_dependencies(), ObjectAddresses::numrefs, recordMultipleDependencies(), and ObjectAddresses::refs.

Referenced by AggregateCreate(), CastCreate(), CreateConstraintEntry(), CreateProceduralLanguage(), CreateTransform(), GenerateTypeDependencies(), heap_create_with_catalog(), index_create(), InsertExtensionTuple(), makeConfigurationDependencies(), makeDictionaryDependencies(), makeOperatorDependencies(), makeParserDependencies(), makeTSTemplateDependencies(), ProcedureCreate(), RangeCreate(), and StorePartitionKey().

◆ recordDependencyOn()

void recordDependencyOn ( const ObjectAddress depender,
const ObjectAddress referenced,
DependencyType  behavior 
)

◆ recordDependencyOnCurrentExtension()

void recordDependencyOnCurrentExtension ( const ObjectAddress object,
bool  isReplace 
)

Definition at line 194 of file pg_depend.c.

196 {
197  /* Only whole objects can be extension members */
198  Assert(object->objectSubId == 0);
199 
200  if (creating_extension)
201  {
202  ObjectAddress extension;
203 
204  /* Only need to check for existing membership if isReplace */
205  if (isReplace)
206  {
207  Oid oldext;
208 
209  /*
210  * Side note: these catalog lookups are safe only because the
211  * object is a pre-existing one. In the not-isReplace case, the
212  * caller has most likely not yet done a CommandCounterIncrement
213  * that would make the new object visible.
214  */
215  oldext = getExtensionOfObject(object->classId, object->objectId);
216  if (OidIsValid(oldext))
217  {
218  /* If already a member of this extension, nothing to do */
219  if (oldext == CurrentExtensionObject)
220  return;
221  /* Already a member of some other extension, so reject */
222  ereport(ERROR,
223  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
224  errmsg("%s is already a member of extension \"%s\"",
225  getObjectDescription(object, false),
226  get_extension_name(oldext))));
227  }
228  /* It's a free-standing object, so reject */
229  ereport(ERROR,
230  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
231  errmsg("%s is not a member of extension \"%s\"",
232  getObjectDescription(object, false),
234  errdetail("An extension is not allowed to replace an object that it does not own.")));
235  }
236 
237  /* OK, record it as a member of CurrentExtensionObject */
238  extension.classId = ExtensionRelationId;
239  extension.objectId = CurrentExtensionObject;
240  extension.objectSubId = 0;
241 
242  recordDependencyOn(object, &extension, DEPENDENCY_EXTENSION);
243  }
244 }
#define OidIsValid(objectId)
Definition: c.h:775

References Assert, ObjectAddress::classId, creating_extension, CurrentExtensionObject, DEPENDENCY_EXTENSION, ereport, errcode(), errdetail(), errmsg(), ERROR, get_extension_name(), getExtensionOfObject(), getObjectDescription(), ObjectAddress::objectId, ObjectAddress::objectSubId, OidIsValid, and recordDependencyOn().

Referenced by CastCreate(), CollationCreate(), ConversionCreate(), CreateAccessMethod(), CreateForeignDataWrapper(), CreateForeignServer(), CreateOpFamily(), CreateProceduralLanguage(), CreateTransform(), DefineOpClass(), DefineVirtualRelation(), GenerateTypeDependencies(), heap_create_with_catalog(), insert_event_trigger_tuple(), makeConfigurationDependencies(), makeDictionaryDependencies(), makeOperatorDependencies(), makeParserDependencies(), makeTSTemplateDependencies(), NamespaceCreate(), and ProcedureCreate().

◆ recordDependencyOnExpr()

void recordDependencyOnExpr ( const ObjectAddress depender,
Node expr,
List rtable,
DependencyType  behavior 
)

Definition at line 1553 of file dependency.c.

1556 {
1558 
1559  context.addrs = new_object_addresses();
1560 
1561  /* Set up interpretation for Vars at varlevelsup = 0 */
1562  context.rtables = list_make1(rtable);
1563 
1564  /* Scan the expression tree for referenceable objects */
1566 
1567  /* Remove any duplicates */
1569 
1570  /* And record 'em */
1571  recordMultipleDependencies(depender,
1572  context.addrs->refs, context.addrs->numrefs,
1573  behavior);
1574 
1576 }
static bool find_expr_references_walker(Node *node, find_expr_references_context *context)
Definition: dependency.c:1698
#define list_make1(x1)
Definition: pg_list.h:212
tree context
Definition: radixtree.h:1835

References context, eliminate_duplicate_dependencies(), find_expr_references_walker(), free_object_addresses(), list_make1, new_object_addresses(), and recordMultipleDependencies().

Referenced by AlterPolicy(), CreatePolicy(), CreateTriggerFiringOn(), GenerateTypeDependencies(), InsertRule(), and ProcedureCreate().

◆ recordDependencyOnOwner()

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

◆ recordDependencyOnSingleRelExpr()

void recordDependencyOnSingleRelExpr ( const ObjectAddress depender,
Node expr,
Oid  relId,
DependencyType  behavior,
DependencyType  self_behavior,
bool  reverse_self 
)

Definition at line 1596 of file dependency.c.

1601 {
1603  RangeTblEntry rte = {0};
1604 
1605  context.addrs = new_object_addresses();
1606 
1607  /* We gin up a rather bogus rangetable list to handle Vars */
1608  rte.type = T_RangeTblEntry;
1609  rte.rtekind = RTE_RELATION;
1610  rte.relid = relId;
1611  rte.relkind = RELKIND_RELATION; /* no need for exactness here */
1612  rte.rellockmode = AccessShareLock;
1613 
1614  context.rtables = list_make1(list_make1(&rte));
1615 
1616  /* Scan the expression tree for referenceable objects */
1618 
1619  /* Remove any duplicates */
1621 
1622  /* Separate self-dependencies if necessary */
1623  if ((behavior != self_behavior || reverse_self) &&
1624  context.addrs->numrefs > 0)
1625  {
1626  ObjectAddresses *self_addrs;
1627  ObjectAddress *outobj;
1628  int oldref,
1629  outrefs;
1630 
1631  self_addrs = new_object_addresses();
1632 
1633  outobj = context.addrs->refs;
1634  outrefs = 0;
1635  for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
1636  {
1637  ObjectAddress *thisobj = context.addrs->refs + oldref;
1638 
1639  if (thisobj->classId == RelationRelationId &&
1640  thisobj->objectId == relId)
1641  {
1642  /* Move this ref into self_addrs */
1643  add_exact_object_address(thisobj, self_addrs);
1644  }
1645  else
1646  {
1647  /* Keep it in context.addrs */
1648  *outobj = *thisobj;
1649  outobj++;
1650  outrefs++;
1651  }
1652  }
1653  context.addrs->numrefs = outrefs;
1654 
1655  /* Record the self-dependencies with the appropriate direction */
1656  if (!reverse_self)
1657  recordMultipleDependencies(depender,
1658  self_addrs->refs, self_addrs->numrefs,
1659  self_behavior);
1660  else
1661  {
1662  /* Can't use recordMultipleDependencies, so do it the hard way */
1663  int selfref;
1664 
1665  for (selfref = 0; selfref < self_addrs->numrefs; selfref++)
1666  {
1667  ObjectAddress *thisobj = self_addrs->refs + selfref;
1668 
1669  recordDependencyOn(thisobj, depender, self_behavior);
1670  }
1671  }
1672 
1673  free_object_addresses(self_addrs);
1674  }
1675 
1676  /* Record the external dependencies */
1677  recordMultipleDependencies(depender,
1678  context.addrs->refs, context.addrs->numrefs,
1679  behavior);
1680 
1682 }
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2533
@ RTE_RELATION
Definition: parsenodes.h:1028
RTEKind rtekind
Definition: parsenodes.h:1057

References AccessShareLock, add_exact_object_address(), ObjectAddress::classId, context, eliminate_duplicate_dependencies(), find_expr_references_walker(), free_object_addresses(), list_make1, new_object_addresses(), ObjectAddresses::numrefs, ObjectAddress::objectId, recordDependencyOn(), recordMultipleDependencies(), ObjectAddresses::refs, RangeTblEntry::relid, RTE_RELATION, and RangeTblEntry::rtekind.

Referenced by CreateConstraintEntry(), CreateStatistics(), index_create(), publication_add_relation(), StoreAttrDefault(), and StorePartitionKey().

◆ recordDependencyOnTablespace()

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

Definition at line 370 of file pg_shdepend.c.

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

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

Referenced by heap_create().

◆ recordMultipleDependencies()

void recordMultipleDependencies ( const ObjectAddress depender,
const ObjectAddress referenced,
int  nreferenced,
DependencyType  behavior 
)

Definition at line 58 of file pg_depend.c.

62 {
63  Relation dependDesc;
64  CatalogIndexState indstate;
65  TupleTableSlot **slot;
66  int i,
67  max_slots,
68  slot_init_count,
69  slot_stored_count;
70 
71  if (nreferenced <= 0)
72  return; /* nothing to do */
73 
74  /*
75  * During bootstrap, do nothing since pg_depend may not exist yet.
76  *
77  * Objects created during bootstrap are most likely pinned, and the few
78  * that are not do not have dependencies on each other, so that there
79  * would be no need to make a pg_depend entry anyway.
80  */
82  return;
83 
84  dependDesc = table_open(DependRelationId, RowExclusiveLock);
85 
86  /*
87  * Allocate the slots to use, but delay costly initialization until we
88  * know that they will be used.
89  */
90  max_slots = Min(nreferenced,
92  slot = palloc(sizeof(TupleTableSlot *) * max_slots);
93 
94  /* Don't open indexes unless we need to make an update */
95  indstate = NULL;
96 
97  /* number of slots currently storing tuples */
98  slot_stored_count = 0;
99  /* number of slots currently initialized */
100  slot_init_count = 0;
101  for (i = 0; i < nreferenced; i++, referenced++)
102  {
103  /*
104  * If the referenced object is pinned by the system, there's no real
105  * need to record dependencies on it. This saves lots of space in
106  * pg_depend, so it's worth the time taken to check.
107  */
108  if (isObjectPinned(referenced))
109  continue;
110 
111  if (slot_init_count < max_slots)
112  {
113  slot[slot_stored_count] = MakeSingleTupleTableSlot(RelationGetDescr(dependDesc),
114  &TTSOpsHeapTuple);
115  slot_init_count++;
116  }
117 
118  ExecClearTuple(slot[slot_stored_count]);
119 
120  /*
121  * Record the dependency. Note we don't bother to check for duplicate
122  * dependencies; there's no harm in them.
123  */
124  slot[slot_stored_count]->tts_values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
125  slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
126  slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
127  slot[slot_stored_count]->tts_values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
128  slot[slot_stored_count]->tts_values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
129  slot[slot_stored_count]->tts_values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
130  slot[slot_stored_count]->tts_values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
131 
132  memset(slot[slot_stored_count]->tts_isnull, false,
133  slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
134 
135  ExecStoreVirtualTuple(slot[slot_stored_count]);
136  slot_stored_count++;
137 
138  /* If slots are full, insert a batch of tuples */
139  if (slot_stored_count == max_slots)
140  {
141  /* fetch index info only when we know we need it */
142  if (indstate == NULL)
143  indstate = CatalogOpenIndexes(dependDesc);
144 
145  CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count,
146  indstate);
147  slot_stored_count = 0;
148  }
149  }
150 
151  /* Insert any tuples left in the buffer */
152  if (slot_stored_count > 0)
153  {
154  /* fetch index info only when we know we need it */
155  if (indstate == NULL)
156  indstate = CatalogOpenIndexes(dependDesc);
157 
158  CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count,
159  indstate);
160  }
161 
162  if (indstate != NULL)
163  CatalogCloseIndexes(indstate);
164 
165  table_close(dependDesc, RowExclusiveLock);
166 
167  /* Drop only the number of slots used */
168  for (i = 0; i < slot_init_count; i++)
170  pfree(slot);
171 }
#define Min(x, y)
Definition: c.h:1004
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:454
FormData_pg_depend
Definition: pg_depend.h:65
static Datum CharGetDatum(char X)
Definition: postgres.h:122

References CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTuplesMultiInsertWithInfo(), CharGetDatum(), ObjectAddress::classId, ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), FormData_pg_depend, i, Int32GetDatum(), IsBootstrapProcessingMode, isObjectPinned(), MakeSingleTupleTableSlot(), MAX_CATALOG_MULTI_INSERT_BYTES, Min, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, palloc(), pfree(), RelationGetDescr, RowExclusiveLock, table_close(), table_open(), TupleTableSlot::tts_values, and TTSOpsHeapTuple.

Referenced by record_object_address_dependencies(), recordDependencyOn(), recordDependencyOnExpr(), and recordDependencyOnSingleRelExpr().

◆ recordSharedDependencyOn()

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

Definition at line 125 of file pg_shdepend.c.

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

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

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

◆ ReleaseDeletionLock()

void ReleaseDeletionLock ( const ObjectAddress object)

Definition at line 1528 of file dependency.c.

1529 {
1530  if (object->classId == RelationRelationId)
1532  else
1533  /* assume we should lock the whole object not a sub-object */
1534  UnlockDatabaseObject(object->classId, object->objectId, 0,
1536 }
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:227
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1053

References AccessExclusiveLock, ObjectAddress::classId, ObjectAddressStack::object, ObjectAddress::objectId, UnlockDatabaseObject(), and UnlockRelationOid().

Referenced by findDependentObjects(), and shdepDropOwned().

◆ sequenceIsOwned()

bool sequenceIsOwned ( Oid  seqId,
char  deptype,
Oid tableId,
int32 colId 
)

Definition at line 829 of file pg_depend.c.

830 {
831  bool ret = false;
832  Relation depRel;
833  ScanKeyData key[2];
834  SysScanDesc scan;
835  HeapTuple tup;
836 
837  depRel = table_open(DependRelationId, AccessShareLock);
838 
839  ScanKeyInit(&key[0],
840  Anum_pg_depend_classid,
841  BTEqualStrategyNumber, F_OIDEQ,
842  ObjectIdGetDatum(RelationRelationId));
843  ScanKeyInit(&key[1],
844  Anum_pg_depend_objid,
845  BTEqualStrategyNumber, F_OIDEQ,
846  ObjectIdGetDatum(seqId));
847 
848  scan = systable_beginscan(depRel, DependDependerIndexId, true,
849  NULL, 2, key);
850 
851  while (HeapTupleIsValid((tup = systable_getnext(scan))))
852  {
853  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
854 
855  if (depform->refclassid == RelationRelationId &&
856  depform->deptype == deptype)
857  {
858  *tableId = depform->refobjid;
859  *colId = depform->refobjsubid;
860  ret = true;
861  break; /* no need to keep scanning */
862  }
863  }
864 
865  systable_endscan(scan);
866 
867  table_close(depRel, AccessShareLock);
868 
869  return ret;
870 }

References AccessShareLock, BTEqualStrategyNumber, GETSTRUCT, HeapTupleIsValid, sort-test::key, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterTableNamespace(), ATExecChangeOwner(), and process_owned_by().

◆ shdepDropOwned()

void shdepDropOwned ( List roleids,
DropBehavior  behavior 
)

Definition at line 1342 of file pg_shdepend.c.

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

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

Referenced by DropOwnedObjects().

◆ shdepLockAndCheckObject()

void shdepLockAndCheckObject ( Oid  classId,
Oid  objectId 
)

Definition at line 1211 of file pg_shdepend.c.

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

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

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

◆ shdepReassignOwned()

void shdepReassignOwned ( List roleids,
Oid  newrole 
)

Definition at line 1530 of file pg_shdepend.c.

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

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

Referenced by ReassignOwnedObjects().

◆ sort_object_addresses()

void sort_object_addresses ( ObjectAddresses addrs)

Definition at line 2761 of file dependency.c.

2762 {
2763  if (addrs->numrefs > 1)
2764  qsort(addrs->refs, addrs->numrefs,
2765  sizeof(ObjectAddress),
2767 }
static int object_address_comparator(const void *a, const void *b)
Definition: dependency.c:2443

References ObjectAddresses::numrefs, object_address_comparator(), qsort, and ObjectAddresses::refs.

Referenced by shdepDropOwned().

◆ updateAclDependencies()

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

Definition at line 491 of file pg_shdepend.c.

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

References SHARED_DEPENDENCY_ACL, and updateAclDependenciesWorker().

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

◆ updateInitAclDependencies()

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

Definition at line 512 of file pg_shdepend.c.

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

References InvalidOid, SHARED_DEPENDENCY_INITACL, and updateAclDependenciesWorker().

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