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_ROLE_MEMBERSHIP , OCLASS_DATABASE , OCLASS_TBLSPACE ,
  OCLASS_FDW , OCLASS_FOREIGN_SERVER , OCLASS_USER_MAPPING , OCLASS_DEFACL ,
  OCLASS_EXTENSION , OCLASS_EVENT_TRIGGER , OCLASS_PARAMETER_ACL , 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)
 
void checkMembershipInCurrentExtension (const ObjectAddress *object)
 
long deleteDependencyRecordsFor (Oid classId, Oid objectId, bool skipExtensionDeps)
 
long deleteDependencyRecordsForClass (Oid classId, Oid objectId, Oid refclassId, char deptype)
 
long deleteDependencyRecordsForSpecific (Oid classId, Oid objectId, char deptype, Oid refclassId, Oid refobjectId)
 
long changeDependencyFor (Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
 
long changeDependenciesOf (Oid classId, Oid oldObjectId, Oid newObjectId)
 
long changeDependenciesOn (Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
 
Oid getExtensionOfObject (Oid classId, Oid objectId)
 
ListgetAutoExtensionsOfObject (Oid classId, Oid objectId)
 
bool sequenceIsOwned (Oid seqId, char deptype, Oid *tableId, int32 *colId)
 
ListgetOwnedSequences (Oid relid)
 
Oid getIdentitySequence (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 objsubId, 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 *roleids, DropBehavior behavior)
 
void shdepReassignOwned (List *roleids, Oid newrole)
 

Macro Definition Documentation

◆ LAST_OCLASS

#define LAST_OCLASS   OCLASS_TRANSFORM

Definition at line 133 of file dependency.h.

◆ PERFORM_DELETION_CONCURRENT_LOCK

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

Definition at line 141 of file dependency.h.

◆ PERFORM_DELETION_CONCURRENTLY

#define PERFORM_DELETION_CONCURRENTLY   0x0002 /* concurrent drop */

Definition at line 137 of file dependency.h.

◆ PERFORM_DELETION_INTERNAL

#define PERFORM_DELETION_INTERNAL   0x0001 /* internal action */

Definition at line 136 of file dependency.h.

◆ PERFORM_DELETION_QUIETLY

#define PERFORM_DELETION_QUIETLY   0x0004 /* suppress notices */

Definition at line 138 of file dependency.h.

◆ PERFORM_DELETION_SKIP_EXTENSIONS

#define PERFORM_DELETION_SKIP_EXTENSIONS   0x0010 /* keep extensions */

Definition at line 140 of file dependency.h.

◆ PERFORM_DELETION_SKIP_ORIGINAL

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

Definition at line 139 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_ROLE_MEMBERSHIP 
OCLASS_DATABASE 
OCLASS_TBLSPACE 
OCLASS_FDW 
OCLASS_FOREIGN_SERVER 
OCLASS_USER_MAPPING 
OCLASS_DEFACL 
OCLASS_EXTENSION 
OCLASS_EVENT_TRIGGER 
OCLASS_PARAMETER_ACL 
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_ROLE_MEMBERSHIP, /* pg_auth_members */
116  OCLASS_DATABASE, /* pg_database */
117  OCLASS_TBLSPACE, /* pg_tablespace */
118  OCLASS_FDW, /* pg_foreign_data_wrapper */
119  OCLASS_FOREIGN_SERVER, /* pg_foreign_server */
120  OCLASS_USER_MAPPING, /* pg_user_mapping */
121  OCLASS_DEFACL, /* pg_default_acl */
122  OCLASS_EXTENSION, /* pg_extension */
123  OCLASS_EVENT_TRIGGER, /* pg_event_trigger */
124  OCLASS_PARAMETER_ACL, /* pg_parameter_acl */
125  OCLASS_POLICY, /* pg_policy */
126  OCLASS_PUBLICATION, /* pg_publication */
127  OCLASS_PUBLICATION_NAMESPACE, /* pg_publication_namespace */
128  OCLASS_PUBLICATION_REL, /* pg_publication_rel */
129  OCLASS_SUBSCRIPTION, /* pg_subscription */
130  OCLASS_TRANSFORM /* pg_transform */
131 } ObjectClass;
ObjectClass
Definition: dependency.h:89
@ OCLASS_OPERATOR
Definition: dependency.h:100
@ OCLASS_PARAMETER_ACL
Definition: dependency.h:124
@ OCLASS_LARGEOBJECT
Definition: dependency.h:99
@ OCLASS_FDW
Definition: dependency.h:118
@ OCLASS_OPFAMILY
Definition: dependency.h:102
@ OCLASS_DEFACL
Definition: dependency.h:121
@ 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:117
@ 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:129
@ OCLASS_PUBLICATION_NAMESPACE
Definition: dependency.h:127
@ OCLASS_EXTENSION
Definition: dependency.h:122
@ OCLASS_COLLATION
Definition: dependency.h:94
@ OCLASS_FOREIGN_SERVER
Definition: dependency.h:119
@ 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:116
@ OCLASS_ROLE_MEMBERSHIP
Definition: dependency.h:115
@ OCLASS_SCHEMA
Definition: dependency.h:108
@ OCLASS_EVENT_TRIGGER
Definition: dependency.h:123
@ OCLASS_CLASS
Definition: dependency.h:90
@ OCLASS_TRANSFORM
Definition: dependency.h:130
@ OCLASS_ROLE
Definition: dependency.h:114
@ OCLASS_CONSTRAINT
Definition: dependency.h:95
@ OCLASS_POLICY
Definition: dependency.h:125
@ OCLASS_USER_MAPPING
Definition: dependency.h:120
@ OCLASS_PUBLICATION_REL
Definition: dependency.h:128
@ OCLASS_AM
Definition: dependency.h:103
@ OCLASS_TSDICT
Definition: dependency.h:111
@ OCLASS_PUBLICATION
Definition: dependency.h:126
@ 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 1545 of file dependency.c.

1546 {
1547  if (object->classId == RelationRelationId)
1548  {
1549  /*
1550  * In DROP INDEX CONCURRENTLY, take only ShareUpdateExclusiveLock on
1551  * the index for the moment. index_drop() will promote the lock once
1552  * it's safe to do so. In all other cases we need full exclusive
1553  * lock.
1554  */
1555  if (flags & PERFORM_DELETION_CONCURRENTLY)
1557  else
1559  }
1560  else if (object->classId == AuthMemRelationId)
1561  LockSharedObject(object->classId, object->objectId, 0,
1563  else
1564  {
1565  /* assume we should lock the whole object not a sub-object */
1566  LockDatabaseObject(object->classId, object->objectId, 0,
1568  }
1569 }
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:137
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1046
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1005
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(), LockSharedObject(), ObjectAddressStack::object, ObjectAddress::objectId, PERFORM_DELETION_CONCURRENTLY, and ShareUpdateExclusiveLock.

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

◆ add_exact_object_address()

void add_exact_object_address ( const ObjectAddress object,
ObjectAddresses addrs 
)

Definition at line 2581 of file dependency.c.

2583 {
2584  ObjectAddress *item;
2585 
2586  /* enlarge array if needed */
2587  if (addrs->numrefs >= addrs->maxrefs)
2588  {
2589  addrs->maxrefs *= 2;
2590  addrs->refs = (ObjectAddress *)
2591  repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2592  Assert(!addrs->extras);
2593  }
2594  /* record this item */
2595  item = addrs->refs + addrs->numrefs;
2596  *item = *object;
2597  addrs->numrefs++;
2598 }
Assert(fmt[strlen(fmt) - 1] !='\n')
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476
ObjectAddressExtra * extras
Definition: dependency.c:117
ObjectAddress * refs
Definition: dependency.c:116

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

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

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

Referenced by index_concurrently_swap().

◆ changeDependenciesOn()

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

Definition at line 620 of file pg_depend.c.

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

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

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

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

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

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

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

Referenced by SetRelationTableSpace().

◆ checkMembershipInCurrentExtension()

void checkMembershipInCurrentExtension ( const ObjectAddress object)

Definition at line 257 of file pg_depend.c.

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

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

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

◆ checkSharedDependencies()

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

Definition at line 631 of file pg_shdepend.c.

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

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

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

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

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

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

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

◆ deleteDependencyRecordsForClass()

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

Definition at line 350 of file pg_depend.c.

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

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

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

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

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

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

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

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 954 of file pg_shdepend.c.

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

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

969 {
970  Oid constraintId = InvalidOid;
971  Relation depRel;
972  ScanKeyData key[3];
973  SysScanDesc scan;
974  HeapTuple tup;
975 
976  /* Search the dependency table for the index */
977  depRel = table_open(DependRelationId, AccessShareLock);
978 
979  ScanKeyInit(&key[0],
980  Anum_pg_depend_classid,
981  BTEqualStrategyNumber, F_OIDEQ,
982  ObjectIdGetDatum(RelationRelationId));
983  ScanKeyInit(&key[1],
984  Anum_pg_depend_objid,
985  BTEqualStrategyNumber, F_OIDEQ,
986  ObjectIdGetDatum(indexId));
987  ScanKeyInit(&key[2],
988  Anum_pg_depend_objsubid,
989  BTEqualStrategyNumber, F_INT4EQ,
990  Int32GetDatum(0));
991 
992  scan = systable_beginscan(depRel, DependDependerIndexId, true,
993  NULL, 3, key);
994 
995  while (HeapTupleIsValid(tup = systable_getnext(scan)))
996  {
997  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
998 
999  /*
1000  * We assume any internal dependency on a constraint must be what we
1001  * are looking for.
1002  */
1003  if (deprec->refclassid == ConstraintRelationId &&
1004  deprec->refobjsubid == 0 &&
1005  deprec->deptype == DEPENDENCY_INTERNAL)
1006  {
1007  constraintId = deprec->refobjid;
1008  break;
1009  }
1010  }
1011 
1012  systable_endscan(scan);
1013  table_close(depRel, AccessShareLock);
1014 
1015  return constraintId;
1016 }
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212

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

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

◆ get_index_ref_constraints()

List* get_index_ref_constraints ( Oid  indexId)

Definition at line 1024 of file pg_depend.c.

1025 {
1026  List *result = NIL;
1027  Relation depRel;
1028  ScanKeyData key[3];
1029  SysScanDesc scan;
1030  HeapTuple tup;
1031 
1032  /* Search the dependency table for the index */
1033  depRel = table_open(DependRelationId, AccessShareLock);
1034 
1035  ScanKeyInit(&key[0],
1036  Anum_pg_depend_refclassid,
1037  BTEqualStrategyNumber, F_OIDEQ,
1038  ObjectIdGetDatum(RelationRelationId));
1039  ScanKeyInit(&key[1],
1040  Anum_pg_depend_refobjid,
1041  BTEqualStrategyNumber, F_OIDEQ,
1042  ObjectIdGetDatum(indexId));
1043  ScanKeyInit(&key[2],
1044  Anum_pg_depend_refobjsubid,
1045  BTEqualStrategyNumber, F_INT4EQ,
1046  Int32GetDatum(0));
1047 
1048  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1049  NULL, 3, key);
1050 
1051  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1052  {
1053  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1054 
1055  /*
1056  * We assume any normal dependency from a constraint must be what we
1057  * are looking for.
1058  */
1059  if (deprec->classid == ConstraintRelationId &&
1060  deprec->objsubid == 0 &&
1061  deprec->deptype == DEPENDENCY_NORMAL)
1062  {
1063  result = lappend_oid(result, deprec->objid);
1064  }
1065  }
1066 
1067  systable_endscan(scan);
1068  table_close(depRel, AccessShareLock);
1069 
1070  return result;
1071 }
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374

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

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

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

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

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

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

◆ getIdentitySequence()

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

Definition at line 944 of file pg_depend.c.

945 {
947 
948  if (list_length(seqlist) > 1)
949  elog(ERROR, "more than one owned sequence found");
950  else if (seqlist == NIL)
951  {
952  if (missing_ok)
953  return InvalidOid;
954  else
955  elog(ERROR, "no owned sequence found");
956  }
957 
958  return linitial_oid(seqlist);
959 }
int16 attnum
Definition: pg_attribute.h:74
static List * getOwnedSequences_internal(Oid relid, AttrNumber attnum, char deptype)
Definition: pg_depend.c:876
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_oid(l)
Definition: pg_list.h:180

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

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

◆ getObjectClass()

ObjectClass getObjectClass ( const ObjectAddress object)

Definition at line 2836 of file dependency.c.

2837 {
2838  /* only pg_class entries can have nonzero objectSubId */
2839  if (object->classId != RelationRelationId &&
2840  object->objectSubId != 0)
2841  elog(ERROR, "invalid non-zero objectSubId for object class %u",
2842  object->classId);
2843 
2844  switch (object->classId)
2845  {
2846  case RelationRelationId:
2847  /* caller must check objectSubId */
2848  return OCLASS_CLASS;
2849 
2850  case ProcedureRelationId:
2851  return OCLASS_PROC;
2852 
2853  case TypeRelationId:
2854  return OCLASS_TYPE;
2855 
2856  case CastRelationId:
2857  return OCLASS_CAST;
2858 
2859  case CollationRelationId:
2860  return OCLASS_COLLATION;
2861 
2862  case ConstraintRelationId:
2863  return OCLASS_CONSTRAINT;
2864 
2865  case ConversionRelationId:
2866  return OCLASS_CONVERSION;
2867 
2868  case AttrDefaultRelationId:
2869  return OCLASS_DEFAULT;
2870 
2871  case LanguageRelationId:
2872  return OCLASS_LANGUAGE;
2873 
2874  case LargeObjectRelationId:
2875  return OCLASS_LARGEOBJECT;
2876 
2877  case OperatorRelationId:
2878  return OCLASS_OPERATOR;
2879 
2880  case OperatorClassRelationId:
2881  return OCLASS_OPCLASS;
2882 
2883  case OperatorFamilyRelationId:
2884  return OCLASS_OPFAMILY;
2885 
2886  case AccessMethodRelationId:
2887  return OCLASS_AM;
2888 
2889  case AccessMethodOperatorRelationId:
2890  return OCLASS_AMOP;
2891 
2892  case AccessMethodProcedureRelationId:
2893  return OCLASS_AMPROC;
2894 
2895  case RewriteRelationId:
2896  return OCLASS_REWRITE;
2897 
2898  case TriggerRelationId:
2899  return OCLASS_TRIGGER;
2900 
2901  case NamespaceRelationId:
2902  return OCLASS_SCHEMA;
2903 
2904  case StatisticExtRelationId:
2905  return OCLASS_STATISTIC_EXT;
2906 
2907  case TSParserRelationId:
2908  return OCLASS_TSPARSER;
2909 
2910  case TSDictionaryRelationId:
2911  return OCLASS_TSDICT;
2912 
2913  case TSTemplateRelationId:
2914  return OCLASS_TSTEMPLATE;
2915 
2916  case TSConfigRelationId:
2917  return OCLASS_TSCONFIG;
2918 
2919  case AuthIdRelationId:
2920  return OCLASS_ROLE;
2921 
2922  case AuthMemRelationId:
2923  return OCLASS_ROLE_MEMBERSHIP;
2924 
2925  case DatabaseRelationId:
2926  return OCLASS_DATABASE;
2927 
2928  case TableSpaceRelationId:
2929  return OCLASS_TBLSPACE;
2930 
2931  case ForeignDataWrapperRelationId:
2932  return OCLASS_FDW;
2933 
2934  case ForeignServerRelationId:
2935  return OCLASS_FOREIGN_SERVER;
2936 
2937  case UserMappingRelationId:
2938  return OCLASS_USER_MAPPING;
2939 
2940  case DefaultAclRelationId:
2941  return OCLASS_DEFACL;
2942 
2943  case ExtensionRelationId:
2944  return OCLASS_EXTENSION;
2945 
2946  case EventTriggerRelationId:
2947  return OCLASS_EVENT_TRIGGER;
2948 
2949  case ParameterAclRelationId:
2950  return OCLASS_PARAMETER_ACL;
2951 
2952  case PolicyRelationId:
2953  return OCLASS_POLICY;
2954 
2955  case PublicationNamespaceRelationId:
2957 
2958  case PublicationRelationId:
2959  return OCLASS_PUBLICATION;
2960 
2961  case PublicationRelRelationId:
2962  return OCLASS_PUBLICATION_REL;
2963 
2964  case SubscriptionRelationId:
2965  return OCLASS_SUBSCRIPTION;
2966 
2967  case TransformRelationId:
2968  return OCLASS_TRANSFORM;
2969  }
2970 
2971  /* shouldn't get here */
2972  elog(ERROR, "unrecognized object class: %u", object->classId);
2973  return OCLASS_CLASS; /* keep compiler quiet */
2974 }

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_PARAMETER_ACL, OCLASS_POLICY, OCLASS_PROC, OCLASS_PUBLICATION, OCLASS_PUBLICATION_NAMESPACE, OCLASS_PUBLICATION_REL, OCLASS_REWRITE, OCLASS_ROLE, OCLASS_ROLE_MEMBERSHIP, 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 935 of file pg_depend.c.

936 {
937  return getOwnedSequences_internal(relid, 0, 0);
938 }

References getOwnedSequences_internal().

Referenced by ATRewriteTables(), and ExecuteTruncateGuts().

◆ new_object_addresses()

◆ object_address_present()

bool object_address_present ( const ObjectAddress object,
const ObjectAddresses addrs 
)

Definition at line 2641 of file dependency.c.

2643 {
2644  int i;
2645 
2646  for (i = addrs->numrefs - 1; i >= 0; i--)
2647  {
2648  const ObjectAddress *thisobj = addrs->refs + i;
2649 
2650  if (object->classId == thisobj->classId &&
2651  object->objectId == thisobj->objectId)
2652  {
2653  if (object->objectSubId == thisobj->objectSubId ||
2654  thisobj->objectSubId == 0)
2655  return true;
2656  }
2657  }
2658 
2659  return false;
2660 }

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

330 {
331  Relation depRel;
332  ObjectAddresses *targetObjects;
333 
334  /*
335  * We save some cycles by opening pg_depend just once and passing the
336  * Relation pointer down to all the recursive deletion steps.
337  */
338  depRel = table_open(DependRelationId, RowExclusiveLock);
339 
340  /*
341  * Acquire deletion lock on the target object. (Ideally the caller has
342  * done this already, but many places are sloppy about it.)
343  */
344  AcquireDeletionLock(object, 0);
345 
346  /*
347  * Construct a list of objects to delete (ie, the given object plus
348  * everything directly or indirectly dependent on it).
349  */
350  targetObjects = new_object_addresses();
351 
352  findDependentObjects(object,
354  flags,
355  NULL, /* empty stack */
356  targetObjects,
357  NULL, /* no pendingObjects */
358  &depRel);
359 
360  /*
361  * Check if deletion is allowed, and report about cascaded deletes.
362  */
363  reportDependentObjects(targetObjects,
364  behavior,
365  flags,
366  object);
367 
368  /* do the deed */
369  deleteObjectsInList(targetObjects, &depRel, flags);
370 
371  /* And clean up */
372  free_object_addresses(targetObjects);
373 
374  table_close(depRel, RowExclusiveLock);
375 }
void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1545
#define DEPFLAG_ORIGINAL
Definition: dependency.c:102
static void reportDependentObjects(const ObjectAddresses *targetObjects, DropBehavior behavior, int flags, const ObjectAddress *origObject)
Definition: dependency.c:1029
static void findDependentObjects(const ObjectAddress *object, int objflags, int flags, ObjectAddressStack *stack, ObjectAddresses *targetObjects, const ObjectAddresses *pendingObjects, Relation *depRel)
Definition: dependency.c:487
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2532
static void deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, int flags)
Definition: dependency.c:240
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2821

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(), 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 387 of file dependency.c.

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

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

2793 {
2795  recordMultipleDependencies(depender,
2796  referenced->refs, referenced->numrefs,
2797  behavior);
2798 }
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs)
Definition: dependency.c:2428
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 192 of file pg_depend.c.

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

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

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

