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

Go to the source code of this file.

Macros

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

Typedefs

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

Enumerations

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

Functions

void AcquireDeletionLock (const ObjectAddress *object, int flags)
 
void ReleaseDeletionLock (const ObjectAddress *object)
 
void performDeletion (const ObjectAddress *object, DropBehavior behavior, int flags)
 
void performDeletionCheck (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 collectDependenciesOfExpr (ObjectAddresses *addrs, Node *expr, List *rtable)
 
void recordDependencyOnSingleRelExpr (const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
 
bool find_temp_object (const ObjectAddresses *addrs, bool local_temp_okay, ObjectAddress *foundobj)
 
bool query_uses_temp_object (Query *query, ObjectAddress *temp_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)
 
Oid getExtensionType (Oid extensionOid, const char *typname)
 
bool sequenceIsOwned (Oid seqId, char deptype, Oid *tableId, int32 *colId)
 
ListgetOwnedSequences (Oid relid)
 
Oid getIdentitySequence (Relation rel, AttrNumber attnum, bool missing_ok)
 
Oid get_index_constraint (Oid indexId)
 
Listget_index_ref_constraints (Oid indexId)
 
void recordSharedDependencyOn (ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
 
void deleteSharedDependencyRecordsFor (Oid classId, Oid objectId, int32 objectSubId)
 
void recordDependencyOnOwner (Oid classId, Oid objectId, Oid owner)
 
void changeDependencyOnOwner (Oid classId, Oid objectId, Oid newOwnerId)
 
void recordDependencyOnTablespace (Oid classId, Oid objectId, Oid tablespace)
 
void changeDependencyOnTablespace (Oid classId, Oid objectId, Oid newTablespaceId)
 
void updateAclDependencies (Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
 
void updateInitAclDependencies (Oid classId, Oid objectId, int32 objsubId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
 
bool checkSharedDependencies (Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
 
void shdepLockAndCheckObject (Oid classId, Oid objectId)
 
void copyTemplateDependencies (Oid templateDbId, Oid newDbId)
 
void dropDatabaseDependencies (Oid databaseId)
 
void shdepDropOwned (List *roleids, DropBehavior behavior)
 
void shdepReassignOwned (List *roleids, Oid newrole)
 

Macro Definition Documentation

◆ PERFORM_DELETION_CONCURRENT_LOCK

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

Definition at line 97 of file dependency.h.

◆ PERFORM_DELETION_CONCURRENTLY

#define PERFORM_DELETION_CONCURRENTLY   0x0002 /* concurrent drop */

Definition at line 93 of file dependency.h.

◆ PERFORM_DELETION_INTERNAL

#define PERFORM_DELETION_INTERNAL   0x0001 /* internal action */

Definition at line 92 of file dependency.h.

◆ PERFORM_DELETION_QUIETLY

#define PERFORM_DELETION_QUIETLY   0x0004 /* suppress notices */

Definition at line 94 of file dependency.h.

◆ PERFORM_DELETION_SKIP_EXTENSIONS

#define PERFORM_DELETION_SKIP_EXTENSIONS   0x0010 /* keep extensions */

Definition at line 96 of file dependency.h.

◆ PERFORM_DELETION_SKIP_ORIGINAL

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

Definition at line 95 of file dependency.h.

Typedef Documentation

◆ DependencyType

◆ ObjectAddresses

Definition at line 89 of file dependency.h.

◆ SharedDependencyType

Enumeration Type Documentation

◆ DependencyType

Enumerator
DEPENDENCY_NORMAL 
DEPENDENCY_AUTO 
DEPENDENCY_INTERNAL 
DEPENDENCY_PARTITION_PRI 
DEPENDENCY_PARTITION_SEC 
DEPENDENCY_EXTENSION 
DEPENDENCY_AUTO_EXTENSION 

Definition at line 31 of file dependency.h.

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

◆ SharedDependencyType

Enumerator
SHARED_DEPENDENCY_OWNER 
SHARED_DEPENDENCY_ACL 
SHARED_DEPENDENCY_INITACL 
SHARED_DEPENDENCY_POLICY 
SHARED_DEPENDENCY_TABLESPACE 
SHARED_DEPENDENCY_INVALID 

Definition at line 78 of file dependency.h.

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

Function Documentation

◆ AcquireDeletionLock()

void AcquireDeletionLock ( const ObjectAddress object,
int  flags 
)
extern

Definition at line 1567 of file dependency.c.

1568{
1569 if (object->classId == RelationRelationId)
1570 {
1571 /*
1572 * In DROP INDEX CONCURRENTLY, take only ShareUpdateExclusiveLock on
1573 * the index for the moment. index_drop() will promote the lock once
1574 * it's safe to do so. In all other cases we need full exclusive
1575 * lock.
1576 */
1579 else
1581 }
1582 else if (object->classId == AuthMemRelationId)
1583 LockSharedObject(object->classId, object->objectId, 0,
1585 else
1586 {
1587 /* assume we should lock the whole object not a sub-object */
1588 LockDatabaseObject(object->classId, object->objectId, 0,
1590 }
1591}
#define PERFORM_DELETION_CONCURRENTLY
Definition dependency.h:93
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1088
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1008
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
#define AccessExclusiveLock
Definition lockdefs.h:43
#define ShareUpdateExclusiveLock
Definition lockdefs.h:39
static int fb(int x)

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

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

◆ add_exact_object_address()

void add_exact_object_address ( const ObjectAddress object,
ObjectAddresses addrs 
)
extern

Definition at line 2750 of file dependency.c.

2752{
2753 ObjectAddress *item;
2754
2755 /* enlarge array if needed */
2756 if (addrs->numrefs >= addrs->maxrefs)
2757 {
2758 addrs->maxrefs *= 2;
2759 addrs->refs = (ObjectAddress *)
2760 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2761 Assert(!addrs->extras);
2762 }
2763 /* record this item */
2764 item = addrs->refs + addrs->numrefs;
2765 *item = *object;
2766 addrs->numrefs++;
2767}
#define Assert(condition)
Definition c.h:943
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1635
ObjectAddressExtra * extras
Definition dependency.c:122
ObjectAddress * refs
Definition dependency.c:121

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

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

◆ changeDependenciesOf()

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

Definition at line 585 of file pg_depend.c.

587{
588 long count = 0;
590 ScanKeyData key[2];
591 SysScanDesc scan;
593
595
596 ScanKeyInit(&key[0],
599 ObjectIdGetDatum(classId));
600 ScanKeyInit(&key[1],
604
606 NULL, 2, key);
607
608 while (HeapTupleIsValid((tup = systable_getnext(scan))))
609 {
611
612 /* make a modifiable copy */
615
616 depform->objid = newObjectId;
617
618 CatalogTupleUpdate(depRel, &tup->t_self, tup);
619
621
622 count++;
623 }
624
625 systable_endscan(scan);
626
628
629 return count;
630}
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:515
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:686
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
#define RowExclusiveLock
Definition lockdefs.h:38
END_CATALOG_STRUCT typedef FormData_pg_depend * Form_pg_depend
Definition pg_depend.h:76
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
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(), fb(), Form_pg_depend, GETSTRUCT(), heap_copytuple(), heap_freetuple(), HeapTupleIsValid, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by index_concurrently_swap().

◆ changeDependenciesOn()

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

Definition at line 641 of file pg_depend.c.

643{
644 long count = 0;
646 ScanKeyData key[2];
647 SysScanDesc scan;
650 bool newIsPinned;
651
653
654 /*
655 * If oldRefObjectId is pinned, there won't be any dependency entries on
656 * it --- we can't cope in that case. (This isn't really worth expending
657 * code to fix, in current usage; it just means you can't rename stuff out
658 * of pg_catalog, which would likely be a bad move anyway.)
659 */
660 objAddr.classId = refClassId;
661 objAddr.objectId = oldRefObjectId;
662 objAddr.objectSubId = 0;
663
667 errmsg("cannot remove dependency on %s because it is a system object",
668 getObjectDescription(&objAddr, false))));
669
670 /*
671 * We can handle adding a dependency on something pinned, though, since
672 * that just means deleting the dependency entry.
673 */
674 objAddr.objectId = newRefObjectId;
675
677
678 /* Now search for dependency records */
679 ScanKeyInit(&key[0],
683 ScanKeyInit(&key[1],
687
689 NULL, 2, key);
690
691 while (HeapTupleIsValid((tup = systable_getnext(scan))))
692 {
693 if (newIsPinned)
694 CatalogTupleDelete(depRel, &tup->t_self);
695 else
696 {
698
699 /* make a modifiable copy */
702
703 depform->refobjid = newRefObjectId;
704
705 CatalogTupleUpdate(depRel, &tup->t_self, tup);
706
708 }
709
710 count++;
711 }
712
713 systable_endscan(scan);
714
716
717 return count;
718}
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
static char * errmsg
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
static bool isObjectPinned(const ObjectAddress *object)
Definition pg_depend.c:729

References BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), ereport, errcode(), errmsg, ERROR, fb(), Form_pg_depend, getObjectDescription(), GETSTRUCT(), heap_copytuple(), heap_freetuple(), HeapTupleIsValid, isObjectPinned(), ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by index_concurrently_swap().

◆ changeDependencyFor()

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

Definition at line 470 of file pg_depend.c.

473{
474 long count = 0;
476 ScanKeyData key[2];
477 SysScanDesc scan;
481 bool oldIsPinned;
482 bool newIsPinned;
483
484 /*
485 * Check to see if either oldRefObjectId or newRefObjectId is pinned.
486 * Pinned objects should not have any dependency entries pointing to them,
487 * so in these cases we should add or remove a pg_depend entry, or do
488 * nothing at all, rather than update an entry as in the normal case.
489 */
491 objAddr.objectId = oldRefObjectId;
492 objAddr.objectSubId = 0;
493
495
496 objAddr.objectId = newRefObjectId;
497
499
500 if (oldIsPinned)
501 {
502 /*
503 * If both are pinned, we need do nothing. However, return 1 not 0,
504 * else callers will think this is an error case.
505 */
506 if (newIsPinned)
507 return 1;
508
509 /*
510 * There is no old dependency record, but we should insert a new one.
511 * Assume a normal dependency is wanted.
512 */
513 depAddr.classId = classId;
514 depAddr.objectId = objectId;
515 depAddr.objectSubId = 0;
517
518 return 1;
519 }
520
521 /*
522 * Make sure the new referenced object doesn't go away while we record the
523 * dependency.
524 */
525 if (!newIsPinned)
527
529
530 /* There should be existing dependency record(s), so search. */
531 ScanKeyInit(&key[0],
534 ObjectIdGetDatum(classId));
535 ScanKeyInit(&key[1],
538 ObjectIdGetDatum(objectId));
539
541 NULL, 2, key);
542
543 while (HeapTupleIsValid((tup = systable_getnext(scan))))
544 {
546
547 if (depform->refclassid == refClassId &&
548 depform->refobjid == oldRefObjectId)
549 {
550 if (newIsPinned)
551 CatalogTupleDelete(depRel, &tup->t_self);
552 else
553 {
554 /* make a modifiable copy */
557
558 depform->refobjid = newRefObjectId;
559
560 CatalogTupleUpdate(depRel, &tup->t_self, tup);
561
563 }
564
565 count++;
566 }
567 }
568
569 systable_endscan(scan);
570
572
573 return count;
574}
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:51
static void dependencyLockAndCheckObject(Oid classId, Oid objectId)
Definition pg_depend.c:752

References BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), ObjectAddress::classId, DEPENDENCY_NORMAL, dependencyLockAndCheckObject(), fb(), Form_pg_depend, GETSTRUCT(), heap_copytuple(), heap_freetuple(), HeapTupleIsValid, isObjectPinned(), ObjectIdGetDatum(), recordDependencyOn(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

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

◆ changeDependencyOnOwner()

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

Definition at line 316 of file pg_shdepend.c.

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

References fb(), 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 
)
extern

◆ checkMembershipInCurrentExtension()

void checkMembershipInCurrentExtension ( const ObjectAddress object)
extern

Definition at line 271 of file pg_depend.c.

272{
273 /*
274 * This is actually the same condition tested in
275 * recordDependencyOnCurrentExtension; but we want to issue a
276 * differently-worded error, and anyway it would be pretty confusing to
277 * call recordDependencyOnCurrentExtension in these circumstances.
278 */
279
280 /* Only whole objects can be extension members */
281 Assert(object->objectSubId == 0);
282
284 {
285 Oid oldext;
286
287 oldext = getExtensionOfObject(object->classId, object->objectId);
288 /* If already a member of this extension, OK */
290 return;
291 /* Else complain */
294 errmsg("%s is not a member of extension \"%s\"",
295 getObjectDescription(object, false),
297 errdetail("An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns.")));
298 }
299}
int errdetail(const char *fmt,...) pg_attribute_printf(1
bool creating_extension
Definition extension.c:80
Oid CurrentExtensionObject
Definition extension.c:81
char * get_extension_name(Oid ext_oid)
Definition extension.c:251
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition pg_depend.c:865
unsigned int Oid

References Assert, ObjectAddress::classId, creating_extension, CurrentExtensionObject, ereport, errcode(), errdetail(), errmsg, ERROR, fb(), 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 
)
extern

Definition at line 676 of file pg_shdepend.c.

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

References AccessShareLock, appendStringInfo(), BTEqualStrategyNumber, ShDependObjectInfo::deptype, ereport, errcode(), errmsg, ERROR, fb(), Form_pg_shdepend, getObjectDescription(), GETSTRUCT(), HeapTupleIsValid, i, initStringInfo(), InvalidOid, IsPinnedObject(), lappend(), lfirst, list_free_deep(), LOCAL_OBJECT, MAX_REPORTED_DEPS, MyDatabaseId, ngettext, NIL, ShDependObjectInfo::object, ObjectIdGetDatum(), ShDependObjectInfo::objtype, palloc(), palloc_object, 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().

◆ collectDependenciesOfExpr()

void collectDependenciesOfExpr ( ObjectAddresses addrs,
Node expr,
List rtable 
)
extern

Definition at line 1667 of file dependency.c.

1669{
1671
1672 context.addrs = addrs;
1673
1674 /* Set up interpretation for Vars at varlevelsup = 0 */
1675 context.rtables = list_make1(rtable);
1676
1677 /* Scan the expression tree for referenceable objects */
1678 find_expr_references_walker(expr, &context);
1679}
static bool find_expr_references_walker(Node *node, find_expr_references_context *context)
#define list_make1(x1)
Definition pg_list.h:244
ObjectAddresses * addrs
Definition dependency.c:147

References find_expr_references_context::addrs, find_expr_references_walker(), list_make1, and find_expr_references_context::rtables.

Referenced by ProcedureCreate(), query_uses_temp_object(), and recordDependencyOnExpr().

◆ copyTemplateDependencies()

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)
extern

Definition at line 895 of file pg_shdepend.c.

896{
899 ScanKeyData key[1];
900 SysScanDesc scan;
903 TupleTableSlot **slot;
904 int max_slots,
907
910
911 /*
912 * Allocate the slots to use, but delay costly initialization until we
913 * know that they will be used.
914 */
917
919
920 /* Scan all entries with dbid = templateDbId */
921 ScanKeyInit(&key[0],
925
927 NULL, 1, key);
928
929 /* number of slots currently storing tuples */
931 /* number of slots currently initialized */
932 slot_init_count = 0;
933
934 /*
935 * Copy the entries of the original database, changing the database Id to
936 * that of the new database. Note that because we are not copying rows
937 * with dbId == 0 (ie, rows describing dependent shared objects) we won't
938 * copy the ownership dependency of the template database itself; this is
939 * what we want.
940 */
941 while (HeapTupleIsValid(tup = systable_getnext(scan)))
942 {
944
946 {
949 }
950
952
953 memset(slot[slot_stored_count]->tts_isnull, false,
954 slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
955
957
965
968
969 /* If slots are full, insert a batch of tuples */
971 {
974 }
975 }
976
977 /* Insert any tuples left in the buffer */
978 if (slot_stored_count > 0)
980
981 systable_endscan(scan);
982
985
986 /* Drop only the number of slots used */
987 for (int i = 0; i < slot_init_count; i++)
989 pfree(slot);
990}
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
const TupleTableSlotOps TTSOpsHeapTuple
Definition execTuples.c:85
#define palloc_array(type, count)
Definition fe_memutils.h:91
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:68
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
static Datum CharGetDatum(char X)
Definition postgres.h:132
#define RelationGetDescr(relation)
Definition rel.h:542
Datum * tts_values
Definition tuptable.h:131
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:476

References BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTuplesMultiInsertWithInfo(), CharGetDatum(), ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), fb(), Form_pg_shdepend, FormData_pg_shdepend, GETSTRUCT(), HeapTupleIsValid, i, Int32GetDatum(), MakeSingleTupleTableSlot(), MAX_CATALOG_MULTI_INSERT_BYTES, ObjectIdGetDatum(), palloc_array, 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 
)
extern

Definition at line 314 of file pg_depend.c.

316{
317 long count = 0;
319 ScanKeyData key[2];
320 SysScanDesc scan;
322
324
325 ScanKeyInit(&key[0],
328 ObjectIdGetDatum(classId));
329 ScanKeyInit(&key[1],
332 ObjectIdGetDatum(objectId));
333
335 NULL, 2, key);
336
337 while (HeapTupleIsValid(tup = systable_getnext(scan)))
338 {
339 if (skipExtensionDeps &&
341 continue;
342
343 CatalogTupleDelete(depRel, &tup->t_self);
344 count++;
345 }
346
347 systable_endscan(scan);
348
350
351 return count;
352}

References BTEqualStrategyNumber, CatalogTupleDelete(), DEPENDENCY_EXTENSION, fb(), Form_pg_depend, GETSTRUCT(), HeapTupleIsValid, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

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

◆ deleteDependencyRecordsForClass()

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

Definition at line 364 of file pg_depend.c.

366{
367 long count = 0;
369 ScanKeyData key[2];
370 SysScanDesc scan;
372
374
375 ScanKeyInit(&key[0],
378 ObjectIdGetDatum(classId));
379 ScanKeyInit(&key[1],
382 ObjectIdGetDatum(objectId));
383
385 NULL, 2, key);
386
387 while (HeapTupleIsValid(tup = systable_getnext(scan)))
388 {
390
391 if (depform->refclassid == refclassId && depform->deptype == deptype)
392 {
393 CatalogTupleDelete(depRel, &tup->t_self);
394 count++;
395 }
396 }
397
398 systable_endscan(scan);
399
401
402 return count;
403}

