PostgreSQL Source Code  git master
dependency.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_am.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_default_acl.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_init_privs.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_policy.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_publication.h"
#include "catalog/pg_publication_rel.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_transform.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
#include "commands/comment.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/policy.h"
#include "commands/proclang.h"
#include "commands/publicationcmds.h"
#include "commands/schemacmds.h"
#include "commands/seclabel.h"
#include "commands/sequence.h"
#include "commands/trigger.h"
#include "commands/typecmds.h"
#include "nodes/nodeFuncs.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteRemove.h"
#include "storage/lmgr.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for dependency.c:

Go to the source code of this file.

Data Structures

struct  ObjectAddressExtra
 
struct  ObjectAddresses
 
struct  ObjectAddressStack
 
struct  find_expr_references_context
 

Macros

#define DEPFLAG_ORIGINAL   0x0001 /* an original deletion target */
 
#define DEPFLAG_NORMAL   0x0002 /* reached via normal dependency */
 
#define DEPFLAG_AUTO   0x0004 /* reached via auto dependency */
 
#define DEPFLAG_INTERNAL   0x0008 /* reached via internal dependency */
 
#define DEPFLAG_EXTENSION   0x0010 /* reached via extension dependency */
 
#define DEPFLAG_REVERSE   0x0020 /* reverse internal/extension link */
 
#define MAX_REPORTED_DEPS   100
 

Typedefs

typedef struct ObjectAddressStack ObjectAddressStack
 

Functions

static void findDependentObjects (const ObjectAddress *object, int objflags, int flags, ObjectAddressStack *stack, ObjectAddresses *targetObjects, const ObjectAddresses *pendingObjects, Relation *depRel)
 
static void reportDependentObjects (const ObjectAddresses *targetObjects, DropBehavior behavior, int flags, const ObjectAddress *origObject)
 
static void deleteOneObject (const ObjectAddress *object, Relation *depRel, int32 flags)
 
static void doDeletion (const ObjectAddress *object, int flags)
 
static void AcquireDeletionLock (const ObjectAddress *object, int flags)
 
static void ReleaseDeletionLock (const ObjectAddress *object)
 
static bool find_expr_references_walker (Node *node, find_expr_references_context *context)
 
static void eliminate_duplicate_dependencies (ObjectAddresses *addrs)
 
static int object_address_comparator (const void *a, const void *b)
 
static void add_object_address (ObjectClass oclass, Oid objectId, int32 subId, ObjectAddresses *addrs)
 
static void add_exact_object_address_extra (const ObjectAddress *object, const ObjectAddressExtra *extra, ObjectAddresses *addrs)
 
static bool object_address_present_add_flags (const ObjectAddress *object, int flags, ObjectAddresses *addrs)
 
static bool stack_address_present_add_flags (const ObjectAddress *object, int flags, ObjectAddressStack *stack)
 
static void DeleteInitPrivs (const ObjectAddress *object)
 
static void deleteObjectsInList (ObjectAddresses *targetObjects, Relation *depRel, int flags)
 
void performDeletion (const ObjectAddress *object, DropBehavior behavior, int flags)
 
void performMultipleDeletions (const ObjectAddresses *objects, DropBehavior behavior, int flags)
 
static void deleteOneObject (const ObjectAddress *object, Relation *depRel, int flags)
 
void recordDependencyOnExpr (const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
 
void recordDependencyOnSingleRelExpr (const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool ignore_self)
 
ObjectAddressesnew_object_addresses (void)
 
void add_exact_object_address (const ObjectAddress *object, ObjectAddresses *addrs)
 
bool object_address_present (const ObjectAddress *object, const ObjectAddresses *addrs)
 
void record_object_address_dependencies (const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
 
void free_object_addresses (ObjectAddresses *addrs)
 
ObjectClass getObjectClass (const ObjectAddress *object)
 

Variables

static const Oid object_classes []
 

Macro Definition Documentation

◆ DEPFLAG_AUTO

#define DEPFLAG_AUTO   0x0004 /* reached via auto dependency */

Definition at line 99 of file dependency.c.

Referenced by findDependentObjects(), and reportDependentObjects().

◆ DEPFLAG_EXTENSION

#define DEPFLAG_EXTENSION   0x0010 /* reached via extension dependency */

Definition at line 101 of file dependency.c.

Referenced by findDependentObjects(), and reportDependentObjects().

◆ DEPFLAG_INTERNAL

#define DEPFLAG_INTERNAL   0x0008 /* reached via internal dependency */

Definition at line 100 of file dependency.c.

Referenced by findDependentObjects(), and reportDependentObjects().

◆ DEPFLAG_NORMAL

#define DEPFLAG_NORMAL   0x0002 /* reached via normal dependency */

Definition at line 98 of file dependency.c.

Referenced by deleteObjectsInList(), and findDependentObjects().

◆ DEPFLAG_ORIGINAL

#define DEPFLAG_ORIGINAL   0x0001 /* an original deletion target */

◆ DEPFLAG_REVERSE

#define DEPFLAG_REVERSE   0x0020 /* reverse internal/extension link */

Definition at line 102 of file dependency.c.

Referenced by deleteObjectsInList(), and findDependentObjects().

◆ MAX_REPORTED_DEPS

#define MAX_REPORTED_DEPS   100

Referenced by reportDependentObjects().

Typedef Documentation

◆ ObjectAddressStack

Function Documentation

◆ AcquireDeletionLock()

static void AcquireDeletionLock ( const ObjectAddress object,
int  flags 
)
static

Definition at line 1308 of file dependency.c.

References AccessExclusiveLock, ObjectAddress::classId, LockDatabaseObject(), LockRelationOid(), ObjectAddress::objectId, PERFORM_DELETION_CONCURRENTLY, and ShareUpdateExclusiveLock.

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

1309 {
1310  if (object->classId == RelationRelationId)
1311  {
1312  /*
1313  * In DROP INDEX CONCURRENTLY, take only ShareUpdateExclusiveLock on
1314  * the index for the moment. index_drop() will promote the lock once
1315  * it's safe to do so. In all other cases we need full exclusive
1316  * lock.
1317  */
1318  if (flags & PERFORM_DELETION_CONCURRENTLY)
1320  else
1322  }
1323  else
1324  {
1325  /* assume we should lock the whole object not a sub-object */
1326  LockDatabaseObject(object->classId, object->objectId, 0,
1328  }
1329 }
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:190
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:856
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define AccessExclusiveLock
Definition: lockdefs.h:45
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105

◆ add_exact_object_address()

void add_exact_object_address ( const ObjectAddress object,
ObjectAddresses addrs 
)

Definition at line 2185 of file dependency.c.

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

Referenced by AlterConstraintNamespaces(), AlterIndexNamespaces(), AlterRelationNamespaceInternal(), AlterTypeNamespaceInternal(), makeConfigurationDependencies(), recordDependencyOnSingleRelExpr(), RemoveObjects(), RemoveRelations(), and shdepDropOwned().

2187 {
2188  ObjectAddress *item;
2189 
2190  /* enlarge array if needed */
2191  if (addrs->numrefs >= addrs->maxrefs)
2192  {
2193  addrs->maxrefs *= 2;
2194  addrs->refs = (ObjectAddress *)
2195  repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2196  Assert(!addrs->extras);
2197  }
2198  /* record this item */
2199  item = addrs->refs + addrs->numrefs;
2200  *item = *object;
2201  addrs->numrefs++;
2202 }
ObjectAddress * refs
Definition: dependency.c:108
#define Assert(condition)
Definition: c.h:699
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
ObjectAddressExtra * extras
Definition: dependency.c:109

◆ add_exact_object_address_extra()

static void add_exact_object_address_extra ( const ObjectAddress object,
const ObjectAddressExtra extra,
ObjectAddresses addrs 
)
static

Definition at line 2210 of file dependency.c.

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

Referenced by findDependentObjects().

2213 {
2214  ObjectAddress *item;
2215  ObjectAddressExtra *itemextra;
2216 
2217  /* allocate extra space if first time */
2218  if (!addrs->extras)
2219  addrs->extras = (ObjectAddressExtra *)
2220  palloc(addrs->maxrefs * sizeof(ObjectAddressExtra));
2221 
2222  /* enlarge array if needed */
2223  if (addrs->numrefs >= addrs->maxrefs)
2224  {
2225  addrs->maxrefs *= 2;
2226  addrs->refs = (ObjectAddress *)
2227  repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2228  addrs->extras = (ObjectAddressExtra *)
2229  repalloc(addrs->extras, addrs->maxrefs * sizeof(ObjectAddressExtra));
2230  }
2231  /* record this item */
2232  item = addrs->refs + addrs->numrefs;
2233  *item = *object;
2234  itemextra = addrs->extras + addrs->numrefs;
2235  *itemextra = *extra;
2236  addrs->numrefs++;
2237 }
ObjectAddress * refs
Definition: dependency.c:108
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
ObjectAddressExtra * extras
Definition: dependency.c:109
void * palloc(Size size)
Definition: mcxt.c:924

◆ add_object_address()

static void add_object_address ( ObjectClass  oclass,
Oid  objectId,
int32  subId,
ObjectAddresses addrs 
)
static

Definition at line 2152 of file dependency.c.

References Assert, ObjectAddress::classId, ObjectAddresses::extras, LAST_OCLASS, lengthof, ObjectAddresses::maxrefs, ObjectAddresses::numrefs, object_classes, ObjectAddress::objectId, ObjectAddress::objectSubId, ObjectAddresses::refs, repalloc(), and StaticAssertStmt.

Referenced by find_expr_references_walker().

2154 {
2155  ObjectAddress *item;
2156 
2157  /*
2158  * Make sure object_classes is kept up to date with the ObjectClass enum.
2159  */
2161  "object_classes[] must cover all ObjectClasses");
2162 
2163  /* enlarge array if needed */
2164  if (addrs->numrefs >= addrs->maxrefs)
2165  {
2166  addrs->maxrefs *= 2;
2167  addrs->refs = (ObjectAddress *)
2168  repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2169  Assert(!addrs->extras);
2170  }
2171  /* record this item */
2172  item = addrs->refs + addrs->numrefs;
2173  item->classId = object_classes[oclass];
2174  item->objectId = objectId;
2175  item->objectSubId = subId;
2176  addrs->numrefs++;
2177 }
#define LAST_OCLASS
Definition: dependency.h:186
#define lengthof(array)
Definition: c.h:629
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:795
static const Oid object_classes[]
Definition: dependency.c:135
ObjectAddress * refs
Definition: dependency.c:108
#define Assert(condition)
Definition: c.h:699
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
ObjectAddressExtra * extras
Definition: dependency.c:109

◆ DeleteInitPrivs()

static void DeleteInitPrivs ( const ObjectAddress object)
static

Definition at line 2551 of file dependency.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), ObjectAddress::classId, heap_close, heap_open(), HeapTupleIsValid, InitPrivsObjIndexId, Int32GetDatum, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by deleteOneObject().

2552 {
2553  Relation relation;
2554  ScanKeyData key[3];
2555  SysScanDesc scan;
2556  HeapTuple oldtuple;
2557 
2558  relation = heap_open(InitPrivsRelationId, RowExclusiveLock);
2559 
2560  ScanKeyInit(&key[0],
2561  Anum_pg_init_privs_objoid,
2562  BTEqualStrategyNumber, F_OIDEQ,
2563  ObjectIdGetDatum(object->objectId));
2564  ScanKeyInit(&key[1],
2565  Anum_pg_init_privs_classoid,
2566  BTEqualStrategyNumber, F_OIDEQ,
2567  ObjectIdGetDatum(object->classId));
2568  ScanKeyInit(&key[2],
2569  Anum_pg_init_privs_objsubid,
2570  BTEqualStrategyNumber, F_INT4EQ,
2571  Int32GetDatum(object->objectSubId));
2572 
2573  scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
2574  NULL, 3, key);
2575 
2576  while (HeapTupleIsValid(oldtuple = systable_getnext(scan)))
2577  CatalogTupleDelete(relation, &oldtuple->t_self);
2578 
2579  systable_endscan(scan);
2580 
2581  heap_close(relation, RowExclusiveLock);
2582 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
#define InitPrivsObjIndexId
Definition: indexing.h:173
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Int32GetDatum(X)
Definition: postgres.h:462
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ deleteObjectsInList()

static void deleteObjectsInList ( ObjectAddresses targetObjects,
Relation depRel,
int  flags 
)
static

Definition at line 216 of file dependency.c.

References deleteOneObject(), DEPFLAG_NORMAL, DEPFLAG_ORIGINAL, DEPFLAG_REVERSE, EventTriggerSQLDropAddObject(), EventTriggerSupportsObjectClass(), ObjectAddresses::extras, ObjectAddressExtra::flags, getObjectClass(), i, ObjectAddresses::numrefs, PERFORM_DELETION_INTERNAL, PERFORM_DELETION_SKIP_ORIGINAL, ObjectAddresses::refs, and trackDroppedObjectsNeeded().

Referenced by performDeletion(), and performMultipleDeletions().

218 {
219  int i;
220 
221  /*
222  * Keep track of objects for event triggers, if necessary.
223  */
225  {
226  for (i = 0; i < targetObjects->numrefs; i++)
227  {
228  const ObjectAddress *thisobj = &targetObjects->refs[i];
229  const ObjectAddressExtra *extra = &targetObjects->extras[i];
230  bool original = false;
231  bool normal = false;
232 
233  if (extra->flags & DEPFLAG_ORIGINAL)
234  original = true;
235  if (extra->flags & DEPFLAG_NORMAL)
236  normal = true;
237  if (extra->flags & DEPFLAG_REVERSE)
238  normal = true;
239 
241  {
242  EventTriggerSQLDropAddObject(thisobj, original, normal);
243  }
244  }
245  }
246 
247  /*
248  * Delete all the objects in the proper order, except that if told to, we
249  * should skip the original object(s).
250  */
251  for (i = 0; i < targetObjects->numrefs; i++)
252  {
253  ObjectAddress *thisobj = targetObjects->refs + i;
254  ObjectAddressExtra *thisextra = targetObjects->extras + i;
255 
256  if ((flags & PERFORM_DELETION_SKIP_ORIGINAL) &&
257  (thisextra->flags & DEPFLAG_ORIGINAL))
258  continue;
259 
260  deleteOneObject(thisobj, depRel, flags);
261  }
262 }
static void deleteOneObject(const ObjectAddress *object, Relation *depRel, int32 flags)
bool trackDroppedObjectsNeeded(void)
#define PERFORM_DELETION_SKIP_ORIGINAL
Definition: dependency.h:192
#define DEPFLAG_REVERSE
Definition: dependency.c:102
ObjectClass getObjectClass(const ObjectAddress *object)
Definition: dependency.c:2416
#define DEPFLAG_ORIGINAL
Definition: dependency.c:97
ObjectAddress * refs
Definition: dependency.c:108
bool EventTriggerSupportsObjectClass(ObjectClass objclass)
void EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool normal)
ObjectAddressExtra * extras
Definition: dependency.c:109
#define DEPFLAG_NORMAL
Definition: dependency.c:98
int i
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:189