◆ recordDependencyOnExpr()

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

Definition at line 1602 of file dependency.c.

1605 {
1607 
1608  context.addrs = new_object_addresses();
1609 
1610  /* Set up interpretation for Vars at varlevelsup = 0 */
1611  context.rtables = list_make1(rtable);
1612 
1613  /* Scan the expression tree for referenceable objects */
1614  find_expr_references_walker(expr, &context);
1615 
1616  /* Remove any duplicates */
1618 
1619  /* And record 'em */
1620  recordMultipleDependencies(depender,
1621  context.addrs->refs, context.addrs->numrefs,
1622  behavior);
1623 
1624  free_object_addresses(context.addrs);
1625 }
static bool find_expr_references_walker(Node *node, find_expr_references_context *context)
Definition: dependency.c:1747
#define list_make1(x1)
Definition: pg_list.h:212
ObjectAddresses * addrs
Definition: dependency.c:142

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

1650 {
1652  RangeTblEntry rte = {0};
1653 
1654  context.addrs = new_object_addresses();
1655 
1656  /* We gin up a rather bogus rangetable list to handle Vars */
1657  rte.type = T_RangeTblEntry;
1658  rte.rtekind = RTE_RELATION;
1659  rte.relid = relId;
1660  rte.relkind = RELKIND_RELATION; /* no need for exactness here */
1662 
1663  context.rtables = list_make1(list_make1(&rte));
1664 
1665  /* Scan the expression tree for referenceable objects */
1666  find_expr_references_walker(expr, &context);
1667 
1668  /* Remove any duplicates */
1670 
1671  /* Separate self-dependencies if necessary */
1672  if ((behavior != self_behavior || reverse_self) &&
1673  context.addrs->numrefs > 0)
1674  {
1675  ObjectAddresses *self_addrs;
1676  ObjectAddress *outobj;
1677  int oldref,
1678  outrefs;
1679 
1680  self_addrs = new_object_addresses();
1681 
1682  outobj = context.addrs->refs;
1683  outrefs = 0;
1684  for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
1685  {
1686  ObjectAddress *thisobj = context.addrs->refs + oldref;
1687 
1688  if (thisobj->classId == RelationRelationId &&
1689  thisobj->objectId == relId)
1690  {
1691  /* Move this ref into self_addrs */
1692  add_exact_object_address(thisobj, self_addrs);
1693  }
1694  else
1695  {
1696  /* Keep it in context.addrs */
1697  *outobj = *thisobj;
1698  outobj++;
1699  outrefs++;
1700  }
1701  }
1702  context.addrs->numrefs = outrefs;
1703 
1704  /* Record the self-dependencies with the appropriate direction */
1705  if (!reverse_self)
1706  recordMultipleDependencies(depender,
1707  self_addrs->refs, self_addrs->numrefs,
1708  self_behavior);
1709  else
1710  {
1711  /* Can't use recordMultipleDependencies, so do it the hard way */
1712  int selfref;
1713 
1714  for (selfref = 0; selfref < self_addrs->numrefs; selfref++)
1715  {
1716  ObjectAddress *thisobj = self_addrs->refs + selfref;
1717 
1718  recordDependencyOn(thisobj, depender, self_behavior);
1719  }
1720  }
1721 
1722  free_object_addresses(self_addrs);
1723  }
1724 
1725  /* Record the external dependencies */
1726  recordMultipleDependencies(depender,
1727  context.addrs->refs, context.addrs->numrefs,
1728  behavior);
1729 
1730  free_object_addresses(context.addrs);
1731 }
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2581
@ RTE_RELATION
Definition: parsenodes.h:1014
RTEKind rtekind
Definition: parsenodes.h:1033

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, new_object_addresses(), ObjectAddresses::numrefs, ObjectAddress::objectId, recordDependencyOn(), recordMultipleDependencies(), ObjectAddresses::refs, RangeTblEntry::relid, RangeTblEntry::relkind, RangeTblEntry::rellockmode, find_expr_references_context::rtables, RTE_RELATION, and RangeTblEntry::rtekind.

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