References BTEqualStrategyNumber, CatalogTupleDelete(), fb(), Form_pg_depend, GETSTRUCT(), HeapTupleIsValid, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

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

◆ deleteDependencyRecordsForSpecific()

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

Definition at line 411 of file pg_depend.c.

413{
414 long count = 0;
416 ScanKeyData key[2];
417 SysScanDesc scan;
419
421
422 ScanKeyInit(&key[0],
425 ObjectIdGetDatum(classId));
426 ScanKeyInit(&key[1],
429 ObjectIdGetDatum(objectId));
430
432 NULL, 2, key);
433
434 while (HeapTupleIsValid(tup = systable_getnext(scan)))
435 {
437
438 if (depform->refclassid == refclassId &&
439 depform->refobjid == refobjectId &&
440 depform->deptype == deptype)
441 {
442 CatalogTupleDelete(depRel, &tup->t_self);
443 count++;
444 }
445 }
446
447 systable_endscan(scan);
448
450
451 return count;
452}

References BTEqualStrategyNumber, CatalogTupleDelete(), fb(), Form_pg_depend, GETSTRUCT(), HeapTupleIsValid, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterSubscription(), ExecAlterObjectDependsStmt(), and RemoveInheritedConstraint().

◆ deleteSharedDependencyRecordsFor()

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)
extern