◆ deleteOneObject() [1/2]

static void deleteOneObject ( const ObjectAddress object,
Relation depRel,
int32  flags 
)
static

Referenced by deleteObjectsInList().

◆ deleteOneObject() [2/2]

static void deleteOneObject ( const ObjectAddress object,
Relation depRel,
int  flags 
)
static

Definition at line 1008 of file dependency.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), ObjectAddress::classId, CommandCounterIncrement(), DeleteComments(), DeleteInitPrivs(), DeleteSecurityLabel(), deleteSharedDependencyRecordsFor(), DependDependerIndexId, doDeletion(), heap_close, heap_open(), HeapTupleIsValid, Int32GetDatum, InvokeObjectDropHookArg, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, PERFORM_DELETION_CONCURRENTLY, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

1009 {
1010  ScanKeyData key[3];
1011  int nkeys;
1012  SysScanDesc scan;
1013  HeapTuple tup;
1014 
1015  /* DROP hook of the objects being removed */
1016  InvokeObjectDropHookArg(object->classId, object->objectId,
1017  object->objectSubId, flags);
1018 
1019  /*
1020  * Close depRel if we are doing a drop concurrently. The object deletion
1021  * subroutine will commit the current transaction, so we can't keep the
1022  * relation open across doDeletion().
1023  */
1024  if (flags & PERFORM_DELETION_CONCURRENTLY)
1025  heap_close(*depRel, RowExclusiveLock);
1026 
1027  /*
1028  * Delete the object itself, in an object-type-dependent way.
1029  *
1030  * We used to do this after removing the outgoing dependency links, but it
1031  * seems just as reasonable to do it beforehand. In the concurrent case
1032  * we *must* do it in this order, because we can't make any transactional
1033  * updates before calling doDeletion() --- they'd get committed right
1034  * away, which is not cool if the deletion then fails.
1035  */
1036  doDeletion(object, flags);
1037 
1038  /*
1039  * Reopen depRel if we closed it above
1040  */
1041  if (flags & PERFORM_DELETION_CONCURRENTLY)
1042  *depRel = heap_open(DependRelationId, RowExclusiveLock);
1043 
1044  /*
1045  * Now remove any pg_depend records that link from this object to others.
1046  * (Any records linking to this object should be gone already.)
1047  *
1048  * When dropping a whole object (subId = 0), remove all pg_depend records
1049  * for its sub-objects too.
1050  */
1051  ScanKeyInit(&key[0],
1052  Anum_pg_depend_classid,
1053  BTEqualStrategyNumber, F_OIDEQ,
1054  ObjectIdGetDatum(object->classId));
1055  ScanKeyInit(&key[1],
1056  Anum_pg_depend_objid,
1057  BTEqualStrategyNumber, F_OIDEQ,
1058  ObjectIdGetDatum(object->objectId));
1059  if (object->objectSubId != 0)
1060  {
1061  ScanKeyInit(&key[2],
1062  Anum_pg_depend_objsubid,
1063  BTEqualStrategyNumber, F_INT4EQ,
1064  Int32GetDatum(object->objectSubId));
1065  nkeys = 3;
1066  }
1067  else
1068  nkeys = 2;
1069 
1070  scan = systable_beginscan(*depRel, DependDependerIndexId, true,
1071  NULL, nkeys, key);
1072 
1073  while (HeapTupleIsValid(tup = systable_getnext(scan)))
1074  {
1075  CatalogTupleDelete(*depRel, &tup->t_self);
1076  }
1077 
1078  systable_endscan(scan);
1079 
1080  /*
1081  * Delete shared dependency references related to this object. Again, if
1082  * subId = 0, remove records for sub-objects too.
1083  */
1085  object->objectSubId);
1086 
1087 
1088  /*
1089  * Delete any comments, security labels, or initial privileges associated
1090  * with this object. (This is a convenient place to do these things,
1091  * rather than having every object type know to do it.)
1092  */
1093  DeleteComments(object->objectId, object->classId, object->objectSubId);
1094  DeleteSecurityLabel(object);
1095  DeleteInitPrivs(object);
1096 
1097  /*
1098  * CommandCounterIncrement here to ensure that preceding changes are all
1099  * visible to the next deletion step.
1100  */
1102 
1103  /*
1104  * And we're done!
1105  */
1106 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define DependDependerIndexId
Definition: indexing.h:146
void DeleteSecurityLabel(const ObjectAddress *object)
Definition: seclabel.c:446
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:190
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:823
void CommandCounterIncrement(void)
Definition: xact.c:914
void DeleteComments(Oid oid, Oid classoid, int32 subid)
Definition: comment.c:325
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void doDeletion(const ObjectAddress *object, int flags)
Definition: dependency.c:1112
#define Int32GetDatum(X)
Definition: postgres.h:462
static void DeleteInitPrivs(const ObjectAddress *object)
Definition: dependency.c:2551
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define InvokeObjectDropHookArg(classId, objectId, subId, dropflags)
Definition: objectaccess.h:156
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ doDeletion()

static void doDeletion ( const ObjectAddress object,
int  flags 
)
static

Definition at line 1112 of file dependency.c.

References Assert, DeleteSequenceTuple(), DropCastById(), DropProceduralLanguageById(), DropTransformById(), elog, ERROR, get_rel_relkind(), getObjectClass(), heap_drop_with_catalog(), index_drop(), LargeObjectDrop(), ObjectAddress::objectId, ObjectAddress::objectSubId, OCLASS_AM, OCLASS_AMOP, OCLASS_AMPROC, OCLASS_CAST, OCLASS_CLASS, OCLASS_COLLATION, OCLASS_CONSTRAINT, OCLASS_CONVERSION, OCLASS_DATABASE, OCLASS_DEFACL, OCLASS_DEFAULT, OCLASS_EVENT_TRIGGER, OCLASS_EXTENSION, OCLASS_FDW, OCLASS_FOREIGN_SERVER, OCLASS_LANGUAGE, OCLASS_LARGEOBJECT, OCLASS_OPCLASS, OCLASS_OPERATOR, OCLASS_OPFAMILY, OCLASS_POLICY, OCLASS_PROC, OCLASS_PUBLICATION, OCLASS_PUBLICATION_REL, OCLASS_REWRITE, OCLASS_ROLE, OCLASS_SCHEMA, OCLASS_STATISTIC_EXT, OCLASS_SUBSCRIPTION, OCLASS_TBLSPACE, OCLASS_TRANSFORM, OCLASS_TRIGGER, OCLASS_TSCONFIG, OCLASS_TSDICT, OCLASS_TSPARSER, OCLASS_TSTEMPLATE, OCLASS_TYPE, OCLASS_USER_MAPPING, PERFORM_DELETION_CONCURRENTLY, RemoveAccessMethodById(), RemoveAmOpEntryById(), RemoveAmProcEntryById(), RemoveAttrDefaultById(), RemoveAttributeById(), RemoveCollationById(), RemoveConstraintById(), RemoveConversionById(), RemoveDefaultACLById(), RemoveEventTriggerById(), RemoveExtensionById(), RemoveForeignDataWrapperById(), RemoveForeignServerById(), RemoveFunctionById(), RemoveOpClassById(), RemoveOperatorById(), RemoveOpFamilyById(), RemovePolicyById(), RemovePublicationById(), RemovePublicationRelById(), RemoveRewriteRuleById(), RemoveSchemaById(), RemoveStatisticsById(), RemoveTriggerById(), RemoveTSConfigurationById(), RemoveTSDictionaryById(), RemoveTSParserById(), RemoveTSTemplateById(), RemoveTypeById(), and RemoveUserMappingById().

Referenced by deleteOneObject().

