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 LAST_OCLASS   OCLASS_TRANSFORM
 
#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
 
typedef enum ObjectClass ObjectClass
 

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_POLICY = 'r' , SHARED_DEPENDENCY_TABLESPACE = 't' ,
  SHARED_DEPENDENCY_INVALID = 0
}
 
enum  ObjectClass {
  OCLASS_CLASS , OCLASS_PROC , OCLASS_TYPE , OCLASS_CAST ,
  OCLASS_COLLATION , OCLASS_CONSTRAINT , OCLASS_CONVERSION , OCLASS_DEFAULT ,
  OCLASS_LANGUAGE , OCLASS_LARGEOBJECT , OCLASS_OPERATOR , OCLASS_OPCLASS ,
  OCLASS_OPFAMILY , OCLASS_AM , OCLASS_AMOP , OCLASS_AMPROC ,
  OCLASS_REWRITE , OCLASS_TRIGGER , OCLASS_SCHEMA , OCLASS_STATISTIC_EXT ,
  OCLASS_TSPARSER , OCLASS_TSDICT , OCLASS_TSTEMPLATE , OCLASS_TSCONFIG ,
  OCLASS_ROLE , OCLASS_DATABASE , OCLASS_TBLSPACE , OCLASS_FDW ,
  OCLASS_FOREIGN_SERVER , OCLASS_USER_MAPPING , OCLASS_DEFACL , OCLASS_EXTENSION ,
  OCLASS_EVENT_TRIGGER , OCLASS_POLICY , OCLASS_PUBLICATION , OCLASS_PUBLICATION_NAMESPACE ,
  OCLASS_PUBLICATION_REL , OCLASS_SUBSCRIPTION , OCLASS_TRANSFORM
}
 

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)
 
ObjectClass getObjectClass (const ObjectAddress *object)
 
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)
 
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 (Oid relid, 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 objectSubId, Oid ownerId, 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 *relids, DropBehavior behavior)
 
void shdepReassignOwned (List *relids, Oid newrole)
 

Macro Definition Documentation

◆ LAST_OCLASS

#define LAST_OCLASS   OCLASS_TRANSFORM

Definition at line 131 of file dependency.h.

◆ PERFORM_DELETION_CONCURRENT_LOCK

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

Definition at line 139 of file dependency.h.

◆ PERFORM_DELETION_CONCURRENTLY

#define PERFORM_DELETION_CONCURRENTLY   0x0002 /* concurrent drop */

Definition at line 135 of file dependency.h.

◆ PERFORM_DELETION_INTERNAL

#define PERFORM_DELETION_INTERNAL   0x0001 /* internal action */

Definition at line 134 of file dependency.h.

◆ PERFORM_DELETION_QUIETLY

#define PERFORM_DELETION_QUIETLY   0x0004 /* suppress notices */

Definition at line 136 of file dependency.h.

◆ PERFORM_DELETION_SKIP_EXTENSIONS

#define PERFORM_DELETION_SKIP_EXTENSIONS   0x0010 /* keep extensions */

Definition at line 138 of file dependency.h.

◆ PERFORM_DELETION_SKIP_ORIGINAL

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

Definition at line 137 of file dependency.h.

Typedef Documentation

◆ DependencyType

◆ ObjectAddresses

Definition at line 1 of file dependency.h.

◆ ObjectClass

typedef enum ObjectClass ObjectClass

◆ 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

◆ ObjectClass

Enumerator
OCLASS_CLASS 
OCLASS_PROC 
OCLASS_TYPE 
OCLASS_CAST 
OCLASS_COLLATION 
OCLASS_CONSTRAINT 
OCLASS_CONVERSION 
OCLASS_DEFAULT 
OCLASS_LANGUAGE 
OCLASS_LARGEOBJECT 
OCLASS_OPERATOR 
OCLASS_OPCLASS 
OCLASS_OPFAMILY 
OCLASS_AM 
OCLASS_AMOP 
OCLASS_AMPROC 
OCLASS_REWRITE 
OCLASS_TRIGGER 
OCLASS_SCHEMA 
OCLASS_STATISTIC_EXT 
OCLASS_TSPARSER 
OCLASS_TSDICT 
OCLASS_TSTEMPLATE 
OCLASS_TSCONFIG 
OCLASS_ROLE 
OCLASS_DATABASE 
OCLASS_TBLSPACE 
OCLASS_FDW 
OCLASS_FOREIGN_SERVER 
OCLASS_USER_MAPPING 
OCLASS_DEFACL 
OCLASS_EXTENSION 
OCLASS_EVENT_TRIGGER 
OCLASS_POLICY 
OCLASS_PUBLICATION 
OCLASS_PUBLICATION_NAMESPACE 
OCLASS_PUBLICATION_REL 
OCLASS_SUBSCRIPTION 
OCLASS_TRANSFORM 

Definition at line 88 of file dependency.h.

89 {
90  OCLASS_CLASS, /* pg_class */
91  OCLASS_PROC, /* pg_proc */
92  OCLASS_TYPE, /* pg_type */
93  OCLASS_CAST, /* pg_cast */
94  OCLASS_COLLATION, /* pg_collation */
95  OCLASS_CONSTRAINT, /* pg_constraint */
96  OCLASS_CONVERSION, /* pg_conversion */
97  OCLASS_DEFAULT, /* pg_attrdef */
98  OCLASS_LANGUAGE, /* pg_language */
99  OCLASS_LARGEOBJECT, /* pg_largeobject */
100  OCLASS_OPERATOR, /* pg_operator */
101  OCLASS_OPCLASS, /* pg_opclass */
102  OCLASS_OPFAMILY, /* pg_opfamily */
103  OCLASS_AM, /* pg_am */
104  OCLASS_AMOP, /* pg_amop */
105  OCLASS_AMPROC, /* pg_amproc */
106  OCLASS_REWRITE, /* pg_rewrite */
107  OCLASS_TRIGGER, /* pg_trigger */
108  OCLASS_SCHEMA, /* pg_namespace */
109  OCLASS_STATISTIC_EXT, /* pg_statistic_ext */
110  OCLASS_TSPARSER, /* pg_ts_parser */
111  OCLASS_TSDICT, /* pg_ts_dict */
112  OCLASS_TSTEMPLATE, /* pg_ts_template */
113  OCLASS_TSCONFIG, /* pg_ts_config */
114  OCLASS_ROLE, /* pg_authid */
115  OCLASS_DATABASE, /* pg_database */
116  OCLASS_TBLSPACE, /* pg_tablespace */
117  OCLASS_FDW, /* pg_foreign_data_wrapper */
118  OCLASS_FOREIGN_SERVER, /* pg_foreign_server */
119  OCLASS_USER_MAPPING, /* pg_user_mapping */
120  OCLASS_DEFACL, /* pg_default_acl */
121  OCLASS_EXTENSION, /* pg_extension */
122  OCLASS_EVENT_TRIGGER, /* pg_event_trigger */
123  OCLASS_POLICY, /* pg_policy */
124  OCLASS_PUBLICATION, /* pg_publication */
125  OCLASS_PUBLICATION_NAMESPACE, /* pg_publication_namespace */
126  OCLASS_PUBLICATION_REL, /* pg_publication_rel */
127  OCLASS_SUBSCRIPTION, /* pg_subscription */
128  OCLASS_TRANSFORM /* pg_transform */
129 } ObjectClass;
ObjectClass
Definition: dependency.h:89
@ OCLASS_OPERATOR
Definition: dependency.h:100
@ OCLASS_LARGEOBJECT
Definition: dependency.h:99
@ OCLASS_FDW
Definition: dependency.h:117
@ OCLASS_OPFAMILY
Definition: dependency.h:102
@ OCLASS_DEFACL
Definition: dependency.h:120
@ OCLASS_TSPARSER
Definition: dependency.h:110
@ OCLASS_TRIGGER
Definition: dependency.h:107
@ OCLASS_DEFAULT
Definition: dependency.h:97
@ OCLASS_TSTEMPLATE
Definition: dependency.h:112
@ OCLASS_AMPROC
Definition: dependency.h:105
@ OCLASS_TBLSPACE
Definition: dependency.h:116
@ OCLASS_TSCONFIG
Definition: dependency.h:113
@ OCLASS_TYPE
Definition: dependency.h:92
@ OCLASS_LANGUAGE
Definition: dependency.h:98
@ OCLASS_CAST
Definition: dependency.h:93
@ OCLASS_SUBSCRIPTION
Definition: dependency.h:127
@ OCLASS_PUBLICATION_NAMESPACE
Definition: dependency.h:125
@ OCLASS_EXTENSION
Definition: dependency.h:121
@ OCLASS_COLLATION
Definition: dependency.h:94
@ OCLASS_FOREIGN_SERVER
Definition: dependency.h:118
@ OCLASS_REWRITE
Definition: dependency.h:106
@ OCLASS_STATISTIC_EXT
Definition: dependency.h:109
@ OCLASS_PROC
Definition: dependency.h:91
@ OCLASS_OPCLASS
Definition: dependency.h:101
@ OCLASS_CONVERSION
Definition: dependency.h:96
@ OCLASS_DATABASE
Definition: dependency.h:115
@ OCLASS_SCHEMA
Definition: dependency.h:108
@ OCLASS_EVENT_TRIGGER
Definition: dependency.h:122
@ OCLASS_CLASS
Definition: dependency.h:90
@ OCLASS_TRANSFORM
Definition: dependency.h:128
@ OCLASS_ROLE
Definition: dependency.h:114
@ OCLASS_CONSTRAINT
Definition: dependency.h:95
@ OCLASS_POLICY
Definition: dependency.h:123
@ OCLASS_USER_MAPPING
Definition: dependency.h:119
@ OCLASS_PUBLICATION_REL
Definition: dependency.h:126
@ OCLASS_AM
Definition: dependency.h:103
@ OCLASS_TSDICT
Definition: dependency.h:111
@ OCLASS_PUBLICATION
Definition: dependency.h:124
@ OCLASS_AMOP
Definition: dependency.h:104

