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

Go to the source code of this file.

Macros

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

Typedefs

typedef enum DependencyType DependencyType
 
typedef enum SharedDependencyType SharedDependencyType
 
typedef struct ObjectAddresses ObjectAddresses
 
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

◆ PERFORM_DELETION_CONCURRENT_LOCK

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

Definition at line 139 of file dependency.h.

◆ PERFORM_DELETION_CONCURRENTLY

#define PERFORM_DELETION_CONCURRENTLY   0x0002 /* concurrent drop */

Definition at line 135 of file dependency.h.

◆ PERFORM_DELETION_INTERNAL

#define PERFORM_DELETION_INTERNAL   0x0001 /* internal action */

Definition at line 134 of file dependency.h.

◆ PERFORM_DELETION_QUIETLY

#define PERFORM_DELETION_QUIETLY   0x0004 /* suppress notices */

Definition at line 136 of file dependency.h.

◆ PERFORM_DELETION_SKIP_EXTENSIONS

#define PERFORM_DELETION_SKIP_EXTENSIONS   0x0010 /* keep extensions */

Definition at line 138 of file dependency.h.

◆ PERFORM_DELETION_SKIP_ORIGINAL

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

Definition at line 137 of file dependency.h.

Typedef Documentation

◆ DependencyType

◆ ObjectAddresses

Definition at line 1 of file dependency.h.

◆ ObjectClass

typedef enum ObjectClass ObjectClass

◆ SharedDependencyType

Enumeration Type Documentation

◆ DependencyType

Enumerator
DEPENDENCY_NORMAL 
DEPENDENCY_AUTO 
DEPENDENCY_INTERNAL 
DEPENDENCY_PARTITION_PRI 
DEPENDENCY_PARTITION_SEC 
DEPENDENCY_EXTENSION 
DEPENDENCY_AUTO_EXTENSION 

Definition at line 31 of file dependency.h.

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

◆ ObjectClass

Enumerator
OCLASS_CLASS 
OCLASS_PROC 
OCLASS_TYPE 
OCLASS_CAST 
OCLASS_COLLATION 
OCLASS_CONSTRAINT 
OCLASS_CONVERSION 
OCLASS_DEFAULT 
OCLASS_LANGUAGE 
OCLASS_LARGEOBJECT 
OCLASS_OPERATOR 
OCLASS_OPCLASS 
OCLASS_OPFAMILY 
OCLASS_AM 
OCLASS_AMOP 
OCLASS_AMPROC 
OCLASS_REWRITE 
OCLASS_TRIGGER 
OCLASS_SCHEMA 
OCLASS_STATISTIC_EXT 
OCLASS_TSPARSER 
OCLASS_TSDICT 
OCLASS_TSTEMPLATE 
OCLASS_TSCONFIG 
OCLASS_ROLE 
OCLASS_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 1496 of file dependency.c.

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

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

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

◆ add_exact_object_address()

void add_exact_object_address ( const ObjectAddress object,
ObjectAddresses addrs 
)

Definition at line 2529 of file dependency.c.

2531 {
2532  ObjectAddress *item;
2533 
2534  /* enlarge array if needed */
2535  if (addrs->numrefs >= addrs->maxrefs)
2536  {
2537  addrs->maxrefs *= 2;
2538  addrs->refs = (ObjectAddress *)
2539  repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2540  Assert(!addrs->extras);
2541  }
2542  /* record this item */
2543  item = addrs->refs + addrs->numrefs;
2544  *item = *object;
2545  addrs->numrefs++;
2546 }
Assert(fmt[strlen(fmt) - 1] !='\n')
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1528
ObjectAddressExtra * extras
Definition: dependency.c:116
ObjectAddress * refs
Definition: dependency.c:115

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

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

◆ changeDependenciesOf()

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

Definition at line 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:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:72
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

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

Referenced by index_concurrently_swap().

◆ changeDependenciesOn()

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

Definition at line 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:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#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(), AlterTypeNamespaceInternal(), and swap_relation_files().

◆ changeDependencyOnOwner()

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

Definition at line 308 of file pg_shdepend.c.

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

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

