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 "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 (Oid relid, 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 564 of file pg_depend.c.

566 {
567  long count = 0;
568  Relation depRel;
569  ScanKeyData key[2];
570  SysScanDesc scan;
571  HeapTuple tup;
572 
573  depRel = table_open(DependRelationId, RowExclusiveLock);
574 
575  ScanKeyInit(&key[0],
576  Anum_pg_depend_classid,
577  BTEqualStrategyNumber, F_OIDEQ,
578  ObjectIdGetDatum(classId));
579  ScanKeyInit(&key[1],
580  Anum_pg_depend_objid,
581  BTEqualStrategyNumber, F_OIDEQ,
582  ObjectIdGetDatum(oldObjectId));
583 
584  scan = systable_beginscan(depRel, DependDependerIndexId, true,
585  NULL, 2, key);
586 
587  while (HeapTupleIsValid((tup = systable_getnext(scan))))
588  {
589  Form_pg_depend depform;
590 
591  /* make a modifiable copy */
592  tup = heap_copytuple(tup);
593  depform = (Form_pg_depend) GETSTRUCT(tup);
594 
595  depform->objid = newObjectId;
596 
597  CatalogTupleUpdate(depRel, &tup->t_self, tup);
598 
599  heap_freetuple(tup);
600 
601  count++;
602  }
603 
604  systable_endscan(scan);
605 
606  table_close(depRel, RowExclusiveLock);
607 
608  return count;
609 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:72
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

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

Referenced by index_concurrently_swap().

◆ changeDependenciesOn()

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

Definition at line 620 of file pg_depend.c.

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

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

Referenced by index_concurrently_swap().

◆ changeDependencyFor()

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

Definition at line 456 of file pg_depend.c.

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

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

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

◆ checkMembershipInCurrentExtension()

void checkMembershipInCurrentExtension ( const ObjectAddress object)

Definition at line 257 of file pg_depend.c.

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

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

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

◆ deleteDependencyRecordsFor()

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

Definition at line 300 of file pg_depend.c.

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

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

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

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

◆ deleteDependencyRecordsForSpecific()

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

Definition at line 397 of file pg_depend.c.

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

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

Referenced by ExecAlterObjectDependsStmt().

◆ get_index_constraint()

Oid get_index_constraint ( Oid  indexId)

Definition at line 968 of file pg_depend.c.

969 {
970  Oid constraintId = InvalidOid;
971  Relation depRel;
972  ScanKeyData key[3];
973  SysScanDesc scan;
974  HeapTuple tup;
975 
976  /* Search the dependency table for the index */
977  depRel = table_open(DependRelationId, AccessShareLock);
978 
979  ScanKeyInit(&key[0],
980  Anum_pg_depend_classid,
981  BTEqualStrategyNumber, F_OIDEQ,
982  ObjectIdGetDatum(RelationRelationId));
983  ScanKeyInit(&key[1],
984  Anum_pg_depend_objid,
985  BTEqualStrategyNumber, F_OIDEQ,
986  ObjectIdGetDatum(indexId));
987  ScanKeyInit(&key[2],
988  Anum_pg_depend_objsubid,
989  BTEqualStrategyNumber, F_INT4EQ,
990  Int32GetDatum(0));
991 
992  scan = systable_beginscan(depRel, DependDependerIndexId, true,
993  NULL, 3, key);
994 
995  while (HeapTupleIsValid(tup = systable_getnext(scan)))
996  {
997  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
998 
999  /*
1000  * We assume any internal dependency on a constraint must be what we
1001  * are looking for.
1002  */
1003  if (deprec->refclassid == ConstraintRelationId &&
1004  deprec->refobjsubid == 0 &&
1005  deprec->deptype == DEPENDENCY_INTERNAL)
1006  {
1007  constraintId = deprec->refobjid;
1008  break;
1009  }
1010  }
1011 
1012  systable_endscan(scan);
1013  table_close(depRel, AccessShareLock);
1014 
1015  return constraintId;
1016 }
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
#define AccessShareLock
Definition: lockdefs.h:36
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36

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

Referenced by generateClonedIndexStmt(), index_concurrently_swap(), RememberIndexForRebuilding(), RenameRelationInternal(), and transformIndexConstraint().

◆ get_index_ref_constraints()

List* get_index_ref_constraints ( Oid  indexId)

Definition at line 1024 of file pg_depend.c.

1025 {
1026  List *result = NIL;
1027  Relation depRel;
1028  ScanKeyData key[3];
1029  SysScanDesc scan;
1030  HeapTuple tup;
1031 
1032  /* Search the dependency table for the index */
1033  depRel = table_open(DependRelationId, AccessShareLock);
1034 
1035  ScanKeyInit(&key[0],
1036  Anum_pg_depend_refclassid,
1037  BTEqualStrategyNumber, F_OIDEQ,
1038  ObjectIdGetDatum(RelationRelationId));
1039  ScanKeyInit(&key[1],
1040  Anum_pg_depend_refobjid,
1041  BTEqualStrategyNumber, F_OIDEQ,
1042  ObjectIdGetDatum(indexId));
1043  ScanKeyInit(&key[2],
1044  Anum_pg_depend_refobjsubid,
1045  BTEqualStrategyNumber, F_INT4EQ,
1046  Int32GetDatum(0));
1047 
1048  scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1049  NULL, 3, key);
1050 
1051  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1052  {
1053  Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1054 
1055  /*
1056  * We assume any normal dependency from a constraint must be what we
1057  * are looking for.
1058  */
1059  if (deprec->classid == ConstraintRelationId &&
1060  deprec->objsubid == 0 &&
1061  deprec->deptype == DEPENDENCY_NORMAL)
1062  {
1063  result = lappend_oid(result, deprec->objid);
1064  }
1065  }
1066 
1067  systable_endscan(scan);
1068  table_close(depRel, AccessShareLock);
1069 
1070  return result;
1071 }
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
#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 777 of file pg_depend.c.

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

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

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

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