Definition at line 999 of file pg_shdepend.c.

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

References BTEqualStrategyNumber, CatalogTupleDelete(), fb(), HeapTupleIsValid, InvalidOid, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_INVALID, shdepDropDependency(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by dropdb().

◆ find_temp_object()

bool find_temp_object ( const ObjectAddresses addrs,
bool  local_temp_okay,
ObjectAddress foundobj 
)
extern

Definition at line 2544 of file dependency.c.

2546{
2547 for (int i = 0; i < addrs->numrefs; i++)
2548 {
2549 const ObjectAddress *thisobj = addrs->refs + i;
2551
2552 /*
2553 * Use get_object_namespace() to see if this object belongs to a
2554 * schema. If not, we can skip it.
2555 */
2557
2558 /*
2559 * If the object is in a temporary namespace, complain, except if
2560 * local_temp_okay and it's our own temp namespace.
2561 */
2564 {
2565 *foundobj = *thisobj;
2566 return true;
2567 }
2568 }
2569 return false;
2570}
#define OidIsValid(objectId)
Definition c.h:858
bool isTempNamespace(Oid namespaceId)
Definition namespace.c:3721
bool isAnyTempNamespace(Oid namespaceId)
Definition namespace.c:3759
Oid get_object_namespace(const ObjectAddress *address)

References fb(), get_object_namespace(), i, isAnyTempNamespace(), isTempNamespace(), ObjectAddresses::numrefs, OidIsValid, and ObjectAddresses::refs.

Referenced by ProcedureCreate(), and query_uses_temp_object().

◆ free_object_addresses()

◆ get_index_constraint()

Oid get_index_constraint ( Oid  indexId)
extern

Definition at line 1192 of file pg_depend.c.

1193{
1196 ScanKeyData key[3];
1197 SysScanDesc scan;
1198 HeapTuple tup;
1199
1200 /* Search the dependency table for the index */
1202
1203 ScanKeyInit(&key[0],
1207 ScanKeyInit(&key[1],
1211 ScanKeyInit(&key[2],
1214 Int32GetDatum(0));
1215
1217 NULL, 3, key);
1218
1219 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1220 {
1222
1223 /*
1224 * We assume any internal dependency on a constraint must be what we
1225 * are looking for.
1226 */
1227 if (deprec->refclassid == ConstraintRelationId &&
1228 deprec->refobjsubid == 0 &&
1229 deprec->deptype == DEPENDENCY_INTERNAL)
1230 {
1231 constraintId = deprec->refobjid;
1232 break;
1233 }
1234 }
1235
1236 systable_endscan(scan);
1238
1239 return constraintId;
1240}

References AccessShareLock, BTEqualStrategyNumber, DEPENDENCY_INTERNAL, fb(), Form_pg_depend, GETSTRUCT(), HeapTupleIsValid, Int32GetDatum(), InvalidOid, 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)
extern

Definition at line 1248 of file pg_depend.c.

1249{
1250 List *result = NIL;
1252 ScanKeyData key[3];
1253 SysScanDesc scan;
1254 HeapTuple tup;
1255
1256 /* Search the dependency table for the index */
1258
1259 ScanKeyInit(&key[0],
1263 ScanKeyInit(&key[1],
1267 ScanKeyInit(&key[2],
1270 Int32GetDatum(0));
1271
1273 NULL, 3, key);
1274
1275 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1276 {
1278
1279 /*
1280 * We assume any normal dependency from a constraint must be what we
1281 * are looking for.
1282 */
1283 if (deprec->classid == ConstraintRelationId &&
1284 deprec->objsubid == 0 &&
1285 deprec->deptype == DEPENDENCY_NORMAL)
1286 {
1287 result = lappend_oid(result, deprec->objid);
1288 }
1289 }
1290
1291 systable_endscan(scan);
1293
1294 return result;
1295}
uint32 result
List * lappend_oid(List *list, Oid datum)
Definition list.c:375

References AccessShareLock, BTEqualStrategyNumber, DEPENDENCY_NORMAL, fb(), Form_pg_depend, GETSTRUCT(), HeapTupleIsValid, Int32GetDatum(), lappend_oid(), NIL, ObjectIdGetDatum(), result, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by index_concurrently_swap().

◆ getAutoExtensionsOfObject()

◆ getExtensionOfObject()

Oid getExtensionOfObject ( Oid  classId,
Oid  objectId 
)
extern

Definition at line 865 of file pg_depend.c.

866{
869 ScanKeyData key[2];
870 SysScanDesc scan;
872
874
875 ScanKeyInit(&key[0],
878 ObjectIdGetDatum(classId));
879 ScanKeyInit(&key[1],
882 ObjectIdGetDatum(objectId));
883
885 NULL, 2, key);
886
887 while (HeapTupleIsValid((tup = systable_getnext(scan))))
888 {
890
891 if (depform->refclassid == ExtensionRelationId &&
892 depform->deptype == DEPENDENCY_EXTENSION)
893 {
894 result = depform->refobjid;
895 break; /* no need to keep scanning */
896 }
897 }
898
899 systable_endscan(scan);
900
902
903 return result;
904}

References AccessShareLock, BTEqualStrategyNumber, DEPENDENCY_EXTENSION, fb(), Form_pg_depend, GETSTRUCT(), HeapTupleIsValid, InvalidOid, ObjectIdGetDatum(), result, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

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

◆ getExtensionType()

Oid getExtensionType ( Oid  extensionOid,
const char typname 
)
extern

Definition at line 963 of file pg_depend.c.

964{
967 ScanKeyData key[3];
968 SysScanDesc scan;
970
972
973 ScanKeyInit(&key[0],
977 ScanKeyInit(&key[1],
981 ScanKeyInit(&key[2],
984 Int32GetDatum(0));
985
987 NULL, 3, key);
988
989 while (HeapTupleIsValid(tup = systable_getnext(scan)))
990 {
992
993 if (depform->classid == TypeRelationId &&
994 depform->deptype == DEPENDENCY_EXTENSION)
995 {
996 Oid typoid = depform->objid;
998
1001 continue; /* should we throw an error? */
1003 typname) == 0)
1004 {
1005 result = typoid;
1007 break; /* no need to keep searching */
1008 }
1010 }
1011 }
1012
1013 systable_endscan(scan);
1014
1016
1017 return result;
1018}
#define NameStr(name)
Definition c.h:835
END_CATALOG_STRUCT typedef FormData_pg_type * Form_pg_type
Definition pg_type.h:265
NameData typname
Definition pg_type.h:43
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221

