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

Go to the source code of this file.

Macros

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

Typedefs

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

Enumerations

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

Functions

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

Macro Definition Documentation

◆ PERFORM_DELETION_CONCURRENT_LOCK

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

Definition at line 97 of file dependency.h.

◆ PERFORM_DELETION_CONCURRENTLY

#define PERFORM_DELETION_CONCURRENTLY   0x0002 /* concurrent drop */

Definition at line 93 of file dependency.h.

◆ PERFORM_DELETION_INTERNAL

#define PERFORM_DELETION_INTERNAL   0x0001 /* internal action */

Definition at line 92 of file dependency.h.

◆ PERFORM_DELETION_QUIETLY

#define PERFORM_DELETION_QUIETLY   0x0004 /* suppress notices */

Definition at line 94 of file dependency.h.

◆ PERFORM_DELETION_SKIP_EXTENSIONS

#define PERFORM_DELETION_SKIP_EXTENSIONS   0x0010 /* keep extensions */

Definition at line 96 of file dependency.h.

◆ PERFORM_DELETION_SKIP_ORIGINAL

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

Definition at line 95 of file dependency.h.

Typedef Documentation

◆ DependencyType

◆ ObjectAddresses

Definition at line 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 
)

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 */
1508 else
1510 }
1511 else if (object->classId == AuthMemRelationId)
1512 LockSharedObject(object->classId, object->objectId, 0,
1514 else
1515 {
1516 /* assume we should lock the whole object not a sub-object */
1517 LockDatabaseObject(object->classId, object->objectId, 0,
1519 }
1520}
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:93
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1072
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:993
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
#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 2548 of file dependency.c.

2550{
2551 ObjectAddress *item;
2552
2553 /* enlarge array if needed */
2554 if (addrs->numrefs >= addrs->maxrefs)
2555 {
2556 addrs->maxrefs *= 2;
2557 addrs->refs = (ObjectAddress *)
2558 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2559 Assert(!addrs->extras);
2560 }
2561 /* record this item */
2562 item = addrs->refs + addrs->numrefs;
2563 *item = *object;
2564 addrs->numrefs++;
2565}
#define Assert(condition)
Definition: c.h:815
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
ObjectAddressExtra * extras
Definition: dependency.c:116
ObjectAddress * refs
Definition: dependency.c:115

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

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

◆ changeDependenciesOf()

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

Definition at line 565 of file pg_depend.c.

567{
568 long count = 0;
569 Relation depRel;
570 ScanKeyData key[2];
571 SysScanDesc scan;
572 HeapTuple tup;
573
574 depRel = table_open(DependRelationId, RowExclusiveLock);
575
576 ScanKeyInit(&key[0],
577 Anum_pg_depend_classid,
578 BTEqualStrategyNumber, F_OIDEQ,
579 ObjectIdGetDatum(classId));
580 ScanKeyInit(&key[1],
581 Anum_pg_depend_objid,
582 BTEqualStrategyNumber, F_OIDEQ,
583 ObjectIdGetDatum(oldObjectId));
584
585 scan = systable_beginscan(depRel, DependDependerIndexId, true,
586 NULL, 2, key);
587
588 while (HeapTupleIsValid((tup = systable_getnext(scan))))
589 {
590 Form_pg_depend depform;
591
592 /* make a modifiable copy */
593 tup = heap_copytuple(tup);
594 depform = (Form_pg_depend) GETSTRUCT(tup);
595
596 depform->objid = newObjectId;
597
598 CatalogTupleUpdate(depRel, &tup->t_self, tup);
599
600 heap_freetuple(tup);
601
602 count++;
603 }
604
605 systable_endscan(scan);
606
608
609 return count;
610}
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:606
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:513
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:778
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
#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:257
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 621 of file pg_depend.c.

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

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

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

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

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

◆ changeDependencyOnOwner()

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

Definition at line 316 of file pg_shdepend.c.

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

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

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

◆ changeDependencyOnTablespace()

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

Definition at line 391 of file pg_shdepend.c.

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

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

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

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

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

◆ checkSharedDependencies()

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

Definition at line 676 of file pg_shdepend.c.

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

Referenced by DropRole(), and DropTableSpace().

◆ copyTemplateDependencies()

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)

Definition at line 895 of file pg_shdepend.c.

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

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

Referenced by createdb().

◆ deleteDependencyRecordsFor()

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