1113 {
1114  switch (getObjectClass(object))
1115  {
1116  case OCLASS_CLASS:
1117  {
1118  char relKind = get_rel_relkind(object->objectId);
1119 
1120  if (relKind == RELKIND_INDEX ||
1121  relKind == RELKIND_PARTITIONED_INDEX)
1122  {
1123  bool concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY) != 0);
1124 
1125  Assert(object->objectSubId == 0);
1126  index_drop(object->objectId, concurrent);
1127  }
1128  else
1129  {
1130  if (object->objectSubId != 0)
1131  RemoveAttributeById(object->objectId,
1132  object->objectSubId);
1133  else
1135  }
1136 
1137  /*
1138  * for a sequence, in addition to dropping the heap, also
1139  * delete pg_sequence tuple
1140  */
1141  if (relKind == RELKIND_SEQUENCE)
1142  DeleteSequenceTuple(object->objectId);
1143  break;
1144  }
1145 
1146  case OCLASS_PROC:
1147  RemoveFunctionById(object->objectId);
1148  break;
1149 
1150  case OCLASS_TYPE:
1151  RemoveTypeById(object->objectId);
1152  break;
1153 
1154  case OCLASS_CAST:
1155  DropCastById(object->objectId);
1156  break;
1157 
1158  case OCLASS_COLLATION:
1159  RemoveCollationById(object->objectId);
1160  break;
1161 
1162  case OCLASS_CONSTRAINT:
1163  RemoveConstraintById(object->objectId);
1164  break;
1165 
1166  case OCLASS_CONVERSION:
1167  RemoveConversionById(object->objectId);
1168  break;
1169 
1170  case OCLASS_DEFAULT:
1172  break;
1173 
1174  case OCLASS_LANGUAGE:
1176  break;
1177 
1178  case OCLASS_LARGEOBJECT:
1179  LargeObjectDrop(object->objectId);
1180  break;
1181 
1182  case OCLASS_OPERATOR:
1183  RemoveOperatorById(object->objectId);
1184  break;
1185 
1186  case OCLASS_OPCLASS:
1187  RemoveOpClassById(object->objectId);
1188  break;
1189 
1190  case OCLASS_OPFAMILY:
1191  RemoveOpFamilyById(object->objectId);
1192  break;
1193 
1194  case OCLASS_AM:
1196  break;
1197 
1198  case OCLASS_AMOP:
1199  RemoveAmOpEntryById(object->objectId);
1200  break;
1201 
1202  case OCLASS_AMPROC:
1204  break;
1205 
1206  case OCLASS_REWRITE:
1208  break;
1209 
1210  case OCLASS_TRIGGER:
1211  RemoveTriggerById(object->objectId);
1212  break;
1213 
1214  case OCLASS_SCHEMA:
1215  RemoveSchemaById(object->objectId);
1216  break;
1217 
1218  case OCLASS_STATISTIC_EXT:
1219  RemoveStatisticsById(object->objectId);
1220  break;
1221 
1222  case OCLASS_TSPARSER:
1223  RemoveTSParserById(object->objectId);
1224  break;
1225 
1226  case OCLASS_TSDICT:
1228  break;
1229 
1230  case OCLASS_TSTEMPLATE:
1231  RemoveTSTemplateById(object->objectId);
1232  break;
1233 
1234  case OCLASS_TSCONFIG:
1236  break;
1237 
1238  /*
1239  * OCLASS_ROLE, OCLASS_DATABASE, OCLASS_TBLSPACE intentionally not
1240  * handled here
1241  */
1242 
1243  case OCLASS_FDW:
1245  break;
1246 
1247  case OCLASS_FOREIGN_SERVER:
1249  break;
1250 
1251  case OCLASS_USER_MAPPING:
1253  break;
1254 
1255  case OCLASS_DEFACL:
1256  RemoveDefaultACLById(object->objectId);
1257  break;
1258 
1259  case OCLASS_EXTENSION:
1260  RemoveExtensionById(object->objectId);
1261  break;
1262 
1263  case OCLASS_EVENT_TRIGGER:
1265  break;
1266 
1267  case OCLASS_POLICY:
1268  RemovePolicyById(object->objectId);
1269  break;
1270 
1271  case OCLASS_PUBLICATION:
1273  break;
1274 
1277  break;
1278 
1279  case OCLASS_TRANSFORM:
1280  DropTransformById(object->objectId);
1281  break;
1282 
1283  /*
1284  * These global object types are not supported here.
1285  */
1286  case OCLASS_ROLE:
1287  case OCLASS_DATABASE:
1288  case OCLASS_TBLSPACE:
1289  case OCLASS_SUBSCRIPTION:
1290  elog(ERROR, "global objects cannot be deleted by doDeletion");
1291  break;
1292 
1293  /*
1294  * There's intentionally no default: case here; we want the
1295  * compiler to warn if a new OCLASS hasn't been handled above.
1296  */
1297  }
1298 }
void RemoveTriggerById(Oid trigOid)
Definition: trigger.c:1481
void RemoveStatisticsById(Oid statsOid)
Definition: statscmds.c:379
void RemoveOpClassById(Oid opclassOid)
Definition: opclasscmds.c:1603
void DropTransformById(Oid transformOid)
void RemoveExtensionById(Oid extId)
Definition: extension.c:1826
void DropProceduralLanguageById(Oid langOid)
Definition: proclang.c:524
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
void RemoveForeignDataWrapperById(Oid fdwId)
Definition: foreigncmds.c:837
void RemoveSchemaById(Oid schemaOid)
Definition: schemacmds.c:218
void index_drop(Oid indexId, bool concurrent)
Definition: index.c:1443
void RemovePublicationById(Oid pubid)
void RemovePublicationRelById(Oid proid)
void RemoveAmProcEntryById(Oid entryOid)
Definition: opclasscmds.c:1651
void RemoveTypeById(Oid typeOid)
Definition: typecmds.c:686
ObjectClass getObjectClass(const ObjectAddress *object)
Definition: dependency.c:2416
void RemoveCollationById(Oid collationOid)
Definition: pg_collation.c:210
void RemoveUserMappingById(Oid umId)
Definition: foreigncmds.c:1422
void RemoveConversionById(Oid conversionOid)
void RemoveAccessMethodById(Oid amOid)
Definition: amcmds.c:115
void RemoveOperatorById(Oid operOid)
Definition: operatorcmds.c:339
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:190
void RemoveDefaultACLById(Oid defaclOid)
Definition: aclchk.c:1523
#define ERROR
Definition: elog.h:43
void RemoveTSConfigurationById(Oid cfgId)
Definition: tsearchcmds.c:1125
void RemoveOpFamilyById(Oid opfamilyOid)
Definition: opclasscmds.c:1584
void RemovePolicyById(Oid policy_id)
Definition: policy.c:353
void RemoveTSParserById(Oid prsId)
Definition: tsearchcmds.c:292
void RemoveAttributeById(Oid relid, AttrNumber attnum)
Definition: heap.c:1552
void RemoveTSTemplateById(Oid tmplId)
Definition: tsearchcmds.c:821
void DeleteSequenceTuple(Oid relid)
Definition: sequence.c:515
void RemoveEventTriggerById(Oid trigOid)
void RemoveAttrDefaultById(Oid attrdefId)
Definition: heap.c:1694
void LargeObjectDrop(Oid loid)
void RemoveAmOpEntryById(Oid entryOid)
Definition: opclasscmds.c:1622
void RemoveForeignServerById(Oid srvId)
Definition: foreigncmds.c:1084
#define Assert(condition)
Definition: c.h:699
void RemoveFunctionById(Oid funcOid)
void RemoveRewriteRuleById(Oid ruleOid)
Definition: rewriteRemove.c:38
void DropCastById(Oid castOid)
#define elog
Definition: elog.h:219
void heap_drop_with_catalog(Oid relid)
Definition: heap.c:1767
void RemoveConstraintById(Oid conId)
void RemoveTSDictionaryById(Oid dictId)
Definition: tsearchcmds.c:501

◆ eliminate_duplicate_dependencies()

static void eliminate_duplicate_dependencies ( ObjectAddresses addrs)
static

Definition at line 2039 of file dependency.c.

References Assert, ObjectAddress::classId, ObjectAddresses::extras, ObjectAddresses::numrefs, object_address_comparator(), ObjectAddress::objectId, ObjectAddress::objectSubId, qsort, and ObjectAddresses::refs.

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