◆ SharedDependencyType

Enumerator
SHARED_DEPENDENCY_OWNER 
SHARED_DEPENDENCY_ACL 
SHARED_DEPENDENCY_POLICY 
SHARED_DEPENDENCY_TABLESPACE 
SHARED_DEPENDENCY_INVALID 

Definition at line 72 of file dependency.h.

73 {
SharedDependencyType
Definition: dependency.h:73
@ SHARED_DEPENDENCY_TABLESPACE
Definition: dependency.h:77
@ SHARED_DEPENDENCY_INVALID
Definition: dependency.h:78
@ SHARED_DEPENDENCY_POLICY
Definition: dependency.h:76
@ SHARED_DEPENDENCY_ACL
Definition: dependency.h:75
@ SHARED_DEPENDENCY_OWNER
Definition: dependency.h:74

Function Documentation

◆ AcquireDeletionLock()

void AcquireDeletionLock ( const ObjectAddress object,
int  flags 
)

Definition at line 1532 of file dependency.c.

1533 {
1534  if (object->classId == RelationRelationId)
1535  {
1536  /*
1537  * In DROP INDEX CONCURRENTLY, take only ShareUpdateExclusiveLock on
1538  * the index for the moment. index_drop() will promote the lock once
1539  * it's safe to do so. In all other cases we need full exclusive
1540  * lock.
1541  */
1542  if (flags & PERFORM_DELETION_CONCURRENTLY)
1544  else
1546  }
1547  else
1548  {
1549  /* assume we should lock the whole object not a sub-object */
1550  LockDatabaseObject(object->classId, object->objectId, 0,
1552  }
1553 }
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:135
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:977
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
#define AccessExclusiveLock
Definition: lockdefs.h:43
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39

References AccessExclusiveLock, ObjectAddress::classId, ObjectAddressStack::flags, LockDatabaseObject(), LockRelationOid(), 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 2500 of file dependency.c.

2502 {
2503  ObjectAddress *item;
2504 
2505  /* enlarge array if needed */
2506  if (addrs->numrefs >= addrs->maxrefs)
2507  {
2508  addrs->maxrefs *= 2;
2509  addrs->refs = (ObjectAddress *)
2510  repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2511  Assert(!addrs->extras);
2512  }
2513  /* record this item */
2514  item = addrs->refs + addrs->numrefs;
2515  *item = *object;
2516  addrs->numrefs++;
2517 }
Assert(fmt[strlen(fmt) - 1] !='\n')
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
ObjectAddressExtra * extras
Definition: dependency.c:114
ObjectAddress * refs
Definition: dependency.c:113

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 507 of file pg_depend.c.

509 {
510  long count = 0;
511  Relation depRel;
512  ScanKeyData key[2];
513  SysScanDesc scan;
514  HeapTuple tup;
515 
516  depRel = table_open(DependRelationId, RowExclusiveLock);
517 
518  ScanKeyInit(&key[0],
519  Anum_pg_depend_classid,
520  BTEqualStrategyNumber, F_OIDEQ,
521  ObjectIdGetDatum(classId));
522  ScanKeyInit(&key[1],
523  Anum_pg_depend_objid,
524  BTEqualStrategyNumber, F_OIDEQ,
525  ObjectIdGetDatum(oldObjectId));
526 
527  scan = systable_beginscan(depRel, DependDependerIndexId, true,
528  NULL, 2, key);
529 
530  while (HeapTupleIsValid((tup = systable_getnext(scan))))
531  {
532  Form_pg_depend depform;
533 
534  /* make a modifiable copy */
535  tup = heap_copytuple(tup);
536  depform = (Form_pg_depend) GETSTRUCT(tup);
537 
538  depform->objid = newObjectId;
539 
540  CatalogTupleUpdate(depRel, &tup->t_self, tup);
541 
542  heap_freetuple(tup);
543 
544  count++;
545  }
546 
547  systable_endscan(scan);
548 
549  table_close(depRel, RowExclusiveLock);
550 
551  return count;
552 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:598
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:505
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:386
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:72
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
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:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

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 563 of file pg_depend.c.

565 {
566  long count = 0;
567  Relation depRel;
568  ScanKeyData key[2];
569  SysScanDesc scan;
570  HeapTuple tup;
571  ObjectAddress objAddr;
572  bool newIsPinned;
573 
574  depRel = table_open(DependRelationId, RowExclusiveLock);
575 
576  /*
577  * If oldRefObjectId is pinned, there won't be any dependency entries on
578  * it --- we can't cope in that case. (This isn't really worth expending
579  * code to fix, in current usage; it just means you can't rename stuff out
580  * of pg_catalog, which would likely be a bad move anyway.)
581  */
582  objAddr.classId = refClassId;
583  objAddr.objectId = oldRefObjectId;
584  objAddr.objectSubId = 0;
585 
586  if (isObjectPinned(&objAddr))
587  ereport(ERROR,
588  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
589  errmsg("cannot remove dependency on %s because it is a system object",
590  getObjectDescription(&objAddr, false))));
591 
592  /*
593  * We can handle adding a dependency on something pinned, though, since
594  * that just means deleting the dependency entry.
595  */
596  objAddr.objectId = newRefObjectId;
597 
598  newIsPinned = isObjectPinned(&objAddr);
599 
600  /* Now search for dependency records */
601  ScanKeyInit(&key[0],
602  Anum_pg_depend_refclassid,
603  BTEqualStrategyNumber, F_OIDEQ,
604  ObjectIdGetDatum(refClassId));
605  ScanKeyInit(&key[1],
606  Anum_pg_depend_refobjid,
607  BTEqualStrategyNumber, F_OIDEQ,
608  ObjectIdGetDatum(oldRefObjectId));
609 
610  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
611  NULL, 2, key);
612 
613  while (HeapTupleIsValid((tup = systable_getnext(scan))))
614  {
615  if (newIsPinned)
616  CatalogTupleDelete(depRel, &tup->t_self);
617  else
618  {
619  Form_pg_depend depform;
620 
621  /* make a modifiable copy */
622  tup = heap_copytuple(tup);
623  depform = (Form_pg_depend) GETSTRUCT(tup);
624 
625  depform->refobjid = newRefObjectId;
626 
627  CatalogTupleUpdate(depRel, &tup->t_self, tup);
628 
629  heap_freetuple(tup);
630  }
631 
632  count++;
633  }
634 
635  systable_endscan(scan);
636 
637  table_close(depRel, RowExclusiveLock);
638 
639  return count;
640 }
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
static bool isObjectPinned(const ObjectAddress *object)
Definition: pg_depend.c:651

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 399 of file pg_depend.c.

402 {
403  long count = 0;
404  Relation depRel;
405  ScanKeyData key[2];
406  SysScanDesc scan;
407  HeapTuple tup;
408  ObjectAddress objAddr;
409  ObjectAddress depAddr;
410  bool oldIsPinned;
411  bool newIsPinned;
412 
413  /*
414  * Check to see if either oldRefObjectId or newRefObjectId is pinned.
415  * Pinned objects should not have any dependency entries pointing to them,
416  * so in these cases we should add or remove a pg_depend entry, or do
417  * nothing at all, rather than update an entry as in the normal case.
418  */
419  objAddr.classId = refClassId;
420  objAddr.objectId = oldRefObjectId;
421  objAddr.objectSubId = 0;
422 
423  oldIsPinned = isObjectPinned(&objAddr);
424 
425  objAddr.objectId = newRefObjectId;
426 
427  newIsPinned = isObjectPinned(&objAddr);
428 
429  if (oldIsPinned)
430  {
431  /*
432  * If both are pinned, we need do nothing. However, return 1 not 0,
433  * else callers will think this is an error case.
434  */
435  if (newIsPinned)
436  return 1;
437 
438  /*
439  * There is no old dependency record, but we should insert a new one.
440  * Assume a normal dependency is wanted.
441  */
442  depAddr.classId = classId;
443  depAddr.objectId = objectId;
444  depAddr.objectSubId = 0;
445  recordDependencyOn(&depAddr, &objAddr, DEPENDENCY_NORMAL);
446 
447  return 1;
448  }
449 
450  depRel = table_open(DependRelationId, RowExclusiveLock);
451 
452  /* There should be existing dependency record(s), so search. */
453  ScanKeyInit(&key[0],
454  Anum_pg_depend_classid,
455  BTEqualStrategyNumber, F_OIDEQ,
456  ObjectIdGetDatum(classId));
457  ScanKeyInit(&key[1],
458  Anum_pg_depend_objid,
459  BTEqualStrategyNumber, F_OIDEQ,
460  ObjectIdGetDatum(objectId));
461 
462  scan = systable_beginscan(depRel, DependDependerIndexId, true,
463  NULL, 2, key);
464 
465  while (HeapTupleIsValid((tup = systable_getnext(scan))))
466  {
467  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
468 
469  if (depform->refclassid == refClassId &&
470  depform->refobjid == oldRefObjectId)
471  {
472  if (newIsPinned)
473  CatalogTupleDelete(depRel, &tup->t_self);
474  else
475  {
476  /* make a modifiable copy */
477  tup = heap_copytuple(tup);
478  depform = (Form_pg_depend) GETSTRUCT(tup);
479 
480  depform->refobjid = newRefObjectId;
481 
482  CatalogTupleUpdate(depRel, &tup->t_self, tup);
483 
484  heap_freetuple(tup);
485  }
486 
487  count++;
488  }
489  }
490 
491  systable_endscan(scan);
492 
493  table_close(depRel, RowExclusiveLock);
494 
495  return count;
496 }
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44

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(), and AlterTypeNamespaceInternal().

◆ changeDependencyOnOwner()

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

Definition at line 312 of file pg_shdepend.c.

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

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

382 {
383  Relation sdepRel;
384 
385  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
386 
387  if (newTablespaceId != DEFAULTTABLESPACE_OID &&
388  newTablespaceId != InvalidOid)
389  shdepChangeDep(sdepRel,
390  classId, objectId, 0,
391  TableSpaceRelationId, newTablespaceId,
393  else
394  shdepDropDependency(sdepRel,
395  classId, objectId, 0, true,
398 
399  table_close(sdepRel, RowExclusiveLock);
400 }
#define InvalidOid
Definition: postgres_ext.h:36

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

Referenced by SetRelationTableSpace().

◆ checkSharedDependencies()

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

Definition at line 630 of file pg_shdepend.c.

632 {
633  Relation sdepRel;
634  ScanKeyData key[2];
635  SysScanDesc scan;
636  HeapTuple tup;
637  int numReportedDeps = 0;
638  int numNotReportedDeps = 0;
639  int numNotReportedDbs = 0;
640  List *remDeps = NIL;
641  ListCell *cell;
642  ObjectAddress object;
643  ShDependObjectInfo *objects;
644  int numobjects;
645  int allocedobjects;
646  StringInfoData descs;
647  StringInfoData alldescs;
648 
649  /* This case can be dispatched quickly */
650  if (IsPinnedObject(classId, objectId))
651  {
652  object.classId = classId;
653  object.objectId = objectId;
654  object.objectSubId = 0;
655  ereport(ERROR,
656  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
657  errmsg("cannot drop %s because it is required by the database system",
658  getObjectDescription(&object, false))));
659  }
660 
661  /*
662  * We limit the number of dependencies reported to the client to
663  * MAX_REPORTED_DEPS, since client software may not deal well with
664  * enormous error strings. The server log always gets a full report.
665  *
666  * For stability of regression test results, we sort local and shared
667  * objects by OID before reporting them. We don't worry about the order
668  * in which other databases are reported, though.
669  */
670 #define MAX_REPORTED_DEPS 100
671 
672  allocedobjects = 128; /* arbitrary initial array size */
673  objects = (ShDependObjectInfo *)
674  palloc(allocedobjects * sizeof(ShDependObjectInfo));
675  numobjects = 0;
676  initStringInfo(&descs);
677  initStringInfo(&alldescs);
678 
679  sdepRel = table_open(SharedDependRelationId, AccessShareLock);
680 
681  ScanKeyInit(&key[0],
682  Anum_pg_shdepend_refclassid,
683  BTEqualStrategyNumber, F_OIDEQ,
684  ObjectIdGetDatum(classId));
685  ScanKeyInit(&key[1],
686  Anum_pg_shdepend_refobjid,
687  BTEqualStrategyNumber, F_OIDEQ,
688  ObjectIdGetDatum(objectId));
689 
690  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
691  NULL, 2, key);
692 
693  while (HeapTupleIsValid(tup = systable_getnext(scan)))
694  {
695  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
696 
697  object.classId = sdepForm->classid;
698  object.objectId = sdepForm->objid;
699  object.objectSubId = sdepForm->objsubid;
700 
701  /*
702  * If it's a dependency local to this database or it's a shared
703  * object, add it to the objects array.
704  *
705  * If it's a remote dependency, keep track of it so we can report the
706  * number of them later.
707  */
708  if (sdepForm->dbid == MyDatabaseId ||
709  sdepForm->dbid == InvalidOid)
710  {
711  if (numobjects >= allocedobjects)
712  {
713  allocedobjects *= 2;
714  objects = (ShDependObjectInfo *)
715  repalloc(objects,
716  allocedobjects * sizeof(ShDependObjectInfo));
717  }
718  objects[numobjects].object = object;
719  objects[numobjects].deptype = sdepForm->deptype;
720  objects[numobjects].objtype = (sdepForm->dbid == MyDatabaseId) ?
722  numobjects++;
723  }
724  else
725  {
726  /* It's not local nor shared, so it must be remote. */
727  remoteDep *dep;
728  bool stored = false;
729 
730  /*
731  * XXX this info is kept on a simple List. Maybe it's not good
732  * for performance, but using a hash table seems needlessly
733  * complex. The expected number of databases is not high anyway,
734  * I suppose.
735  */
736  foreach(cell, remDeps)
737  {
738  dep = lfirst(cell);
739  if (dep->dbOid == sdepForm->dbid)
740  {
741  dep->count++;
742  stored = true;
743  break;
744  }
745  }
746  if (!stored)
747  {
748  dep = (remoteDep *) palloc(sizeof(remoteDep));
749  dep->dbOid = sdepForm->dbid;
750  dep->count = 1;
751  remDeps = lappend(remDeps, dep);
752  }
753  }
754  }
755 
756  systable_endscan(scan);
757 
758  table_close(sdepRel, AccessShareLock);
759 
760  /*
761  * Sort and report local and shared objects.
762  */
763  if (numobjects > 1)
764  qsort((void *) objects, numobjects,
766 
767  for (int i = 0; i < numobjects; i++)
768  {
769  if (numReportedDeps < MAX_REPORTED_DEPS)
770  {
771  numReportedDeps++;
772  storeObjectDescription(&descs,
773  objects[i].objtype,
774  &objects[i].object,
775  objects[i].deptype,
776  0);
777  }
778  else
779  numNotReportedDeps++;
780  storeObjectDescription(&alldescs,
781  objects[i].objtype,
782  &objects[i].object,
783  objects[i].deptype,
784  0);
785  }
786 
787  /*
788  * Summarize dependencies in remote databases.
789  */
790  foreach(cell, remDeps)
791  {
792  remoteDep *dep = lfirst(cell);
793 
794  object.classId = DatabaseRelationId;
795  object.objectId = dep->dbOid;
796  object.objectSubId = 0;
797 
798  if (numReportedDeps < MAX_REPORTED_DEPS)
799  {
800  numReportedDeps++;
801  storeObjectDescription(&descs, REMOTE_OBJECT, &object,
803  }
804  else
805  numNotReportedDbs++;
806  storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
808  }
809 
810  pfree(objects);
811  list_free_deep(remDeps);
812 
813  if (descs.len == 0)
814  {
815  pfree(descs.data);
816  pfree(alldescs.data);
817  *detail_msg = *detail_log_msg = NULL;
818  return false;
819  }
820 
821  if (numNotReportedDeps > 0)
822  appendStringInfo(&descs, ngettext("\nand %d other object "
823  "(see server log for list)",
824  "\nand %d other objects "
825  "(see server log for list)",
826  numNotReportedDeps),
827  numNotReportedDeps);
828  if (numNotReportedDbs > 0)
829  appendStringInfo(&descs, ngettext("\nand objects in %d other database "
830  "(see server log for list)",
831  "\nand objects in %d other databases "
832  "(see server log for list)",
833  numNotReportedDbs),
834  numNotReportedDbs);
835 
836  *detail_msg = descs.data;
837  *detail_log_msg = alldescs.data;
838  return true;
839 }
#define ngettext(s, p, n)
Definition: c.h:1179
bool IsPinnedObject(Oid classId, Oid objectId)
Definition: catalog.c:307
Oid MyDatabaseId
Definition: globals.c:88
int i
Definition: isn.c:73
List * lappend(List *list, void *datum)
Definition: list.c:336
void list_free_deep(List *list)
Definition: list.c:1519
#define AccessShareLock
Definition: lockdefs.h:36
void pfree(void *pointer)
Definition: mcxt.c:1169
void * palloc(Size size)
Definition: mcxt.c:1062
#define lfirst(lc)
Definition: pg_list.h:169
#define NIL
Definition: pg_list.h:65
static int shared_dependency_comparator(const void *a, const void *b)
Definition: pg_shdepend.c:564
#define MAX_REPORTED_DEPS
static void storeObjectDescription(StringInfo descs, SharedDependencyObjectType type, ObjectAddress *object, SharedDependencyType deptype, int count)
Definition: pg_shdepend.c:1230
@ SHARED_OBJECT
Definition: pg_shdepend.c:74
@ LOCAL_OBJECT
Definition: pg_shdepend.c:73
@ REMOTE_OBJECT
Definition: pg_shdepend.c:75
FormData_pg_shdepend * Form_pg_shdepend
Definition: pg_shdepend.h:73
#define qsort(a, b, c, d)
Definition: port.h:495
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
Definition: pg_list.h:51
ObjectAddress object
Definition: pg_shdepend.c:80
SharedDependencyObjectType objtype
Definition: pg_shdepend.c:82

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

850 {
851  Relation sdepRel;
852  TupleDesc sdepDesc;
853  ScanKeyData key[1];
854  SysScanDesc scan;
855  HeapTuple tup;
856  CatalogIndexState indstate;
857  TupleTableSlot **slot;
858  int max_slots,
859  slot_init_count,
860  slot_stored_count;
861 
862  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
863  sdepDesc = RelationGetDescr(sdepRel);
864 
865  /*
866  * Allocate the slots to use, but delay costly initialization until we
867  * know that they will be used.
868  */
870  slot = palloc(sizeof(TupleTableSlot *) * max_slots);
871 
872  indstate = CatalogOpenIndexes(sdepRel);
873 
874  /* Scan all entries with dbid = templateDbId */
875  ScanKeyInit(&key[0],
876  Anum_pg_shdepend_dbid,
877  BTEqualStrategyNumber, F_OIDEQ,
878  ObjectIdGetDatum(templateDbId));
879 
880  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
881  NULL, 1, key);
882 
883  /* number of slots currently storing tuples */
884  slot_stored_count = 0;
885  /* number of slots currently initialized */
886  slot_init_count = 0;
887 
888  /*
889  * Copy the entries of the original database, changing the database Id to
890  * that of the new database. Note that because we are not copying rows
891  * with dbId == 0 (ie, rows describing dependent shared objects) we won't
892  * copy the ownership dependency of the template database itself; this is
893  * what we want.
894  */
895  while (HeapTupleIsValid(tup = systable_getnext(scan)))
896  {
897  Form_pg_shdepend shdep;
898 
899  if (slot_init_count < max_slots)
900  {
901  slot[slot_stored_count] = MakeSingleTupleTableSlot(sdepDesc, &TTSOpsHeapTuple);
902  slot_init_count++;
903  }
904 
905  ExecClearTuple(slot[slot_stored_count]);
906 
907  memset(slot[slot_stored_count]->tts_isnull, false,
908  slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
909 
910  shdep = (Form_pg_shdepend) GETSTRUCT(tup);
911 
912  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId);
913  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_classid - 1] = shdep->classid;
914  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objid - 1] = shdep->objid;
915  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objsubid - 1] = shdep->objsubid;
916  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refclassid - 1] = shdep->refclassid;
917  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refobjid - 1] = shdep->refobjid;
918  slot[slot_stored_count]->tts_values[Anum_pg_shdepend_deptype - 1] = shdep->deptype;
919 
920  ExecStoreVirtualTuple(slot[slot_stored_count]);
921  slot_stored_count++;
922 
923  /* If slots are full, insert a batch of tuples */
924  if (slot_stored_count == max_slots)
925  {
926  CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
927  slot_stored_count = 0;
928  }
929  }
930 
931  /* Insert any tuples left in the buffer */
932  if (slot_stored_count > 0)
933  CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate);
934 
935  systable_endscan(scan);
936 
937  CatalogCloseIndexes(indstate);
938  table_close(sdepRel, RowExclusiveLock);
939 
940  /* Drop only the number of slots used */
941  for (int i = 0; i < slot_init_count; i++)
943  pfree(slot);
944 }
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1552
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1254
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1238
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
Definition: indexing.c:261
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:504
Datum * tts_values
Definition: tuptable.h:126
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425

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 243 of file pg_depend.c.