378 {
379  Relation sdepRel;
380 
381  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
382 
383  if (newTablespaceId != DEFAULTTABLESPACE_OID &&
384  newTablespaceId != InvalidOid)
385  shdepChangeDep(sdepRel,
386  classId, objectId, 0,
387  TableSpaceRelationId, newTablespaceId,
389  else
390  shdepDropDependency(sdepRel,
391  classId, objectId, 0, true,
394 
395  table_close(sdepRel, RowExclusiveLock);
396 }
#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:1205
bool creating_extension
Definition: extension.c:71
Oid CurrentExtensionObject
Definition: extension.c:72
char * get_extension_name(Oid ext_oid)
Definition: extension.c:190
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition: pg_depend.c: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 626 of file pg_shdepend.c.

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

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

Referenced by DropRole(), and DropTableSpace().

◆ copyTemplateDependencies()

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)

Definition at line 845 of file pg_shdepend.c.

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

◆ deleteDependencyRecordsForClass()

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

Definition at line 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(), ExecAlterExtensionContentsRecurse(), index_constraint_create(), IndexSetParentIndex(), process_owned_by(), and TriggerSetParentTrigger().

◆ deleteDependencyRecordsForSpecific()

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

Definition at line 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 997 of file pg_shdepend.c.

998 {
999  Relation sdepRel;
1000 
1001  sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
1002 
1003  shdepDropDependency(sdepRel, classId, objectId, objectSubId,
1004  (objectSubId == 0),
1007 
1008  table_close(sdepRel, RowExclusiveLock);
1009 }

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

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

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:375

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

Referenced by index_concurrently_swap().

◆ getAutoExtensionsOfObject()

List* getAutoExtensionsOfObject ( Oid  classId,
Oid  objectId 
)

Definition at line 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(), ExecAlterExtensionContentsRecurse(), 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 }
#define elog(elevel,...)
Definition: elog.h:224
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 2784 of file dependency.c.

2785 {
2786  /* only pg_class entries can have nonzero objectSubId */
2787  if (object->classId != RelationRelationId &&
2788  object->objectSubId != 0)
2789  elog(ERROR, "invalid non-zero objectSubId for object class %u",
2790  object->classId);
2791 
2792  switch (object->classId)
2793  {
2794  case RelationRelationId:
2795  /* caller must check objectSubId */
2796  return OCLASS_CLASS;
2797 
2798  case ProcedureRelationId:
2799  return OCLASS_PROC;
2800 
2801  case TypeRelationId:
2802  return OCLASS_TYPE;
2803 
2804  case CastRelationId:
2805  return OCLASS_CAST;
2806 
2807  case CollationRelationId:
2808  return OCLASS_COLLATION;
2809 
2810  case ConstraintRelationId:
2811  return OCLASS_CONSTRAINT;
2812 
2813  case ConversionRelationId:
2814  return OCLASS_CONVERSION;
2815 
2816  case AttrDefaultRelationId:
2817  return OCLASS_DEFAULT;
2818 
2819  case LanguageRelationId:
2820  return OCLASS_LANGUAGE;
2821 
2822  case LargeObjectRelationId:
2823  return OCLASS_LARGEOBJECT;
2824 
2825  case OperatorRelationId:
2826  return OCLASS_OPERATOR;
2827 
2828  case OperatorClassRelationId:
2829  return OCLASS_OPCLASS;
2830 
2831  case OperatorFamilyRelationId:
2832  return OCLASS_OPFAMILY;
2833 
2834  case AccessMethodRelationId:
2835  return OCLASS_AM;
2836 
2837  case AccessMethodOperatorRelationId:
2838  return OCLASS_AMOP;
2839 
2840  case AccessMethodProcedureRelationId:
2841  return OCLASS_AMPROC;
2842 
2843  case RewriteRelationId:
2844  return OCLASS_REWRITE;
2845 
2846  case TriggerRelationId:
2847  return OCLASS_TRIGGER;
2848 
2849  case NamespaceRelationId:
2850  return OCLASS_SCHEMA;
2851 
2852  case StatisticExtRelationId:
2853  return OCLASS_STATISTIC_EXT;
2854 
2855  case TSParserRelationId:
2856  return OCLASS_TSPARSER;
2857 
2858  case TSDictionaryRelationId:
2859  return OCLASS_TSDICT;
2860 
2861  case TSTemplateRelationId:
2862  return OCLASS_TSTEMPLATE;
2863 
2864  case TSConfigRelationId:
2865  return OCLASS_TSCONFIG;
2866 
2867  case AuthIdRelationId:
2868  return OCLASS_ROLE;
2869 
2870  case AuthMemRelationId:
2871  return OCLASS_ROLE_MEMBERSHIP;
2872 
2873  case DatabaseRelationId:
2874  return OCLASS_DATABASE;
2875 
2876  case TableSpaceRelationId:
2877  return OCLASS_TBLSPACE;
2878 
2879  case ForeignDataWrapperRelationId:
2880  return OCLASS_FDW;
2881 
2882  case ForeignServerRelationId:
2883  return OCLASS_FOREIGN_SERVER;
2884 
2885  case UserMappingRelationId:
2886  return OCLASS_USER_MAPPING;
2887 
2888  case DefaultAclRelationId:
2889  return OCLASS_DEFACL;
2890 
2891  case ExtensionRelationId:
2892  return OCLASS_EXTENSION;
2893 
2894  case EventTriggerRelationId:
2895  return OCLASS_EVENT_TRIGGER;
2896 
2897  case ParameterAclRelationId:
2898  return OCLASS_PARAMETER_ACL;
2899 
2900  case PolicyRelationId:
2901  return OCLASS_POLICY;
2902 
2903  case PublicationNamespaceRelationId:
2905 
2906  case PublicationRelationId:
2907  return OCLASS_PUBLICATION;
2908 
2909  case PublicationRelRelationId:
2910  return OCLASS_PUBLICATION_REL;
2911 
2912  case SubscriptionRelationId:
2913  return OCLASS_SUBSCRIPTION;
2914 
2915  case TransformRelationId:
2916  return OCLASS_TRANSFORM;
2917  }
2918 
2919  /* shouldn't get here */
2920  elog(ERROR, "unrecognized object class: %u", object->classId);
2921  return OCLASS_CLASS; /* keep compiler quiet */
2922 }

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(), deleteObjectsInList(), doDeletion(), EventTriggerSQLDropAddObject(), getObjectDescription(), getObjectIdentityParts(), getObjectTypeDescription(), and RememberAllDependentForRebuilding().

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

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

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

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

◆ performDeletion()

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

Definition at line 273 of file dependency.c.

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

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

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

◆ performMultipleDeletions()

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

Definition at line 332 of file dependency.c.

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

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

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

◆ record_object_address_dependencies()

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

Definition at line 2738 of file dependency.c.

2741 {
2743  recordMultipleDependencies(depender,
2744  referenced->refs, referenced->numrefs,
2745  behavior);
2746 }
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs)
Definition: dependency.c:2379
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()

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