2040 {
2041  ObjectAddress *priorobj;
2042  int oldref,
2043  newrefs;
2044 
2045  /*
2046  * We can't sort if the array has "extra" data, because there's no way to
2047  * keep it in sync. Fortunately that combination of features is not
2048  * needed.
2049  */
2050  Assert(!addrs->extras);
2051 
2052  if (addrs->numrefs <= 1)
2053  return; /* nothing to do */
2054 
2055  /* Sort the refs so that duplicates are adjacent */
2056  qsort((void *) addrs->refs, addrs->numrefs, sizeof(ObjectAddress),
2058 
2059  /* Remove dups */
2060  priorobj = addrs->refs;
2061  newrefs = 1;
2062  for (oldref = 1; oldref < addrs->numrefs; oldref++)
2063  {
2064  ObjectAddress *thisobj = addrs->refs + oldref;
2065 
2066  if (priorobj->classId == thisobj->classId &&
2067  priorobj->objectId == thisobj->objectId)
2068  {
2069  if (priorobj->objectSubId == thisobj->objectSubId)
2070  continue; /* identical, so drop thisobj */
2071 
2072  /*
2073  * If we have a whole-object reference and a reference to a part
2074  * of the same object, we don't need the whole-object reference
2075  * (for example, we don't need to reference both table foo and
2076  * column foo.bar). The whole-object reference will always appear
2077  * first in the sorted list.
2078  */
2079  if (priorobj->objectSubId == 0)
2080  {
2081  /* replace whole ref with partial */
2082  priorobj->objectSubId = thisobj->objectSubId;
2083  continue;
2084  }
2085  }
2086  /* Not identical, so add thisobj to output set */
2087  priorobj++;
2088  *priorobj = *thisobj;
2089  newrefs++;
2090  }
2091 
2092  addrs->numrefs = newrefs;
2093 }
static int object_address_comparator(const void *a, const void *b)
Definition: dependency.c:2099
ObjectAddress * refs
Definition: dependency.c:108
#define Assert(condition)
Definition: c.h:699
ObjectAddressExtra * extras
Definition: dependency.c:109
#define qsort(a, b, c, d)
Definition: port.h:421

◆ find_expr_references_walker()

static bool find_expr_references_walker ( Node node,
find_expr_references_context context 
)
static

Definition at line 1496 of file dependency.c.

References add_object_address(), find_expr_references_context::addrs, Aggref::aggfnoid, FieldSelect::arg, CMD_INSERT, CMD_UPDATE, CollateExpr::collOid, Query::commandType, Const::constcollid, Const::constisnull, OnConflictExpr::constraint, Query::constraintDeps, Const::consttype, Const::constvalue, DatumGetObjectId, Query::distinctClause, elog, WindowClause::endInRangeFunc, SortGroupClause::eqop, ereport, errcode(), errmsg(), ERROR, expression_tree_walker(), exprType(), FieldSelect::fieldnum, FieldStore::fieldnums, RangeTblFunction::funccolcollations, RangeTblFunction::funccoltypes, FuncExpr::funcid, get_typ_typrelid(), getBaseType(), Query::groupClause, SetOperationStmt::groupClauses, WindowClause::inRangeColl, InvalidAttrNumber, IsA, RangeTblEntry::joinaliasvars, lcons(), lfirst, lfirst_int, lfirst_oid, list_copy_tail(), list_delete_first(), list_free(), list_length(), list_nth(), NAMESPACEOID, ObjectIdGetDatum, OCLASS_CLASS, OCLASS_COLLATION, OCLASS_CONSTRAINT, OCLASS_OPERATOR, OCLASS_OPFAMILY, OCLASS_PROC, OCLASS_SCHEMA, OCLASS_TSCONFIG, OCLASS_TSDICT, OCLASS_TYPE, OidIsValid, OPEROID, RowCompareExpr::opfamilies, OpExpr::opno, ScalarArrayOpExpr::opno, RowCompareExpr::opnos, Param::paramcollid, Param::paramtype, PROCOID, QTW_IGNORE_JOINALIASES, query_tree_walker(), RangeTblEntry::relid, RELOID, reltype, TargetEntry::resjunk, TargetEntry::resno, FieldSelect::resultcollid, RelabelType::resultcollid, CoerceViaIO::resultcollid, ArrayCoerceExpr::resultcollid, Query::resultRelation, FieldSelect::resulttype, FieldStore::resulttype, RelabelType::resulttype, CoerceViaIO::resulttype, ArrayCoerceExpr::resulttype, ConvertRowtypeExpr::resulttype, CoerceToDomain::resulttype, RowExpr::row_typeid, rt_fetch, Query::rtable, find_expr_references_context::rtables, RTE_JOIN, RTE_RELATION, RangeTblEntry::rtekind, SearchSysCacheExists1, NextValueExpr::seqid, Query::sortClause, SortGroupClause::sortop, WindowClause::startInRangeFunc, Query::targetList, TSCONFIGOID, TSDICTOID, TableSampleClause::tsmhandler, TYPEOID, Var::varattno, Var::varlevelsup, Var::varno, Query::windowClause, and WindowFunc::winfnoid.

Referenced by recordDependencyOnExpr(), and recordDependencyOnSingleRelExpr().

1498 {
1499  if (node == NULL)
1500  return false;
1501  if (IsA(node, Var))
1502  {
1503  Var *var = (Var *) node;
1504  List *rtable;
1505  RangeTblEntry *rte;
1506 
1507  /* Find matching rtable entry, or complain if not found */
1508  if (var->varlevelsup >= list_length(context->rtables))
1509  elog(ERROR, "invalid varlevelsup %d", var->varlevelsup);
1510  rtable = (List *) list_nth(context->rtables, var->varlevelsup);
1511  if (var->varno <= 0 || var->varno > list_length(rtable))
1512  elog(ERROR, "invalid varno %d", var->varno);
1513  rte = rt_fetch(var->varno, rtable);
1514 
1515  /*
1516  * A whole-row Var references no specific columns, so adds no new
1517  * dependency. (We assume that there is a whole-table dependency
1518  * arising from each underlying rangetable entry. While we could
1519  * record such a dependency when finding a whole-row Var that
1520  * references a relation directly, it's quite unclear how to extend
1521  * that to whole-row Vars for JOINs, so it seems better to leave the
1522  * responsibility with the range table. Note that this poses some
1523  * risks for identifying dependencies of stand-alone expressions:
1524  * whole-table references may need to be created separately.)
1525  */
1526  if (var->varattno == InvalidAttrNumber)
1527  return false;
1528  if (rte->rtekind == RTE_RELATION)
1529  {
1530  /* If it's a plain relation, reference this column */
1532  context->addrs);
1533  }
1534  else if (rte->rtekind == RTE_JOIN)
1535  {
1536  /* Scan join output column to add references to join inputs */
1537  List *save_rtables;
1538 
1539  /* We must make the context appropriate for join's level */
1540  save_rtables = context->rtables;
1541  context->rtables = list_copy_tail(context->rtables,
1542  var->varlevelsup);
1543  if (var->varattno <= 0 ||
1544  var->varattno > list_length(rte->joinaliasvars))
1545  elog(ERROR, "invalid varattno %d", var->varattno);
1547  var->varattno - 1),
1548  context);
1549  list_free(context->rtables);
1550  context->rtables = save_rtables;
1551  }
1552  return false;
1553  }
1554  else if (IsA(node, Const))
1555  {
1556  Const *con = (Const *) node;
1557  Oid objoid;
1558 
1559  /* A constant must depend on the constant's datatype */
1561  context->addrs);
1562 
1563  /*
1564  * We must also depend on the constant's collation: it could be
1565  * different from the datatype's, if a CollateExpr was const-folded to
1566  * a simple constant. However we can save work in the most common
1567  * case where the collation is "default", since we know that's pinned.
1568  */
1569  if (OidIsValid(con->constcollid) &&
1570  con->constcollid != DEFAULT_COLLATION_OID)
1572  context->addrs);
1573 
1574  /*
1575  * If it's a regclass or similar literal referring to an existing
1576  * object, add a reference to that object. (Currently, only the
1577  * regclass and regconfig cases have any likely use, but we may as
1578  * well handle all the OID-alias datatypes consistently.)
1579  */
1580  if (!con->constisnull)
1581  {
1582  switch (con->consttype)
1583  {
1584  case REGPROCOID:
1585  case REGPROCEDUREOID:
1586  objoid = DatumGetObjectId(con->constvalue);
1588  ObjectIdGetDatum(objoid)))
1589  add_object_address(OCLASS_PROC, objoid, 0,
1590  context->addrs);
1591  break;
1592  case REGOPEROID:
1593  case REGOPERATOROID:
1594  objoid = DatumGetObjectId(con->constvalue);
1596  ObjectIdGetDatum(objoid)))
1598  context->addrs);
1599  break;
1600  case REGCLASSOID:
1601  objoid = DatumGetObjectId(con->constvalue);
1603  ObjectIdGetDatum(objoid)))
1604  add_object_address(OCLASS_CLASS, objoid, 0,
1605  context->addrs);
1606  break;
1607  case REGTYPEOID:
1608  objoid = DatumGetObjectId(con->constvalue);
1610  ObjectIdGetDatum(objoid)))
1611  add_object_address(OCLASS_TYPE, objoid, 0,
1612  context->addrs);
1613  break;
1614  case REGCONFIGOID:
1615  objoid = DatumGetObjectId(con->constvalue);
1617  ObjectIdGetDatum(objoid)))
1619  context->addrs);
1620  break;
1621  case REGDICTIONARYOID:
1622  objoid = DatumGetObjectId(con->constvalue);
1624  ObjectIdGetDatum(objoid)))
1625  add_object_address(OCLASS_TSDICT, objoid, 0,
1626  context->addrs);
1627  break;
1628 
1629  case REGNAMESPACEOID:
1630  objoid = DatumGetObjectId(con->constvalue);
1632  ObjectIdGetDatum(objoid)))
1633  add_object_address(OCLASS_SCHEMA, objoid, 0,
1634  context->addrs);
1635  break;
1636 
1637  /*
1638  * Dependencies for regrole should be shared among all
1639  * databases, so explicitly inhibit to have dependencies.
1640  */
1641  case REGROLEOID:
1642  ereport(ERROR,
1643  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1644  errmsg("constant of the type %s cannot be used here",
1645  "regrole")));
1646  break;
1647  }
1648  }
1649  return false;
1650  }
1651  else if (IsA(node, Param))
1652  {
1653  Param *param = (Param *) node;
1654 
1655  /* A parameter must depend on the parameter's datatype */
1657  context->addrs);
1658  /* and its collation, just as for Consts */
1659  if (OidIsValid(param->paramcollid) &&
1660  param->paramcollid != DEFAULT_COLLATION_OID)
1662  context->addrs);
1663  }
1664  else if (IsA(node, FuncExpr))
1665  {
1666  FuncExpr *funcexpr = (FuncExpr *) node;
1667 
1668  add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
1669  context->addrs);
1670  /* fall through to examine arguments */
1671  }
1672  else if (IsA(node, OpExpr))
1673  {
1674  OpExpr *opexpr = (OpExpr *) node;
1675 
1677  context->addrs);
1678  /* fall through to examine arguments */
1679  }
1680  else if (IsA(node, DistinctExpr))
1681  {
1682  DistinctExpr *distinctexpr = (DistinctExpr *) node;
1683 
1684  add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
1685  context->addrs);
1686  /* fall through to examine arguments */
1687  }
1688  else if (IsA(node, NullIfExpr))
1689  {
1690  NullIfExpr *nullifexpr = (NullIfExpr *) node;
1691 
1692  add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
1693  context->addrs);
1694  /* fall through to examine arguments */
1695  }
1696  else if (IsA(node, ScalarArrayOpExpr))
1697  {
1698  ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
1699 
1701  context->addrs);
1702  /* fall through to examine arguments */
1703  }
1704  else if (IsA(node, Aggref))
1705  {
1706  Aggref *aggref = (Aggref *) node;
1707 
1709  context->addrs);
1710  /* fall through to examine arguments */
1711  }
1712  else if (IsA(node, WindowFunc))
1713  {
1714  WindowFunc *wfunc = (WindowFunc *) node;
1715 
1717  context->addrs);
1718  /* fall through to examine arguments */
1719  }
1720  else if (IsA(node, SubPlan))
1721  {
1722  /* Extra work needed here if we ever need this case */
1723  elog(ERROR, "already-planned subqueries not supported");
1724  }
1725  else if (IsA(node, FieldSelect))
1726  {
1727  FieldSelect *fselect = (FieldSelect *) node;
1728  Oid argtype = getBaseType(exprType((Node *) fselect->arg));
1729  Oid reltype = get_typ_typrelid(argtype);
1730 
1731  /*
1732  * We need a dependency on the specific column named in FieldSelect,
1733  * assuming we can identify the pg_class OID for it. (Probably we
1734  * always can at the moment, but in future it might be possible for
1735  * argtype to be RECORDOID.) If we can make a column dependency then
1736  * we shouldn't need a dependency on the column's type; but if we
1737  * can't, make a dependency on the type, as it might not appear
1738  * anywhere else in the expression.
1739  */
1740  if (OidIsValid(reltype))
1741  add_object_address(OCLASS_CLASS, reltype, fselect->fieldnum,
1742  context->addrs);
1743  else
1745  context->addrs);
1746  /* the collation might not be referenced anywhere else, either */
1747  if (OidIsValid(fselect->resultcollid) &&
1748  fselect->resultcollid != DEFAULT_COLLATION_OID)
1750  context->addrs);
1751  }
1752  else if (IsA(node, FieldStore))
1753  {
1754  FieldStore *fstore = (FieldStore *) node;
1755  Oid reltype = get_typ_typrelid(fstore->resulttype);
1756 
1757  /* similar considerations to FieldSelect, but multiple column(s) */
1758  if (OidIsValid(reltype))
1759  {
1760  ListCell *l;
1761 
1762  foreach(l, fstore->fieldnums)
1764  context->addrs);
1765  }
1766  else
1768  context->addrs);
1769  }
1770  else if (IsA(node, RelabelType))
1771  {
1772  RelabelType *relab = (RelabelType *) node;
1773 
1774  /* since there is no function dependency, need to depend on type */
1776  context->addrs);
1777  /* the collation might not be referenced anywhere else, either */
1778  if (OidIsValid(relab->resultcollid) &&
1779  relab->resultcollid != DEFAULT_COLLATION_OID)
1781  context->addrs);
1782  }
1783  else if (IsA(node, CoerceViaIO))
1784  {
1785  CoerceViaIO *iocoerce = (CoerceViaIO *) node;
1786 
1787  /* since there is no exposed function, need to depend on type */
1789  context->addrs);
1790  /* the collation might not be referenced anywhere else, either */
1791  if (OidIsValid(iocoerce->resultcollid) &&
1792  iocoerce->resultcollid != DEFAULT_COLLATION_OID)
1794  context->addrs);
1795  }
1796  else if (IsA(node, ArrayCoerceExpr))
1797  {
1798  ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
1799 
1800  /* as above, depend on type */
1802  context->addrs);
1803  /* the collation might not be referenced anywhere else, either */
1804  if (OidIsValid(acoerce->resultcollid) &&
1805  acoerce->resultcollid != DEFAULT_COLLATION_OID)
1807  context->addrs);
1808  /* fall through to examine arguments */
1809  }
1810  else if (IsA(node, ConvertRowtypeExpr))
1811  {
1812  ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node;
1813 
1814  /* since there is no function dependency, need to depend on type */
1816  context->addrs);
1817  }
1818  else if (IsA(node, CollateExpr))
1819  {
1820  CollateExpr *coll = (CollateExpr *) node;
1821 
1823  context->addrs);
1824  }
1825  else if (IsA(node, RowExpr))
1826  {
1827  RowExpr *rowexpr = (RowExpr *) node;
1828 
1830  context->addrs);
1831  }
1832  else if (IsA(node, RowCompareExpr))
1833  {
1834  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1835  ListCell *l;
1836 
1837  foreach(l, rcexpr->opnos)
1838  {
1840  context->addrs);
1841  }
1842  foreach(l, rcexpr->opfamilies)
1843  {
1845  context->addrs);
1846  }
1847  /* fall through to examine arguments */
1848  }
1849  else if (IsA(node, CoerceToDomain))
1850  {
1851  CoerceToDomain *cd = (CoerceToDomain *) node;
1852 
1854  context->addrs);
1855  }
1856  else if (IsA(node, NextValueExpr))
1857  {
1858  NextValueExpr *nve = (NextValueExpr *) node;
1859 
1861  context->addrs);
1862  }
1863  else if (IsA(node, OnConflictExpr))
1864  {
1865  OnConflictExpr *onconflict = (OnConflictExpr *) node;
1866 
1867  if (OidIsValid(onconflict->constraint))
1869  context->addrs);
1870  /* fall through to examine arguments */
1871  }
1872  else if (IsA(node, SortGroupClause))
1873  {
1874  SortGroupClause *sgc = (SortGroupClause *) node;
1875 
1877  context->addrs);
1878  if (OidIsValid(sgc->sortop))
1880  context->addrs);
1881  return false;
1882  }
1883  else if (IsA(node, WindowClause))
1884  {
1885  WindowClause *wc = (WindowClause *) node;
1886 
1887  if (OidIsValid(wc->startInRangeFunc))
1889  context->addrs);
1890  if (OidIsValid(wc->endInRangeFunc))
1892  context->addrs);
1893  if (OidIsValid(wc->inRangeColl) &&
1894  wc->inRangeColl != DEFAULT_COLLATION_OID)
1896  context->addrs);
1897  /* fall through to examine substructure */
1898  }
1899  else if (IsA(node, Query))
1900  {
1901  /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1902  Query *query = (Query *) node;
1903  ListCell *lc;
1904  bool result;
1905 
1906  /*
1907  * Add whole-relation refs for each plain relation mentioned in the
1908  * subquery's rtable.
1909  *
1910  * Note: query_tree_walker takes care of recursing into RTE_FUNCTION
1911  * RTEs, subqueries, etc, so no need to do that here. But keep it
1912  * from looking at join alias lists.
1913  *
1914  * Note: we don't need to worry about collations mentioned in
1915  * RTE_VALUES or RTE_CTE RTEs, because those must just duplicate
1916  * collations referenced in other parts of the Query. We do have to
1917  * worry about collations mentioned in RTE_FUNCTION, but we take care
1918  * of those when we recurse to the RangeTblFunction node(s).
1919  */
1920  foreach(lc, query->rtable)
1921  {
1922  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
1923 
1924  switch (rte->rtekind)
1925  {
1926  case RTE_RELATION:
1928  context->addrs);
1929  break;
1930  default:
1931  break;
1932  }
1933  }
1934 
1935  /*
1936  * If the query is an INSERT or UPDATE, we should create a dependency
1937  * on each target column, to prevent the specific target column from
1938  * being dropped. Although we will visit the TargetEntry nodes again
1939  * during query_tree_walker, we won't have enough context to do this
1940  * conveniently, so do it here.
1941  */
1942  if (query->commandType == CMD_INSERT ||
1943  query->commandType == CMD_UPDATE)
1944  {
1945  RangeTblEntry *rte;
1946 
1947  if (query->resultRelation <= 0 ||
1948  query->resultRelation > list_length(query->rtable))
1949  elog(ERROR, "invalid resultRelation %d",
1950  query->resultRelation);
1951  rte = rt_fetch(query->resultRelation, query->rtable);
1952  if (rte->rtekind == RTE_RELATION)
1953  {
1954  foreach(lc, query->targetList)
1955  {
1956  TargetEntry *tle = (TargetEntry *) lfirst(lc);
1957 
1958  if (tle->resjunk)
1959  continue; /* ignore junk tlist items */
1961  context->addrs);
1962  }
1963  }
1964  }
1965 
1966  /*
1967  * Add dependencies on constraints listed in query's constraintDeps
1968  */
1969  foreach(lc, query->constraintDeps)
1970  {
1972  context->addrs);
1973  }
1974 
1975  /* query_tree_walker ignores ORDER BY etc, but we need those opers */
1976  find_expr_references_walker((Node *) query->sortClause, context);
1977  find_expr_references_walker((Node *) query->groupClause, context);
1978  find_expr_references_walker((Node *) query->windowClause, context);
1979  find_expr_references_walker((Node *) query->distinctClause, context);
1980 
1981  /* Examine substructure of query */
1982  context->rtables = lcons(query->rtable, context->rtables);
1983  result = query_tree_walker(query,
1985  (void *) context,
1987  context->rtables = list_delete_first(context->rtables);
1988  return result;
1989  }
1990  else if (IsA(node, SetOperationStmt))
1991  {
1992  SetOperationStmt *setop = (SetOperationStmt *) node;
1993 
1994  /* we need to look at the groupClauses for operator references */
1995  find_expr_references_walker((Node *) setop->groupClauses, context);
1996  /* fall through to examine child nodes */
1997  }
1998  else if (IsA(node, RangeTblFunction))
1999  {
2000  RangeTblFunction *rtfunc = (RangeTblFunction *) node;
2001  ListCell *ct;
2002 
2003  /*
2004  * Add refs for any datatypes and collations used in a column
2005  * definition list for a RECORD function. (For other cases, it should
2006  * be enough to depend on the function itself.)
2007  */
2008  foreach(ct, rtfunc->funccoltypes)
2009  {
2011  context->addrs);
2012  }
2013  foreach(ct, rtfunc->funccolcollations)
2014  {
2015  Oid collid = lfirst_oid(ct);
2016 
2017  if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
2019  context->addrs);
2020  }
2021  }
2022  else if (IsA(node, TableSampleClause))
2023  {
2024  TableSampleClause *tsc = (TableSampleClause *) node;
2025 
2027  context->addrs);
2028  /* fall through to examine arguments */
2029  }
2030 
2032  (void *) context);
2033 }
Datum constvalue
Definition: primnodes.h:197
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2256
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
List * joinaliasvars
Definition: parsenodes.h:1006
Index varlevelsup
Definition: primnodes.h:174
List * sortClause
Definition: parsenodes.h:158
static bool find_expr_references_walker(Node *node, find_expr_references_context *context)
Definition: dependency.c:1496
Oid resulttype
Definition: primnodes.h:745
ObjectAddresses * addrs
Definition: dependency.c:127
List * constraintDeps
Definition: parsenodes.h:168
#define DatumGetObjectId(X)
Definition: postgres.h:483
Oid reltype
Definition: pg_class.h:33
Oid resulttype
Definition: primnodes.h:816
List * opfamilies
Definition: primnodes.h:1041
int resultRelation
Definition: parsenodes.h:122
Oid endInRangeFunc
Definition: parsenodes.h:1309
Definition: nodes.h:517
int errcode(int sqlerrcode)
Definition: elog.c:575
AttrNumber varattno
Definition: primnodes.h:169
Expr * arg
Definition: primnodes.h:743
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1203
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:164
#define OidIsValid(objectId)
Definition: c.h:605
List * windowClause
Definition: parsenodes.h:154
List * targetList
Definition: parsenodes.h:140
Oid consttype
Definition: primnodes.h:193
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:182
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2475
bool resjunk
Definition: primnodes.h:1383
List * rtable
Definition: parsenodes.h:137
List * distinctClause
Definition: parsenodes.h:156
Oid funcid
Definition: primnodes.h:450
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Oid paramcollid
Definition: primnodes.h:249
#define lfirst_int(lc)
Definition: pg_list.h:107
Oid constcollid
Definition: primnodes.h:195
Oid resultcollid
Definition: primnodes.h:748
void * list_nth(const List *list, int n)
Definition: list.c:410
AttrNumber resno
Definition: primnodes.h:1377
Oid resulttype
Definition: primnodes.h:775
Oid winfnoid
Definition: primnodes.h:356
#define ereport(elevel, rest)
Definition: elog.h:122
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varno
Definition: primnodes.h:167
Oid resultcollid
Definition: primnodes.h:818
Oid resulttype
Definition: primnodes.h:796
Oid resultcollid
Definition: primnodes.h:798
Oid aggfnoid
Definition: primnodes.h:295
CmdType commandType
Definition: parsenodes.h:112
List * lcons(void *datum, List *list)
Definition: list.c:259
List * funccolcollations
Definition: parsenodes.h:1104
#define lfirst(lc)
Definition: pg_list.h:106
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1834
Oid row_typeid
Definition: primnodes.h:992
static int list_length(const List *l)
Definition: pg_list.h:89
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:962
List * groupClause
Definition: parsenodes.h:148
int errmsg(const char *fmt,...)
Definition: elog.c:797
List * fieldnums
Definition: primnodes.h:774
void list_free(List *list)
Definition: list.c:1133
Oid opno
Definition: primnodes.h:497
#define elog
Definition: elog.h:219
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2275
Definition: pg_list.h:45
static void add_object_address(ObjectClass oclass, Oid objectId, int32 subId, ObjectAddresses *addrs)
Definition: dependency.c:2152
Oid startInRangeFunc
Definition: parsenodes.h:1308
Oid paramtype
Definition: primnodes.h:247
bool constisnull
Definition: primnodes.h:198
#define lfirst_oid(lc)
Definition: pg_list.h:108
List * list_delete_first(List *list)
Definition: list.c:666
#define QTW_IGNORE_JOINALIASES
Definition: nodeFuncs.h:23
AttrNumber fieldnum
Definition: primnodes.h:744