245 {
246  long count = 0;
247  Relation depRel;
248  ScanKeyData key[2];
249  SysScanDesc scan;
250  HeapTuple tup;
251 
252  depRel = table_open(DependRelationId, RowExclusiveLock);
253 
254  ScanKeyInit(&key[0],
255  Anum_pg_depend_classid,
256  BTEqualStrategyNumber, F_OIDEQ,
257  ObjectIdGetDatum(classId));
258  ScanKeyInit(&key[1],
259  Anum_pg_depend_objid,
260  BTEqualStrategyNumber, F_OIDEQ,
261  ObjectIdGetDatum(objectId));
262 
263  scan = systable_beginscan(depRel, DependDependerIndexId, true,
264  NULL, 2, key);
265 
266  while (HeapTupleIsValid(tup = systable_getnext(scan)))
267  {
268  if (skipExtensionDeps &&
269  ((Form_pg_depend) GETSTRUCT(tup))->deptype == DEPENDENCY_EXTENSION)
270  continue;
271 
272  CatalogTupleDelete(depRel, &tup->t_self);
273  count++;
274  }
275 
276  systable_endscan(scan);
277 
278  table_close(depRel, RowExclusiveLock);
279 
280  return count;
281 }

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(), CreateProceduralLanguage(), CreateTransform(), CreateTriggerFiringOn(), DefineQueryRewrite(), GenerateTypeDependencies(), InsertRule(), makeConfigurationDependencies(), makeOperatorDependencies(), ProcedureCreate(), swap_relation_files(), and tryAttachPartitionForeignKey().

