PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_depend.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_type.h"
#include "catalog/partition.h"
#include "commands/extension.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "storage/lock.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for pg_depend.c:

Go to the source code of this file.

Functions

static bool isObjectPinned (const ObjectAddress *object)
 
static void dependencyLockAndCheckObject (Oid classId, Oid objectId)
 
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)
 
static ListgetOwnedSequences_internal (Oid relid, AttrNumber attnum, char deptype)
 
ListgetOwnedSequences (Oid relid)
 
Oid getIdentitySequence (Relation rel, AttrNumber attnum, bool missing_ok)
 
Oid get_index_constraint (Oid indexId)
 
Listget_index_ref_constraints (Oid indexId)
 

Function Documentation

◆ changeDependenciesOf()

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

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
static int fb(int x)
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 
)

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 
)

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}
@ DEPENDENCY_NORMAL
Definition dependency.h:33
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().

◆ checkMembershipInCurrentExtension()

void checkMembershipInCurrentExtension ( const ObjectAddress object)

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}
#define Assert(condition)
Definition c.h:943
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().

◆ deleteDependencyRecordsFor()

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

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}
@ DEPENDENCY_EXTENSION
Definition dependency.h:38

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 
)

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 
)

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

◆ dependencyLockAndCheckObject()

static void dependencyLockAndCheckObject ( Oid  classId,
Oid  objectId 
)
static

Definition at line 752 of file pg_depend.c.

753{
754 /*
755 * Pinned objects cannot be dropped concurrently, and callers checked this
756 * already.
757 */
758 Assert(!IsPinnedObject(classId, objectId));
759
760 if (classId != RelationRelationId)
761 {
762 LOCKTAG tag;
763 SysCacheIdentifier cache;
764 Relation rel;
765 SysScanDesc scan;
767 HeapTuple tuple;
768
771 classId,
772 objectId,
773 0);
774
775 if (LockHeldByMe(&tag, AccessShareLock, true))
776 return;
777
778 /* Assume we should lock the whole object not a sub-object */
779 LockDatabaseObject(classId, objectId, 0, AccessShareLock);
780
781 /*
782 * Check that the object still exists. If the catalog has a suitable
783 * syscache, check that first.
784 */
785 cache = get_object_catcache_oid(classId);
786 if (cache != SYSCACHEID_INVALID)
787 {
788 if (SearchSysCacheExists1(cache, ObjectIdGetDatum(objectId)))
789 return;
790 }
791
792 /*
793 * If it's not found in the syscache, or there's no suitable syscache
794 * we can use, scan the catalog table using SnapshotSelf. This
795 * handles the case that it's an object we just created (for example,
796 * if it's a composite type created as part of creating a table).
797 */
798 rel = table_open(classId, AccessShareLock);
799
801 get_object_attnum_oid(classId),
803 ObjectIdGetDatum(objectId));
804
805 scan = systable_beginscan(rel, get_object_oid_index(classId),
806 true, SnapshotSelf, 1, &skey);
807
808 tuple = systable_getnext(scan);
809 if (!HeapTupleIsValid(tuple))
812 errmsg("referenced %s was concurrently dropped",
813 get_object_class_descr(classId))));
814
815 systable_endscan(scan);
817 }
818 else
819 {
820 /*
821 * Same logic for pg_class entries, but locking relations is handled
822 * by different functions.
823 *
824 * Callers are more careful with locking relations than other objects,
825 * so we should already have a lock on the relation, or on another
826 * object that indirectly prevents the relation from being dropped.
827 * For example, we might have a strong lock on a table while adding
828 * dependency to its index. However, we cannot detect the indirectly
829 * protected case here easily. To err on the safe side, acquire a
830 * lock directly on the relation if we're not holding one already.
831 */
832
833 /* all shared relations are pinned */
834 Assert(!IsSharedRelation(objectId));
835
836 if (CheckRelationOidLockedByMe(objectId, AccessShareLock, true))
837 return;
839
841 return;
844 errmsg("referenced relation was concurrently dropped")));
845 }
846}
bool IsPinnedObject(Oid classId, Oid objectId)
Definition catalog.c:370
bool IsSharedRelation(Oid relationId)
Definition catalog.c:304
Oid MyDatabaseId
Definition globals.c:96
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1008
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
bool CheckRelationOidLockedByMe(Oid relid, LOCKMODE lockmode, bool orstronger)
Definition lmgr.c:351
bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
Definition lock.c:640
#define AccessShareLock
Definition lockdefs.h:36
#define SET_LOCKTAG_OBJECT(locktag, dboid, classoid, objoid, objsubid)
Definition locktag.h:162
AttrNumber get_object_attnum_oid(Oid class_id)
const char * get_object_class_descr(Oid class_id)
Oid get_object_oid_index(Oid class_id)
SysCacheIdentifier get_object_catcache_oid(Oid class_id)
#define SnapshotSelf
Definition snapmgr.h:32
#define SearchSysCacheExists1(cacheId, key1)
Definition syscache.h:100