◆ findDependentObjects()

static void findDependentObjects ( const ObjectAddress object,
int  objflags,
int  flags,
ObjectAddressStack stack,
ObjectAddresses targetObjects,
const ObjectAddresses pendingObjects,
Relation depRel 
)
static

Definition at line 459 of file dependency.c.

References AcquireDeletionLock(), add_exact_object_address_extra(), BTEqualStrategyNumber, ObjectAddress::classId, creating_extension, CurrentExtensionObject, DependDependerIndexId, ObjectAddressExtra::dependee, DEPENDENCY_AUTO, DEPENDENCY_AUTO_EXTENSION, DEPENDENCY_EXTENSION, DEPENDENCY_INTERNAL, DEPENDENCY_INTERNAL_AUTO, DEPENDENCY_NORMAL, DEPENDENCY_PIN, DependReferenceIndexId, DEPFLAG_AUTO, DEPFLAG_EXTENSION, DEPFLAG_INTERNAL, DEPFLAG_NORMAL, DEPFLAG_REVERSE, elog, ereport, errcode(), errhint(), errmsg(), ERROR, ObjectAddressExtra::flags, ObjectAddressStack::flags, getObjectDescription(), GETSTRUCT, HeapTupleIsValid, Int32GetDatum, ObjectAddressStack::next, ObjectAddressStack::object, object_address_present(), object_address_present_add_flags(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, PERFORM_DELETION_SKIP_EXTENSIONS, ReleaseDeletionLock(), ScanKeyInit(), stack_address_present_add_flags(), systable_beginscan(), systable_endscan(), systable_getnext(), and systable_recheck_tuple().

Referenced by performDeletion(), and performMultipleDeletions().

466 {
467  ScanKeyData key[3];
468  int nkeys;
469  SysScanDesc scan;
470  HeapTuple tup;
471  ObjectAddress otherObject;
472  ObjectAddressStack mystack;
473  ObjectAddressExtra extra;
474 
475  /*
476  * If the target object is already being visited in an outer recursion
477  * level, just report the current objflags back to that level and exit.
478  * This is needed to avoid infinite recursion in the face of circular
479  * dependencies.
480  *
481  * The stack check alone would result in dependency loops being broken at
482  * an arbitrary point, ie, the first member object of the loop to be
483  * visited is the last one to be deleted. This is obviously unworkable.
484  * However, the check for internal dependency below guarantees that we
485  * will not break a loop at an internal dependency: if we enter the loop
486  * at an "owned" object we will switch and start at the "owning" object
487  * instead. We could probably hack something up to avoid breaking at an
488  * auto dependency, too, if we had to. However there are no known cases
489  * where that would be necessary.
490  */
491  if (stack_address_present_add_flags(object, objflags, stack))
492  return;
493 
494  /*
495  * It's also possible that the target object has already been completely
496  * processed and put into targetObjects. If so, again we just add the
497  * specified objflags to its entry and return.
498  *
499  * (Note: in these early-exit cases we could release the caller-taken
500  * lock, since the object is presumably now locked multiple times; but it
501  * seems not worth the cycles.)
502  */
503  if (object_address_present_add_flags(object, objflags, targetObjects))
504  return;
505 
506  /*
507  * The target object might be internally dependent on some other object
508  * (its "owner"), and/or be a member of an extension (also considered its
509  * owner). If so, and if we aren't recursing from the owning object, we
510  * have to transform this deletion request into a deletion request of the
511  * owning object. (We'll eventually recurse back to this object, but the
512  * owning object has to be visited first so it will be deleted after.) The
513  * way to find out about this is to scan the pg_depend entries that show
514  * what this object depends on.
515  */
516  ScanKeyInit(&key[0],
517  Anum_pg_depend_classid,
518  BTEqualStrategyNumber, F_OIDEQ,
519  ObjectIdGetDatum(object->classId));
520  ScanKeyInit(&key[1],
521  Anum_pg_depend_objid,
522  BTEqualStrategyNumber, F_OIDEQ,
523  ObjectIdGetDatum(object->objectId));
524  if (object->objectSubId != 0)
525  {
526  ScanKeyInit(&key[2],
527  Anum_pg_depend_objsubid,
528  BTEqualStrategyNumber, F_INT4EQ,
529  Int32GetDatum(object->objectSubId));
530  nkeys = 3;
531  }
532  else
533  nkeys = 2;
534 
535  scan = systable_beginscan(*depRel, DependDependerIndexId, true,
536  NULL, nkeys, key);
537 
538  while (HeapTupleIsValid(tup = systable_getnext(scan)))
539  {
540  Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
541 
542  otherObject.classId = foundDep->refclassid;
543  otherObject.objectId = foundDep->refobjid;
544  otherObject.objectSubId = foundDep->refobjsubid;
545 
546  switch (foundDep->deptype)
547  {
548  case DEPENDENCY_NORMAL:
549  case DEPENDENCY_AUTO:
551  /* no problem */
552  break;
553 
555 
556  /*
557  * If told to, ignore EXTENSION dependencies altogether. This
558  * flag is normally used to prevent dropping extensions during
559  * temporary-object cleanup, even if a temp object was created
560  * during an extension script.
561  */
563  break;
564 
565  /*
566  * If the other object is the extension currently being
567  * created/altered, ignore this dependency and continue with
568  * the deletion. This allows dropping of an extension's
569  * objects within the extension's scripts, as well as corner
570  * cases such as dropping a transient object created within
571  * such a script.
572  */
573  if (creating_extension &&
574  otherObject.classId == ExtensionRelationId &&
575  otherObject.objectId == CurrentExtensionObject)
576  break;
577 
578  /* Otherwise, treat this like an internal dependency */
579  /* FALL THRU */
580 
581  case DEPENDENCY_INTERNAL:
583 
584  /*
585  * This object is part of the internal implementation of
586  * another object, or is part of the extension that is the
587  * other object. We have three cases:
588  *
589  * 1. At the outermost recursion level, disallow the DROP. (We
590  * just ereport here, rather than proceeding, since no other
591  * dependencies are likely to be interesting.) However, if
592  * the owning object is listed in pendingObjects, just release
593  * the caller's lock and return; we'll eventually complete the
594  * DROP when we reach that entry in the pending list.
595  */
596  if (stack == NULL)
597  {
598  char *otherObjDesc;
599 
600  if (pendingObjects &&
601  object_address_present(&otherObject, pendingObjects))
602  {
603  systable_endscan(scan);
604  /* need to release caller's lock; see notes below */
605  ReleaseDeletionLock(object);
606  return;
607  }
608  otherObjDesc = getObjectDescription(&otherObject);
609  ereport(ERROR,
610  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
611  errmsg("cannot drop %s because %s requires it",
612  getObjectDescription(object),
613  otherObjDesc),
614  errhint("You can drop %s instead.",
615  otherObjDesc)));
616  }
617 
618  /*
619  * 2. When recursing from the other end of this dependency,
620  * it's okay to continue with the deletion. This holds when
621  * recursing from a whole object that includes the nominal
622  * other end as a component, too. Since there can be more
623  * than one "owning" object, we have to allow matches that are
624  * more than one level down in the stack.
625  */
626  if (stack_address_present_add_flags(&otherObject, 0, stack))
627  break;
628 
629  /*
630  * 3. Not all the owning objects have been visited, so
631  * transform this deletion request into a delete of this
632  * owning object.
633  *
634  * For INTERNAL_AUTO dependencies, we don't enforce this; in
635  * other words, we don't follow the links back to the owning
636  * object.
637  */
638  if (foundDep->deptype == DEPENDENCY_INTERNAL_AUTO)
639  break;
640 
641  /*
642  * First, release caller's lock on this object and get
643  * deletion lock on the owning object. (We must release
644  * caller's lock to avoid deadlock against a concurrent
645  * deletion of the owning object.)
646  */
647  ReleaseDeletionLock(object);
648  AcquireDeletionLock(&otherObject, 0);
649 
650  /*
651  * The owning object might have been deleted while we waited
652  * to lock it; if so, neither it nor the current object are
653  * interesting anymore. We test this by checking the
654  * pg_depend entry (see notes below).
655  */
656  if (!systable_recheck_tuple(scan, tup))
657  {
658  systable_endscan(scan);
659  ReleaseDeletionLock(&otherObject);
660  return;
661  }
662 
663  /*
664  * Okay, recurse to the owning object instead of proceeding.
665  *
666  * We do not need to stack the current object; we want the
667  * traversal order to be as if the original reference had
668  * linked to the owning object instead of this one.
669  *
670  * The dependency type is a "reverse" dependency: we need to
671  * delete the owning object if this one is to be deleted, but
672  * this linkage is never a reason for an automatic deletion.
673  */
674  findDependentObjects(&otherObject,
676  flags,
677  stack,
678  targetObjects,
679  pendingObjects,
680  depRel);
681  /* And we're done here. */
682  systable_endscan(scan);
683  return;
684 
685  case DEPENDENCY_PIN:
686 
687  /*
688  * Should not happen; PIN dependencies should have zeroes in
689  * the depender fields...
690  */
691  elog(ERROR, "incorrect use of PIN dependency with %s",
692  getObjectDescription(object));
693  break;
694  default:
695  elog(ERROR, "unrecognized dependency type '%c' for %s",
696  foundDep->deptype, getObjectDescription(object));
697  break;
698  }
699  }
700 
701  systable_endscan(scan);
702 
703  /*
704  * Now recurse to any dependent objects. We must visit them first since
705  * they have to be deleted before the current object.
706  */
707  mystack.object = object; /* set up a new stack level */
708  mystack.flags = objflags;
709  mystack.next = stack;
710 
711  ScanKeyInit(&key[0],
712  Anum_pg_depend_refclassid,
713  BTEqualStrategyNumber, F_OIDEQ,
714  ObjectIdGetDatum(object->classId));
715  ScanKeyInit(&key[1],
716  Anum_pg_depend_refobjid,
717  BTEqualStrategyNumber, F_OIDEQ,
718  ObjectIdGetDatum(object->objectId));
719  if (object->objectSubId != 0)
720  {
721  ScanKeyInit(&key[2],
722  Anum_pg_depend_refobjsubid,
723  BTEqualStrategyNumber, F_INT4EQ,
724  Int32GetDatum(object->objectSubId));
725  nkeys = 3;
726  }
727  else
728  nkeys = 2;
729 
730  scan = systable_beginscan(*depRel, DependReferenceIndexId, true,
731  NULL, nkeys, key);
732 
733  while (HeapTupleIsValid(tup = systable_getnext(scan)))
734  {
735  Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
736  int subflags;
737 
738  otherObject.classId = foundDep->classid;
739  otherObject.objectId = foundDep->objid;
740  otherObject.objectSubId = foundDep->objsubid;
741 
742  /*
743  * Must lock the dependent object before recursing to it.
744  */
745  AcquireDeletionLock(&otherObject, 0);
746 
747  /*
748  * The dependent object might have been deleted while we waited to
749  * lock it; if so, we don't need to do anything more with it. We can
750  * test this cheaply and independently of the object's type by seeing
751  * if the pg_depend tuple we are looking at is still live. (If the
752  * object got deleted, the tuple would have been deleted too.)
753  */
754  if (!systable_recheck_tuple(scan, tup))
755  {
756  /* release the now-useless lock */
757  ReleaseDeletionLock(&otherObject);
758  /* and continue scanning for dependencies */
759  continue;
760  }
761 
762  /* Recurse, passing objflags indicating the dependency type */
763  switch (foundDep->deptype)
764  {
765  case DEPENDENCY_NORMAL:
766  subflags = DEPFLAG_NORMAL;
767  break;
768  case DEPENDENCY_AUTO:
770  subflags = DEPFLAG_AUTO;
771  break;
773  case DEPENDENCY_INTERNAL:
774  subflags = DEPFLAG_INTERNAL;
775  break;
777  subflags = DEPFLAG_EXTENSION;
778  break;
779  case DEPENDENCY_PIN:
780 
781  /*
782  * For a PIN dependency we just ereport immediately; there
783  * won't be any others to report.
784  */
785  ereport(ERROR,
786  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
787  errmsg("cannot drop %s because it is required by the database system",
788  getObjectDescription(object))));
789  subflags = 0; /* keep compiler quiet */
790  break;
791  default:
792  elog(ERROR, "unrecognized dependency type '%c' for %s",
793  foundDep->deptype, getObjectDescription(object));
794  subflags = 0; /* keep compiler quiet */
795  break;
796  }
797 
798  findDependentObjects(&otherObject,
799  subflags,
800  flags,
801  &mystack,
802  targetObjects,
803  pendingObjects,
804  depRel);
805  }
806 
807  systable_endscan(scan);
808 
809  /*
810  * Finally, we can add the target object to targetObjects. Be careful to
811  * include any flags that were passed back down to us from inner recursion
812  * levels.
813  */
814  extra.flags = mystack.flags;
815  if (stack)
816  extra.dependee = *stack->object;
817  else
818  memset(&extra.dependee, 0, sizeof(extra.dependee));
819  add_exact_object_address_extra(object, &extra, targetObjects);
820 }
static void findDependentObjects(const ObjectAddress *object, int objflags, int flags, ObjectAddressStack *stack, ObjectAddresses *targetObjects, const ObjectAddresses *pendingObjects, Relation *depRel)
Definition: dependency.c:459
Oid CurrentExtensionObject
Definition: extension.c:68
static void ReleaseDeletionLock(const ObjectAddress *object)
Definition: dependency.c:1335
int errhint(const char *fmt,...)
Definition: elog.c:987
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
static void add_exact_object_address_extra(const ObjectAddress *object, const ObjectAddressExtra *extra, ObjectAddresses *addrs)
Definition: dependency.c:2210
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2245
#define DependReferenceIndexId
Definition: indexing.h:148
#define DependDependerIndexId
Definition: indexing.h:146
int errcode(int sqlerrcode)
Definition: elog.c:575
#define DEPFLAG_REVERSE
Definition: dependency.c:102
struct ObjectAddressStack * next
Definition: dependency.c:121
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
char * getObjectDescription(const ObjectAddress *object)
bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
Definition: genam.c:457
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define DEPFLAG_AUTO
Definition: dependency.c:99
const ObjectAddress * object
Definition: dependency.c:119
#define DEPFLAG_INTERNAL
Definition: dependency.c:100
static bool object_address_present_add_flags(const ObjectAddress *object, int flags, ObjectAddresses *addrs)
Definition: dependency.c:2271
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:71
#define ereport(elevel, rest)
Definition: elog.h:122
static void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1308
bool creating_extension
Definition: extension.c:67
#define DEPFLAG_EXTENSION
Definition: dependency.c:101
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Int32GetDatum(X)
Definition: postgres.h:462
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define DEPFLAG_NORMAL
Definition: dependency.c:98
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
static bool stack_address_present_add_flags(const ObjectAddress *object, int flags, ObjectAddressStack *stack)
Definition: dependency.c:2338
#define PERFORM_DELETION_SKIP_EXTENSIONS
Definition: dependency.h:193
ObjectAddress dependee
Definition: dependency.c:93
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ free_object_addresses()