References AccessShareLock, BTEqualStrategyNumber, DEPENDENCY_EXTENSION, fb(), Form_pg_depend, Form_pg_type, GETSTRUCT(), HeapTupleIsValid, Int32GetDatum(), InvalidOid, NameStr, ObjectIdGetDatum(), ReleaseSysCache(), result, ScanKeyInit(), SearchSysCache1(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and typname.

Referenced by get_function_sibling_type().

◆ getIdentitySequence()

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

Definition at line 1149 of file pg_depend.c.

1150{
1151 Oid relid = RelationGetRelid(rel);
1152 List *seqlist;
1153
1154 /*
1155 * The identity sequence is associated with the topmost partitioned table,
1156 * which might have column order different than the given partition.
1157 */
1159 {
1160 List *ancestors = get_partition_ancestors(relid);
1161 const char *attname = get_attname(relid, attnum, false);
1162
1163 relid = llast_oid(ancestors);
1164 attnum = get_attnum(relid, attname);
1166 elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u",
1167 attname, relid);
1168 list_free(ancestors);
1169 }
1170
1172 if (list_length(seqlist) > 1)
1173 elog(ERROR, "more than one owned sequence found");
1174 else if (seqlist == NIL)
1175 {
1176 if (missing_ok)
1177 return InvalidOid;
1178 else
1179 elog(ERROR, "no owned sequence found");
1180 }
1181
1182 return linitial_oid(seqlist);
1183}
#define InvalidAttrNumber
Definition attnum.h:23
#define elog(elevel,...)
Definition elog.h:228
void list_free(List *list)
Definition list.c:1546
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:1076
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:1045
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
NameData attname
int16 attnum
static List * getOwnedSequences_internal(Oid relid, AttrNumber attnum, char deptype)
Definition pg_depend.c:1081
static int list_length(const List *l)
Definition pg_list.h:152
#define llast_oid(l)
Definition pg_list.h:200
#define linitial_oid(l)
Definition pg_list.h:180
#define RelationGetForm(relation)
Definition rel.h:510
#define RelationGetRelid(relation)
Definition rel.h:516

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

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