◆ deleteDependencyRecordsForClass()

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

Definition at line 293 of file pg_depend.c.

295 {
296  long count = 0;
297  Relation depRel;
298  ScanKeyData key[2];
299  SysScanDesc scan;
300  HeapTuple tup;
301 
302  depRel = table_open(DependRelationId, RowExclusiveLock);
303 
304  ScanKeyInit(&key[0],
305  Anum_pg_depend_classid,
306  BTEqualStrategyNumber, F_OIDEQ,
307  ObjectIdGetDatum(classId));
308  ScanKeyInit(&key[1],
309  Anum_pg_depend_objid,
310  BTEqualStrategyNumber, F_OIDEQ,
311  ObjectIdGetDatum(objectId));
312 
313  scan = systable_beginscan(depRel, DependDependerIndexId, true,
314  NULL, 2, key);
315 
316  while (HeapTupleIsValid(tup = systable_getnext(scan)))
317  {
318  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
319 
320  if (depform->refclassid == refclassId && depform->deptype == deptype)
321  {
322  CatalogTupleDelete(depRel, &tup->t_self);
323  count++;
324  }
325  }
326 
327  systable_endscan(scan);
328 
329  table_close(depRel, RowExclusiveLock);
330 
331  return count;
332 }

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(), ConstraintSetParentConstraint(), DetachPartitionFinalize(), DropClonedTriggersFromPartition(), ExecAlterExtensionContentsStmt(), 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 340 of file pg_depend.c.

342 {
343  long count = 0;
344  Relation depRel;
345  ScanKeyData key[2];
346  SysScanDesc scan;
347  HeapTuple tup;
348 
349  depRel = table_open(DependRelationId, RowExclusiveLock);
350 
351  ScanKeyInit(&key[0],
352  Anum_pg_depend_classid,
353  BTEqualStrategyNumber, F_OIDEQ,
354  ObjectIdGetDatum(classId));
355  ScanKeyInit(&key[1],
356  Anum_pg_depend_objid,
357  BTEqualStrategyNumber, F_OIDEQ,
358  ObjectIdGetDatum(objectId));
359 
360  scan = systable_beginscan(depRel, DependDependerIndexId, true,
361  NULL, 2, key);
362 
363  while (HeapTupleIsValid(tup = systable_getnext(scan)))
364  {
365  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
366 
367  if (depform->refclassid == refclassId &&
368  depform->refobjid == refobjectId &&
369  depform->deptype == deptype)
370  {
371  CatalogTupleDelete(depRel, &tup->t_self);
372  count++;
373  }
374  }
375 
376  systable_endscan(scan);
377 
378  table_close(depRel, RowExclusiveLock);
379 
380  return count;
381 }

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

1002 {
1003  Relation sdepRel;
1004 
1005  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1006 
1007  shdepDropDependency(sdepRel, classId, objectId, objectSubId,
1008  (objectSubId == 0),
1011 
1012  table_close(sdepRel, RowExclusiveLock);
1013 }

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

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

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 953 of file pg_shdepend.c.

954 {
955  Relation sdepRel;
956  ScanKeyData key[1];
957  SysScanDesc scan;
958  HeapTuple tup;
959 
960  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
961 
962  /*
963  * First, delete all the entries that have the database Oid in the dbid
964  * field.
965  */
966  ScanKeyInit(&key[0],
967  Anum_pg_shdepend_dbid,
968  BTEqualStrategyNumber, F_OIDEQ,
969  ObjectIdGetDatum(databaseId));
970  /* We leave the other index fields unspecified */
971 
972  scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
973  NULL, 1, key);
974 
975  while (HeapTupleIsValid(tup = systable_getnext(scan)))
976  {
977  CatalogTupleDelete(sdepRel, &tup->t_self);
978  }
979 
980  systable_endscan(scan);
981 
982  /* Now delete all entries corresponding to the database itself */
983  shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
986 
987  table_close(sdepRel, RowExclusiveLock);
988 }

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 911 of file pg_depend.c.