void free_object_addresses ( ObjectAddresses addrs)

Definition at line 2401 of file dependency.c.

References ObjectAddresses::extras, pfree(), and ObjectAddresses::refs.

Referenced by AlterTableNamespace(), AlterTypeNamespace(), makeConfigurationDependencies(), performDeletion(), performMultipleDeletions(), recordDependencyOnExpr(), recordDependencyOnSingleRelExpr(), RemoveObjects(), RemoveRelations(), and shdepDropOwned().

2402 {
2403  pfree(addrs->refs);
2404  if (addrs->extras)
2405  pfree(addrs->extras);
2406  pfree(addrs);
2407 }
void pfree(void *pointer)
Definition: mcxt.c:1031
ObjectAddress * refs
Definition: dependency.c:108
ObjectAddressExtra * extras
Definition: dependency.c:109

◆ getObjectClass()

ObjectClass getObjectClass ( const ObjectAddress object)

Definition at line 2416 of file dependency.c.

References ObjectAddress::classId, elog, ERROR, ObjectAddress::objectSubId, OCLASS_AM, OCLASS_AMOP, OCLASS_AMPROC, OCLASS_CAST, OCLASS_CLASS, OCLASS_COLLATION, OCLASS_CONSTRAINT, OCLASS_CONVERSION, OCLASS_DATABASE, OCLASS_DEFACL, OCLASS_DEFAULT, OCLASS_EVENT_TRIGGER, OCLASS_EXTENSION, OCLASS_FDW, OCLASS_FOREIGN_SERVER, OCLASS_LANGUAGE, OCLASS_LARGEOBJECT, OCLASS_OPCLASS, OCLASS_OPERATOR, OCLASS_OPFAMILY, OCLASS_POLICY, OCLASS_PROC, OCLASS_PUBLICATION, OCLASS_PUBLICATION_REL, OCLASS_REWRITE, OCLASS_ROLE, OCLASS_SCHEMA, OCLASS_STATISTIC_EXT, OCLASS_SUBSCRIPTION, OCLASS_TBLSPACE, OCLASS_TRANSFORM, OCLASS_TRIGGER, OCLASS_TSCONFIG, OCLASS_TSDICT, OCLASS_TSPARSER, OCLASS_TSTEMPLATE, OCLASS_TYPE, and OCLASS_USER_MAPPING.

Referenced by AlterObjectNamespace_oid(), ATExecAlterColumnType(), deleteObjectsInList(), doDeletion(), EventTriggerSQLDropAddObject(), getObjectDescription(), getObjectIdentityParts(), and getObjectTypeDescription().