◆ getOwnedSequences()

List * getOwnedSequences ( Oid  relid)
extern

Definition at line 1140 of file pg_depend.c.

1141{
1142 return getOwnedSequences_internal(relid, 0, 0);
1143}

References getOwnedSequences_internal().

Referenced by ATRewriteTables(), and ExecuteTruncateGuts().

◆ new_object_addresses()

◆ object_address_present()

bool object_address_present ( const ObjectAddress object,
const ObjectAddresses addrs 
)
extern

Definition at line 2810 of file dependency.c.

2812{
2813 int i;
2814
2815 for (i = addrs->numrefs - 1; i >= 0; i--)
2816 {
2817 const ObjectAddress *thisobj = addrs->refs + i;
2818
2819 if (object->classId == thisobj->classId &&
2820 object->objectId == thisobj->objectId)
2821 {
2822 if (object->objectSubId == thisobj->objectSubId ||
2823 thisobj->objectSubId == 0)
2824 return true;
2825 }
2826 }
2827
2828 return false;
2829}

References ObjectAddress::classId, fb(), 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 
)
extern

Definition at line 279 of file dependency.c.

281{
284
285 /*
286 * We save some cycles by opening pg_depend just once and passing the
287 * Relation pointer down to all the recursive deletion steps.
288 */
290
291 /*
292 * Acquire deletion lock on the target object. (Ideally the caller has
293 * done this already, but many places are sloppy about it.)
294 */
295 AcquireDeletionLock(object, 0);
296
297 /*
298 * Construct a list of objects to delete (ie, the given object plus
299 * everything directly or indirectly dependent on it).
300 */
302
305 flags,
306 NULL, /* empty stack */
308 NULL, /* no pendingObjects */
309 &depRel);
310
311 /*
312 * Check if deletion is allowed, and report about cascaded deletes.
313 */
315 behavior,
316 flags,
317 object);
318
319 /* do the deed */
321
322 /* And clean up */
324
326}
void AcquireDeletionLock(const ObjectAddress *object, int flags)
#define DEPFLAG_ORIGINAL
Definition dependency.c:107
static void reportDependentObjects(const ObjectAddresses *targetObjects, DropBehavior behavior, int flags, const ObjectAddress *origObject)
static void findDependentObjects(const ObjectAddress *object, int objflags, int flags, ObjectAddressStack *stack, ObjectAddresses *targetObjects, const ObjectAddresses *pendingObjects, Relation *depRel)
Definition dependency.c:488
ObjectAddresses * new_object_addresses(void)
static void deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, int flags)
Definition dependency.c:191
void free_object_addresses(ObjectAddresses *addrs)

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

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