Definition at line 301 of file pg_depend.c.

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

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

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

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

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

◆ deleteDependencyRecordsForSpecific()

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

Definition at line 398 of file pg_depend.c.

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

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

◆ deleteSharedDependencyRecordsFor()

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

◆ dropDatabaseDependencies()

void dropDatabaseDependencies ( Oid  databaseId)

Definition at line 999 of file pg_shdepend.c.

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

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

Referenced by dropdb().

◆ free_object_addresses()

◆ get_index_constraint()

Oid get_index_constraint ( Oid  indexId)

Definition at line 988 of file pg_depend.c.

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

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

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

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

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

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

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

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

◆ getIdentitySequence()

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

Definition at line 945 of file pg_depend.c.

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

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

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

◆ getOwnedSequences()

List * getOwnedSequences ( Oid  relid)

Definition at line 936 of file pg_depend.c.

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

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

2610{
2611 int i;
2612
2613 for (i = addrs->numrefs - 1; i >= 0; i--)
2614 {
2615 const ObjectAddress *thisobj = addrs->refs + i;
2616
2617 if (object->classId == thisobj->classId &&
2618 object->objectId == thisobj->objectId)
2619 {
2620 if (object->objectSubId == thisobj->objectSubId ||
2621 thisobj->objectSubId == 0)
2622 return true;
2623 }
2624 }
2625
2626 return false;
2627}

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
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
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:2502
static void deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, int flags)
Definition: dependency.c:185
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2788

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

Referenced by AlterDomainDropConstraint(), AlterDomainNotNull(), 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
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(), shdepDropOwned(), and tryAttachPartitionForeignKey().

◆ record_object_address_dependencies()

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

◆ recordDependencyOn()

◆ recordDependencyOnCurrentExtension()

void recordDependencyOnCurrentExtension ( const ObjectAddress object,
bool  isReplace 
)

Definition at line 193 of file pg_depend.c.

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

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 */
1572 context.addrs->refs, context.addrs->numrefs,
1573 behavior);
1574
1576}
static bool find_expr_references_walker(Node *node, find_expr_references_context *context)
Definition: dependency.c:1698
#define list_make1(x1)
Definition: pg_list.h:212
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 */
1612 rte.rellockmode = AccessShareLock;
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)
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 */
1678 context.addrs->refs, context.addrs->numrefs,
1679 behavior);
1680
1682}
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2548
@ RTE_RELATION
Definition: parsenodes.h:1026
RTEKind rtekind
Definition: parsenodes.h:1056

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

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

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

Referenced by heap_create().

◆ recordMultipleDependencies()

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

Definition at line 57 of file pg_depend.c.

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

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

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

◆ recordSharedDependencyOn()

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

Definition at line 125 of file pg_shdepend.c.

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

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

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

◆ ReleaseDeletionLock()

void ReleaseDeletionLock ( const ObjectAddress object)

Definition at line 1528 of file dependency.c.

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

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

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

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

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

◆ shdepDropOwned()

void shdepDropOwned ( List roleids,
DropBehavior  behavior 
)

Definition at line 1342 of file pg_shdepend.c.

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

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

Referenced by DropOwnedObjects().

◆ shdepLockAndCheckObject()

void shdepLockAndCheckObject ( Oid  classId,
Oid  objectId 
)

Definition at line 1211 of file pg_shdepend.c.

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

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

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

◆ shdepReassignOwned()

void shdepReassignOwned ( List roleids,
Oid  newrole 
)

Definition at line 1530 of file pg_shdepend.c.

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

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

Referenced by ReassignOwnedObjects().

◆ sort_object_addresses()

void sort_object_addresses ( ObjectAddresses addrs)

Definition at line 2776 of file dependency.c.

2777{
2778 if (addrs->numrefs > 1)
2779 qsort(addrs->refs, addrs->numrefs,
2780 sizeof(ObjectAddress),
2782}
static int object_address_comparator(const void *a, const void *b)
Definition: dependency.c:2458

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

Referenced by shdepDropOwned().

◆ updateAclDependencies()

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

Definition at line 491 of file pg_shdepend.c.

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

References SHARED_DEPENDENCY_ACL, and updateAclDependenciesWorker().

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

◆ updateInitAclDependencies()

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

Definition at line 512 of file pg_shdepend.c.

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

References InvalidOid, SHARED_DEPENDENCY_INITACL, and updateAclDependenciesWorker().

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