2417 {
2418  /* only pg_class entries can have nonzero objectSubId */
2419  if (object->classId != RelationRelationId &&
2420  object->objectSubId != 0)
2421  elog(ERROR, "invalid non-zero objectSubId for object class %u",
2422  object->classId);
2423 
2424  switch (object->classId)
2425  {
2426  case RelationRelationId:
2427  /* caller must check objectSubId */
2428  return OCLASS_CLASS;
2429 
2430  case ProcedureRelationId:
2431  return OCLASS_PROC;
2432 
2433  case TypeRelationId:
2434  return OCLASS_TYPE;
2435 
2436  case CastRelationId:
2437  return OCLASS_CAST;
2438 
2439  case CollationRelationId:
2440  return OCLASS_COLLATION;
2441 
2442  case ConstraintRelationId:
2443  return OCLASS_CONSTRAINT;
2444 
2445  case ConversionRelationId:
2446  return OCLASS_CONVERSION;
2447 
2448  case AttrDefaultRelationId:
2449  return OCLASS_DEFAULT;
2450 
2451  case LanguageRelationId:
2452  return OCLASS_LANGUAGE;
2453 
2454  case LargeObjectRelationId:
2455  return OCLASS_LARGEOBJECT;
2456 
2457  case OperatorRelationId:
2458  return OCLASS_OPERATOR;
2459 
2460  case OperatorClassRelationId:
2461  return OCLASS_OPCLASS;
2462 
2463  case OperatorFamilyRelationId:
2464  return OCLASS_OPFAMILY;
2465 
2466  case AccessMethodRelationId:
2467  return OCLASS_AM;
2468 
2469  case AccessMethodOperatorRelationId:
2470  return OCLASS_AMOP;
2471 
2472  case AccessMethodProcedureRelationId:
2473  return OCLASS_AMPROC;
2474 
2475  case RewriteRelationId:
2476  return OCLASS_REWRITE;
2477 
2478  case TriggerRelationId:
2479  return OCLASS_TRIGGER;
2480 
2481  case NamespaceRelationId:
2482  return OCLASS_SCHEMA;
2483 
2484  case StatisticExtRelationId:
2485  return OCLASS_STATISTIC_EXT;
2486 
2487  case TSParserRelationId:
2488  return OCLASS_TSPARSER;
2489 
2490  case TSDictionaryRelationId:
2491  return OCLASS_TSDICT;
2492 
2493  case TSTemplateRelationId:
2494  return OCLASS_TSTEMPLATE;
2495 
2496  case TSConfigRelationId:
2497  return OCLASS_TSCONFIG;
2498 
2499  case AuthIdRelationId:
2500  return OCLASS_ROLE;
2501 
2502  case DatabaseRelationId:
2503  return OCLASS_DATABASE;
2504 
2505  case TableSpaceRelationId:
2506  return OCLASS_TBLSPACE;
2507 
2508  case ForeignDataWrapperRelationId:
2509  return OCLASS_FDW;
2510 
2511  case ForeignServerRelationId:
2512  return OCLASS_FOREIGN_SERVER;
2513 
2514  case UserMappingRelationId:
2515  return OCLASS_USER_MAPPING;
2516 
2517  case DefaultAclRelationId:
2518  return OCLASS_DEFACL;
2519 
2520  case ExtensionRelationId:
2521  return OCLASS_EXTENSION;
2522 
2523  case EventTriggerRelationId:
2524  return OCLASS_EVENT_TRIGGER;
2525 
2526  case PolicyRelationId:
2527  return OCLASS_POLICY;
2528 
2529  case PublicationRelationId:
2530  return OCLASS_PUBLICATION;
2531 
2532  case PublicationRelRelationId:
2533  return OCLASS_PUBLICATION_REL;
2534 
2535  case SubscriptionRelationId:
2536  return OCLASS_SUBSCRIPTION;
2537 
2538  case TransformRelationId:
2539  return OCLASS_TRANSFORM;
2540  }
2541 
2542  /* shouldn't get here */
2543  elog(ERROR, "unrecognized object class: %u", object->classId);
2544  return OCLASS_CLASS; /* keep compiler quiet */
2545 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219

◆ new_object_addresses()

ObjectAddresses* new_object_addresses ( void  )

Definition at line 2130 of file dependency.c.

References ObjectAddresses::extras, ObjectAddresses::maxrefs, ObjectAddresses::numrefs, palloc(), and ObjectAddresses::refs.

Referenced by AlterExtensionNamespace(), AlterTableNamespace(), AlterTypeNamespace(), makeConfigurationDependencies(), performDeletion(), performMultipleDeletions(), recordDependencyOnExpr(), recordDependencyOnSingleRelExpr(), RemoveObjects(), RemoveRelations(), and shdepDropOwned().

2131 {
2132  ObjectAddresses *addrs;
2133 
2134  addrs = palloc(sizeof(ObjectAddresses));
2135 
2136  addrs->numrefs = 0;
2137  addrs->maxrefs = 32;
2138  addrs->refs = (ObjectAddress *)
2139  palloc(addrs->maxrefs * sizeof(ObjectAddress));
2140  addrs->extras = NULL; /* until/unless needed */
2141 
2142  return addrs;
2143 }
ObjectAddress * refs
Definition: dependency.c:108
ObjectAddressExtra * extras
Definition: dependency.c:109
void * palloc(Size size)
Definition: mcxt.c:924

◆ object_address_comparator()

static int object_address_comparator ( const void *  a,
const void *  b 
)
static

Definition at line 2099 of file dependency.c.

References ObjectAddress::classId, ObjectAddress::objectId, and ObjectAddress::objectSubId.

Referenced by eliminate_duplicate_dependencies().

2100 {
2101  const ObjectAddress *obja = (const ObjectAddress *) a;
2102  const ObjectAddress *objb = (const ObjectAddress *) b;
2103 
2104  if (obja->classId < objb->classId)
2105  return -1;
2106  if (obja->classId > objb->classId)
2107  return 1;
2108  if (obja->objectId < objb->objectId)
2109  return -1;
2110  if (obja->objectId > objb->objectId)
2111  return 1;
2112 
2113  /*
2114  * We sort the subId as an unsigned int so that 0 will come first. See
2115  * logic in eliminate_duplicate_dependencies.
2116  */
2117  if ((unsigned int) obja->objectSubId < (unsigned int) objb->objectSubId)
2118  return -1;
2119  if ((unsigned int) obja->objectSubId > (unsigned int) objb->objectSubId)
2120  return 1;
2121  return 0;
2122 }

◆ object_address_present()

bool object_address_present ( const ObjectAddress object,
const ObjectAddresses addrs 
)

Definition at line 2245 of file dependency.c.

References ObjectAddress::classId, i, ObjectAddresses::numrefs, ObjectAddress::objectId, ObjectAddress::objectSubId, and ObjectAddresses::refs.

Referenced by AlterConstraintNamespaces(), AlterIndexNamespaces(), AlterRelationNamespaceInternal(), AlterTypeNamespaceInternal(), and findDependentObjects().

2247 {
2248  int i;
2249 
2250  for (i = addrs->numrefs - 1; i >= 0; i--)
2251  {
2252  const ObjectAddress *thisobj = addrs->refs + i;
2253 
2254  if (object->classId == thisobj->classId &&
2255  object->objectId == thisobj->objectId)
2256  {
2257  if (object->objectSubId == thisobj->objectSubId ||
2258  thisobj->objectSubId == 0)
2259  return true;
2260  }
2261  }
2262 
2263  return false;
2264 }
ObjectAddress * refs
Definition: dependency.c:108
int i

◆ object_address_present_add_flags()

static bool object_address_present_add_flags ( const ObjectAddress object,
int  flags,
ObjectAddresses addrs 
)
static

Definition at line 2271 of file dependency.c.

References ObjectAddress::classId, ObjectAddresses::extras, ObjectAddressExtra::flags, ObjectAddressStack::flags, i, ObjectAddresses::numrefs, ObjectAddress::objectId, ObjectAddress::objectSubId, and ObjectAddresses::refs.

Referenced by findDependentObjects().

2274 {
2275  bool result = false;
2276  int i;
2277 
2278  for (i = addrs->numrefs - 1; i >= 0; i--)
2279  {
2280  ObjectAddress *thisobj = addrs->refs + i;
2281 
2282  if (object->classId == thisobj->classId &&
2283  object->objectId == thisobj->objectId)
2284  {
2285  if (object->objectSubId == thisobj->objectSubId)
2286  {
2287  ObjectAddressExtra *thisextra = addrs->extras + i;
2288 
2289  thisextra->flags |= flags;
2290  result = true;
2291  }
2292  else if (thisobj->objectSubId == 0)
2293  {
2294  /*
2295  * We get here if we find a need to delete a column after
2296  * having already decided to drop its whole table. Obviously
2297  * we no longer need to drop the subobject, so report that we
2298  * found the subobject in the array. But don't plaster its
2299  * flags on the whole object.
2300  */
2301  result = true;
2302  }
2303  else if (object->objectSubId == 0)
2304  {
2305  /*
2306  * We get here if we find a need to delete a whole table after
2307  * having already decided to drop one of its columns. We
2308  * can't report that the whole object is in the array, but we
2309  * should mark the subobject with the whole object's flags.
2310  *
2311  * It might seem attractive to physically delete the column's
2312  * array entry, or at least mark it as no longer needing
2313  * separate deletion. But that could lead to, e.g., dropping
2314  * the column's datatype before we drop the table, which does
2315  * not seem like a good idea. This is a very rare situation
2316  * in practice, so we just take the hit of doing a separate
2317  * DROP COLUMN action even though we know we're gonna delete
2318  * the table later.
2319  *
2320  * Because there could be other subobjects of this object in
2321  * the array, this case means we always have to loop through
2322  * the whole array; we cannot exit early on a match.
2323  */
2324  ObjectAddressExtra *thisextra = addrs->extras + i;
2325 
2326  thisextra->flags |= flags;
2327  }
2328  }
2329  }
2330 
2331  return result;
2332 }
ObjectAddress * refs
Definition: dependency.c:108
ObjectAddressExtra * extras
Definition: dependency.c:109
int i

◆ performDeletion()

void performDeletion ( const ObjectAddress object,
DropBehavior  behavior,
int  flags 
)

Definition at line 300 of file dependency.c.

References AcquireDeletionLock(), deleteObjectsInList(), DEPFLAG_ORIGINAL, findDependentObjects(), free_object_addresses(), heap_close, heap_open(), new_object_addresses(), reportDependentObjects(), and RowExclusiveLock.

Referenced by AlterDomainDropConstraint(), ATExecDropColumn(), ATExecDropConstraint(), ATExecDropIdentity(), ATPostAlterTypeCleanup(), DefineQueryRewrite(), do_autovacuum(), dropOperators(), dropProcedures(), finish_heap_swap(), inv_drop(), PreCommit_on_commit_actions(), PublicationDropTables(), RemoveAttrDefault(), RemoveTempRelations(), RemoveUserMapping(), and SetDefaultACL().

302 {
303  Relation depRel;
304  ObjectAddresses *targetObjects;
305 
306  /*
307  * We save some cycles by opening pg_depend just once and passing the
308  * Relation pointer down to all the recursive deletion steps.
309  */
310  depRel = heap_open(DependRelationId, RowExclusiveLock);
311 
312  /*
313  * Acquire deletion lock on the target object. (Ideally the caller has
314  * done this already, but many places are sloppy about it.)
315  */
316  AcquireDeletionLock(object, 0);
317 
318  /*
319  * Construct a list of objects to delete (ie, the given object plus
320  * everything directly or indirectly dependent on it).
321  */
322  targetObjects = new_object_addresses();
323 
324  findDependentObjects(object,
326  flags,
327  NULL, /* empty stack */
328  targetObjects,
329  NULL, /* no pendingObjects */
330  &depRel);
331 
332  /*
333  * Check if deletion is allowed, and report about cascaded deletes.
334  */
335  reportDependentObjects(targetObjects,
336  behavior,
337  flags,
338  object);
339 
340  /* do the deed */
341  deleteObjectsInList(targetObjects, &depRel, flags);
342 
343  /* And clean up */
344  free_object_addresses(targetObjects);
345 
346  heap_close(depRel, RowExclusiveLock);
347 }
static void findDependentObjects(const ObjectAddress *object, int objflags, int flags, ObjectAddressStack *stack, ObjectAddresses *targetObjects, const ObjectAddresses *pendingObjects, Relation *depRel)
Definition: dependency.c:459
#define heap_close(r, l)
Definition: heapam.h:97
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2130
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2401
#define DEPFLAG_ORIGINAL
Definition: dependency.c:97
#define RowExclusiveLock
Definition: lockdefs.h:38
static void reportDependentObjects(const ObjectAddresses *targetObjects, DropBehavior behavior, int flags, const ObjectAddress *origObject)
Definition: dependency.c:836
static void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1308
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
static void deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, int flags)
Definition: dependency.c:216

◆ performMultipleDeletions()

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

Definition at line 359 of file dependency.c.

References AcquireDeletionLock(), deleteObjectsInList(), DEPFLAG_ORIGINAL, findDependentObjects(), free_object_addresses(), heap_close, heap_open(), i, new_object_addresses(), ObjectAddresses::numrefs, ObjectAddresses::refs, reportDependentObjects(), and RowExclusiveLock.

Referenced by RemoveObjects(), RemoveRelations(), and shdepDropOwned().

361 {
362  Relation depRel;
363  ObjectAddresses *targetObjects;
364  int i;
365 
366  /* No work if no objects... */
367  if (objects->numrefs <= 0)
368  return;
369 
370  /*
371  * We save some cycles by opening pg_depend just once and passing the
372  * Relation pointer down to all the recursive deletion steps.
373  */
374  depRel = heap_open(DependRelationId, RowExclusiveLock);
375 
376  /*
377  * Construct a list of objects to delete (ie, the given objects plus
378  * everything directly or indirectly dependent on them). Note that
379  * because we pass the whole objects list as pendingObjects context, we
380  * won't get a failure from trying to delete an object that is internally
381  * dependent on another one in the list; we'll just skip that object and
382  * delete it when we reach its owner.
383  */
384  targetObjects = new_object_addresses();
385 
386  for (i = 0; i < objects->numrefs; i++)
387  {
388  const ObjectAddress *thisobj = objects->refs + i;
389 
390  /*
391  * Acquire deletion lock on each target object. (Ideally the caller
392  * has done this already, but many places are sloppy about it.)
393  */
394  AcquireDeletionLock(thisobj, flags);
395 
396  findDependentObjects(thisobj,
398  flags,
399  NULL, /* empty stack */
400  targetObjects,
401  objects,
402  &depRel);
403  }
404 
405  /*
406  * Check if deletion is allowed, and report about cascaded deletes.
407  *
408  * If there's exactly one object being deleted, report it the same way as
409  * in performDeletion(), else we have to be vaguer.
410  */
411  reportDependentObjects(targetObjects,
412  behavior,
413  flags,
414  (objects->numrefs == 1 ? objects->refs : NULL));
415 
416  /* do the deed */
417  deleteObjectsInList(targetObjects, &depRel, flags);
418 
419  /* And clean up */
420  free_object_addresses(targetObjects);
421 
422  heap_close(depRel, RowExclusiveLock);
423 }
static void findDependentObjects(const ObjectAddress *object, int objflags, int flags, ObjectAddressStack *stack, ObjectAddresses *targetObjects, const ObjectAddresses *pendingObjects, Relation *depRel)
Definition: dependency.c:459
#define heap_close(r, l)
Definition: heapam.h:97
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2130
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2401
#define DEPFLAG_ORIGINAL
Definition: dependency.c:97
ObjectAddress * refs
Definition: dependency.c:108
#define RowExclusiveLock
Definition: lockdefs.h:38
static void reportDependentObjects(const ObjectAddresses *targetObjects, DropBehavior behavior, int flags, const ObjectAddress *origObject)
Definition: dependency.c:836
static void AcquireDeletionLock(const ObjectAddress *object, int flags)
Definition: dependency.c:1308
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
int i
static void deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, int flags)
Definition: dependency.c:216

◆ record_object_address_dependencies()

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

Definition at line 2387 of file dependency.c.

References eliminate_duplicate_dependencies(), ObjectAddresses::numrefs, recordMultipleDependencies(), and ObjectAddresses::refs.

Referenced by makeConfigurationDependencies().

2390 {
2392  recordMultipleDependencies(depender,
2393  referenced->refs, referenced->numrefs,
2394  behavior);
2395 }
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs)
Definition: dependency.c:2039
ObjectAddress * refs
Definition: dependency.c:108
void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
Definition: pg_depend.c:56

◆ recordDependencyOnExpr()

void recordDependencyOnExpr ( const ObjectAddress depender,
Node expr,
List rtable,
DependencyType  behavior 
)

Definition at line 1360 of file dependency.c.

References find_expr_references_context::addrs, eliminate_duplicate_dependencies(), find_expr_references_walker(), free_object_addresses(), list_make1, new_object_addresses(), ObjectAddresses::numrefs, recordMultipleDependencies(), ObjectAddresses::refs, and find_expr_references_context::rtables.

Referenced by AlterPolicy(), CreatePolicy(), CreateTrigger(), GenerateTypeDependencies(), InsertRule(), ProcedureCreate(), RemoveRoleFromObjectPolicy(), and StoreAttrDefault().

1363 {
1365 
1366  context.addrs = new_object_addresses();
1367 
1368  /* Set up interpretation for Vars at varlevelsup = 0 */
1369  context.rtables = list_make1(rtable);
1370 
1371  /* Scan the expression tree for referenceable objects */
1372  find_expr_references_walker(expr, &context);
1373 
1374  /* Remove any duplicates */
1376 
1377  /* And record 'em */
1378  recordMultipleDependencies(depender,
1379  context.addrs->refs, context.addrs->numrefs,
1380  behavior);
1381 
1382  free_object_addresses(context.addrs);
1383 }
static bool find_expr_references_walker(Node *node, find_expr_references_context *context)
Definition: dependency.c:1496
ObjectAddresses * addrs
Definition: dependency.c:127
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2130
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2401
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs)
Definition: dependency.c:2039
#define list_make1(x1)
Definition: pg_list.h:139
ObjectAddress * refs
Definition: dependency.c:108
void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
Definition: pg_depend.c:56

◆ recordDependencyOnSingleRelExpr()

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

Definition at line 1401 of file dependency.c.

References add_exact_object_address(), find_expr_references_context::addrs, ObjectAddress::classId, eliminate_duplicate_dependencies(), find_expr_references_walker(), free_object_addresses(), list_make1, MemSet, new_object_addresses(), ObjectAddresses::numrefs, ObjectAddress::objectId, recordMultipleDependencies(), ObjectAddresses::refs, RangeTblEntry::relid, RangeTblEntry::relkind, find_expr_references_context::rtables, RTE_RELATION, RangeTblEntry::rtekind, T_RangeTblEntry, and RangeTblEntry::type.