◆ performDeletionCheck()

void performDeletionCheck ( const ObjectAddress object,
DropBehavior  behavior,
int  flags 
)
extern

Definition at line 338 of file dependency.c.

340{
343
344 Assert(behavior == DROP_RESTRICT);
345
347
348 AcquireDeletionLock(object, 0);
349
350 /*
351 * Construct a list of objects we want to delete later (ie, the given
352 * object plus everything directly or indirectly dependent on it).
353 */
355
358 flags,
359 NULL, /* empty stack */
361 NULL, /* no pendingObjects */
362 &depRel);
363
364 /*
365 * Check if deletion is allowed.
366 */
368 behavior,
369 flags,
370 object);
371
372 /* And clean up */
374
376}
@ DROP_RESTRICT

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

Referenced by ATExecMergePartitions(), and ATExecSplitPartition().

◆ performMultipleDeletions()

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

Definition at line 388 of file dependency.c.

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

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

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

◆ query_uses_temp_object()

bool query_uses_temp_object ( Query query,
ObjectAddress temp_object 
)
extern

Definition at line 2579 of file dependency.c.

2580{
2581 bool result;
2582 ObjectAddresses *addrs;
2583
2584 addrs = new_object_addresses();
2585
2586 /* Collect all dependencies from the Query */
2587 collectDependenciesOfExpr(addrs, (Node *) query, NIL);
2588
2589 /* Look for one that is temp */
2590 result = find_temp_object(addrs, false, temp_object);
2591
2592 free_object_addresses(addrs);
2593
2594 return result;
2595}
void collectDependenciesOfExpr(ObjectAddresses *addrs, Node *expr, List *rtable)
bool find_temp_object(const ObjectAddresses *addrs, bool local_temp_okay, ObjectAddress *foundobj)
Definition nodes.h:135

References collectDependenciesOfExpr(), fb(), find_temp_object(), free_object_addresses(), new_object_addresses(), NIL, and result.

Referenced by DefineView(), and transformCreateTableAsStmt().

◆ record_object_address_dependencies()

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

◆ recordDependencyOn()

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

Definition at line 51 of file pg_depend.c.

54{
56}

References fb(), and recordMultipleDependencies().

Referenced by add_column_collation_dependency(), add_column_datatype_dependency(), addFkConstraint(), AddNewAttributeTuples(), AlterForeignDataWrapper(), AlterFunction(), AlterPolicy(), AlterSubscription(), ApplyExtensionUpdates(), applyPartitionIndexExtDeps(), ATExecAddOf(), ATExecSetAccessMethodNoStorage(), changeDependencyFor(), CollationCreate(), ConstraintSetParentConstraint(), ConversionCreate(), copy_index_constraints(), create_toast_table(), CreateAccessMethod(), CreateForeignDataWrapper(), CreateForeignServer(), CreateForeignTable(), CreateOpFamily(), CreatePolicy(), CreateStatistics(), CreateSubscription(), CreateTriggerFiringOn(), CreateUserMapping(), DefineOpClass(), ExecAlterExtensionContentsRecurse(), ExecAlterObjectDependsStmt(), GenerateTypeDependencies(), index_constraint_create(), index_create(), IndexSetParentIndex(), insert_element_record(), insert_event_trigger_tuple(), insert_label_record(), insert_property_record(), InsertRule(), makeMultirangeConstructors(), makeRangeConstructors(), process_owned_by(), publication_add_relation(), publication_add_schema(), RangeCreate(), recordDependencyOnCurrentExtension(), recordDependencyOnSingleRelExpr(), SetDefaultACL(), StoreAttrDefault(), StoreCatalogInheritance1(), storeOperators(), StorePartitionKey(), storeProcedures(), swap_relation_files(), and TriggerSetParentTrigger().