◆ getIdentitySequence()

Oid getIdentitySequence ( Oid  relid,
AttrNumber  attnum,
bool  missing_ok 
)

Definition at line 944 of file pg_depend.c.

945 {
947 
948  if (list_length(seqlist) > 1)
949  elog(ERROR, "more than one owned sequence found");
950  else if (seqlist == NIL)
951  {
952  if (missing_ok)
953  return InvalidOid;
954  else
955  elog(ERROR, "no owned sequence found");
956  }
957 
958  return linitial_oid(seqlist);
959 }
#define elog(elevel,...)
Definition: elog.h:224
int16 attnum
Definition: pg_attribute.h:74
static List * getOwnedSequences_internal(Oid relid, AttrNumber attnum, char deptype)
Definition: pg_depend.c:876
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_oid(l)
Definition: pg_list.h:180

References attnum, DEPENDENCY_INTERNAL, elog, ERROR, getOwnedSequences_internal(), InvalidOid, linitial_oid, list_length(), and NIL.

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

◆ getOwnedSequences()

List* getOwnedSequences ( Oid  relid)

Definition at line 935 of file pg_depend.c.

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

References getOwnedSequences_internal().

Referenced by ATRewriteTables(), and ExecuteTruncateGuts().

◆ getOwnedSequences_internal()

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

Definition at line 876 of file pg_depend.c.

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

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

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

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

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

References recordMultipleDependencies().

Referenced by add_column_collation_dependency(), add_column_datatype_dependency(), addFkRecurseReferenced(), addFkRecurseReferencing(), AddNewAttributeTuples(), AlterForeignDataWrapper(), AlterFunction(), AlterPolicy(), ApplyExtensionUpdates(), ATExecAddOf(), changeDependencyFor(), CloneFkReferencing(), 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 192 of file pg_depend.c.

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

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

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

◆ recordMultipleDependencies()

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

Definition at line 56 of file pg_depend.c.

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

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

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

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

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