References AccessShareLock, Assert, BTEqualStrategyNumber, CheckRelationOidLockedByMe(), ereport, errcode(), errmsg, ERROR, fb(), get_object_attnum_oid(), get_object_catcache_oid(), get_object_class_descr(), get_object_oid_index(), HeapTupleIsValid, IsPinnedObject(), IsSharedRelation(), LockDatabaseObject(), LockHeldByMe(), LockRelationOid(), MyDatabaseId, ObjectIdGetDatum(), ScanKeyInit(), SearchSysCacheExists1, SET_LOCKTAG_OBJECT, SnapshotSelf, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by changeDependencyFor(), and recordMultipleDependencies().

◆ get_index_constraint()

Oid get_index_constraint ( Oid  indexId)

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}
@ DEPENDENCY_INTERNAL
Definition dependency.h:35
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define InvalidOid

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)

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
#define NIL
Definition pg_list.h:68
Definition pg_list.h:54

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 
)

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 
)

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 
)

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:1015
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:984
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)

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

◆ getOwnedSequences_internal()

static List * getOwnedSequences_internal ( Oid  relid,
AttrNumber  attnum,
char  deptype 
)
static

Definition at line 1081 of file pg_depend.c.

1082{
1083 List *result = NIL;
1085 ScanKeyData key[3];
1086 SysScanDesc scan;
1087 HeapTuple tup;
1088
1090
1091 ScanKeyInit(&key[0],
1095 ScanKeyInit(&key[1],
1098 ObjectIdGetDatum(relid));
1099 if (attnum)
1100 ScanKeyInit(&key[2],
1104
1106 NULL, attnum ? 3 : 2, key);
1107
1108 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1109 {
1111
1112 /*
1113 * We assume any auto or internal dependency of a sequence on a column
1114 * must be what we are looking for. (We need the relkind test because
1115 * indexes can also have auto dependencies on columns.)
1116 */
1117 if (deprec->classid == RelationRelationId &&
1118 deprec->objsubid == 0 &&
1119 deprec->refobjsubid != 0 &&
1120 (deprec->deptype == DEPENDENCY_AUTO || deprec->deptype == DEPENDENCY_INTERNAL) &&
1122 {
1123 if (!deptype || deprec->deptype == deptype)
1124 result = lappend_oid(result, deprec->objid);
1125 }
1126 }
1127
1128 systable_endscan(scan);
1129
1131
1132 return result;
1133}
@ DEPENDENCY_AUTO
Definition dependency.h:34
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2234

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

Referenced by getIdentitySequence(), and getOwnedSequences().

◆ isObjectPinned()

static bool isObjectPinned ( const ObjectAddress object)
static

Definition at line 729 of file pg_depend.c.

730{
731 return IsPinnedObject(object->classId, object->objectId);
732}

References ObjectAddress::classId, IsPinnedObject(), and ObjectAddress::objectId.

Referenced by changeDependenciesOn(), changeDependencyFor(), and recordMultipleDependencies().

◆ recordDependencyOn()

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

Definition at line 51 of file pg_depend.c.

54{
56}
void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
Definition pg_depend.c:63

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 
)

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}
#define OidIsValid(objectId)
Definition c.h:858

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

◆ recordMultipleDependencies()

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

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
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
int i
Definition isn.c:77
void pfree(void *pointer)
Definition mcxt.c:1619
#define IsBootstrapProcessingMode()
Definition miscadmin.h:486
FormData_pg_depend
Definition pg_depend.h:67
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 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().

◆ sequenceIsOwned()

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

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