◆ recordDependencyOnTablespace()

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

Definition at line 361 of file pg_shdepend.c.

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

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:988
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:414
FormData_pg_depend
Definition: pg_depend.h:65
static Datum CharGetDatum(char X)
Definition: postgres.h:122

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

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

◆ recordSharedDependencyOn()

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

Definition at line 122 of file pg_shdepend.c.

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

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

1578 {
1579  if (object->classId == RelationRelationId)
1581  else
1582  /* assume we should lock the whole object not a sub-object */
1583  UnlockDatabaseObject(object->classId, object->objectId, 0,
1585 }
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:228
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1026

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

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

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

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

◆ shdepDropOwned()

void shdepDropOwned ( List roleids,
DropBehavior  behavior 
)

Definition at line 1295 of file pg_shdepend.c.

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

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

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 roleids,
Oid  newrole 
)

Definition at line 1468 of file pg_shdepend.c.

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

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

2810 {
2811  if (addrs->numrefs > 1)
2812  qsort(addrs->refs, addrs->numrefs,
2813  sizeof(ObjectAddress),
2815 }
static int object_address_comparator(const void *a, const void *b)
Definition: dependency.c:2488

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

Referenced by shdepDropOwned().

◆ updateAclDependencies()

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

Definition at line 482 of file pg_shdepend.c.

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

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

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