912 {
913  Oid constraintId = InvalidOid;
914  Relation depRel;
915  ScanKeyData key[3];
916  SysScanDesc scan;
917  HeapTuple tup;
918 
919  /* Search the dependency table for the index */
920  depRel = table_open(DependRelationId, AccessShareLock);
921 
922  ScanKeyInit(&key[0],
923  Anum_pg_depend_classid,
924  BTEqualStrategyNumber, F_OIDEQ,
925  ObjectIdGetDatum(RelationRelationId));
926  ScanKeyInit(&key[1],
927  Anum_pg_depend_objid,
928  BTEqualStrategyNumber, F_OIDEQ,
929  ObjectIdGetDatum(indexId));
930  ScanKeyInit(&key[2],
931  Anum_pg_depend_objsubid,
932  BTEqualStrategyNumber, F_INT4EQ,
933  Int32GetDatum(0));
934 
935  scan = systable_beginscan(depRel, DependDependerIndexId, true,
936  NULL, 3, key);
937 
938  while (HeapTupleIsValid(tup = systable_getnext(scan)))
939  {
940  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
941 
942  /*
943  * We assume any internal dependency on a constraint must be what we
944  * are looking for.
945  */
946  if (deprec->refclassid == ConstraintRelationId &&
947  deprec->refobjsubid == 0 &&
948  deprec->deptype == DEPENDENCY_INTERNAL)
949  {
950  constraintId = deprec->refobjid;
951  break;
952  }
953  }
954 
955  systable_endscan(scan);
956  table_close(depRel, AccessShareLock);
957 
958  return constraintId;
959 }
#define Int32GetDatum(X)
Definition: postgres.h:523
unsigned int Oid
Definition: postgres_ext.h:31

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 967 of file pg_depend.c.

968 {
969  List *result = NIL;
970  Relation depRel;
971  ScanKeyData key[3];
972  SysScanDesc scan;
973  HeapTuple tup;
974 
975  /* Search the dependency table for the index */
976  depRel = table_open(DependRelationId, AccessShareLock);
977 
978  ScanKeyInit(&key[0],
979  Anum_pg_depend_refclassid,
980  BTEqualStrategyNumber, F_OIDEQ,
981  ObjectIdGetDatum(RelationRelationId));
982  ScanKeyInit(&key[1],
983  Anum_pg_depend_refobjid,
984  BTEqualStrategyNumber, F_OIDEQ,
985  ObjectIdGetDatum(indexId));
986  ScanKeyInit(&key[2],
987  Anum_pg_depend_refobjsubid,
988  BTEqualStrategyNumber, F_INT4EQ,
989  Int32GetDatum(0));
990 
991  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
992  NULL, 3, key);
993 
994  while (HeapTupleIsValid(tup = systable_getnext(scan)))
995  {
996  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
997 
998  /*
999  * We assume any normal dependency from a constraint must be what we
1000  * are looking for.
1001  */
1002  if (deprec->classid == ConstraintRelationId &&
1003  deprec->objsubid == 0 &&
1004  deprec->deptype == DEPENDENCY_NORMAL)
1005  {
1006  result = lappend_oid(result, deprec->objid);
1007  }
1008  }
1009 
1010  systable_endscan(scan);
1011  table_close(depRel, AccessShareLock);
1012 
1013  return result;
1014 }
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372

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 720 of file pg_depend.c.

721 {
722  List *result = NIL;
723  Relation depRel;
724  ScanKeyData key[2];
725  SysScanDesc scan;
726  HeapTuple tup;
727 
728  depRel = table_open(DependRelationId, AccessShareLock);
729 
730  ScanKeyInit(&key[0],
731  Anum_pg_depend_classid,
732  BTEqualStrategyNumber, F_OIDEQ,
733  ObjectIdGetDatum(classId));
734  ScanKeyInit(&key[1],
735  Anum_pg_depend_objid,
736  BTEqualStrategyNumber, F_OIDEQ,
737  ObjectIdGetDatum(objectId));
738 
739  scan = systable_beginscan(depRel, DependDependerIndexId, true,
740  NULL, 2, key);
741 
742  while (HeapTupleIsValid((tup = systable_getnext(scan))))
743  {
744  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
745 
746  if (depform->refclassid == ExtensionRelationId &&
747  depform->deptype == DEPENDENCY_AUTO_EXTENSION)
748  result = lappend_oid(result, depform->refobjid);
749  }
750 
751  systable_endscan(scan);
752 
753  table_close(depRel, AccessShareLock);
754 
755  return result;
756 }

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 674 of file pg_depend.c.

675 {
676  Oid result = InvalidOid;
677  Relation depRel;
678  ScanKeyData key[2];
679  SysScanDesc scan;
680  HeapTuple tup;
681 
682  depRel = table_open(DependRelationId, AccessShareLock);
683 
684  ScanKeyInit(&key[0],
685  Anum_pg_depend_classid,
686  BTEqualStrategyNumber, F_OIDEQ,
687  ObjectIdGetDatum(classId));
688  ScanKeyInit(&key[1],
689  Anum_pg_depend_objid,
690  BTEqualStrategyNumber, F_OIDEQ,
691  ObjectIdGetDatum(objectId));
692 
693  scan = systable_beginscan(depRel, DependDependerIndexId, true,
694  NULL, 2, key);
695 
696  while (HeapTupleIsValid((tup = systable_getnext(scan))))
697  {
698  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
699 
700  if (depform->refclassid == ExtensionRelationId &&
701  depform->deptype == DEPENDENCY_EXTENSION)
702  {
703  result = depform->refobjid;
704  break; /* no need to keep scanning */
705  }
706  }
707 
708  systable_endscan(scan);
709 
710  table_close(depRel, AccessShareLock);
711 
712  return result;
713 }

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(), ExecAlterExtensionContentsStmt(), lookup_shippable(), pg_extension_config_dump(), and recordDependencyOnCurrentExtension().

◆ getIdentitySequence()

Oid getIdentitySequence ( Oid  relid,
AttrNumber  attnum,
bool  missing_ok 
)

Definition at line 887 of file pg_depend.c.

888 {
890 
891  if (list_length(seqlist) > 1)
892  elog(ERROR, "more than one owned sequence found");
893  else if (list_length(seqlist) < 1)
894  {
895  if (missing_ok)
896  return InvalidOid;
897  else
898  elog(ERROR, "no owned sequence found");
899  }
900 
901  return linitial_oid(seqlist);
902 }
#define elog(elevel,...)
Definition: elog.h:218
int16 attnum
Definition: pg_attribute.h:83
static List * getOwnedSequences_internal(Oid relid, AttrNumber attnum, char deptype)
Definition: pg_depend.c:819
static int list_length(const List *l)
Definition: pg_list.h:149
#define linitial_oid(l)
Definition: pg_list.h:176

References attnum, DEPENDENCY_INTERNAL, elog, ERROR, getOwnedSequences_internal(), InvalidOid, linitial_oid, and list_length().

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

◆ getObjectClass()

ObjectClass getObjectClass ( const ObjectAddress object)

Definition at line 2755 of file dependency.c.

2756 {
2757  /* only pg_class entries can have nonzero objectSubId */
2758  if (object->classId != RelationRelationId &&
2759  object->objectSubId != 0)
2760  elog(ERROR, "invalid non-zero objectSubId for object class %u",
2761  object->classId);
2762 
2763  switch (object->classId)
2764  {
2765  case RelationRelationId:
2766  /* caller must check objectSubId */
2767  return OCLASS_CLASS;
2768 
2769  case ProcedureRelationId:
2770  return OCLASS_PROC;
2771 
2772  case TypeRelationId:
2773  return OCLASS_TYPE;
2774 
2775  case CastRelationId:
2776  return OCLASS_CAST;
2777 
2778  case CollationRelationId:
2779  return OCLASS_COLLATION;
2780 
2781  case ConstraintRelationId:
2782  return OCLASS_CONSTRAINT;
2783 
2784  case ConversionRelationId:
2785  return OCLASS_CONVERSION;
2786 
2787  case AttrDefaultRelationId:
2788  return OCLASS_DEFAULT;
2789 
2790  case LanguageRelationId:
2791  return OCLASS_LANGUAGE;
2792 
2793  case LargeObjectRelationId:
2794  return OCLASS_LARGEOBJECT;
2795 
2796  case OperatorRelationId:
2797  return OCLASS_OPERATOR;
2798 
2799  case OperatorClassRelationId:
2800  return OCLASS_OPCLASS;
2801 
2802  case OperatorFamilyRelationId:
2803  return OCLASS_OPFAMILY;
2804 
2805  case AccessMethodRelationId:
2806  return OCLASS_AM;
2807 
2808  case AccessMethodOperatorRelationId:
2809  return OCLASS_AMOP;
2810 
2811  case AccessMethodProcedureRelationId:
2812  return OCLASS_AMPROC;
2813 
2814  case RewriteRelationId:
2815  return OCLASS_REWRITE;
2816 
2817  case TriggerRelationId:
2818  return OCLASS_TRIGGER;
2819 
2820  case NamespaceRelationId:
2821  return OCLASS_SCHEMA;
2822 
2823  case StatisticExtRelationId:
2824  return OCLASS_STATISTIC_EXT;
2825 
2826  case TSParserRelationId:
2827  return OCLASS_TSPARSER;
2828 
2829  case TSDictionaryRelationId:
2830  return OCLASS_TSDICT;
2831 
2832  case TSTemplateRelationId:
2833  return OCLASS_TSTEMPLATE;
2834 
2835  case TSConfigRelationId:
2836  return OCLASS_TSCONFIG;
2837 
2838  case AuthIdRelationId:
2839  return OCLASS_ROLE;
2840 
2841  case DatabaseRelationId:
2842  return OCLASS_DATABASE;
2843 
2844  case TableSpaceRelationId:
2845  return OCLASS_TBLSPACE;
2846 
2847  case ForeignDataWrapperRelationId:
2848  return OCLASS_FDW;
2849 
2850  case ForeignServerRelationId:
2851  return OCLASS_FOREIGN_SERVER;
2852 
2853  case UserMappingRelationId:
2854  return OCLASS_USER_MAPPING;
2855 
2856  case DefaultAclRelationId:
2857  return OCLASS_DEFACL;
2858 
2859  case ExtensionRelationId:
2860  return OCLASS_EXTENSION;
2861 
2862  case EventTriggerRelationId:
2863  return OCLASS_EVENT_TRIGGER;
2864 
2865  case PolicyRelationId:
2866  return OCLASS_POLICY;
2867 
2868  case PublicationNamespaceRelationId:
2870 
2871  case PublicationRelationId:
2872  return OCLASS_PUBLICATION;
2873 
2874  case PublicationRelRelationId:
2875  return OCLASS_PUBLICATION_REL;
2876 
2877  case SubscriptionRelationId:
2878  return OCLASS_SUBSCRIPTION;
2879 
2880  case TransformRelationId:
2881  return OCLASS_TRANSFORM;
2882  }
2883 
2884  /* shouldn't get here */
2885  elog(ERROR, "unrecognized object class: %u", object->classId);
2886  return OCLASS_CLASS; /* keep compiler quiet */
2887 }