◆ recordDependencyOnCurrentExtension()

void recordDependencyOnCurrentExtension ( const ObjectAddress object,
bool  isReplace 
)
extern

Definition at line 206 of file pg_depend.c.

208{
209 /* Only whole objects can be extension members */
210 Assert(object->objectSubId == 0);
211
213 {
215
216 /* Only need to check for existing membership if isReplace */
217 if (isReplace)
218 {
219 Oid oldext;
220
221 /*
222 * Side note: these catalog lookups are safe only because the
223 * object is a pre-existing one. In the not-isReplace case, the
224 * caller has most likely not yet done a CommandCounterIncrement
225 * that would make the new object visible.
226 */
227 oldext = getExtensionOfObject(object->classId, object->objectId);
228 if (OidIsValid(oldext))
229 {
230 /* If already a member of this extension, nothing to do */
232 return;
233 /* Already a member of some other extension, so reject */
236 errmsg("%s is already a member of extension \"%s\"",
237 getObjectDescription(object, false),
239 }
240 /* It's a free-standing object, so reject */
243 errmsg("%s is not a member of extension \"%s\"",
244 getObjectDescription(object, false),
246 errdetail("An extension is not allowed to replace an object that it does not own.")));
247 }
248
249 /* OK, record it as a member of CurrentExtensionObject */
252 extension.objectSubId = 0;
253
255 }
256}

References Assert, ObjectAddress::classId, creating_extension, CurrentExtensionObject, DEPENDENCY_EXTENSION, ereport, errcode(), errdetail(), errmsg, ERROR, fb(), 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 
)
extern

Definition at line 1624 of file dependency.c.

1627{
1628 ObjectAddresses *addrs;
1629
1630 addrs = new_object_addresses();
1631
1632 /* Collect all dependencies from the expression */
1633 collectDependenciesOfExpr(addrs, expr, rtable);
1634
1635 /* Remove duplicates */
1637
1638 /* And record 'em */
1640 addrs->refs, addrs->numrefs,
1641 behavior);
1642
1643 free_object_addresses(addrs);
1644}

References collectDependenciesOfExpr(), eliminate_duplicate_dependencies(), fb(), free_object_addresses(), new_object_addresses(), ObjectAddresses::numrefs, recordMultipleDependencies(), and ObjectAddresses::refs.

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

◆ recordDependencyOnOwner()

◆ recordDependencyOnSingleRelExpr()

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

Definition at line 1699 of file dependency.c.

1704{
1706 RangeTblEntry rte = {0};
1707
1708 context.addrs = new_object_addresses();
1709
1710 /* We gin up a rather bogus rangetable list to handle Vars */
1711 rte.type = T_RangeTblEntry;
1712 rte.rtekind = RTE_RELATION;
1713 rte.relid = relId;
1714 rte.relkind = RELKIND_RELATION; /* no need for exactness here */
1715 rte.rellockmode = AccessShareLock;
1716
1717 context.rtables = list_make1(list_make1(&rte));
1718
1719 /* Scan the expression tree for referenceable objects */
1720 find_expr_references_walker(expr, &context);
1721
1722 /* Remove any duplicates */
1724
1725 /* Separate self-dependencies if necessary */
1726 if ((behavior != self_behavior || reverse_self) &&
1727 context.addrs->numrefs > 0)
1728 {
1731 int oldref,
1732 outrefs;
1733
1735
1736 outobj = context.addrs->refs;
1737 outrefs = 0;
1738 for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
1739 {
1740 ObjectAddress *thisobj = context.addrs->refs + oldref;
1741
1742 if (thisobj->classId == RelationRelationId &&
1743 thisobj->objectId == relId)
1744 {
1745 /* Move this ref into self_addrs */
1747 }
1748 else
1749 {
1750 /* Keep it in context.addrs */
1751 *outobj = *thisobj;
1752 outobj++;
1753 outrefs++;
1754 }
1755 }
1756 context.addrs->numrefs = outrefs;
1757
1758 /* Record the self-dependencies with the appropriate direction */
1759 if (!reverse_self)
1761 self_addrs->refs, self_addrs->numrefs,
1763 else
1764 {
1765 /* Can't use recordMultipleDependencies, so do it the hard way */
1766 int selfref;
1767
1768 for (selfref = 0; selfref < self_addrs->numrefs; selfref++)
1769 {
1771
1773 }
1774 }
1775
1777 }
1778
1779 /* Record the external dependencies */
1781 context.addrs->refs, context.addrs->numrefs,
1782 behavior);
1783
1785}
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
@ RTE_RELATION

References AccessShareLock, add_exact_object_address(), find_expr_references_context::addrs, eliminate_duplicate_dependencies(), fb(), find_expr_references_walker(), free_object_addresses(), list_make1, new_object_addresses(), ObjectAddresses::numrefs, recordDependencyOn(), recordMultipleDependencies(), ObjectAddresses::refs, find_expr_references_context::rtables, and RTE_RELATION.

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

◆ recordDependencyOnTablespace()

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

Definition at line 370 of file pg_shdepend.c.

371{
374
375 ObjectAddressSet(myself, classId, objectId);
377
380}
#define ObjectAddressSet(addr, class_id, object_id)
static char * tablespace
Definition pgbench.c:217

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

