PostgreSQL Source Code git master
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/partition.h"
#include "commands/extension.h"
#include "miscadmin.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
Include dependency graph for pg_depend.c:

Go to the source code of this file.

Functions

static bool isObjectPinned (const ObjectAddress *object)
 
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)
 
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 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
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
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}
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
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().

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

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

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

◆ 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}
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
#define AccessShareLock
Definition: lockdefs.h:36
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
#define InvalidOid
Definition: postgres_ext.h:37

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

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}
@ DEPENDENCY_AUTO_EXTENSION
Definition: dependency.h:39

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:859
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:828
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:506
#define RelationGetRelid(relation)
Definition: rel.h:512

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

◆ getOwnedSequences_internal()

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

Definition at line 877 of file pg_depend.c.

878{
879 List *result = NIL;
880 Relation depRel;
881 ScanKeyData key[3];
882 SysScanDesc scan;
883 HeapTuple tup;
884
885 depRel = table_open(DependRelationId, AccessShareLock);
886
887 ScanKeyInit(&key[0],
888 Anum_pg_depend_refclassid,
889 BTEqualStrategyNumber, F_OIDEQ,
890 ObjectIdGetDatum(RelationRelationId));
891 ScanKeyInit(&key[1],
892 Anum_pg_depend_refobjid,
893 BTEqualStrategyNumber, F_OIDEQ,
894 ObjectIdGetDatum(relid));
895 if (attnum)
896 ScanKeyInit(&key[2],
897 Anum_pg_depend_refobjsubid,
898 BTEqualStrategyNumber, F_INT4EQ,
900
901 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
902 NULL, attnum ? 3 : 2, key);
903
904 while (HeapTupleIsValid(tup = systable_getnext(scan)))
905 {
907
908 /*
909 * We assume any auto or internal dependency of a sequence on a column
910 * must be what we are looking for. (We need the relkind test because
911 * indexes can also have auto dependencies on columns.)
912 */
913 if (deprec->classid == RelationRelationId &&
914 deprec->objsubid == 0 &&
915 deprec->refobjsubid != 0 &&
916 (deprec->deptype == DEPENDENCY_AUTO || deprec->deptype == DEPENDENCY_INTERNAL) &&
917 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
918 {
919 if (!deptype || deprec->deptype == deptype)
920 result = lappend_oid(result, deprec->objid);
921 }
922 }
923
924 systable_endscan(scan);
925
927
928 return result;
929}
@ DEPENDENCY_AUTO
Definition: dependency.h:34
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2030

References AccessShareLock, attnum, BTEqualStrategyNumber, DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, get_rel_relkind(), GETSTRUCT(), HeapTupleIsValid, Int32GetDatum(), sort-test::key, lappend_oid(), NIL, ObjectIdGetDatum(), 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 709 of file pg_depend.c.

710{
711 return IsPinnedObject(object->classId, object->objectId);
712}
bool IsPinnedObject(Oid classId, Oid objectId)
Definition: catalog.c:341

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

48{
49 recordMultipleDependencies(depender, referenced, 1, behavior);
50}
void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
Definition: pg_depend.c:57

References recordMultipleDependencies().

Referenced by add_column_collation_dependency(), add_column_datatype_dependency(), addFkConstraint(), AddNewAttributeTuples(), AlterForeignDataWrapper(), AlterFunction(), AlterPolicy(), ApplyExtensionUpdates(), ATExecAddOf(), ATExecSetAccessMethodNoStorage(), changeDependencyFor(), CollationCreate(), ConstraintSetParentConstraint(), ConversionCreate(), create_toast_table(), CreateAccessMethod(), CreateForeignDataWrapper(), CreateForeignServer(), CreateForeignTable(), CreateOpFamily(), CreatePolicy(), CreateStatistics(), CreateTriggerFiringOn(), CreateUserMapping(), DefineOpClass(), ExecAlterExtensionContentsRecurse(), ExecAlterObjectDependsStmt(), GenerateTypeDependencies(), index_constraint_create(), index_create(), IndexSetParentIndex(), insert_event_trigger_tuple(), 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 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().

◆ 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
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
int i
Definition: isn.c:72
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:466
FormData_pg_depend
Definition: pg_depend.h:65
static Datum CharGetDatum(char X)
Definition: postgres.h:127
#define RelationGetDescr(relation)
Definition: rel.h:538
Datum * tts_values
Definition: tuptable.h:125
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454

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

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