References ObjectAddress::classId, elog, ERROR, ObjectAddressStack::object, ObjectAddress::objectSubId, OCLASS_AM, OCLASS_AMOP, OCLASS_AMPROC, OCLASS_CAST, OCLASS_CLASS, OCLASS_COLLATION, OCLASS_CONSTRAINT, OCLASS_CONVERSION, OCLASS_DATABASE, OCLASS_DEFACL, OCLASS_DEFAULT, OCLASS_EVENT_TRIGGER, OCLASS_EXTENSION, OCLASS_FDW, OCLASS_FOREIGN_SERVER, OCLASS_LANGUAGE, OCLASS_LARGEOBJECT, OCLASS_OPCLASS, OCLASS_OPERATOR, OCLASS_OPFAMILY, OCLASS_POLICY, OCLASS_PROC, OCLASS_PUBLICATION, OCLASS_PUBLICATION_NAMESPACE, OCLASS_PUBLICATION_REL, OCLASS_REWRITE, OCLASS_ROLE, OCLASS_SCHEMA, OCLASS_STATISTIC_EXT, OCLASS_SUBSCRIPTION, OCLASS_TBLSPACE, OCLASS_TRANSFORM, OCLASS_TRIGGER, OCLASS_TSCONFIG, OCLASS_TSDICT, OCLASS_TSPARSER, OCLASS_TSTEMPLATE, OCLASS_TYPE, and OCLASS_USER_MAPPING.

Referenced by AlterObjectNamespace_oid(), ATExecAlterColumnType(), deleteObjectsInList(), doDeletion(), EventTriggerSQLDropAddObject(), getObjectDescription(), getObjectIdentityParts(), and getObjectTypeDescription().

◆ getOwnedSequences()

List* getOwnedSequences ( Oid  relid)

Definition at line 878 of file pg_depend.c.

879 {
880  return getOwnedSequences_internal(relid, 0, 0);
881 }

References getOwnedSequences_internal().

Referenced by ExecuteTruncateGuts().

◆ new_object_addresses()

◆ object_address_present()

bool object_address_present ( const ObjectAddress object,
const ObjectAddresses addrs 
)

Definition at line 2560 of file dependency.c.

2562 {
2563  int i;
2564 
2565  for (i = addrs->numrefs - 1; i >= 0; i--)
2566  {
2567  const ObjectAddress *thisobj = addrs->refs + i;
2568 
2569  if (object->classId == thisobj->classId &&
2570  object->objectId == thisobj->objectId)
2571  {
2572  if (object->objectSubId == thisobj->objectSubId ||
2573  thisobj->objectSubId == 0)
2574  return true;
2575  }
2576  }
2577 
2578  return false;
2579 }

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 315 of file dependency.c.

317 {
318  Relation depRel;
319  ObjectAddresses *targetObjects;
320 
321  /*
322  * We save some cycles by opening pg_depend just once and passing the
323  * Relation pointer down to all the recursive deletion steps.
324  */
325  depRel = table_open(DependRelationId, RowExclusiveLock);
326 
327  /*
328  * Acquire deletion lock on the target object. (Ideally the caller has
329  * done this already, but many places are sloppy about it.)
330  */
331  AcquireDeletionLock(object, 0);
332 
333  /*
334  * Construct a list of objects to delete (ie, the given object plus
335  * everything directly or indirectly dependent on it).
336  */
337  targetObjects = new_object_addresses();
338 
339  findDependentObjects(object,
341  flags,
342  NULL, /* empty stack */
343  targetObjects,
344  NULL, /* no pendingObjects */
345  &depRel);
346 
347  /*
348  * Check if deletion is allowed, and report about cascaded deletes.
349  */
350  reportDependentObjects(targetObjects,
351  behavior,
352  flags,
353  object);
354 
355  /* do the deed */
356  deleteObjectsInList(targetObjects, &depRel, flags);
357 
358  /* And clean up */
359  free_object_addresses(targetObjects);
360 
361  table_close(depRel, RowExclusiveLock);
362 }
void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1532
#define DEPFLAG_ORIGINAL
Definition: dependency.c:99
static void reportDependentObjects(const ObjectAddresses *targetObjects, DropBehavior behavior, int flags, const ObjectAddress *origObject)
Definition: dependency.c:1016
static void findDependentObjects(const ObjectAddress *object, int objflags, int flags, ObjectAddressStack *stack, ObjectAddresses *targetObjects, const ObjectAddresses *pendingObjects, Relation *depRel)
Definition: dependency.c:474
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2445
static void deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, int flags)
Definition: dependency.c:227
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2740

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

Referenced by AlterDomainDropConstraint(), ATExecDropConstraint(), ATExecDropIdentity(), DefineQueryRewrite(), 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 374 of file dependency.c.

376 {
377  Relation depRel;
378  ObjectAddresses *targetObjects;
379  int i;
380 
381  /* No work if no objects... */
382  if (objects->numrefs <= 0)
383  return;
384 
385  /*
386  * We save some cycles by opening pg_depend just once and passing the
387  * Relation pointer down to all the recursive deletion steps.
388  */
389  depRel = table_open(DependRelationId, RowExclusiveLock);
390 
391  /*
392  * Construct a list of objects to delete (ie, the given objects plus
393  * everything directly or indirectly dependent on them). Note that
394  * because we pass the whole objects list as pendingObjects context, we
395  * won't get a failure from trying to delete an object that is internally
396  * dependent on another one in the list; we'll just skip that object and
397  * delete it when we reach its owner.
398  */
399  targetObjects = new_object_addresses();
400 
401  for (i = 0; i < objects->numrefs; i++)
402  {
403  const ObjectAddress *thisobj = objects->refs + i;
404 
405  /*
406  * Acquire deletion lock on each target object. (Ideally the caller
407  * has done this already, but many places are sloppy about it.)
408  */
409  AcquireDeletionLock(thisobj, flags);
410 
411  findDependentObjects(thisobj,
413  flags,
414  NULL, /* empty stack */
415  targetObjects,
416  objects,
417  &depRel);
418  }
419 
420  /*
421  * Check if deletion is allowed, and report about cascaded deletes.
422  *
423  * If there's exactly one object being deleted, report it the same way as
424  * in performDeletion(), else we have to be vaguer.
425  */
426  reportDependentObjects(targetObjects,
427  behavior,
428  flags,
429  (objects->numrefs == 1 ? objects->refs : NULL));
430 
431  /* do the deed */
432  deleteObjectsInList(targetObjects, &depRel, flags);
433 
434  /* And clean up */
435  free_object_addresses(targetObjects);
436 
437  table_close(depRel, RowExclusiveLock);
438 }

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 2709 of file dependency.c.

2712 {
2714  recordMultipleDependencies(depender,
2715  referenced->refs, referenced->numrefs,
2716  behavior);
2717 }
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs)
Definition: dependency.c:2341
void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
Definition: pg_depend.c:56

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

◆ recordDependencyOnCurrentExtension()

void recordDependencyOnCurrentExtension ( const ObjectAddress object,
bool  isReplace 
)

Definition at line 191 of file pg_depend.c.

193 {
194  /* Only whole objects can be extension members */
195  Assert(object->objectSubId == 0);
196 
197  if (creating_extension)
198  {
199  ObjectAddress extension;
200 
201  /* Only need to check for existing membership if isReplace */
202  if (isReplace)
203  {
204  Oid oldext;
205 
206  oldext = getExtensionOfObject(object->classId, object->objectId);
207  if (OidIsValid(oldext))
208  {
209  /* If already a member of this extension, nothing to do */
210  if (oldext == CurrentExtensionObject)
211  return;
212  /* Already a member of some other extension, so reject */
213  ereport(ERROR,
214  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
215  errmsg("%s is already a member of extension \"%s\"",
216  getObjectDescription(object, false),
217  get_extension_name(oldext))));
218  }
219  }
220 
221  /* OK, record it as a member of CurrentExtensionObject */
222  extension.classId = ExtensionRelationId;
223  extension.objectId = CurrentExtensionObject;
224  extension.objectSubId = 0;
225 
226  recordDependencyOn(object, &extension, DEPENDENCY_EXTENSION);
227  }
228 }
#define OidIsValid(objectId)
Definition: c.h:710
bool creating_extension
Definition: extension.c:71
Oid CurrentExtensionObject
Definition: extension.c:72
char * get_extension_name(Oid ext_oid)
Definition: extension.c:185
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c:674