Referenced by heap_create().

◆ recordMultipleDependencies()

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

Definition at line 63 of file pg_depend.c.

67{
70 TupleTableSlot **slot;
71 int i,
75
76 if (nreferenced <= 0)
77 return; /* nothing to do */
78
79 /*
80 * During bootstrap, do nothing since pg_depend may not exist yet.
81 *
82 * Objects created during bootstrap are most likely pinned, and the few
83 * that are not do not have dependencies on each other, so that there
84 * would be no need to make a pg_depend entry anyway.
85 */
87 return;
88
90
91 /*
92 * Allocate the slots to use, but delay costly initialization until we
93 * know that they will be used.
94 */
98
99 /* Don't open indexes unless we need to make an update */
100 indstate = NULL;
101
102 /* number of slots currently storing tuples */
104 /* number of slots currently initialized */
105 slot_init_count = 0;
106 for (i = 0; i < nreferenced; i++, referenced++)
107 {
108 /*
109 * If the referenced object is pinned by the system, there's no real
110 * need to record dependencies on it. This saves lots of space in
111 * pg_depend, so it's worth the time taken to check.
112 */
114 continue;
115
116 /*
117 * Make sure the new referenced object doesn't go away while we record
118 * the dependency. DROP routines should lock the object exclusively
119 * before they check dependencies.
120 */
122
124 {
128 }
129
131
132 /*
133 * Record the dependency. Note we don't bother to check for duplicate
134 * dependencies; there's no harm in them.
135 */
143
144 memset(slot[slot_stored_count]->tts_isnull, false,
145 slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
146
149
150 /* If slots are full, insert a batch of tuples */
152 {
153 /* fetch index info only when we know we need it */
154 if (indstate == NULL)
156
158 indstate);
160 }
161 }
162
163 /* Insert any tuples left in the buffer */
164 if (slot_stored_count > 0)
165 {
166 /* fetch index info only when we know we need it */
167 if (indstate == NULL)
169
171 indstate);
172 }
173
174 if (indstate != NULL)
176
178
179 /* Drop only the number of slots used */
180 for (i = 0; i < slot_init_count; i++)
182 pfree(slot);
183}
#define Min(x, y)
Definition c.h:1091
#define IsBootstrapProcessingMode()
Definition miscadmin.h:486
FormData_pg_depend
Definition pg_depend.h:67

References CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTuplesMultiInsertWithInfo(), CharGetDatum(), dependencyLockAndCheckObject(), ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), fb(), FormData_pg_depend, i, Int32GetDatum(), IsBootstrapProcessingMode, isObjectPinned(), MakeSingleTupleTableSlot(), MAX_CATALOG_MULTI_INSERT_BYTES, Min, ObjectIdGetDatum(), palloc_array, 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 
)
extern

Definition at line 125 of file pg_shdepend.c.

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

References Assert, fb(), IsBootstrapProcessingMode, IsPinnedObject(), RowExclusiveLock, shdepAddDependency(), table_close(), and table_open().

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

◆ ReleaseDeletionLock()

void ReleaseDeletionLock ( const ObjectAddress object)
extern

Definition at line 1599 of file dependency.c.

1600{
1601 if (object->classId == RelationRelationId)
1603 else
1604 /* assume we should lock the whole object not a sub-object */
1605 UnlockDatabaseObject(object->classId, object->objectId, 0,
1607}
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:229
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1068

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

Referenced by findDependentObjects(), and shdepDropOwned().

◆ sequenceIsOwned()

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

Definition at line 1032 of file pg_depend.c.

1033{
1034 bool ret = false;
1036 ScanKeyData key[2];
1037 SysScanDesc scan;
1038 HeapTuple tup;
1039
1041
1042 ScanKeyInit(&key[0],
1046 ScanKeyInit(&key[1],
1050
1052 NULL, 2, key);
1053
1054 while (HeapTupleIsValid((tup = systable_getnext(scan))))
1055 {
1057
1058 if (depform->refclassid == RelationRelationId &&
1059 depform->deptype == deptype)
1060 {
1061 *tableId = depform->refobjid;
1062 *colId = depform->refobjsubid;
1063 ret = true;
1064 break; /* no need to keep scanning */
1065 }
1066 }
1067
1068 systable_endscan(scan);
1069
1071
1072 return ret;
1073}

References AccessShareLock, BTEqualStrategyNumber, fb(), Form_pg_depend, GETSTRUCT(), HeapTupleIsValid, 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 
)
extern

Definition at line 1342 of file pg_shdepend.c.

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

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

Referenced by DropOwnedObjects().

◆ shdepLockAndCheckObject()

void shdepLockAndCheckObject ( Oid  classId,
Oid  objectId 
)
extern

Definition at line 1211 of file pg_shdepend.c.

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

References AccessShareLock, elog, ereport, errcode(), errmsg, ERROR, fb(), 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 
)
extern

Definition at line 1530 of file pg_shdepend.c.

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

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

Referenced by ReassignOwnedObjects().

◆ sort_object_addresses()

void sort_object_addresses ( ObjectAddresses addrs)
extern

Definition at line 2978 of file dependency.c.

2979{
2980 if (addrs->numrefs > 1)
2981 qsort(addrs->refs, addrs->numrefs,
2982 sizeof(ObjectAddress),
2984}
static int object_address_comparator(const void *a, const void *b)

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

Definition at line 491 of file pg_shdepend.c.

495{
496 updateAclDependenciesWorker(classId, objectId, objsubId,
497 ownerId, SHARED_DEPENDENCY_ACL,
500}
static void updateAclDependenciesWorker(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, SharedDependencyType deptype, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)

References fb(), SHARED_DEPENDENCY_ACL, and updateAclDependenciesWorker().

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

◆ updateInitAclDependencies()

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