Referenced by CreateConstraintEntry(), index_create(), and StorePartitionKey().

1406 {
1408  RangeTblEntry rte;
1409 
1410  context.addrs = new_object_addresses();
1411 
1412  /* We gin up a rather bogus rangetable list to handle Vars */
1413  MemSet(&rte, 0, sizeof(rte));
1414  rte.type = T_RangeTblEntry;
1415  rte.rtekind = RTE_RELATION;
1416  rte.relid = relId;
1417  rte.relkind = RELKIND_RELATION; /* no need for exactness here */
1418 
1419  context.rtables = list_make1(list_make1(&rte));
1420 
1421  /* Scan the expression tree for referenceable objects */
1422  find_expr_references_walker(expr, &context);
1423 
1424  /* Remove any duplicates */
1426 
1427  /* Separate self-dependencies if necessary */
1428  if (behavior != self_behavior && context.addrs->numrefs > 0)
1429  {
1430  ObjectAddresses *self_addrs;
1431  ObjectAddress *outobj;
1432  int oldref,
1433  outrefs;
1434 
1435  self_addrs = new_object_addresses();
1436 
1437  outobj = context.addrs->refs;
1438  outrefs = 0;
1439  for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
1440  {
1441  ObjectAddress *thisobj = context.addrs->refs + oldref;
1442 
1443  if (thisobj->classId == RelationRelationId &&
1444  thisobj->objectId == relId)
1445  {
1446  /* Move this ref into self_addrs */
1447  add_exact_object_address(thisobj, self_addrs);
1448  }
1449  else
1450  {
1451  /* Keep it in context.addrs */
1452  *outobj = *thisobj;
1453  outobj++;
1454  outrefs++;
1455  }
1456  }
1457  context.addrs->numrefs = outrefs;
1458 
1459  /* Record the self-dependencies */
1460  if (!ignore_self)
1461  recordMultipleDependencies(depender,
1462  self_addrs->refs, self_addrs->numrefs,
1463  self_behavior);
1464 
1465  free_object_addresses(self_addrs);
1466  }
1467 
1468  /* Record the external dependencies */
1469  recordMultipleDependencies(depender,
1470  context.addrs->refs, context.addrs->numrefs,
1471  behavior);
1472 
1473  free_object_addresses(context.addrs);
1474 }
static bool find_expr_references_walker(Node *node, find_expr_references_context *context)
Definition: dependency.c:1496
ObjectAddresses * addrs
Definition: dependency.c:127
#define MemSet(start, val, len)
Definition: c.h:908
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2185
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2130
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2401
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs)
Definition: dependency.c:2039
#define list_make1(x1)
Definition: pg_list.h:139
ObjectAddress * refs
Definition: dependency.c:108
void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
Definition: pg_depend.c:56
RTEKind rtekind
Definition: parsenodes.h:962
NodeTag type
Definition: parsenodes.h:960

◆ ReleaseDeletionLock()

static void ReleaseDeletionLock ( const ObjectAddress object)
static

Definition at line 1335 of file dependency.c.

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

Referenced by findDependentObjects().

1336 {
1337  if (object->classId == RelationRelationId)
1339  else
1340  /* assume we should lock the whole object not a sub-object */
1341  UnlockDatabaseObject(object->classId, object->objectId, 0,
1343 }
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:877
#define AccessExclusiveLock
Definition: lockdefs.h:45

◆ reportDependentObjects()

static void reportDependentObjects ( const ObjectAddresses targetObjects,
DropBehavior  behavior,
int  flags,
const ObjectAddress origObject 
)
static

Definition at line 836 of file dependency.c.

References _, appendStringInfo(), appendStringInfoChar(), client_min_messages, StringInfoData::data, DEBUG2, ObjectAddressExtra::dependee, DEPFLAG_AUTO, DEPFLAG_EXTENSION, DEPFLAG_INTERNAL, DEPFLAG_ORIGINAL, DROP_CASCADE, DROP_RESTRICT, ereport, errcode(), errdetail(), errdetail_log(), errhint(), errmsg(), errmsg_internal(), errmsg_plural(), ERROR, ObjectAddresses::extras, ObjectAddressExtra::flags, getObjectDescription(), i, initStringInfo(), StringInfoData::len, LOG, log_min_messages, MAX_REPORTED_DEPS, ngettext, NOTICE, ObjectAddresses::numrefs, PERFORM_DELETION_QUIETLY, pfree(), and ObjectAddresses::refs.

Referenced by performDeletion(), and performMultipleDeletions().

840 {
841  int msglevel = (flags & PERFORM_DELETION_QUIETLY) ? DEBUG2 : NOTICE;
842  bool ok = true;
843  StringInfoData clientdetail;
844  StringInfoData logdetail;
845  int numReportedClient = 0;
846  int numNotReportedClient = 0;
847  int i;
848 
849  /*
850  * If no error is to be thrown, and the msglevel is too low to be shown to
851  * either client or server log, there's no need to do any of the work.
852  *
853  * Note: this code doesn't know all there is to be known about elog
854  * levels, but it works for NOTICE and DEBUG2, which are the only values
855  * msglevel can currently have. We also assume we are running in a normal
856  * operating environment.
857  */
858  if (behavior == DROP_CASCADE &&
859  msglevel < client_min_messages &&
860  (msglevel < log_min_messages || log_min_messages == LOG))
861  return;
862 
863  /*
864  * We limit the number of dependencies reported to the client to
865  * MAX_REPORTED_DEPS, since client software may not deal well with
866  * enormous error strings. The server log always gets a full report.
867  */
868 #define MAX_REPORTED_DEPS 100
869 
870  initStringInfo(&clientdetail);
871  initStringInfo(&logdetail);
872 
873  /*
874  * We process the list back to front (ie, in dependency order not deletion
875  * order), since this makes for a more understandable display.
876  */
877  for (i = targetObjects->numrefs - 1; i >= 0; i--)
878  {
879  const ObjectAddress *obj = &targetObjects->refs[i];
880  const ObjectAddressExtra *extra = &targetObjects->extras[i];
881  char *objDesc;
882 
883  /* Ignore the original deletion target(s) */
884  if (extra->flags & DEPFLAG_ORIGINAL)
885  continue;
886 
887  objDesc = getObjectDescription(obj);
888 
889  /*
890  * If, at any stage of the recursive search, we reached the object via
891  * an AUTO, INTERNAL, or EXTENSION dependency, then it's okay to
892  * delete it even in RESTRICT mode.
893  */
894  if (extra->flags & (DEPFLAG_AUTO |
897  {
898  /*
899  * auto-cascades are reported at DEBUG2, not msglevel. We don't
900  * try to combine them with the regular message because the
901  * results are too confusing when client_min_messages and
902  * log_min_messages are different.
903  */
904  ereport(DEBUG2,
905  (errmsg("drop auto-cascades to %s",
906  objDesc)));
907  }
908  else if (behavior == DROP_RESTRICT)
909  {
910  char *otherDesc = getObjectDescription(&extra->dependee);
911 
912  if (numReportedClient < MAX_REPORTED_DEPS)
913  {
914  /* separate entries with a newline */
915  if (clientdetail.len != 0)
916  appendStringInfoChar(&clientdetail, '\n');
917  appendStringInfo(&clientdetail, _("%s depends on %s"),
918  objDesc, otherDesc);
919  numReportedClient++;
920  }
921  else
922  numNotReportedClient++;
923  /* separate entries with a newline */
924  if (logdetail.len != 0)
925  appendStringInfoChar(&logdetail, '\n');
926  appendStringInfo(&logdetail, _("%s depends on %s"),
927  objDesc, otherDesc);
928  pfree(otherDesc);
929  ok = false;
930  }
931  else
932  {
933  if (numReportedClient < MAX_REPORTED_DEPS)
934  {
935  /* separate entries with a newline */
936  if (clientdetail.len != 0)
937  appendStringInfoChar(&clientdetail, '\n');
938  appendStringInfo(&clientdetail, _("drop cascades to %s"),
939  objDesc);
940  numReportedClient++;
941  }
942  else
943  numNotReportedClient++;
944  /* separate entries with a newline */
945  if (logdetail.len != 0)
946  appendStringInfoChar(&logdetail, '\n');
947  appendStringInfo(&logdetail, _("drop cascades to %s"),
948  objDesc);
949  }
950 
951  pfree(objDesc);
952  }
953 
954  if (numNotReportedClient > 0)
955  appendStringInfo(&clientdetail, ngettext("\nand %d other object "
956  "(see server log for list)",
957  "\nand %d other objects "
958  "(see server log for list)",
959  numNotReportedClient),
960  numNotReportedClient);
961 
962  if (!ok)
963  {
964  if (origObject)
965  ereport(ERROR,
966  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
967  errmsg("cannot drop %s because other objects depend on it",
968  getObjectDescription(origObject)),
969  errdetail("%s", clientdetail.data),
970  errdetail_log("%s", logdetail.data),
971  errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
972  else
973  ereport(ERROR,
974  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
975  errmsg("cannot drop desired object(s) because other objects depend on them"),
976  errdetail("%s", clientdetail.data),
977  errdetail_log("%s", logdetail.data),
978  errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
979  }
980  else if (numReportedClient > 1)
981  {
982  ereport(msglevel,
983  /* translator: %d always has a value larger than 1 */
984  (errmsg_plural("drop cascades to %d other object",
985  "drop cascades to %d other objects",
986  numReportedClient + numNotReportedClient,
987  numReportedClient + numNotReportedClient),
988  errdetail("%s", clientdetail.data),
989  errdetail_log("%s", logdetail.data)));
990  }
991  else if (numReportedClient == 1)
992  {
993  /* we just use the single item as-is */
994  ereport(msglevel,
995  (errmsg_internal("%s", clientdetail.data)));
996  }
997 
998  pfree(clientdetail.data);
999  pfree(logdetail.data);
1000 }
int errhint(const char *fmt,...)
Definition: elog.c:987
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:850
int errcode(int sqlerrcode)
Definition: elog.c:575
#define LOG
Definition: elog.h:26
char * getObjectDescription(const ObjectAddress *object)
void pfree(void *pointer)
Definition: mcxt.c:1031
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ERROR
Definition: elog.h:43
#define DEPFLAG_ORIGINAL
Definition: dependency.c:97
#define DEPFLAG_AUTO
Definition: dependency.c:99
#define DEPFLAG_INTERNAL
Definition: dependency.c:100
#define DEBUG2
Definition: elog.h:24
ObjectAddress * refs
Definition: dependency.c:108
int errdetail(const char *fmt,...)
Definition: elog.c:873
int errdetail_log(const char *fmt,...)
Definition: elog.c:921
#define ereport(elevel, rest)
Definition: elog.h:122
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define ngettext(s, p, n)
Definition: c.h:1022
int log_min_messages
Definition: guc.c:454
#define DEPFLAG_EXTENSION
Definition: dependency.c:101
#define NOTICE
Definition: elog.h:37
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
#define PERFORM_DELETION_QUIETLY
Definition: dependency.h:191
ObjectAddressExtra * extras
Definition: dependency.c:109
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
int client_min_messages
Definition: guc.c:455
#define MAX_REPORTED_DEPS
ObjectAddress dependee
Definition: dependency.c:93
#define _(x)
Definition: elog.c:84

◆ stack_address_present_add_flags()

static bool stack_address_present_add_flags ( const ObjectAddress object,
int  flags,
ObjectAddressStack stack 
)
static

Definition at line 2338 of file dependency.c.

References ObjectAddress::classId, ObjectAddressStack::flags, ObjectAddressStack::next, ObjectAddressStack::object, ObjectAddress::objectId, and ObjectAddress::objectSubId.

Referenced by findDependentObjects().

2341 {
2342  bool result = false;
2343  ObjectAddressStack *stackptr;
2344 
2345  for (stackptr = stack; stackptr; stackptr = stackptr->next)
2346  {
2347  const ObjectAddress *thisobj = stackptr->object;
2348 
2349  if (object->classId == thisobj->classId &&
2350  object->objectId == thisobj->objectId)
2351  {
2352  if (object->objectSubId == thisobj->objectSubId)
2353  {
2354  stackptr->flags |= flags;
2355  result = true;
2356  }
2357  else if (thisobj->objectSubId == 0)
2358  {
2359  /*
2360  * We're visiting a column with whole table already on stack.
2361  * As in object_address_present_add_flags(), we can skip
2362  * further processing of the subobject, but we don't want to
2363  * propagate flags for the subobject to the whole object.
2364  */
2365  result = true;
2366  }
2367  else if (object->objectSubId == 0)
2368  {
2369  /*
2370  * We're visiting a table with column already on stack. As in
2371  * object_address_present_add_flags(), we should propagate
2372  * flags for the whole object to each of its subobjects.
2373  */
2374  stackptr->flags |= flags;
2375  }
2376  }
2377  }
2378 
2379  return result;
2380 }
struct ObjectAddressStack * next
Definition: dependency.c:121
const ObjectAddress * object
Definition: dependency.c:119

Variable Documentation

◆ object_classes

const Oid object_classes[]
static

Definition at line 135 of file dependency.c.

Referenced by add_object_address().