References Assert(), ObjectAddress::classId, creating_extension, CurrentExtensionObject, DEPENDENCY_EXTENSION, ereport, errcode(), 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(), 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 1586 of file dependency.c.

1589 {
1591 
1592  context.addrs = new_object_addresses();
1593 
1594  /* Set up interpretation for Vars at varlevelsup = 0 */
1595  context.rtables = list_make1(rtable);
1596 
1597  /* Scan the expression tree for referenceable objects */
1598  find_expr_references_walker(expr, &context);
1599 
1600  /* Remove any duplicates */
1602 
1603  /* And record 'em */
1604  recordMultipleDependencies(depender,
1605  context.addrs->refs, context.addrs->numrefs,
1606  behavior);
1607 
1608  free_object_addresses(context.addrs);
1609 }
static bool find_expr_references_walker(Node *node, find_expr_references_context *context)
Definition: dependency.c:1732
#define list_make1(x1)
Definition: pg_list.h:206
ObjectAddresses * addrs
Definition: dependency.c:139

References find_expr_references_context::addrs, eliminate_duplicate_dependencies(), find_expr_references_walker(), free_object_addresses(), list_make1, new_object_addresses(), ObjectAddresses::numrefs, recordMultipleDependencies(), ObjectAddresses::refs, and find_expr_references_context::rtables.

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 1629 of file dependency.c.

1634 {
1636  RangeTblEntry rte;
1637 
1638  context.addrs = new_object_addresses();
1639 
1640  /* We gin up a rather bogus rangetable list to handle Vars */
1641  MemSet(&rte, 0, sizeof(rte));
1642  rte.type = T_RangeTblEntry;
1643  rte.rtekind = RTE_RELATION;
1644  rte.relid = relId;
1645  rte.relkind = RELKIND_RELATION; /* no need for exactness here */
1647 
1648  context.rtables = list_make1(list_make1(&rte));
1649 
1650  /* Scan the expression tree for referenceable objects */
1651  find_expr_references_walker(expr, &context);
1652 
1653  /* Remove any duplicates */
1655 
1656  /* Separate self-dependencies if necessary */
1657  if ((behavior != self_behavior || reverse_self) &&
1658  context.addrs->numrefs > 0)
1659  {
1660  ObjectAddresses *self_addrs;
1661  ObjectAddress *outobj;
1662  int oldref,
1663  outrefs;
1664 
1665  self_addrs = new_object_addresses();
1666 
1667  outobj = context.addrs->refs;
1668  outrefs = 0;
1669  for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
1670  {
1671  ObjectAddress *thisobj = context.addrs->refs + oldref;
1672 
1673  if (thisobj->classId == RelationRelationId &&
1674  thisobj->objectId == relId)
1675  {
1676  /* Move this ref into self_addrs */
1677  add_exact_object_address(thisobj, self_addrs);
1678  }
1679  else
1680  {
1681  /* Keep it in context.addrs */
1682  *outobj = *thisobj;
1683  outobj++;
1684  outrefs++;
1685  }
1686  }
1687  context.addrs->numrefs = outrefs;
1688 
1689  /* Record the self-dependencies with the appropriate direction */
1690  if (!reverse_self)
1691  recordMultipleDependencies(depender,
1692  self_addrs->refs, self_addrs->numrefs,
1693  self_behavior);
1694  else
1695  {
1696  /* Can't use recordMultipleDependencies, so do it the hard way */
1697  int selfref;
1698 
1699  for (selfref = 0; selfref < self_addrs->numrefs; selfref++)
1700  {
1701  ObjectAddress *thisobj = self_addrs->refs + selfref;
1702 
1703  recordDependencyOn(thisobj, depender, self_behavior);
1704  }
1705  }
1706 
1707  free_object_addresses(self_addrs);
1708  }
1709 
1710  /* Record the external dependencies */
1711  recordMultipleDependencies(depender,
1712  context.addrs->refs, context.addrs->numrefs,
1713  behavior);
1714 
1715  free_object_addresses(context.addrs);
1716 }
#define MemSet(start, val, len)
Definition: c.h:1008
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2500
@ T_RangeTblEntry
Definition: nodes.h:462
@ RTE_RELATION
Definition: parsenodes.h:990
NodeTag type
Definition: parsenodes.h:1005
RTEKind rtekind
Definition: parsenodes.h:1007

References AccessShareLock, add_exact_object_address(), find_expr_references_context::addrs, ObjectAddress::classId, eliminate_duplicate_dependencies(), find_expr_references_walker(), free_object_addresses(), list_make1, MemSet, new_object_addresses(), ObjectAddresses::numrefs, ObjectAddress::objectId, recordDependencyOn(), recordMultipleDependencies(), ObjectAddresses::refs, RangeTblEntry::relid, RangeTblEntry::relkind, RangeTblEntry::rellockmode, find_expr_references_context::rtables, RTE_RELATION, RangeTblEntry::rtekind, T_RangeTblEntry, and RangeTblEntry::type.

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

◆ recordDependencyOnTablespace()

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

Definition at line 360 of file pg_shdepend.c.