◆ 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:762

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

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

◆ recordDependencyOnExpr()

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

Definition at line 1553 of file dependency.c.

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

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

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

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

357 {
358  ObjectAddress myself,
359  referenced;
360 
361  ObjectAddressSet(myself, classId, objectId);
362  ObjectAddressSet(referenced, TableSpaceRelationId, tablespace);
363 
364  recordSharedDependencyOn(&myself, &referenced,
366 }
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
char * tablespace
Definition: pgbench.c:216

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

Referenced by heap_create().

◆ recordMultipleDependencies()

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

Definition at line 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:991
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:451
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 117 of file pg_shdepend.c.

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

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

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

◆ ReleaseDeletionLock()

void ReleaseDeletionLock ( const ObjectAddress object)

Definition at line 1528 of file dependency.c.

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

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

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

References AcquireDeletionLock(), add_exact_object_address(), 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 1161 of file pg_shdepend.c.

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

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

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

◆ shdepReassignOwned()

void shdepReassignOwned ( List roleids,
Oid  newrole 
)

Definition at line 1463 of file pg_shdepend.c.

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

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

2758 {
2759  if (addrs->numrefs > 1)
2760  qsort(addrs->refs, addrs->numrefs,
2761  sizeof(ObjectAddress),
2763 }
static int object_address_comparator(const void *a, const void *b)
Definition: dependency.c:2439

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

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

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