361 {
362  ObjectAddress myself,
363  referenced;
364 
365  ObjectAddressSet(myself, classId, objectId);
366  ObjectAddressSet(referenced, TableSpaceRelationId, tablespace);
367 
368  recordSharedDependencyOn(&myself, &referenced,
370 }
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
char * tablespace
Definition: pgbench.c:227

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 56 of file pg_depend.c.

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

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

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

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 1561 of file dependency.c.

1562 {
1563  if (object->classId == RelationRelationId)
1565  else
1566  /* assume we should lock the whole object not a sub-object */
1567  UnlockDatabaseObject(object->classId, object->objectId, 0,
1569 }
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:200
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:998

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 770 of file pg_depend.c.

771 {
772  bool ret = false;
773  Relation depRel;
774  ScanKeyData key[2];
775  SysScanDesc scan;
776  HeapTuple tup;
777 
778  depRel = table_open(DependRelationId, AccessShareLock);
779 
780  ScanKeyInit(&key[0],
781  Anum_pg_depend_classid,
782  BTEqualStrategyNumber, F_OIDEQ,
783  ObjectIdGetDatum(RelationRelationId));
784  ScanKeyInit(&key[1],
785  Anum_pg_depend_objid,
786  BTEqualStrategyNumber, F_OIDEQ,
787  ObjectIdGetDatum(seqId));
788 
789  scan = systable_beginscan(depRel, DependDependerIndexId, true,
790  NULL, 2, key);
791 
792  while (HeapTupleIsValid((tup = systable_getnext(scan))))
793  {
794  Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
795 
796  if (depform->refclassid == RelationRelationId &&
797  depform->deptype == deptype)
798  {
799  *tableId = depform->refobjid;
800  *colId = depform->refobjsubid;
801  ret = true;
802  break; /* no need to keep scanning */
803  }
804  }
805 
806  systable_endscan(scan);
807 
808  table_close(depRel, AccessShareLock);
809 
810  return ret;
811 }

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 relids,
DropBehavior  behavior 
)

Definition at line 1294 of file pg_shdepend.c.

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

References AcquireDeletionLock(), add_exact_object_address(), 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(), RemoveRoleFromObjectACL(), RemoveRoleFromObjectPolicy(), RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_ACL, 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 1165 of file pg_shdepend.c.

1166 {
1167  /* AccessShareLock should be OK, since we are not modifying the object */
1168  LockSharedObject(classId, objectId, 0, AccessShareLock);
1169 
1170  switch (classId)
1171  {
1172  case AuthIdRelationId:
1174  ereport(ERROR,
1175  (errcode(ERRCODE_UNDEFINED_OBJECT),
1176  errmsg("role %u was concurrently dropped",
1177  objectId)));
1178  break;
1179 
1180  case TableSpaceRelationId:
1181  {
1182  /* For lack of a syscache on pg_tablespace, do this: */
1183  char *tablespace = get_tablespace_name(objectId);
1184 
1185  if (tablespace == NULL)
1186  ereport(ERROR,
1187  (errcode(ERRCODE_UNDEFINED_OBJECT),
1188  errmsg("tablespace %u was concurrently dropped",
1189  objectId)));
1190  pfree(tablespace);
1191  break;
1192  }
1193 
1194  case DatabaseRelationId:
1195  {
1196  /* For lack of a syscache on pg_database, do this: */
1197  char *database = get_database_name(objectId);
1198 
1199  if (database == NULL)
1200  ereport(ERROR,
1201  (errcode(ERRCODE_UNDEFINED_OBJECT),
1202  errmsg("database %u was concurrently dropped",
1203  objectId)));
1204  pfree(database);
1205  break;
1206  }
1207 
1208 
1209  default:
1210  elog(ERROR, "unrecognized shared classId: %u", classId);
1211  }
1212 }
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1511
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2113
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1018
@ AUTHOID
Definition: syscache.h:45
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:186

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

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

◆ shdepReassignOwned()

void shdepReassignOwned ( List relids,
Oid  newrole 
)

Definition at line 1447 of file pg_shdepend.c.

1448 {
1449  Relation sdepRel;
1450  ListCell *cell;
1451 
1452  /*
1453  * We don't need this strong a lock here, but we'll call routines that
1454  * acquire RowExclusiveLock. Better get that right now to avoid potential
1455  * deadlock problems.
1456  */
1457  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1458 
1459  foreach(cell, roleids)
1460  {
1461  SysScanDesc scan;
1462  ScanKeyData key[2];
1463  HeapTuple tuple;
1464  Oid roleid = lfirst_oid(cell);
1465 
1466  /* Refuse to work on pinned roles */
1467  if (IsPinnedObject(AuthIdRelationId, roleid))
1468  {
1469  ObjectAddress obj;
1470 
1471  obj.classId = AuthIdRelationId;
1472  obj.objectId = roleid;
1473  obj.objectSubId = 0;
1474 
1475  ereport(ERROR,
1476  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1477  errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system",
1478  getObjectDescription(&obj, false))));
1479 
1480  /*
1481  * There's no need to tell the whole truth, which is that we
1482  * didn't track these dependencies at all ...
1483  */
1484  }
1485 
1486  ScanKeyInit(&key[0],
1487  Anum_pg_shdepend_refclassid,
1488  BTEqualStrategyNumber, F_OIDEQ,
1489  ObjectIdGetDatum(AuthIdRelationId));
1490  ScanKeyInit(&key[1],
1491  Anum_pg_shdepend_refobjid,
1492  BTEqualStrategyNumber, F_OIDEQ,
1493  ObjectIdGetDatum(roleid));
1494 
1495  scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
1496  NULL, 2, key);
1497 
1498  while ((tuple = systable_getnext(scan)) != NULL)
1499  {
1500  Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
1501  MemoryContext cxt,
1502  oldcxt;
1503 
1504  /*
1505  * We only operate on shared objects and objects in the current
1506  * database
1507  */
1508  if (sdepForm->dbid != MyDatabaseId &&
1509  sdepForm->dbid != InvalidOid)
1510  continue;
1511 
1512  /* We leave non-owner dependencies alone */
1513  if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
1514  continue;
1515 
1516  /*
1517  * The various ALTER OWNER routines tend to leak memory in
1518  * CurrentMemoryContext. That's not a problem when they're only
1519  * called once per command; but in this usage where we might be
1520  * touching many objects, it can amount to a serious memory leak.
1521  * Fix that by running each call in a short-lived context.
1522  */
1524  "shdepReassignOwned",
1526  oldcxt = MemoryContextSwitchTo(cxt);
1527 
1528  /* Issue the appropriate ALTER OWNER call */
1529  switch (sdepForm->classid)
1530  {
1531  case TypeRelationId:
1532  AlterTypeOwner_oid(sdepForm->objid, newrole, true);
1533  break;
1534 
1535  case NamespaceRelationId:
1536  AlterSchemaOwner_oid(sdepForm->objid, newrole);
1537  break;
1538 
1539  case RelationRelationId:
1540 
1541  /*
1542  * Pass recursing = true so that we don't fail on indexes,
1543  * owned sequences, etc when we happen to visit them
1544  * before their parent table.
1545  */
1546  ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
1547  break;
1548 
1549  case DefaultAclRelationId:
1550 
1551  /*
1552  * Ignore default ACLs; they should be handled by DROP
1553  * OWNED, not REASSIGN OWNED.
1554  */
1555  break;
1556 
1557  case UserMappingRelationId:
1558  /* ditto */
1559  break;
1560 
1561  case ForeignServerRelationId:
1562  AlterForeignServerOwner_oid(sdepForm->objid, newrole);
1563  break;
1564 
1565  case ForeignDataWrapperRelationId:
1566  AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
1567  break;
1568 
1569  case EventTriggerRelationId:
1570  AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
1571  break;
1572 
1573  case PublicationRelationId:
1574  AlterPublicationOwner_oid(sdepForm->objid, newrole);
1575  break;
1576 
1577  case SubscriptionRelationId:
1578  AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
1579  break;
1580 
1581  /* Generic alter owner cases */
1582  case CollationRelationId:
1583  case ConversionRelationId:
1584  case OperatorRelationId:
1585  case ProcedureRelationId:
1586  case LanguageRelationId:
1587  case LargeObjectRelationId:
1588  case OperatorFamilyRelationId:
1589  case OperatorClassRelationId:
1590  case ExtensionRelationId:
1591  case StatisticExtRelationId:
1592  case TableSpaceRelationId:
1593  case DatabaseRelationId:
1594  case TSConfigRelationId:
1595  case TSDictionaryRelationId:
1596  {
1597  Oid classId = sdepForm->classid;
1598  Relation catalog;
1599 
1600  if (classId == LargeObjectRelationId)
1601  classId = LargeObjectMetadataRelationId;
1602 
1603  catalog = table_open(classId, RowExclusiveLock);
1604 
1605  AlterObjectOwner_internal(catalog, sdepForm->objid,
1606  newrole);
1607 
1608  table_close(catalog, NoLock);
1609  }
1610  break;
1611 
1612  default:
1613  elog(ERROR, "unexpected classid %u", sdepForm->classid);
1614  break;
1615  }
1616 
1617  /* Clean up */
1618  MemoryContextSwitchTo(oldcxt);
1619  MemoryContextDelete(cxt);
1620 
1621  /* Make sure the next iteration will see my changes */
1623  }
1624 
1625  systable_endscan(scan);
1626  }
1627 
1628  table_close(sdepRel, RowExclusiveLock);
1629 }
void AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
Definition: alter.c:935
void AlterEventTriggerOwner_oid(Oid trigOid, Oid newOwnerId)
void AlterForeignServerOwner_oid(Oid srvId, Oid newOwnerId)
Definition: foreigncmds.c:450
void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId)
Definition: foreigncmds.c:313
#define NoLock
Definition: lockdefs.h:34
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void AlterPublicationOwner_oid(Oid subid, Oid newOwnerId)
void AlterSchemaOwner_oid(Oid oid, Oid newOwnerId)
Definition: schemacmds.c:277
void AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
Definition: tablecmds.c:13620
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3787
void CommandCounterIncrement(void)
Definition: xact.c:1073

References AccessExclusiveLock, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, AlterEventTriggerOwner_oid(), AlterForeignDataWrapperOwner_oid(), AlterForeignServerOwner_oid(), AlterObjectOwner_internal(), AlterPublicationOwner_oid(), AlterSchemaOwner_oid(), AlterSubscriptionOwner_oid(), AlterTypeOwner_oid(), ATExecChangeOwner(), BTEqualStrategyNumber, ObjectAddress::classId, CommandCounterIncrement(), CurrentMemoryContext, elog, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, InvalidOid, IsPinnedObject(), sort-test::key, lfirst_oid, MemoryContextDelete(), MemoryContextSwitchTo(), MyDatabaseId, NoLock, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_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 2728 of file dependency.c.

2729 {
2730  if (addrs->numrefs > 1)
2731  qsort((void *) addrs->refs, addrs->numrefs,
2732  sizeof(ObjectAddress),
2734 }
static int object_address_comparator(const void *a, const void *b)
Definition: dependency.c:2401

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

Referenced by shdepDropOwned().

◆ updateAclDependencies()

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

Definition at line 481 of file pg_shdepend.c.

485 {
486  Relation sdepRel;
487  int i;
488 
489  /*
490  * Remove entries that are common to both lists; those represent existing
491  * dependencies we don't need to change.
492  *
493  * OK to overwrite the inputs since we'll pfree them anyway.
494  */
495  getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers);
496 
497  if (noldmembers > 0 || nnewmembers > 0)
498  {
499  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
500 
501  /* Add new dependencies that weren't already present */
502  for (i = 0; i < nnewmembers; i++)
503  {
504  Oid roleid = newmembers[i];
505 
506  /*
507  * Skip the owner: he has an OWNER shdep entry instead. (This is
508  * not just a space optimization; it makes ALTER OWNER easier. See
509  * notes in changeDependencyOnOwner.)
510  */
511  if (roleid == ownerId)
512  continue;
513 
514  /* Skip pinned roles; they don't need dependency entries */
515  if (IsPinnedObject(AuthIdRelationId, roleid))
516  continue;
517 
518  shdepAddDependency(sdepRel, classId, objectId, objsubId,
519  AuthIdRelationId, roleid,
521  }
522 
523  /* Drop no-longer-used old dependencies */
524  for (i = 0; i < noldmembers; i++)
525  {
526  Oid roleid = oldmembers[i];
527 
528  /* Skip the owner, same as above */
529  if (roleid == ownerId)
530  continue;
531 
532  /* Skip pinned roles */
533  if (IsPinnedObject(AuthIdRelationId, roleid))
534  continue;
535 
536  shdepDropDependency(sdepRel, classId, objectId, objsubId,
537  false, /* exact match on objsubId */
538  AuthIdRelationId, roleid,
540  }
541 
542  table_close(sdepRel, RowExclusiveLock);
543  }
544 
545  if (oldmembers)
546  pfree(oldmembers);
547  if (newmembers)
548  pfree(newmembers);
549 }
static void getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2)
Definition: pg_shdepend.c:411

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

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