1 /*-------------------------------------------------------------------------
2 *
3 * dependency.c
4 * Routines to support inter-object dependencies.
5 *
6 *
7 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 * IDENTIFICATION
11 * src/backend/catalog/dependency.c
12 *
13 *-------------------------------------------------------------------------
14 */
15 #include "postgres.h"
16
17 #include "access/genam.h"
18 #include "access/htup_details.h"
19 #include "access/table.h"
20 #include "access/xact.h"
21 #include "catalog/dependency.h"
22 #include "catalog/heap.h"
23 #include "catalog/index.h"
24 #include "catalog/objectaccess.h"
25 #include "catalog/pg_am.h"
26 #include "catalog/pg_amop.h"
27 #include "catalog/pg_amproc.h"
28 #include "catalog/pg_attrdef.h"
29 #include "catalog/pg_authid.h"
30 #include "catalog/pg_cast.h"
31 #include "catalog/pg_collation.h"
32 #include "catalog/pg_constraint.h"
33 #include "catalog/pg_conversion.h"
34 #include "catalog/pg_database.h"
35 #include "catalog/pg_default_acl.h"
36 #include "catalog/pg_depend.h"
37 #include "catalog/pg_event_trigger.h"
38 #include "catalog/pg_extension.h"
39 #include "catalog/pg_foreign_data_wrapper.h"
40 #include "catalog/pg_foreign_server.h"
41 #include "catalog/pg_init_privs.h"
42 #include "catalog/pg_language.h"
43 #include "catalog/pg_largeobject.h"
44 #include "catalog/pg_namespace.h"
45 #include "catalog/pg_opclass.h"
46 #include "catalog/pg_operator.h"
47 #include "catalog/pg_opfamily.h"
48 #include "catalog/pg_policy.h"
49 #include "catalog/pg_proc.h"
50 #include "catalog/pg_publication.h"
51 #include "catalog/pg_publication_rel.h"
52 #include "catalog/pg_rewrite.h"
53 #include "catalog/pg_statistic_ext.h"
54 #include "catalog/pg_subscription.h"
55 #include "catalog/pg_tablespace.h"
56 #include "catalog/pg_transform.h"
57 #include "catalog/pg_trigger.h"
58 #include "catalog/pg_ts_config.h"
59 #include "catalog/pg_ts_dict.h"
60 #include "catalog/pg_ts_parser.h"
61 #include "catalog/pg_ts_template.h"
62 #include "catalog/pg_type.h"
63 #include "catalog/pg_user_mapping.h"
64 #include "commands/comment.h"
65 #include "commands/defrem.h"
66 #include "commands/event_trigger.h"
67 #include "commands/extension.h"
68 #include "commands/policy.h"
69 #include "commands/publicationcmds.h"
70 #include "commands/seclabel.h"
71 #include "commands/sequence.h"
72 #include "commands/trigger.h"
73 #include "commands/typecmds.h"
74 #include "nodes/nodeFuncs.h"
75 #include "parser/parsetree.h"
76 #include "rewrite/rewriteRemove.h"
77 #include "storage/lmgr.h"
78 #include "utils/acl.h"
79 #include "utils/fmgroids.h"
80 #include "utils/guc.h"
81 #include "utils/lsyscache.h"
82 #include "utils/syscache.h"
83
84
85 /*
86 * Deletion processing requires additional state for each ObjectAddress that
87 * it's planning to delete. For simplicity and code-sharing we make the
88 * ObjectAddresses code support arrays with or without this extra state.
89 */
90 typedef struct
91 {
92 int flags; /* bitmask, see bit definitions below */
93 ObjectAddress dependee; /* object whose deletion forced this one */
94 } ObjectAddressExtra;
95
96 /* ObjectAddressExtra flag bits */
97 #define DEPFLAG_ORIGINAL 0x0001 /* an original deletion target */
98 #define DEPFLAG_NORMAL 0x0002 /* reached via normal dependency */
99 #define DEPFLAG_AUTO 0x0004 /* reached via auto dependency */
100 #define DEPFLAG_INTERNAL 0x0008 /* reached via internal dependency */
101 #define DEPFLAG_PARTITION 0x0010 /* reached via partition dependency */
102 #define DEPFLAG_EXTENSION 0x0020 /* reached via extension dependency */
103 #define DEPFLAG_REVERSE 0x0040 /* reverse internal/extension link */
104 #define DEPFLAG_IS_PART 0x0080 /* has a partition dependency */
105 #define DEPFLAG_SUBOBJECT 0x0100 /* subobject of another deletable object */
106
107
108 /* expansible list of ObjectAddresses */
109 struct ObjectAddresses
110 {
111 ObjectAddress *refs; /* => palloc'd array */
112 ObjectAddressExtra *extras; /* => palloc'd array, or NULL if not used */
113 int numrefs; /* current number of references */
114 int maxrefs; /* current size of palloc'd array(s) */
115 };
116
117 /* typedef ObjectAddresses appears in dependency.h */
118
119 /* threaded list of ObjectAddresses, for recursion detection */
120 typedef struct ObjectAddressStack
121 {
122 const ObjectAddress *object; /* object being visited */
123 int flags; /* its current flag bits */
124 struct ObjectAddressStack *next; /* next outer stack level */
125 } ObjectAddressStack;
126
127 /* temporary storage in findDependentObjects */
128 typedef struct
129 {
130 ObjectAddress obj; /* object to be deleted --- MUST BE FIRST */
131 int subflags; /* flags to pass down when recursing to obj */
132 } ObjectAddressAndFlags;
133
134 /* for find_expr_references_walker */
135 typedef struct
136 {
137 ObjectAddresses *addrs; /* addresses being accumulated */
138 List *rtables; /* list of rangetables to resolve Vars */
139 } find_expr_references_context;
140
141 /*
142 * This constant table maps ObjectClasses to the corresponding catalog OIDs.
143 * See also getObjectClass().
144 */
145 static const Oid object_classes[] = {
146 RelationRelationId, /* OCLASS_CLASS */
147 ProcedureRelationId, /* OCLASS_PROC */
148 TypeRelationId, /* OCLASS_TYPE */
149 CastRelationId, /* OCLASS_CAST */
150 CollationRelationId, /* OCLASS_COLLATION */
151 ConstraintRelationId, /* OCLASS_CONSTRAINT */
152 ConversionRelationId, /* OCLASS_CONVERSION */
153 AttrDefaultRelationId, /* OCLASS_DEFAULT */
154 LanguageRelationId, /* OCLASS_LANGUAGE */
155 LargeObjectRelationId, /* OCLASS_LARGEOBJECT */
156 OperatorRelationId, /* OCLASS_OPERATOR */
157 OperatorClassRelationId, /* OCLASS_OPCLASS */
158 OperatorFamilyRelationId, /* OCLASS_OPFAMILY */
159 AccessMethodRelationId, /* OCLASS_AM */
160 AccessMethodOperatorRelationId, /* OCLASS_AMOP */
161 AccessMethodProcedureRelationId, /* OCLASS_AMPROC */
162 RewriteRelationId, /* OCLASS_REWRITE */
163 TriggerRelationId, /* OCLASS_TRIGGER */
164 NamespaceRelationId, /* OCLASS_SCHEMA */
165 StatisticExtRelationId, /* OCLASS_STATISTIC_EXT */
166 TSParserRelationId, /* OCLASS_TSPARSER */
167 TSDictionaryRelationId, /* OCLASS_TSDICT */
168 TSTemplateRelationId, /* OCLASS_TSTEMPLATE */
169 TSConfigRelationId, /* OCLASS_TSCONFIG */
170 AuthIdRelationId, /* OCLASS_ROLE */
171 DatabaseRelationId, /* OCLASS_DATABASE */
172 TableSpaceRelationId, /* OCLASS_TBLSPACE */
173 ForeignDataWrapperRelationId, /* OCLASS_FDW */
174 ForeignServerRelationId, /* OCLASS_FOREIGN_SERVER */
175 UserMappingRelationId, /* OCLASS_USER_MAPPING */
176 DefaultAclRelationId, /* OCLASS_DEFACL */
177 ExtensionRelationId, /* OCLASS_EXTENSION */
178 EventTriggerRelationId, /* OCLASS_EVENT_TRIGGER */
179 PolicyRelationId, /* OCLASS_POLICY */
180 PublicationRelationId, /* OCLASS_PUBLICATION */
181 PublicationRelRelationId, /* OCLASS_PUBLICATION_REL */
182 SubscriptionRelationId, /* OCLASS_SUBSCRIPTION */
183 TransformRelationId /* OCLASS_TRANSFORM */
184 };
185
186
187 static void findDependentObjects(const ObjectAddress *object,
188 int objflags,
189 int flags,
190 ObjectAddressStack *stack,
191 ObjectAddresses *targetObjects,
192 const ObjectAddresses *pendingObjects,
193 Relation *depRel);
194 static void reportDependentObjects(const ObjectAddresses *targetObjects,
195 DropBehavior behavior,
196 int flags,
197 const ObjectAddress *origObject);
198 static void deleteOneObject(const ObjectAddress *object,
199 Relation *depRel, int32 flags);
200 static void doDeletion(const ObjectAddress *object, int flags);
201 static bool find_expr_references_walker(Node *node,
202 find_expr_references_context *context);
203 static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
204 static int object_address_comparator(const void *a, const void *b);
205 static void add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
206 ObjectAddresses *addrs);
207 static void add_exact_object_address_extra(const ObjectAddress *object,
208 const ObjectAddressExtra *extra,
209 ObjectAddresses *addrs);
210 static bool object_address_present_add_flags(const ObjectAddress *object,
211 int flags,
212 ObjectAddresses *addrs);
213 static bool stack_address_present_add_flags(const ObjectAddress *object,
214 int flags,
215 ObjectAddressStack *stack);
216 static void DeleteInitPrivs(const ObjectAddress *object);
217
218
219 /*
220 * Go through the objects given running the final actions on them, and execute
221 * the actual deletion.
222 */
223 static void
deleteObjectsInList(ObjectAddresses * targetObjects,Relation * depRel,int flags)224 deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel,
225 int flags)
226 {
227 int i;
228
229 /*
230 * Keep track of objects for event triggers, if necessary.
231 */
232 if (trackDroppedObjectsNeeded() && !(flags & PERFORM_DELETION_INTERNAL))
233 {
234 for (i = 0; i < targetObjects->numrefs; i++)
235 {
236 const ObjectAddress *thisobj = &targetObjects->refs[i];
237 const ObjectAddressExtra *extra = &targetObjects->extras[i];
238 bool original = false;
239 bool normal = false;
240
241 if (extra->flags & DEPFLAG_ORIGINAL)
242 original = true;
243 if (extra->flags & DEPFLAG_NORMAL)
244 normal = true;
245 if (extra->flags & DEPFLAG_REVERSE)
246 normal = true;
247
248 if (EventTriggerSupportsObjectClass(getObjectClass(thisobj)))
249 {
250 EventTriggerSQLDropAddObject(thisobj, original, normal);
251 }
252 }
253 }
254
255 /*
256 * Delete all the objects in the proper order, except that if told to, we
257 * should skip the original object(s).
258 */
259 for (i = 0; i < targetObjects->numrefs; i++)
260 {
261 ObjectAddress *thisobj = targetObjects->refs + i;
262 ObjectAddressExtra *thisextra = targetObjects->extras + i;
263
264 if ((flags & PERFORM_DELETION_SKIP_ORIGINAL) &&
265 (thisextra->flags & DEPFLAG_ORIGINAL))
266 continue;
267
268 deleteOneObject(thisobj, depRel, flags);
269 }
270 }
271
272 /*
273 * performDeletion: attempt to drop the specified object. If CASCADE
274 * behavior is specified, also drop any dependent objects (recursively).
275 * If RESTRICT behavior is specified, error out if there are any dependent
276 * objects, except for those that should be implicitly dropped anyway
277 * according to the dependency type.
278 *
279 * This is the outer control routine for all forms of DROP that drop objects
280 * that can participate in dependencies. Note that performMultipleDeletions
281 * is a variant on the same theme; if you change anything here you'll likely
282 * need to fix that too.
283 *
284 * Bits in the flags argument can include:
285 *
286 * PERFORM_DELETION_INTERNAL: indicates that the drop operation is not the
287 * direct result of a user-initiated action. For example, when a temporary
288 * schema is cleaned out so that a new backend can use it, or when a column
289 * default is dropped as an intermediate step while adding a new one, that's
290 * an internal operation. On the other hand, when we drop something because
291 * the user issued a DROP statement against it, that's not internal. Currently
292 * this suppresses calling event triggers and making some permissions checks.
293 *
294 * PERFORM_DELETION_CONCURRENTLY: perform the drop concurrently. This does
295 * not currently work for anything except dropping indexes; don't set it for
296 * other object types or you may get strange results.
297 *
298 * PERFORM_DELETION_QUIETLY: reduce message level from NOTICE to DEBUG2.
299 *
300 * PERFORM_DELETION_SKIP_ORIGINAL: do not delete the specified object(s),
301 * but only what depends on it/them.
302 *
303 * PERFORM_DELETION_SKIP_EXTENSIONS: do not delete extensions, even when
304 * deleting objects that are part of an extension. This should generally
305 * be used only when dropping temporary objects.
306 *
307 * PERFORM_DELETION_CONCURRENT_LOCK: perform the drop normally but with a lock
308 * as if it were concurrent. This is used by REINDEX CONCURRENTLY.
309 *
310 */
311 void
performDeletion(const ObjectAddress * object,DropBehavior behavior,int flags)312 performDeletion(const ObjectAddress *object,
313 DropBehavior behavior, int flags)
314 {
315 Relation depRel;
316 ObjectAddresses *targetObjects;
317
318 /*
319 * We save some cycles by opening pg_depend just once and passing the
320 * Relation pointer down to all the recursive deletion steps.
321 */
322 depRel = table_open(DependRelationId, RowExclusiveLock);
323
324 /*
325 * Acquire deletion lock on the target object. (Ideally the caller has
326 * done this already, but many places are sloppy about it.)
327 */
328 AcquireDeletionLock(object, 0);
329
330 /*
331 * Construct a list of objects to delete (ie, the given object plus
332 * everything directly or indirectly dependent on it).
333 */
334 targetObjects = new_object_addresses();
335
336 findDependentObjects(object,
337 DEPFLAG_ORIGINAL,
338 flags,
339 NULL, /* empty stack */
340 targetObjects,
341 NULL, /* no pendingObjects */
342 &depRel);
343
344 /*
345 * Check if deletion is allowed, and report about cascaded deletes.
346 */
347 reportDependentObjects(targetObjects,
348 behavior,
349 flags,
350 object);
351
352 /* do the deed */
353 deleteObjectsInList(targetObjects, &depRel, flags);
354
355 /* And clean up */
356 free_object_addresses(targetObjects);
357
358 table_close(depRel, RowExclusiveLock);
359 }
360
361 /*
362 * performMultipleDeletions: Similar to performDeletion, but act on multiple
363 * objects at once.
364 *
365 * The main difference from issuing multiple performDeletion calls is that the
366 * list of objects that would be implicitly dropped, for each object to be
367 * dropped, is the union of the implicit-object list for all objects. This
368 * makes each check be more relaxed.
369 */
370 void
performMultipleDeletions(const ObjectAddresses * objects,DropBehavior behavior,int flags)371 performMultipleDeletions(const ObjectAddresses *objects,
372 DropBehavior behavior, int flags)
373 {
374 Relation depRel;
375 ObjectAddresses *targetObjects;
376 int i;
377
378 /* No work if no objects... */
379 if (objects->numrefs <= 0)
380 return;
381
382 /*
383 * We save some cycles by opening pg_depend just once and passing the
384 * Relation pointer down to all the recursive deletion steps.
385 */
386 depRel = table_open(DependRelationId, RowExclusiveLock);
387
388 /*
389 * Construct a list of objects to delete (ie, the given objects plus
390 * everything directly or indirectly dependent on them). Note that
391 * because we pass the whole objects list as pendingObjects context, we
392 * won't get a failure from trying to delete an object that is internally
393 * dependent on another one in the list; we'll just skip that object and
394 * delete it when we reach its owner.
395 */
396 targetObjects = new_object_addresses();
397
398 for (i = 0; i < objects->numrefs; i++)
399 {
400 const ObjectAddress *thisobj = objects->refs + i;
401
402 /*
403 * Acquire deletion lock on each target object. (Ideally the caller
404 * has done this already, but many places are sloppy about it.)
405 */
406 AcquireDeletionLock(thisobj, flags);
407
408 findDependentObjects(thisobj,
409 DEPFLAG_ORIGINAL,
410 flags,
411 NULL, /* empty stack */
412 targetObjects,
413 objects,
414 &depRel);
415 }
416
417 /*
418 * Check if deletion is allowed, and report about cascaded deletes.
419 *
420 * If there's exactly one object being deleted, report it the same way as
421 * in performDeletion(), else we have to be vaguer.
422 */
423 reportDependentObjects(targetObjects,
424 behavior,
425 flags,
426 (objects->numrefs == 1 ? objects->refs : NULL));
427
428 /* do the deed */
429 deleteObjectsInList(targetObjects, &depRel, flags);
430
431 /* And clean up */
432 free_object_addresses(targetObjects);
433
434 table_close(depRel, RowExclusiveLock);
435 }
436
437 /*
438 * findDependentObjects - find all objects that depend on 'object'
439 *
440 * For every object that depends on the starting object, acquire a deletion
441 * lock on the object, add it to targetObjects (if not already there),
442 * and recursively find objects that depend on it. An object's dependencies
443 * will be placed into targetObjects before the object itself; this means
444 * that the finished list's order represents a safe deletion order.
445 *
446 * The caller must already have a deletion lock on 'object' itself,
447 * but must not have added it to targetObjects. (Note: there are corner
448 * cases where we won't add the object either, and will also release the
449 * caller-taken lock. This is a bit ugly, but the API is set up this way
450 * to allow easy rechecking of an object's liveness after we lock it. See
451 * notes within the function.)
452 *
453 * When dropping a whole object (subId = 0), we find dependencies for
454 * its sub-objects too.
455 *
456 * object: the object to add to targetObjects and find dependencies on
457 * objflags: flags to be ORed into the object's targetObjects entry
458 * flags: PERFORM_DELETION_xxx flags for the deletion operation as a whole
459 * stack: list of objects being visited in current recursion; topmost item
460 * is the object that we recursed from (NULL for external callers)
461 * targetObjects: list of objects that are scheduled to be deleted
462 * pendingObjects: list of other objects slated for destruction, but
463 * not necessarily in targetObjects yet (can be NULL if none)
464 * *depRel: already opened pg_depend relation
465 *
466 * Note: objflags describes the reason for visiting this particular object
467 * at this time, and is not passed down when recursing. The flags argument
468 * is passed down, since it describes what we're doing overall.
469 */
470 static void
findDependentObjects(const ObjectAddress * object,int objflags,int flags,ObjectAddressStack * stack,ObjectAddresses * targetObjects,const ObjectAddresses * pendingObjects,Relation * depRel)471 findDependentObjects(const ObjectAddress *object,
472 int objflags,
473 int flags,
474 ObjectAddressStack *stack,
475 ObjectAddresses *targetObjects,
476 const ObjectAddresses *pendingObjects,
477 Relation *depRel)
478 {
479 ScanKeyData key[3];
480 int nkeys;
481 SysScanDesc scan;
482 HeapTuple tup;
483 ObjectAddress otherObject;
484 ObjectAddress owningObject;
485 ObjectAddress partitionObject;
486 ObjectAddressAndFlags *dependentObjects;
487 int numDependentObjects;
488 int maxDependentObjects;
489 ObjectAddressStack mystack;
490 ObjectAddressExtra extra;
491
492 /*
493 * If the target object is already being visited in an outer recursion
494 * level, just report the current objflags back to that level and exit.
495 * This is needed to avoid infinite recursion in the face of circular
496 * dependencies.
497 *
498 * The stack check alone would result in dependency loops being broken at
499 * an arbitrary point, ie, the first member object of the loop to be
500 * visited is the last one to be deleted. This is obviously unworkable.
501 * However, the check for internal dependency below guarantees that we
502 * will not break a loop at an internal dependency: if we enter the loop
503 * at an "owned" object we will switch and start at the "owning" object
504 * instead. We could probably hack something up to avoid breaking at an
505 * auto dependency, too, if we had to. However there are no known cases
506 * where that would be necessary.
507 */
508 if (stack_address_present_add_flags(object, objflags, stack))
509 return;
510
511 /*
512 * It's also possible that the target object has already been completely
513 * processed and put into targetObjects. If so, again we just add the
514 * specified objflags to its entry and return.
515 *
516 * (Note: in these early-exit cases we could release the caller-taken
517 * lock, since the object is presumably now locked multiple times; but it
518 * seems not worth the cycles.)
519 */
520 if (object_address_present_add_flags(object, objflags, targetObjects))
521 return;
522
523 /*
524 * The target object might be internally dependent on some other object
525 * (its "owner"), and/or be a member of an extension (also considered its
526 * owner). If so, and if we aren't recursing from the owning object, we
527 * have to transform this deletion request into a deletion request of the
528 * owning object. (We'll eventually recurse back to this object, but the
529 * owning object has to be visited first so it will be deleted after.) The
530 * way to find out about this is to scan the pg_depend entries that show
531 * what this object depends on.
532 */
533 ScanKeyInit(&key[0],
534 Anum_pg_depend_classid,
535 BTEqualStrategyNumber, F_OIDEQ,
536 ObjectIdGetDatum(object->classId));
537 ScanKeyInit(&key[1],
538 Anum_pg_depend_objid,
539 BTEqualStrategyNumber, F_OIDEQ,
540 ObjectIdGetDatum(object->objectId));
541 if (object->objectSubId != 0)
542 {
543 /* Consider only dependencies of this sub-object */
544 ScanKeyInit(&key[2],
545 Anum_pg_depend_objsubid,
546 BTEqualStrategyNumber, F_INT4EQ,
547 Int32GetDatum(object->objectSubId));
548 nkeys = 3;
549 }
550 else
551 {
552 /* Consider dependencies of this object and any sub-objects it has */
553 nkeys = 2;
554 }
555
556 scan = systable_beginscan(*depRel, DependDependerIndexId, true,
557 NULL, nkeys, key);
558
559 /* initialize variables that loop may fill */
560 memset(&owningObject, 0, sizeof(owningObject));
561 memset(&partitionObject, 0, sizeof(partitionObject));
562
563 while (HeapTupleIsValid(tup = systable_getnext(scan)))
564 {
565 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
566
567 otherObject.classId = foundDep->refclassid;
568 otherObject.objectId = foundDep->refobjid;
569 otherObject.objectSubId = foundDep->refobjsubid;
570
571 /*
572 * When scanning dependencies of a whole object, we may find rows
573 * linking sub-objects of the object to the object itself. (Normally,
574 * such a dependency is implicit, but we must make explicit ones in
575 * some cases involving partitioning.) We must ignore such rows to
576 * avoid infinite recursion.
577 */
578 if (otherObject.classId == object->classId &&
579 otherObject.objectId == object->objectId &&
580 object->objectSubId == 0)
581 continue;
582
583 switch (foundDep->deptype)
584 {
585 case DEPENDENCY_NORMAL:
586 case DEPENDENCY_AUTO:
587 case DEPENDENCY_AUTO_EXTENSION:
588 /* no problem */
589 break;
590
591 case DEPENDENCY_EXTENSION:
592
593 /*
594 * If told to, ignore EXTENSION dependencies altogether. This
595 * flag is normally used to prevent dropping extensions during
596 * temporary-object cleanup, even if a temp object was created
597 * during an extension script.
598 */
599 if (flags & PERFORM_DELETION_SKIP_EXTENSIONS)
600 break;
601
602 /*
603 * If the other object is the extension currently being
604 * created/altered, ignore this dependency and continue with
605 * the deletion. This allows dropping of an extension's
606 * objects within the extension's scripts, as well as corner
607 * cases such as dropping a transient object created within
608 * such a script.
609 */
610 if (creating_extension &&
611 otherObject.classId == ExtensionRelationId &&
612 otherObject.objectId == CurrentExtensionObject)
613 break;
614
615 /* Otherwise, treat this like an internal dependency */
616 /* FALL THRU */
617
618 case DEPENDENCY_INTERNAL:
619
620 /*
621 * This object is part of the internal implementation of
622 * another object, or is part of the extension that is the
623 * other object. We have three cases:
624 *
625 * 1. At the outermost recursion level, we must disallow the
626 * DROP. However, if the owning object is listed in
627 * pendingObjects, just release the caller's lock and return;
628 * we'll eventually complete the DROP when we reach that entry
629 * in the pending list.
630 *
631 * Note: the above statement is true only if this pg_depend
632 * entry still exists by then; in principle, therefore, we
633 * could miss deleting an item the user told us to delete.
634 * However, no inconsistency can result: since we're at outer
635 * level, there is no object depending on this one.
636 */
637 if (stack == NULL)
638 {
639 if (pendingObjects &&
640 object_address_present(&otherObject, pendingObjects))
641 {
642 systable_endscan(scan);
643 /* need to release caller's lock; see notes below */
644 ReleaseDeletionLock(object);
645 return;
646 }
647
648 /*
649 * We postpone actually issuing the error message until
650 * after this loop, so that we can make the behavior
651 * independent of the ordering of pg_depend entries, at
652 * least if there's not more than one INTERNAL and one
653 * EXTENSION dependency. (If there's more, we'll complain
654 * about a random one of them.) Prefer to complain about
655 * EXTENSION, since that's generally a more important
656 * dependency.
657 */
658 if (!OidIsValid(owningObject.classId) ||
659 foundDep->deptype == DEPENDENCY_EXTENSION)
660 owningObject = otherObject;
661 break;
662 }
663
664 /*
665 * 2. When recursing from the other end of this dependency,
666 * it's okay to continue with the deletion. This holds when
667 * recursing from a whole object that includes the nominal
668 * other end as a component, too. Since there can be more
669 * than one "owning" object, we have to allow matches that are
670 * more than one level down in the stack.
671 */
672 if (stack_address_present_add_flags(&otherObject, 0, stack))
673 break;
674
675 /*
676 * 3. Not all the owning objects have been visited, so
677 * transform this deletion request into a delete of this
678 * owning object.
679 *
680 * First, release caller's lock on this object and get
681 * deletion lock on the owning object. (We must release
682 * caller's lock to avoid deadlock against a concurrent
683 * deletion of the owning object.)
684 */
685 ReleaseDeletionLock(object);
686 AcquireDeletionLock(&otherObject, 0);
687
688 /*
689 * The owning object might have been deleted while we waited
690 * to lock it; if so, neither it nor the current object are
691 * interesting anymore. We test this by checking the
692 * pg_depend entry (see notes below).
693 */
694 if (!systable_recheck_tuple(scan, tup))
695 {
696 systable_endscan(scan);
697 ReleaseDeletionLock(&otherObject);
698 return;
699 }
700
701 /*
702 * One way or the other, we're done with the scan; might as
703 * well close it down before recursing, to reduce peak
704 * resource consumption.
705 */
706 systable_endscan(scan);
707
708 /*
709 * Okay, recurse to the owning object instead of proceeding.
710 *
711 * We do not need to stack the current object; we want the
712 * traversal order to be as if the original reference had
713 * linked to the owning object instead of this one.
714 *
715 * The dependency type is a "reverse" dependency: we need to
716 * delete the owning object if this one is to be deleted, but
717 * this linkage is never a reason for an automatic deletion.
718 */
719 findDependentObjects(&otherObject,
720 DEPFLAG_REVERSE,
721 flags,
722 stack,
723 targetObjects,
724 pendingObjects,
725 depRel);
726
727 /*
728 * The current target object should have been added to
729 * targetObjects while processing the owning object; but it
730 * probably got only the flag bits associated with the
731 * dependency we're looking at. We need to add the objflags
732 * that were passed to this recursion level, too, else we may
733 * get a bogus failure in reportDependentObjects (if, for
734 * example, we were called due to a partition dependency).
735 *
736 * If somehow the current object didn't get scheduled for
737 * deletion, bleat. (That would imply that somebody deleted
738 * this dependency record before the recursion got to it.)
739 * Another idea would be to reacquire lock on the current
740 * object and resume trying to delete it, but it seems not
741 * worth dealing with the race conditions inherent in that.
742 */
743 if (!object_address_present_add_flags(object, objflags,
744 targetObjects))
745 elog(ERROR, "deletion of owning object %s failed to delete %s",
746 getObjectDescription(&otherObject, false),
747 getObjectDescription(object, false));
748
749 /* And we're done here. */
750 return;
751
752 case DEPENDENCY_PARTITION_PRI:
753
754 /*
755 * Remember that this object has a partition-type dependency.
756 * After the dependency scan, we'll complain if we didn't find
757 * a reason to delete one of its partition dependencies.
758 */
759 objflags |= DEPFLAG_IS_PART;
760
761 /*
762 * Also remember the primary partition owner, for error
763 * messages. If there are multiple primary owners (which
764 * there should not be), we'll report a random one of them.
765 */
766 partitionObject = otherObject;
767 break;
768
769 case DEPENDENCY_PARTITION_SEC:
770
771 /*
772 * Only use secondary partition owners in error messages if we
773 * find no primary owner (which probably shouldn't happen).
774 */
775 if (!(objflags & DEPFLAG_IS_PART))
776 partitionObject = otherObject;
777
778 /*
779 * Remember that this object has a partition-type dependency.
780 * After the dependency scan, we'll complain if we didn't find
781 * a reason to delete one of its partition dependencies.
782 */
783 objflags |= DEPFLAG_IS_PART;
784 break;
785
786 case DEPENDENCY_PIN:
787
788 /*
789 * Should not happen; PIN dependencies should have zeroes in
790 * the depender fields...
791 */
792 elog(ERROR, "incorrect use of PIN dependency with %s",
793 getObjectDescription(object, false));
794 break;
795 default:
796 elog(ERROR, "unrecognized dependency type '%c' for %s",
797 foundDep->deptype, getObjectDescription(object, false));
798 break;
799 }
800 }
801
802 systable_endscan(scan);
803
804 /*
805 * If we found an INTERNAL or EXTENSION dependency when we're at outer
806 * level, complain about it now. If we also found a PARTITION dependency,
807 * we prefer to report the PARTITION dependency. This is arbitrary but
808 * seems to be more useful in practice.
809 */
810 if (OidIsValid(owningObject.classId))
811 {
812 char *otherObjDesc;
813
814 if (OidIsValid(partitionObject.classId))
815 otherObjDesc = getObjectDescription(&partitionObject, false);
816 else
817 otherObjDesc = getObjectDescription(&owningObject, false);
818
819 ereport(ERROR,
820 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
821 errmsg("cannot drop %s because %s requires it",
822 getObjectDescription(object, false), otherObjDesc),
823 errhint("You can drop %s instead.", otherObjDesc)));
824 }
825
826 /*
827 * Next, identify all objects that directly depend on the current object.
828 * To ensure predictable deletion order, we collect them up in
829 * dependentObjects and sort the list before actually recursing. (The
830 * deletion order would be valid in any case, but doing this ensures
831 * consistent output from DROP CASCADE commands, which is helpful for
832 * regression testing.)
833 */
834 maxDependentObjects = 128; /* arbitrary initial allocation */
835 dependentObjects = (ObjectAddressAndFlags *)
836 palloc(maxDependentObjects * sizeof(ObjectAddressAndFlags));
837 numDependentObjects = 0;
838
839 ScanKeyInit(&key[0],
840 Anum_pg_depend_refclassid,
841 BTEqualStrategyNumber, F_OIDEQ,
842 ObjectIdGetDatum(object->classId));
843 ScanKeyInit(&key[1],
844 Anum_pg_depend_refobjid,
845 BTEqualStrategyNumber, F_OIDEQ,
846 ObjectIdGetDatum(object->objectId));
847 if (object->objectSubId != 0)
848 {
849 ScanKeyInit(&key[2],
850 Anum_pg_depend_refobjsubid,
851 BTEqualStrategyNumber, F_INT4EQ,
852 Int32GetDatum(object->objectSubId));
853 nkeys = 3;
854 }
855 else
856 nkeys = 2;
857
858 scan = systable_beginscan(*depRel, DependReferenceIndexId, true,
859 NULL, nkeys, key);
860
861 while (HeapTupleIsValid(tup = systable_getnext(scan)))
862 {
863 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
864 int subflags;
865
866 otherObject.classId = foundDep->classid;
867 otherObject.objectId = foundDep->objid;
868 otherObject.objectSubId = foundDep->objsubid;
869
870 /*
871 * If what we found is a sub-object of the current object, just ignore
872 * it. (Normally, such a dependency is implicit, but we must make
873 * explicit ones in some cases involving partitioning.)
874 */
875 if (otherObject.classId == object->classId &&
876 otherObject.objectId == object->objectId &&
877 object->objectSubId == 0)
878 continue;
879
880 /*
881 * Must lock the dependent object before recursing to it.
882 */
883 AcquireDeletionLock(&otherObject, 0);
884
885 /*
886 * The dependent object might have been deleted while we waited to
887 * lock it; if so, we don't need to do anything more with it. We can
888 * test this cheaply and independently of the object's type by seeing
889 * if the pg_depend tuple we are looking at is still live. (If the
890 * object got deleted, the tuple would have been deleted too.)
891 */
892 if (!systable_recheck_tuple(scan, tup))
893 {
894 /* release the now-useless lock */
895 ReleaseDeletionLock(&otherObject);
896 /* and continue scanning for dependencies */
897 continue;
898 }
899
900 /*
901 * We do need to delete it, so identify objflags to be passed down,
902 * which depend on the dependency type.
903 */
904 switch (foundDep->deptype)
905 {
906 case DEPENDENCY_NORMAL:
907 subflags = DEPFLAG_NORMAL;
908 break;
909 case DEPENDENCY_AUTO:
910 case DEPENDENCY_AUTO_EXTENSION:
911 subflags = DEPFLAG_AUTO;
912 break;
913 case DEPENDENCY_INTERNAL:
914 subflags = DEPFLAG_INTERNAL;
915 break;
916 case DEPENDENCY_PARTITION_PRI:
917 case DEPENDENCY_PARTITION_SEC:
918 subflags = DEPFLAG_PARTITION;
919 break;
920 case DEPENDENCY_EXTENSION:
921 subflags = DEPFLAG_EXTENSION;
922 break;
923 case DEPENDENCY_PIN:
924
925 /*
926 * For a PIN dependency we just ereport immediately; there
927 * won't be any others to report.
928 */
929 ereport(ERROR,
930 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
931 errmsg("cannot drop %s because it is required by the database system",
932 getObjectDescription(object, false))));
933 subflags = 0; /* keep compiler quiet */
934 break;
935 default:
936 elog(ERROR, "unrecognized dependency type '%c' for %s",
937 foundDep->deptype, getObjectDescription(object, false));
938 subflags = 0; /* keep compiler quiet */
939 break;
940 }
941
942 /* And add it to the pending-objects list */
943 if (numDependentObjects >= maxDependentObjects)
944 {
945 /* enlarge array if needed */
946 maxDependentObjects *= 2;
947 dependentObjects = (ObjectAddressAndFlags *)
948 repalloc(dependentObjects,
949 maxDependentObjects * sizeof(ObjectAddressAndFlags));
950 }
951
952 dependentObjects[numDependentObjects].obj = otherObject;
953 dependentObjects[numDependentObjects].subflags = subflags;
954 numDependentObjects++;
955 }
956
957 systable_endscan(scan);
958
959 /*
960 * Now we can sort the dependent objects into a stable visitation order.
961 * It's safe to use object_address_comparator here since the obj field is
962 * first within ObjectAddressAndFlags.
963 */
964 if (numDependentObjects > 1)
965 qsort((void *) dependentObjects, numDependentObjects,
966 sizeof(ObjectAddressAndFlags),
967 object_address_comparator);
968
969 /*
970 * Now recurse to the dependent objects. We must visit them first since
971 * they have to be deleted before the current object.
972 */
973 mystack.object = object; /* set up a new stack level */
974 mystack.flags = objflags;
975 mystack.next = stack;
976
977 for (int i = 0; i < numDependentObjects; i++)
978 {
979 ObjectAddressAndFlags *depObj = dependentObjects + i;
980
981 findDependentObjects(&depObj->obj,
982 depObj->subflags,
983 flags,
984 &mystack,
985 targetObjects,
986 pendingObjects,
987 depRel);
988 }
989
990 pfree(dependentObjects);
991
992 /*
993 * Finally, we can add the target object to targetObjects. Be careful to
994 * include any flags that were passed back down to us from inner recursion
995 * levels. Record the "dependee" as being either the most important
996 * partition owner if there is one, else the object we recursed from, if
997 * any. (The logic in reportDependentObjects() is such that it can only
998 * need one of those objects.)
999 */
1000 extra.flags = mystack.flags;
1001 if (extra.flags & DEPFLAG_IS_PART)
1002 extra.dependee = partitionObject;
1003 else if (stack)
1004 extra.dependee = *stack->object;
1005 else
1006 memset(&extra.dependee, 0, sizeof(extra.dependee));
1007 add_exact_object_address_extra(object, &extra, targetObjects);
1008 }
1009
1010 /*
1011 * reportDependentObjects - report about dependencies, and fail if RESTRICT
1012 *
1013 * Tell the user about dependent objects that we are going to delete
1014 * (or would need to delete, but are prevented by RESTRICT mode);
1015 * then error out if there are any and it's not CASCADE mode.
1016 *
1017 * targetObjects: list of objects that are scheduled to be deleted
1018 * behavior: RESTRICT or CASCADE
1019 * flags: other flags for the deletion operation
1020 * origObject: base object of deletion, or NULL if not available
1021 * (the latter case occurs in DROP OWNED)
1022 */
1023 static void
reportDependentObjects(const ObjectAddresses * targetObjects,DropBehavior behavior,int flags,const ObjectAddress * origObject)1024 reportDependentObjects(const ObjectAddresses *targetObjects,
1025 DropBehavior behavior,
1026 int flags,
1027 const ObjectAddress *origObject)
1028 {
1029 int msglevel = (flags & PERFORM_DELETION_QUIETLY) ? DEBUG2 : NOTICE;
1030 bool ok = true;
1031 StringInfoData clientdetail;
1032 StringInfoData logdetail;
1033 int numReportedClient = 0;
1034 int numNotReportedClient = 0;
1035 int i;
1036
1037 /*
1038 * If we need to delete any partition-dependent objects, make sure that
1039 * we're deleting at least one of their partition dependencies, too. That
1040 * can be detected by checking that we reached them by a PARTITION
1041 * dependency at some point.
1042 *
1043 * We just report the first such object, as in most cases the only way to
1044 * trigger this complaint is to explicitly try to delete one partition of
1045 * a partitioned object.
1046 */
1047 for (i = 0; i < targetObjects->numrefs; i++)
1048 {
1049 const ObjectAddressExtra *extra = &targetObjects->extras[i];
1050
1051 if ((extra->flags & DEPFLAG_IS_PART) &&
1052 !(extra->flags & DEPFLAG_PARTITION))
1053 {
1054 const ObjectAddress *object = &targetObjects->refs[i];
1055 char *otherObjDesc = getObjectDescription(&extra->dependee,
1056 false);
1057
1058 ereport(ERROR,
1059 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1060 errmsg("cannot drop %s because %s requires it",
1061 getObjectDescription(object, false), otherObjDesc),
1062 errhint("You can drop %s instead.", otherObjDesc)));
1063 }
1064 }
1065
1066 /*
1067 * If no error is to be thrown, and the msglevel is too low to be shown to
1068 * either client or server log, there's no need to do any of the rest of
1069 * the work.
1070 */
1071 if (behavior == DROP_CASCADE &&
1072 !message_level_is_interesting(msglevel))
1073 return;
1074
1075 /*
1076 * We limit the number of dependencies reported to the client to
1077 * MAX_REPORTED_DEPS, since client software may not deal well with
1078 * enormous error strings. The server log always gets a full report.
1079 */
1080 #define MAX_REPORTED_DEPS 100
1081
1082 initStringInfo(&clientdetail);
1083 initStringInfo(&logdetail);
1084
1085 /*
1086 * We process the list back to front (ie, in dependency order not deletion
1087 * order), since this makes for a more understandable display.
1088 */
1089 for (i = targetObjects->numrefs - 1; i >= 0; i--)
1090 {
1091 const ObjectAddress *obj = &targetObjects->refs[i];
1092 const ObjectAddressExtra *extra = &targetObjects->extras[i];
1093 char *objDesc;
1094
1095 /* Ignore the original deletion target(s) */
1096 if (extra->flags & DEPFLAG_ORIGINAL)
1097 continue;
1098
1099 /* Also ignore sub-objects; we'll report the whole object elsewhere */
1100 if (extra->flags & DEPFLAG_SUBOBJECT)
1101 continue;
1102
1103 objDesc = getObjectDescription(obj, false);
1104
1105 /* An object being dropped concurrently doesn't need to be reported */
1106 if (objDesc == NULL)
1107 continue;
1108
1109 /*
1110 * If, at any stage of the recursive search, we reached the object via
1111 * an AUTO, INTERNAL, PARTITION, or EXTENSION dependency, then it's
1112 * okay to delete it even in RESTRICT mode.
1113 */
1114 if (extra->flags & (DEPFLAG_AUTO |
1115 DEPFLAG_INTERNAL |
1116 DEPFLAG_PARTITION |
1117 DEPFLAG_EXTENSION))
1118 {
1119 /*
1120 * auto-cascades are reported at DEBUG2, not msglevel. We don't
1121 * try to combine them with the regular message because the
1122 * results are too confusing when client_min_messages and
1123 * log_min_messages are different.
1124 */
1125 ereport(DEBUG2,
1126 (errmsg_internal("drop auto-cascades to %s",
1127 objDesc)));
1128 }
1129 else if (behavior == DROP_RESTRICT)
1130 {
1131 char *otherDesc = getObjectDescription(&extra->dependee,
1132 false);
1133
1134 if (otherDesc)
1135 {
1136 if (numReportedClient < MAX_REPORTED_DEPS)
1137 {
1138 /* separate entries with a newline */
1139 if (clientdetail.len != 0)
1140 appendStringInfoChar(&clientdetail, '\n');
1141 appendStringInfo(&clientdetail, _("%s depends on %s"),
1142 objDesc, otherDesc);
1143 numReportedClient++;
1144 }
1145 else
1146 numNotReportedClient++;
1147 /* separate entries with a newline */
1148 if (logdetail.len != 0)
1149 appendStringInfoChar(&logdetail, '\n');
1150 appendStringInfo(&logdetail, _("%s depends on %s"),
1151 objDesc, otherDesc);
1152 pfree(otherDesc);
1153 }
1154 else
1155 numNotReportedClient++;
1156 ok = false;
1157 }
1158 else
1159 {
1160 if (numReportedClient < MAX_REPORTED_DEPS)
1161 {
1162 /* separate entries with a newline */
1163 if (clientdetail.len != 0)
1164 appendStringInfoChar(&clientdetail, '\n');
1165 appendStringInfo(&clientdetail, _("drop cascades to %s"),
1166 objDesc);
1167 numReportedClient++;
1168 }
1169 else
1170 numNotReportedClient++;
1171 /* separate entries with a newline */
1172 if (logdetail.len != 0)
1173 appendStringInfoChar(&logdetail, '\n');
1174 appendStringInfo(&logdetail, _("drop cascades to %s"),
1175 objDesc);
1176 }
1177
1178 pfree(objDesc);
1179 }
1180
1181 if (numNotReportedClient > 0)
1182 appendStringInfo(&clientdetail, ngettext("\nand %d other object "
1183 "(see server log for list)",
1184 "\nand %d other objects "
1185 "(see server log for list)",
1186 numNotReportedClient),
1187 numNotReportedClient);
1188
1189 if (!ok)
1190 {
1191 if (origObject)
1192 ereport(ERROR,
1193 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1194 errmsg("cannot drop %s because other objects depend on it",
1195 getObjectDescription(origObject, false)),
1196 errdetail("%s", clientdetail.data),
1197 errdetail_log("%s", logdetail.data),
1198 errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
1199 else
1200 ereport(ERROR,
1201 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1202 errmsg("cannot drop desired object(s) because other objects depend on them"),
1203 errdetail("%s", clientdetail.data),
1204 errdetail_log("%s", logdetail.data),
1205 errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
1206 }
1207 else if (numReportedClient > 1)
1208 {
1209 ereport(msglevel,
1210 /* translator: %d always has a value larger than 1 */
1211 (errmsg_plural("drop cascades to %d other object",
1212 "drop cascades to %d other objects",
1213 numReportedClient + numNotReportedClient,
1214 numReportedClient + numNotReportedClient),
1215 errdetail("%s", clientdetail.data),
1216 errdetail_log("%s", logdetail.data)));
1217 }
1218 else if (numReportedClient == 1)
1219 {
1220 /* we just use the single item as-is */
1221 ereport(msglevel,
1222 (errmsg_internal("%s", clientdetail.data)));
1223 }
1224
1225 pfree(clientdetail.data);
1226 pfree(logdetail.data);
1227 }
1228
1229 /*
1230 * Drop an object by OID. Works for most catalogs, if no special processing
1231 * is needed.
1232 */
1233 static void
DropObjectById(const ObjectAddress * object)1234 DropObjectById(const ObjectAddress *object)
1235 {
1236 int cacheId;
1237 Relation rel;
1238 HeapTuple tup;
1239
1240 cacheId = get_object_catcache_oid(object->classId);
1241
1242 rel = table_open(object->classId, RowExclusiveLock);
1243
1244 /*
1245 * Use the system cache for the oid column, if one exists.
1246 */
1247 if (cacheId >= 0)
1248 {
1249 tup = SearchSysCache1(cacheId, ObjectIdGetDatum(object->objectId));
1250 if (!HeapTupleIsValid(tup))
1251 elog(ERROR, "cache lookup failed for %s %u",
1252 get_object_class_descr(object->classId), object->objectId);
1253
1254 CatalogTupleDelete(rel, &tup->t_self);
1255
1256 ReleaseSysCache(tup);
1257 }
1258 else
1259 {
1260 ScanKeyData skey[1];
1261 SysScanDesc scan;
1262
1263 ScanKeyInit(&skey[0],
1264 get_object_attnum_oid(object->classId),
1265 BTEqualStrategyNumber, F_OIDEQ,
1266 ObjectIdGetDatum(object->objectId));
1267
1268 scan = systable_beginscan(rel, get_object_oid_index(object->classId), true,
1269 NULL, 1, skey);
1270
1271 /* we expect exactly one match */
1272 tup = systable_getnext(scan);
1273 if (!HeapTupleIsValid(tup))
1274 elog(ERROR, "could not find tuple for %s %u",
1275 get_object_class_descr(object->classId), object->objectId);
1276
1277 CatalogTupleDelete(rel, &tup->t_self);
1278
1279 systable_endscan(scan);
1280 }
1281
1282 table_close(rel, RowExclusiveLock);
1283 }
1284
1285 /*
1286 * deleteOneObject: delete a single object for performDeletion.
1287 *
1288 * *depRel is the already-open pg_depend relation.
1289 */
1290 static void
deleteOneObject(const ObjectAddress * object,Relation * depRel,int flags)1291 deleteOneObject(const ObjectAddress *object, Relation *depRel, int flags)
1292 {
1293 ScanKeyData key[3];
1294 int nkeys;
1295 SysScanDesc scan;
1296 HeapTuple tup;
1297
1298 /* DROP hook of the objects being removed */
1299 InvokeObjectDropHookArg(object->classId, object->objectId,
1300 object->objectSubId, flags);
1301
1302 /*
1303 * Close depRel if we are doing a drop concurrently. The object deletion
1304 * subroutine will commit the current transaction, so we can't keep the
1305 * relation open across doDeletion().
1306 */
1307 if (flags & PERFORM_DELETION_CONCURRENTLY)
1308 table_close(*depRel, RowExclusiveLock);
1309
1310 /*
1311 * Delete the object itself, in an object-type-dependent way.
1312 *
1313 * We used to do this after removing the outgoing dependency links, but it
1314 * seems just as reasonable to do it beforehand. In the concurrent case
1315 * we *must* do it in this order, because we can't make any transactional
1316 * updates before calling doDeletion() --- they'd get committed right
1317 * away, which is not cool if the deletion then fails.
1318 */
1319 doDeletion(object, flags);
1320
1321 /*
1322 * Reopen depRel if we closed it above
1323 */
1324 if (flags & PERFORM_DELETION_CONCURRENTLY)
1325 *depRel = table_open(DependRelationId, RowExclusiveLock);
1326
1327 /*
1328 * Now remove any pg_depend records that link from this object to others.
1329 * (Any records linking to this object should be gone already.)
1330 *
1331 * When dropping a whole object (subId = 0), remove all pg_depend records
1332 * for its sub-objects too.
1333 */
1334 ScanKeyInit(&key[0],
1335 Anum_pg_depend_classid,
1336 BTEqualStrategyNumber, F_OIDEQ,
1337 ObjectIdGetDatum(object->classId));
1338 ScanKeyInit(&key[1],
1339 Anum_pg_depend_objid,
1340 BTEqualStrategyNumber, F_OIDEQ,
1341 ObjectIdGetDatum(object->objectId));
1342 if (object->objectSubId != 0)
1343 {
1344 ScanKeyInit(&key[2],
1345 Anum_pg_depend_objsubid,
1346 BTEqualStrategyNumber, F_INT4EQ,
1347 Int32GetDatum(object->objectSubId));
1348 nkeys = 3;
1349 }
1350 else
1351 nkeys = 2;
1352
1353 scan = systable_beginscan(*depRel, DependDependerIndexId, true,
1354 NULL, nkeys, key);
1355
1356 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1357 {
1358 CatalogTupleDelete(*depRel, &tup->t_self);
1359 }
1360
1361 systable_endscan(scan);
1362
1363 /*
1364 * Delete shared dependency references related to this object. Again, if
1365 * subId = 0, remove records for sub-objects too.
1366 */
1367 deleteSharedDependencyRecordsFor(object->classId, object->objectId,
1368 object->objectSubId);
1369
1370
1371 /*
1372 * Delete any comments, security labels, or initial privileges associated
1373 * with this object. (This is a convenient place to do these things,
1374 * rather than having every object type know to do it.)
1375 */
1376 DeleteComments(object->objectId, object->classId, object->objectSubId);
1377 DeleteSecurityLabel(object);
1378 DeleteInitPrivs(object);
1379
1380 /*
1381 * CommandCounterIncrement here to ensure that preceding changes are all
1382 * visible to the next deletion step.
1383 */
1384 CommandCounterIncrement();
1385
1386 /*
1387 * And we're done!
1388 */
1389 }
1390
1391 /*
1392 * doDeletion: actually delete a single object
1393 */
1394 static void
doDeletion(const ObjectAddress * object,int flags)1395 doDeletion(const ObjectAddress *object, int flags)
1396 {
1397 switch (getObjectClass(object))
1398 {
1399 case OCLASS_CLASS:
1400 {
1401 char relKind = get_rel_relkind(object->objectId);
1402
1403 if (relKind == RELKIND_INDEX ||
1404 relKind == RELKIND_PARTITIONED_INDEX)
1405 {
1406 bool concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY) != 0);
1407 bool concurrent_lock_mode = ((flags & PERFORM_DELETION_CONCURRENT_LOCK) != 0);
1408
1409 Assert(object->objectSubId == 0);
1410 index_drop(object->objectId, concurrent, concurrent_lock_mode);
1411 }
1412 else
1413 {
1414 if (object->objectSubId != 0)
1415 RemoveAttributeById(object->objectId,
1416 object->objectSubId);
1417 else
1418 heap_drop_with_catalog(object->objectId);
1419 }
1420
1421 /*
1422 * for a sequence, in addition to dropping the heap, also
1423 * delete pg_sequence tuple
1424 */
1425 if (relKind == RELKIND_SEQUENCE)
1426 DeleteSequenceTuple(object->objectId);
1427 break;
1428 }
1429
1430 case OCLASS_PROC:
1431 RemoveFunctionById(object->objectId);
1432 break;
1433
1434 case OCLASS_TYPE:
1435 RemoveTypeById(object->objectId);
1436 break;
1437
1438 case OCLASS_CONSTRAINT:
1439 RemoveConstraintById(object->objectId);
1440 break;
1441
1442 case OCLASS_DEFAULT:
1443 RemoveAttrDefaultById(object->objectId);
1444 break;
1445
1446 case OCLASS_LARGEOBJECT:
1447 LargeObjectDrop(object->objectId);
1448 break;
1449
1450 case OCLASS_OPERATOR:
1451 RemoveOperatorById(object->objectId);
1452 break;
1453
1454 case OCLASS_REWRITE:
1455 RemoveRewriteRuleById(object->objectId);
1456 break;
1457
1458 case OCLASS_TRIGGER:
1459 RemoveTriggerById(object->objectId);
1460 break;
1461
1462 case OCLASS_STATISTIC_EXT:
1463 RemoveStatisticsById(object->objectId);
1464 break;
1465
1466 case OCLASS_TSCONFIG:
1467 RemoveTSConfigurationById(object->objectId);
1468 break;
1469
1470 case OCLASS_EXTENSION:
1471 RemoveExtensionById(object->objectId);
1472 break;
1473
1474 case OCLASS_POLICY:
1475 RemovePolicyById(object->objectId);
1476 break;
1477
1478 case OCLASS_PUBLICATION_REL:
1479 RemovePublicationRelById(object->objectId);
1480 break;
1481
1482 case OCLASS_PUBLICATION:
1483 RemovePublicationById(object->objectId);
1484 break;
1485
1486 case OCLASS_CAST:
1487 case OCLASS_COLLATION:
1488 case OCLASS_CONVERSION:
1489 case OCLASS_LANGUAGE:
1490 case OCLASS_OPCLASS:
1491 case OCLASS_OPFAMILY:
1492 case OCLASS_AM:
1493 case OCLASS_AMOP:
1494 case OCLASS_AMPROC:
1495 case OCLASS_SCHEMA:
1496 case OCLASS_TSPARSER:
1497 case OCLASS_TSDICT:
1498 case OCLASS_TSTEMPLATE:
1499 case OCLASS_FDW:
1500 case OCLASS_FOREIGN_SERVER:
1501 case OCLASS_USER_MAPPING:
1502 case OCLASS_DEFACL:
1503 case OCLASS_EVENT_TRIGGER:
1504 case OCLASS_TRANSFORM:
1505 DropObjectById(object);
1506 break;
1507
1508 /*
1509 * These global object types are not supported here.
1510 */
1511 case OCLASS_ROLE:
1512 case OCLASS_DATABASE:
1513 case OCLASS_TBLSPACE:
1514 case OCLASS_SUBSCRIPTION:
1515 elog(ERROR, "global objects cannot be deleted by doDeletion");
1516 break;
1517
1518 /*
1519 * There's intentionally no default: case here; we want the
1520 * compiler to warn if a new OCLASS hasn't been handled above.
1521 */
1522 }
1523 }
1524
1525 /*
1526 * AcquireDeletionLock - acquire a suitable lock for deleting an object
1527 *
1528 * Accepts the same flags as performDeletion (though currently only
1529 * PERFORM_DELETION_CONCURRENTLY does anything).
1530 *
1531 * We use LockRelation for relations, LockDatabaseObject for everything
1532 * else. Shared-across-databases objects are not currently supported
1533 * because no caller cares, but could be modified to use LockSharedObject.
1534 */
1535 void
AcquireDeletionLock(const ObjectAddress * object,int flags)1536 AcquireDeletionLock(const ObjectAddress *object, int flags)
1537 {
1538 if (object->classId == RelationRelationId)
1539 {
1540 /*
1541 * In DROP INDEX CONCURRENTLY, take only ShareUpdateExclusiveLock on
1542 * the index for the moment. index_drop() will promote the lock once
1543 * it's safe to do so. In all other cases we need full exclusive
1544 * lock.
1545 */
1546 if (flags & PERFORM_DELETION_CONCURRENTLY)
1547 LockRelationOid(object->objectId, ShareUpdateExclusiveLock);
1548 else
1549 LockRelationOid(object->objectId, AccessExclusiveLock);
1550 }
1551 else
1552 {
1553 /* assume we should lock the whole object not a sub-object */
1554 LockDatabaseObject(object->classId, object->objectId, 0,
1555 AccessExclusiveLock);
1556 }
1557 }
1558
1559 /*
1560 * ReleaseDeletionLock - release an object deletion lock
1561 *
1562 * Companion to AcquireDeletionLock.
1563 */
1564 void
ReleaseDeletionLock(const ObjectAddress * object)1565 ReleaseDeletionLock(const ObjectAddress *object)
1566 {
1567 if (object->classId == RelationRelationId)
1568 UnlockRelationOid(object->objectId, AccessExclusiveLock);
1569 else
1570 /* assume we should lock the whole object not a sub-object */
1571 UnlockDatabaseObject(object->classId, object->objectId, 0,
1572 AccessExclusiveLock);
1573 }
1574
1575 /*
1576 * recordDependencyOnExpr - find expression dependencies
1577 *
1578 * This is used to find the dependencies of rules, constraint expressions,
1579 * etc.
1580 *
1581 * Given an expression or query in node-tree form, find all the objects
1582 * it refers to (tables, columns, operators, functions, etc). Record
1583 * a dependency of the specified type from the given depender object
1584 * to each object mentioned in the expression.
1585 *
1586 * rtable is the rangetable to be used to interpret Vars with varlevelsup=0.
1587 * It can be NIL if no such variables are expected.
1588 */
1589 void
recordDependencyOnExpr(const ObjectAddress * depender,Node * expr,List * rtable,DependencyType behavior)1590 recordDependencyOnExpr(const ObjectAddress *depender,
1591 Node *expr, List *rtable,
1592 DependencyType behavior)
1593 {
1594 find_expr_references_context context;
1595
1596 context.addrs = new_object_addresses();
1597
1598 /* Set up interpretation for Vars at varlevelsup = 0 */
1599 context.rtables = list_make1(rtable);
1600
1601 /* Scan the expression tree for referenceable objects */
1602 find_expr_references_walker(expr, &context);
1603
1604 /* Remove any duplicates */
1605 eliminate_duplicate_dependencies(context.addrs);
1606
1607 /* And record 'em */
1608 recordMultipleDependencies(depender,
1609 context.addrs->refs, context.addrs->numrefs,
1610 behavior);
1611
1612 free_object_addresses(context.addrs);
1613 }
1614
1615 /*
1616 * recordDependencyOnSingleRelExpr - find expression dependencies
1617 *
1618 * As above, but only one relation is expected to be referenced (with
1619 * varno = 1 and varlevelsup = 0). Pass the relation OID instead of a
1620 * range table. An additional frammish is that dependencies on that
1621 * relation's component columns will be marked with 'self_behavior',
1622 * whereas 'behavior' is used for everything else; also, if 'reverse_self'
1623 * is true, those dependencies are reversed so that the columns are made
1624 * to depend on the table not vice versa.
1625 *
1626 * NOTE: the caller should ensure that a whole-table dependency on the
1627 * specified relation is created separately, if one is needed. In particular,
1628 * a whole-row Var "relation.*" will not cause this routine to emit any
1629 * dependency item. This is appropriate behavior for subexpressions of an
1630 * ordinary query, so other cases need to cope as necessary.
1631 */
1632 void
recordDependencyOnSingleRelExpr(const ObjectAddress * depender,Node * expr,Oid relId,DependencyType behavior,DependencyType self_behavior,bool reverse_self)1633 recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
1634 Node *expr, Oid relId,
1635 DependencyType behavior,
1636 DependencyType self_behavior,
1637 bool reverse_self)
1638 {
1639 find_expr_references_context context;
1640 RangeTblEntry rte;
1641
1642 context.addrs = new_object_addresses();
1643
1644 /* We gin up a rather bogus rangetable list to handle Vars */
1645 MemSet(&rte, 0, sizeof(rte));
1646 rte.type = T_RangeTblEntry;
1647 rte.rtekind = RTE_RELATION;
1648 rte.relid = relId;
1649 rte.relkind = RELKIND_RELATION; /* no need for exactness here */
1650 rte.rellockmode = AccessShareLock;
1651
1652 context.rtables = list_make1(list_make1(&rte));
1653
1654 /* Scan the expression tree for referenceable objects */
1655 find_expr_references_walker(expr, &context);
1656
1657 /* Remove any duplicates */
1658 eliminate_duplicate_dependencies(context.addrs);
1659
1660 /* Separate self-dependencies if necessary */
1661 if ((behavior != self_behavior || reverse_self) &&
1662 context.addrs->numrefs > 0)
1663 {
1664 ObjectAddresses *self_addrs;
1665 ObjectAddress *outobj;
1666 int oldref,
1667 outrefs;
1668
1669 self_addrs = new_object_addresses();
1670
1671 outobj = context.addrs->refs;
1672 outrefs = 0;
1673 for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
1674 {
1675 ObjectAddress *thisobj = context.addrs->refs + oldref;
1676
1677 if (thisobj->classId == RelationRelationId &&
1678 thisobj->objectId == relId)
1679 {
1680 /* Move this ref into self_addrs */
1681 add_exact_object_address(thisobj, self_addrs);
1682 }
1683 else
1684 {
1685 /* Keep it in context.addrs */
1686 *outobj = *thisobj;
1687 outobj++;
1688 outrefs++;
1689 }
1690 }
1691 context.addrs->numrefs = outrefs;
1692
1693 /* Record the self-dependencies with the appropriate direction */
1694 if (!reverse_self)
1695 recordMultipleDependencies(depender,
1696 self_addrs->refs, self_addrs->numrefs,
1697 self_behavior);
1698 else
1699 {
1700 /* Can't use recordMultipleDependencies, so do it the hard way */
1701 int selfref;
1702
1703 for (selfref = 0; selfref < self_addrs->numrefs; selfref++)
1704 {
1705 ObjectAddress *thisobj = self_addrs->refs + selfref;
1706
1707 recordDependencyOn(thisobj, depender, self_behavior);
1708 }
1709 }
1710
1711 free_object_addresses(self_addrs);
1712 }
1713
1714 /* Record the external dependencies */
1715 recordMultipleDependencies(depender,
1716 context.addrs->refs, context.addrs->numrefs,
1717 behavior);
1718
1719 free_object_addresses(context.addrs);
1720 }
1721
1722 /*
1723 * Recursively search an expression tree for object references.
1724 *
1725 * Note: in many cases we do not need to create dependencies on the datatypes
1726 * involved in an expression, because we'll have an indirect dependency via
1727 * some other object. For instance Var nodes depend on a column which depends
1728 * on the datatype, and OpExpr nodes depend on the operator which depends on
1729 * the datatype. However we do need a type dependency if there is no such
1730 * indirect dependency, as for example in Const and CoerceToDomain nodes.
1731 *
1732 * Similarly, we don't need to create dependencies on collations except where
1733 * the collation is being freshly introduced to the expression.
1734 */
1735 static bool
find_expr_references_walker(Node * node,find_expr_references_context * context)1736 find_expr_references_walker(Node *node,
1737 find_expr_references_context *context)
1738 {
1739 if (node == NULL)
1740 return false;
1741 if (IsA(node, Var))
1742 {
1743 Var *var = (Var *) node;
1744 List *rtable;
1745 RangeTblEntry *rte;
1746
1747 /* Find matching rtable entry, or complain if not found */
1748 if (var->varlevelsup >= list_length(context->rtables))
1749 elog(ERROR, "invalid varlevelsup %d", var->varlevelsup);
1750 rtable = (List *) list_nth(context->rtables, var->varlevelsup);
1751 if (var->varno <= 0 || var->varno > list_length(rtable))
1752 elog(ERROR, "invalid varno %d", var->varno);
1753 rte = rt_fetch(var->varno, rtable);
1754
1755 /*
1756 * A whole-row Var references no specific columns, so adds no new
1757 * dependency. (We assume that there is a whole-table dependency
1758 * arising from each underlying rangetable entry. While we could
1759 * record such a dependency when finding a whole-row Var that
1760 * references a relation directly, it's quite unclear how to extend
1761 * that to whole-row Vars for JOINs, so it seems better to leave the
1762 * responsibility with the range table. Note that this poses some
1763 * risks for identifying dependencies of stand-alone expressions:
1764 * whole-table references may need to be created separately.)
1765 */
1766 if (var->varattno == InvalidAttrNumber)
1767 return false;
1768 if (rte->rtekind == RTE_RELATION)
1769 {
1770 /* If it's a plain relation, reference this column */
1771 add_object_address(OCLASS_CLASS, rte->relid, var->varattno,
1772 context->addrs);
1773 }
1774
1775 /*
1776 * Vars referencing other RTE types require no additional work. In
1777 * particular, a join alias Var can be ignored, because it must
1778 * reference a merged USING column. The relevant join input columns
1779 * will also be referenced in the join qual, and any type coercion
1780 * functions involved in the alias expression will be dealt with when
1781 * we scan the RTE itself.
1782 */
1783 return false;
1784 }
1785 else if (IsA(node, Const))
1786 {
1787 Const *con = (Const *) node;
1788 Oid objoid;
1789
1790 /* A constant must depend on the constant's datatype */
1791 add_object_address(OCLASS_TYPE, con->consttype, 0,
1792 context->addrs);
1793
1794 /*
1795 * We must also depend on the constant's collation: it could be
1796 * different from the datatype's, if a CollateExpr was const-folded to
1797 * a simple constant. However we can save work in the most common
1798 * case where the collation is "default", since we know that's pinned.
1799 */
1800 if (OidIsValid(con->constcollid) &&
1801 con->constcollid != DEFAULT_COLLATION_OID)
1802 add_object_address(OCLASS_COLLATION, con->constcollid, 0,
1803 context->addrs);
1804
1805 /*
1806 * If it's a regclass or similar literal referring to an existing
1807 * object, add a reference to that object. (Currently, only the
1808 * regclass and regconfig cases have any likely use, but we may as
1809 * well handle all the OID-alias datatypes consistently.)
1810 */
1811 if (!con->constisnull)
1812 {
1813 switch (con->consttype)
1814 {
1815 case REGPROCOID:
1816 case REGPROCEDUREOID:
1817 objoid = DatumGetObjectId(con->constvalue);
1818 if (SearchSysCacheExists1(PROCOID,
1819 ObjectIdGetDatum(objoid)))
1820 add_object_address(OCLASS_PROC, objoid, 0,
1821 context->addrs);
1822 break;
1823 case REGOPEROID:
1824 case REGOPERATOROID:
1825 objoid = DatumGetObjectId(con->constvalue);
1826 if (SearchSysCacheExists1(OPEROID,
1827 ObjectIdGetDatum(objoid)))
1828 add_object_address(OCLASS_OPERATOR, objoid, 0,
1829 context->addrs);
1830 break;
1831 case REGCLASSOID:
1832 objoid = DatumGetObjectId(con->constvalue);
1833 if (SearchSysCacheExists1(RELOID,
1834 ObjectIdGetDatum(objoid)))
1835 add_object_address(OCLASS_CLASS, objoid, 0,
1836 context->addrs);
1837 break;
1838 case REGTYPEOID:
1839 objoid = DatumGetObjectId(con->constvalue);
1840 if (SearchSysCacheExists1(TYPEOID,
1841 ObjectIdGetDatum(objoid)))
1842 add_object_address(OCLASS_TYPE, objoid, 0,
1843 context->addrs);
1844 break;
1845 case REGCONFIGOID:
1846 objoid = DatumGetObjectId(con->constvalue);
1847 if (SearchSysCacheExists1(TSCONFIGOID,
1848 ObjectIdGetDatum(objoid)))
1849 add_object_address(OCLASS_TSCONFIG, objoid, 0,
1850 context->addrs);
1851 break;
1852 case REGDICTIONARYOID:
1853 objoid = DatumGetObjectId(con->constvalue);
1854 if (SearchSysCacheExists1(TSDICTOID,
1855 ObjectIdGetDatum(objoid)))
1856 add_object_address(OCLASS_TSDICT, objoid, 0,
1857 context->addrs);
1858 break;
1859
1860 case REGNAMESPACEOID:
1861 objoid = DatumGetObjectId(con->constvalue);
1862 if (SearchSysCacheExists1(NAMESPACEOID,
1863 ObjectIdGetDatum(objoid)))
1864 add_object_address(OCLASS_SCHEMA, objoid, 0,
1865 context->addrs);
1866 break;
1867
1868 /*
1869 * Dependencies for regrole should be shared among all
1870 * databases, so explicitly inhibit to have dependencies.
1871 */
1872 case REGROLEOID:
1873 ereport(ERROR,
1874 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1875 errmsg("constant of the type %s cannot be used here",
1876 "regrole")));
1877 break;
1878 }
1879 }
1880 return false;
1881 }
1882 else if (IsA(node, Param))
1883 {
1884 Param *param = (Param *) node;
1885
1886 /* A parameter must depend on the parameter's datatype */
1887 add_object_address(OCLASS_TYPE, param->paramtype, 0,
1888 context->addrs);
1889 /* and its collation, just as for Consts */
1890 if (OidIsValid(param->paramcollid) &&
1891 param->paramcollid != DEFAULT_COLLATION_OID)
1892 add_object_address(OCLASS_COLLATION, param->paramcollid, 0,
1893 context->addrs);
1894 }
1895 else if (IsA(node, FuncExpr))
1896 {
1897 FuncExpr *funcexpr = (FuncExpr *) node;
1898
1899 add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
1900 context->addrs);
1901 /* fall through to examine arguments */
1902 }
1903 else if (IsA(node, OpExpr))
1904 {
1905 OpExpr *opexpr = (OpExpr *) node;
1906
1907 add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
1908 context->addrs);
1909 /* fall through to examine arguments */
1910 }
1911 else if (IsA(node, DistinctExpr))
1912 {
1913 DistinctExpr *distinctexpr = (DistinctExpr *) node;
1914
1915 add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
1916 context->addrs);
1917 /* fall through to examine arguments */
1918 }
1919 else if (IsA(node, NullIfExpr))
1920 {
1921 NullIfExpr *nullifexpr = (NullIfExpr *) node;
1922
1923 add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
1924 context->addrs);
1925 /* fall through to examine arguments */
1926 }
1927 else if (IsA(node, ScalarArrayOpExpr))
1928 {
1929 ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
1930
1931 add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
1932 context->addrs);
1933 /* fall through to examine arguments */
1934 }
1935 else if (IsA(node, Aggref))
1936 {
1937 Aggref *aggref = (Aggref *) node;
1938
1939 add_object_address(OCLASS_PROC, aggref->aggfnoid, 0,
1940 context->addrs);
1941 /* fall through to examine arguments */
1942 }
1943 else if (IsA(node, WindowFunc))
1944 {
1945 WindowFunc *wfunc = (WindowFunc *) node;
1946
1947 add_object_address(OCLASS_PROC, wfunc->winfnoid, 0,
1948 context->addrs);
1949 /* fall through to examine arguments */
1950 }
1951 else if (IsA(node, SubscriptingRef))
1952 {
1953 SubscriptingRef *sbsref = (SubscriptingRef *) node;
1954
1955 /*
1956 * The refexpr should provide adequate dependency on refcontainertype,
1957 * and that type in turn depends on refelemtype. However, a custom
1958 * subscripting handler might set refrestype to something different
1959 * from either of those, in which case we'd better record it.
1960 */
1961 if (sbsref->refrestype != sbsref->refcontainertype &&
1962 sbsref->refrestype != sbsref->refelemtype)
1963 add_object_address(OCLASS_TYPE, sbsref->refrestype, 0,
1964 context->addrs);
1965 /* fall through to examine arguments */
1966 }
1967 else if (IsA(node, SubPlan))
1968 {
1969 /* Extra work needed here if we ever need this case */
1970 elog(ERROR, "already-planned subqueries not supported");
1971 }
1972 else if (IsA(node, FieldSelect))
1973 {
1974 FieldSelect *fselect = (FieldSelect *) node;
1975 Oid argtype = getBaseType(exprType((Node *) fselect->arg));
1976 Oid reltype = get_typ_typrelid(argtype);
1977
1978 /*
1979 * We need a dependency on the specific column named in FieldSelect,
1980 * assuming we can identify the pg_class OID for it. (Probably we
1981 * always can at the moment, but in future it might be possible for
1982 * argtype to be RECORDOID.) If we can make a column dependency then
1983 * we shouldn't need a dependency on the column's type; but if we
1984 * can't, make a dependency on the type, as it might not appear
1985 * anywhere else in the expression.
1986 */
1987 if (OidIsValid(reltype))
1988 add_object_address(OCLASS_CLASS, reltype, fselect->fieldnum,
1989 context->addrs);
1990 else
1991 add_object_address(OCLASS_TYPE, fselect->resulttype, 0,
1992 context->addrs);
1993 /* the collation might not be referenced anywhere else, either */
1994 if (OidIsValid(fselect->resultcollid) &&
1995 fselect->resultcollid != DEFAULT_COLLATION_OID)
1996 add_object_address(OCLASS_COLLATION, fselect->resultcollid, 0,
1997 context->addrs);
1998 }
1999 else if (IsA(node, FieldStore))
2000 {
2001 FieldStore *fstore = (FieldStore *) node;
2002 Oid reltype = get_typ_typrelid(fstore->resulttype);
2003
2004 /* similar considerations to FieldSelect, but multiple column(s) */
2005 if (OidIsValid(reltype))
2006 {
2007 ListCell *l;
2008
2009 foreach(l, fstore->fieldnums)
2010 add_object_address(OCLASS_CLASS, reltype, lfirst_int(l),
2011 context->addrs);
2012 }
2013 else
2014 add_object_address(OCLASS_TYPE, fstore->resulttype, 0,
2015 context->addrs);
2016 }
2017 else if (IsA(node, RelabelType))
2018 {
2019 RelabelType *relab = (RelabelType *) node;
2020
2021 /* since there is no function dependency, need to depend on type */
2022 add_object_address(OCLASS_TYPE, relab->resulttype, 0,
2023 context->addrs);
2024 /* the collation might not be referenced anywhere else, either */
2025 if (OidIsValid(relab->resultcollid) &&
2026 relab->resultcollid != DEFAULT_COLLATION_OID)
2027 add_object_address(OCLASS_COLLATION, relab->resultcollid, 0,
2028 context->addrs);
2029 }
2030 else if (IsA(node, CoerceViaIO))
2031 {
2032 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
2033
2034 /* since there is no exposed function, need to depend on type */
2035 add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0,
2036 context->addrs);
2037 /* the collation might not be referenced anywhere else, either */
2038 if (OidIsValid(iocoerce->resultcollid) &&
2039 iocoerce->resultcollid != DEFAULT_COLLATION_OID)
2040 add_object_address(OCLASS_COLLATION, iocoerce->resultcollid, 0,
2041 context->addrs);
2042 }
2043 else if (IsA(node, ArrayCoerceExpr))
2044 {
2045 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
2046
2047 /* as above, depend on type */
2048 add_object_address(OCLASS_TYPE, acoerce->resulttype, 0,
2049 context->addrs);
2050 /* the collation might not be referenced anywhere else, either */
2051 if (OidIsValid(acoerce->resultcollid) &&
2052 acoerce->resultcollid != DEFAULT_COLLATION_OID)
2053 add_object_address(OCLASS_COLLATION, acoerce->resultcollid, 0,
2054 context->addrs);
2055 /* fall through to examine arguments */
2056 }
2057 else if (IsA(node, ConvertRowtypeExpr))
2058 {
2059 ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node;
2060
2061 /* since there is no function dependency, need to depend on type */
2062 add_object_address(OCLASS_TYPE, cvt->resulttype, 0,
2063 context->addrs);
2064 }
2065 else if (IsA(node, CollateExpr))
2066 {
2067 CollateExpr *coll = (CollateExpr *) node;
2068
2069 add_object_address(OCLASS_COLLATION, coll->collOid, 0,
2070 context->addrs);
2071 }
2072 else if (IsA(node, RowExpr))
2073 {
2074 RowExpr *rowexpr = (RowExpr *) node;
2075
2076 add_object_address(OCLASS_TYPE, rowexpr->row_typeid, 0,
2077 context->addrs);
2078 }
2079 else if (IsA(node, RowCompareExpr))
2080 {
2081 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
2082 ListCell *l;
2083
2084 foreach(l, rcexpr->opnos)
2085 {
2086 add_object_address(OCLASS_OPERATOR, lfirst_oid(l), 0,
2087 context->addrs);
2088 }
2089 foreach(l, rcexpr->opfamilies)
2090 {
2091 add_object_address(OCLASS_OPFAMILY, lfirst_oid(l), 0,
2092 context->addrs);
2093 }
2094 /* fall through to examine arguments */
2095 }
2096 else if (IsA(node, CoerceToDomain))
2097 {
2098 CoerceToDomain *cd = (CoerceToDomain *) node;
2099
2100 add_object_address(OCLASS_TYPE, cd->resulttype, 0,
2101 context->addrs);
2102 }
2103 else if (IsA(node, NextValueExpr))
2104 {
2105 NextValueExpr *nve = (NextValueExpr *) node;
2106
2107 add_object_address(OCLASS_CLASS, nve->seqid, 0,
2108 context->addrs);
2109 }
2110 else if (IsA(node, OnConflictExpr))
2111 {
2112 OnConflictExpr *onconflict = (OnConflictExpr *) node;
2113
2114 if (OidIsValid(onconflict->constraint))
2115 add_object_address(OCLASS_CONSTRAINT, onconflict->constraint, 0,
2116 context->addrs);
2117 /* fall through to examine arguments */
2118 }
2119 else if (IsA(node, SortGroupClause))
2120 {
2121 SortGroupClause *sgc = (SortGroupClause *) node;
2122
2123 add_object_address(OCLASS_OPERATOR, sgc->eqop, 0,
2124 context->addrs);
2125 if (OidIsValid(sgc->sortop))
2126 add_object_address(OCLASS_OPERATOR, sgc->sortop, 0,
2127 context->addrs);
2128 return false;
2129 }
2130 else if (IsA(node, WindowClause))
2131 {
2132 WindowClause *wc = (WindowClause *) node;
2133
2134 if (OidIsValid(wc->startInRangeFunc))
2135 add_object_address(OCLASS_PROC, wc->startInRangeFunc, 0,
2136 context->addrs);
2137 if (OidIsValid(wc->endInRangeFunc))
2138 add_object_address(OCLASS_PROC, wc->endInRangeFunc, 0,
2139 context->addrs);
2140 if (OidIsValid(wc->inRangeColl) &&
2141 wc->inRangeColl != DEFAULT_COLLATION_OID)
2142 add_object_address(OCLASS_COLLATION, wc->inRangeColl, 0,
2143 context->addrs);
2144 /* fall through to examine substructure */
2145 }
2146 else if (IsA(node, CTECycleClause))
2147 {
2148 CTECycleClause *cc = (CTECycleClause *) node;
2149
2150 if (OidIsValid(cc->cycle_mark_type))
2151 add_object_address(OCLASS_TYPE, cc->cycle_mark_type, 0,
2152 context->addrs);
2153 if (OidIsValid(cc->cycle_mark_collation))
2154 add_object_address(OCLASS_COLLATION, cc->cycle_mark_collation, 0,
2155 context->addrs);
2156 if (OidIsValid(cc->cycle_mark_neop))
2157 add_object_address(OCLASS_OPERATOR, cc->cycle_mark_neop, 0,
2158 context->addrs);
2159 /* fall through to examine substructure */
2160 }
2161 else if (IsA(node, Query))
2162 {
2163 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
2164 Query *query = (Query *) node;
2165 ListCell *lc;
2166 bool result;
2167
2168 /*
2169 * Add whole-relation refs for each plain relation mentioned in the
2170 * subquery's rtable, and ensure we add refs for any type-coercion
2171 * functions used in join alias lists.
2172 *
2173 * Note: query_tree_walker takes care of recursing into RTE_FUNCTION
2174 * RTEs, subqueries, etc, so no need to do that here. But we must
2175 * tell it not to visit join alias lists, or we'll add refs for join
2176 * input columns whether or not they are actually used in our query.
2177 *
2178 * Note: we don't need to worry about collations mentioned in
2179 * RTE_VALUES or RTE_CTE RTEs, because those must just duplicate
2180 * collations referenced in other parts of the Query. We do have to
2181 * worry about collations mentioned in RTE_FUNCTION, but we take care
2182 * of those when we recurse to the RangeTblFunction node(s).
2183 */
2184 foreach(lc, query->rtable)
2185 {
2186 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
2187
2188 switch (rte->rtekind)
2189 {
2190 case RTE_RELATION:
2191 add_object_address(OCLASS_CLASS, rte->relid, 0,
2192 context->addrs);
2193 break;
2194 case RTE_JOIN:
2195
2196 /*
2197 * Examine joinaliasvars entries only for merged JOIN
2198 * USING columns. Only those entries could contain
2199 * type-coercion functions. Also, their join input
2200 * columns must be referenced in the join quals, so this
2201 * won't accidentally add refs to otherwise-unused join
2202 * input columns. (We want to ref the type coercion
2203 * functions even if the merged column isn't explicitly
2204 * used anywhere, to protect possible expansion of the
2205 * join RTE as a whole-row var, and because it seems like
2206 * a bad idea to allow dropping a function that's present
2207 * in our query tree, whether or not it could get called.)
2208 */
2209 context->rtables = lcons(query->rtable, context->rtables);
2210 for (int i = 0; i < rte->joinmergedcols; i++)
2211 {
2212 Node *aliasvar = list_nth(rte->joinaliasvars, i);
2213
2214 if (!IsA(aliasvar, Var))
2215 find_expr_references_walker(aliasvar, context);
2216 }
2217 context->rtables = list_delete_first(context->rtables);
2218 break;
2219 default:
2220 break;
2221 }
2222 }
2223
2224 /*
2225 * If the query is an INSERT or UPDATE, we should create a dependency
2226 * on each target column, to prevent the specific target column from
2227 * being dropped. Although we will visit the TargetEntry nodes again
2228 * during query_tree_walker, we won't have enough context to do this
2229 * conveniently, so do it here.
2230 */
2231 if (query->commandType == CMD_INSERT ||
2232 query->commandType == CMD_UPDATE)
2233 {
2234 RangeTblEntry *rte;
2235
2236 if (query->resultRelation <= 0 ||
2237 query->resultRelation > list_length(query->rtable))
2238 elog(ERROR, "invalid resultRelation %d",
2239 query->resultRelation);
2240 rte = rt_fetch(query->resultRelation, query->rtable);
2241 if (rte->rtekind == RTE_RELATION)
2242 {
2243 foreach(lc, query->targetList)
2244 {
2245 TargetEntry *tle = (TargetEntry *) lfirst(lc);
2246
2247 if (tle->resjunk)
2248 continue; /* ignore junk tlist items */
2249 add_object_address(OCLASS_CLASS, rte->relid, tle->resno,
2250 context->addrs);
2251 }
2252 }
2253 }
2254
2255 /*
2256 * Add dependencies on constraints listed in query's constraintDeps
2257 */
2258 foreach(lc, query->constraintDeps)
2259 {
2260 add_object_address(OCLASS_CONSTRAINT, lfirst_oid(lc), 0,
2261 context->addrs);
2262 }
2263
2264 /* Examine substructure of query */
2265 context->rtables = lcons(query->rtable, context->rtables);
2266 result = query_tree_walker(query,
2267 find_expr_references_walker,
2268 (void *) context,
2269 QTW_IGNORE_JOINALIASES |
2270 QTW_EXAMINE_SORTGROUP);
2271 context->rtables = list_delete_first(context->rtables);
2272 return result;
2273 }
2274 else if (IsA(node, SetOperationStmt))
2275 {
2276 SetOperationStmt *setop = (SetOperationStmt *) node;
2277
2278 /* we need to look at the groupClauses for operator references */
2279 find_expr_references_walker((Node *) setop->groupClauses, context);
2280 /* fall through to examine child nodes */
2281 }
2282 else if (IsA(node, RangeTblFunction))
2283 {
2284 RangeTblFunction *rtfunc = (RangeTblFunction *) node;
2285 ListCell *ct;
2286
2287 /*
2288 * Add refs for any datatypes and collations used in a column
2289 * definition list for a RECORD function. (For other cases, it should
2290 * be enough to depend on the function itself.)
2291 */
2292 foreach(ct, rtfunc->funccoltypes)
2293 {
2294 add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0,
2295 context->addrs);
2296 }
2297 foreach(ct, rtfunc->funccolcollations)
2298 {
2299 Oid collid = lfirst_oid(ct);
2300
2301 if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
2302 add_object_address(OCLASS_COLLATION, collid, 0,
2303 context->addrs);
2304 }
2305 }
2306 else if (IsA(node, TableFunc))
2307 {
2308 TableFunc *tf = (TableFunc *) node;
2309 ListCell *ct;
2310
2311 /*
2312 * Add refs for the datatypes and collations used in the TableFunc.
2313 */
2314 foreach(ct, tf->coltypes)
2315 {
2316 add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0,
2317 context->addrs);
2318 }
2319 foreach(ct, tf->colcollations)
2320 {
2321 Oid collid = lfirst_oid(ct);
2322
2323 if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
2324 add_object_address(OCLASS_COLLATION, collid, 0,
2325 context->addrs);
2326 }
2327 }
2328 else if (IsA(node, TableSampleClause))
2329 {
2330 TableSampleClause *tsc = (TableSampleClause *) node;
2331
2332 add_object_address(OCLASS_PROC, tsc->tsmhandler, 0,
2333 context->addrs);
2334 /* fall through to examine arguments */
2335 }
2336
2337 return expression_tree_walker(node, find_expr_references_walker,
2338 (void *) context);
2339 }
2340
2341 /*
2342 * Given an array of dependency references, eliminate any duplicates.
2343 */
2344 static void
eliminate_duplicate_dependencies(ObjectAddresses * addrs)2345 eliminate_duplicate_dependencies(ObjectAddresses *addrs)
2346 {
2347 ObjectAddress *priorobj;
2348 int oldref,
2349 newrefs;
2350
2351 /*
2352 * We can't sort if the array has "extra" data, because there's no way to
2353 * keep it in sync. Fortunately that combination of features is not
2354 * needed.
2355 */
2356 Assert(!addrs->extras);
2357
2358 if (addrs->numrefs <= 1)
2359 return; /* nothing to do */
2360
2361 /* Sort the refs so that duplicates are adjacent */
2362 qsort((void *) addrs->refs, addrs->numrefs, sizeof(ObjectAddress),
2363 object_address_comparator);
2364
2365 /* Remove dups */
2366 priorobj = addrs->refs;
2367 newrefs = 1;
2368 for (oldref = 1; oldref < addrs->numrefs; oldref++)
2369 {
2370 ObjectAddress *thisobj = addrs->refs + oldref;
2371
2372 if (priorobj->classId == thisobj->classId &&
2373 priorobj->objectId == thisobj->objectId)
2374 {
2375 if (priorobj->objectSubId == thisobj->objectSubId)
2376 continue; /* identical, so drop thisobj */
2377
2378 /*
2379 * If we have a whole-object reference and a reference to a part
2380 * of the same object, we don't need the whole-object reference
2381 * (for example, we don't need to reference both table foo and
2382 * column foo.bar). The whole-object reference will always appear
2383 * first in the sorted list.
2384 */
2385 if (priorobj->objectSubId == 0)
2386 {
2387 /* replace whole ref with partial */
2388 priorobj->objectSubId = thisobj->objectSubId;
2389 continue;
2390 }
2391 }
2392 /* Not identical, so add thisobj to output set */
2393 priorobj++;
2394 *priorobj = *thisobj;
2395 newrefs++;
2396 }
2397
2398 addrs->numrefs = newrefs;
2399 }
2400
2401 /*
2402 * qsort comparator for ObjectAddress items
2403 */
2404 static int
object_address_comparator(const void * a,const void * b)2405 object_address_comparator(const void *a, const void *b)
2406 {
2407 const ObjectAddress *obja = (const ObjectAddress *) a;
2408 const ObjectAddress *objb = (const ObjectAddress *) b;
2409
2410 /*
2411 * Primary sort key is OID descending. Most of the time, this will result
2412 * in putting newer objects before older ones, which is likely to be the
2413 * right order to delete in.
2414 */
2415 if (obja->objectId > objb->objectId)
2416 return -1;
2417 if (obja->objectId < objb->objectId)
2418 return 1;
2419
2420 /*
2421 * Next sort on catalog ID, in case identical OIDs appear in different
2422 * catalogs. Sort direction is pretty arbitrary here.
2423 */
2424 if (obja->classId < objb->classId)
2425 return -1;
2426 if (obja->classId > objb->classId)
2427 return 1;
2428
2429 /*
2430 * Last, sort on object subId.
2431 *
2432 * We sort the subId as an unsigned int so that 0 (the whole object) will
2433 * come first. This is essential for eliminate_duplicate_dependencies,
2434 * and is also the best order for findDependentObjects.
2435 */
2436 if ((unsigned int) obja->objectSubId < (unsigned int) objb->objectSubId)
2437 return -1;
2438 if ((unsigned int) obja->objectSubId > (unsigned int) objb->objectSubId)
2439 return 1;
2440 return 0;
2441 }
2442
2443 /*
2444 * Routines for handling an expansible array of ObjectAddress items.
2445 *
2446 * new_object_addresses: create a new ObjectAddresses array.
2447 */
2448 ObjectAddresses *
new_object_addresses(void)2449 new_object_addresses(void)
2450 {
2451 ObjectAddresses *addrs;
2452
2453 addrs = palloc(sizeof(ObjectAddresses));
2454
2455 addrs->numrefs = 0;
2456 addrs->maxrefs = 32;
2457 addrs->refs = (ObjectAddress *)
2458 palloc(addrs->maxrefs * sizeof(ObjectAddress));
2459 addrs->extras = NULL; /* until/unless needed */
2460
2461 return addrs;
2462 }
2463
2464 /*
2465 * Add an entry to an ObjectAddresses array.
2466 *
2467 * It is convenient to specify the class by ObjectClass rather than directly
2468 * by catalog OID.
2469 */
2470 static void
add_object_address(ObjectClass oclass,Oid objectId,int32 subId,ObjectAddresses * addrs)2471 add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
2472 ObjectAddresses *addrs)
2473 {
2474 ObjectAddress *item;
2475
2476 /*
2477 * Make sure object_classes is kept up to date with the ObjectClass enum.
2478 */
2479 StaticAssertStmt(lengthof(object_classes) == LAST_OCLASS + 1,
2480 "object_classes[] must cover all ObjectClasses");
2481
2482 /* enlarge array if needed */
2483 if (addrs->numrefs >= addrs->maxrefs)
2484 {
2485 addrs->maxrefs *= 2;
2486 addrs->refs = (ObjectAddress *)
2487 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2488 Assert(!addrs->extras);
2489 }
2490 /* record this item */
2491 item = addrs->refs + addrs->numrefs;
2492 item->classId = object_classes[oclass];
2493 item->objectId = objectId;
2494 item->objectSubId = subId;
2495 addrs->numrefs++;
2496 }
2497
2498 /*
2499 * Add an entry to an ObjectAddresses array.
2500 *
2501 * As above, but specify entry exactly.
2502 */
2503 void
add_exact_object_address(const ObjectAddress * object,ObjectAddresses * addrs)2504 add_exact_object_address(const ObjectAddress *object,
2505 ObjectAddresses *addrs)
2506 {
2507 ObjectAddress *item;
2508
2509 /* enlarge array if needed */
2510 if (addrs->numrefs >= addrs->maxrefs)
2511 {
2512 addrs->maxrefs *= 2;
2513 addrs->refs = (ObjectAddress *)
2514 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2515 Assert(!addrs->extras);
2516 }
2517 /* record this item */
2518 item = addrs->refs + addrs->numrefs;
2519 *item = *object;
2520 addrs->numrefs++;
2521 }
2522
2523 /*
2524 * Add an entry to an ObjectAddresses array.
2525 *
2526 * As above, but specify entry exactly and provide some "extra" data too.
2527 */
2528 static void
add_exact_object_address_extra(const ObjectAddress * object,const ObjectAddressExtra * extra,ObjectAddresses * addrs)2529 add_exact_object_address_extra(const ObjectAddress *object,
2530 const ObjectAddressExtra *extra,
2531 ObjectAddresses *addrs)
2532 {
2533 ObjectAddress *item;
2534 ObjectAddressExtra *itemextra;
2535
2536 /* allocate extra space if first time */
2537 if (!addrs->extras)
2538 addrs->extras = (ObjectAddressExtra *)
2539 palloc(addrs->maxrefs * sizeof(ObjectAddressExtra));
2540
2541 /* enlarge array if needed */
2542 if (addrs->numrefs >= addrs->maxrefs)
2543 {
2544 addrs->maxrefs *= 2;
2545 addrs->refs = (ObjectAddress *)
2546 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
2547 addrs->extras = (ObjectAddressExtra *)
2548 repalloc(addrs->extras, addrs->maxrefs * sizeof(ObjectAddressExtra));
2549 }
2550 /* record this item */
2551 item = addrs->refs + addrs->numrefs;
2552 *item = *object;
2553 itemextra = addrs->extras + addrs->numrefs;
2554 *itemextra = *extra;
2555 addrs->numrefs++;
2556 }
2557
2558 /*
2559 * Test whether an object is present in an ObjectAddresses array.
2560 *
2561 * We return "true" if object is a subobject of something in the array, too.
2562 */
2563 bool
object_address_present(const ObjectAddress * object,const ObjectAddresses * addrs)2564 object_address_present(const ObjectAddress *object,
2565 const ObjectAddresses *addrs)
2566 {
2567 int i;
2568
2569 for (i = addrs->numrefs - 1; i >= 0; i--)
2570 {
2571 const ObjectAddress *thisobj = addrs->refs + i;
2572
2573 if (object->classId == thisobj->classId &&
2574 object->objectId == thisobj->objectId)
2575 {
2576 if (object->objectSubId == thisobj->objectSubId ||
2577 thisobj->objectSubId == 0)
2578 return true;
2579 }
2580 }
2581
2582 return false;
2583 }
2584
2585 /*
2586 * As above, except that if the object is present then also OR the given
2587 * flags into its associated extra data (which must exist).
2588 */
2589 static bool
object_address_present_add_flags(const ObjectAddress * object,int flags,ObjectAddresses * addrs)2590 object_address_present_add_flags(const ObjectAddress *object,
2591 int flags,
2592 ObjectAddresses *addrs)
2593 {
2594 bool result = false;
2595 int i;
2596
2597 for (i = addrs->numrefs - 1; i >= 0; i--)
2598 {
2599 ObjectAddress *thisobj = addrs->refs + i;
2600
2601 if (object->classId == thisobj->classId &&
2602 object->objectId == thisobj->objectId)
2603 {
2604 if (object->objectSubId == thisobj->objectSubId)
2605 {
2606 ObjectAddressExtra *thisextra = addrs->extras + i;
2607
2608 thisextra->flags |= flags;
2609 result = true;
2610 }
2611 else if (thisobj->objectSubId == 0)
2612 {
2613 /*
2614 * We get here if we find a need to delete a column after
2615 * having already decided to drop its whole table. Obviously
2616 * we no longer need to drop the subobject, so report that we
2617 * found the subobject in the array. But don't plaster its
2618 * flags on the whole object.
2619 */
2620 result = true;
2621 }
2622 else if (object->objectSubId == 0)
2623 {
2624 /*
2625 * We get here if we find a need to delete a whole table after
2626 * having already decided to drop one of its columns. We
2627 * can't report that the whole object is in the array, but we
2628 * should mark the subobject with the whole object's flags.
2629 *
2630 * It might seem attractive to physically delete the column's
2631 * array entry, or at least mark it as no longer needing
2632 * separate deletion. But that could lead to, e.g., dropping
2633 * the column's datatype before we drop the table, which does
2634 * not seem like a good idea. This is a very rare situation
2635 * in practice, so we just take the hit of doing a separate
2636 * DROP COLUMN action even though we know we're gonna delete
2637 * the table later.
2638 *
2639 * What we can do, though, is mark this as a subobject so that
2640 * we don't report it separately, which is confusing because
2641 * it's unpredictable whether it happens or not. But do so
2642 * only if flags != 0 (flags == 0 is a read-only probe).
2643 *
2644 * Because there could be other subobjects of this object in
2645 * the array, this case means we always have to loop through
2646 * the whole array; we cannot exit early on a match.
2647 */
2648 ObjectAddressExtra *thisextra = addrs->extras + i;
2649
2650 if (flags)
2651 thisextra->flags |= (flags | DEPFLAG_SUBOBJECT);
2652 }
2653 }
2654 }
2655
2656 return result;
2657 }
2658
2659 /*
2660 * Similar to above, except we search an ObjectAddressStack.
2661 */
2662 static bool
stack_address_present_add_flags(const ObjectAddress * object,int flags,ObjectAddressStack * stack)2663 stack_address_present_add_flags(const ObjectAddress *object,
2664 int flags,
2665 ObjectAddressStack *stack)
2666 {
2667 bool result = false;
2668 ObjectAddressStack *stackptr;
2669
2670 for (stackptr = stack; stackptr; stackptr = stackptr->next)
2671 {
2672 const ObjectAddress *thisobj = stackptr->object;
2673
2674 if (object->classId == thisobj->classId &&
2675 object->objectId == thisobj->objectId)
2676 {
2677 if (object->objectSubId == thisobj->objectSubId)
2678 {
2679 stackptr->flags |= flags;
2680 result = true;
2681 }
2682 else if (thisobj->objectSubId == 0)
2683 {
2684 /*
2685 * We're visiting a column with whole table already on stack.
2686 * As in object_address_present_add_flags(), we can skip
2687 * further processing of the subobject, but we don't want to
2688 * propagate flags for the subobject to the whole object.
2689 */
2690 result = true;
2691 }
2692 else if (object->objectSubId == 0)
2693 {
2694 /*
2695 * We're visiting a table with column already on stack. As in
2696 * object_address_present_add_flags(), we should propagate
2697 * flags for the whole object to each of its subobjects.
2698 */
2699 if (flags)
2700 stackptr->flags |= (flags | DEPFLAG_SUBOBJECT);
2701 }
2702 }
2703 }
2704
2705 return result;
2706 }
2707
2708 /*
2709 * Record multiple dependencies from an ObjectAddresses array, after first
2710 * removing any duplicates.
2711 */
2712 void
record_object_address_dependencies(const ObjectAddress * depender,ObjectAddresses * referenced,DependencyType behavior)2713 record_object_address_dependencies(const ObjectAddress *depender,
2714 ObjectAddresses *referenced,
2715 DependencyType behavior)
2716 {
2717 eliminate_duplicate_dependencies(referenced);
2718 recordMultipleDependencies(depender,
2719 referenced->refs, referenced->numrefs,
2720 behavior);
2721 }
2722
2723 /*
2724 * Sort the items in an ObjectAddresses array.
2725 *
2726 * The major sort key is OID-descending, so that newer objects will be listed
2727 * first in most cases. This is primarily useful for ensuring stable outputs
2728 * from regression tests; it's not recommended if the order of the objects is
2729 * determined by user input, such as the order of targets in a DROP command.
2730 */
2731 void
sort_object_addresses(ObjectAddresses * addrs)2732 sort_object_addresses(ObjectAddresses *addrs)
2733 {
2734 if (addrs->numrefs > 1)
2735 qsort((void *) addrs->refs, addrs->numrefs,
2736 sizeof(ObjectAddress),
2737 object_address_comparator);
2738 }
2739
2740 /*
2741 * Clean up when done with an ObjectAddresses array.
2742 */
2743 void
free_object_addresses(ObjectAddresses * addrs)2744 free_object_addresses(ObjectAddresses *addrs)
2745 {
2746 pfree(addrs->refs);
2747 if (addrs->extras)
2748 pfree(addrs->extras);
2749 pfree(addrs);
2750 }
2751
2752 /*
2753 * Determine the class of a given object identified by objectAddress.
2754 *
2755 * This function is essentially the reverse mapping for the object_classes[]
2756 * table. We implement it as a function because the OIDs aren't consecutive.
2757 */
2758 ObjectClass
getObjectClass(const ObjectAddress * object)2759 getObjectClass(const ObjectAddress *object)
2760 {
2761 /* only pg_class entries can have nonzero objectSubId */
2762 if (object->classId != RelationRelationId &&
2763 object->objectSubId != 0)
2764 elog(ERROR, "invalid non-zero objectSubId for object class %u",
2765 object->classId);
2766
2767 switch (object->classId)
2768 {
2769 case RelationRelationId:
2770 /* caller must check objectSubId */
2771 return OCLASS_CLASS;
2772
2773 case ProcedureRelationId:
2774 return OCLASS_PROC;
2775
2776 case TypeRelationId:
2777 return OCLASS_TYPE;
2778
2779 case CastRelationId:
2780 return OCLASS_CAST;
2781
2782 case CollationRelationId:
2783 return OCLASS_COLLATION;
2784
2785 case ConstraintRelationId:
2786 return OCLASS_CONSTRAINT;
2787
2788 case ConversionRelationId:
2789 return OCLASS_CONVERSION;
2790
2791 case AttrDefaultRelationId:
2792 return OCLASS_DEFAULT;
2793
2794 case LanguageRelationId:
2795 return OCLASS_LANGUAGE;
2796
2797 case LargeObjectRelationId:
2798 return OCLASS_LARGEOBJECT;
2799
2800 case OperatorRelationId:
2801 return OCLASS_OPERATOR;
2802
2803 case OperatorClassRelationId:
2804 return OCLASS_OPCLASS;
2805
2806 case OperatorFamilyRelationId:
2807 return OCLASS_OPFAMILY;
2808
2809 case AccessMethodRelationId:
2810 return OCLASS_AM;
2811
2812 case AccessMethodOperatorRelationId:
2813 return OCLASS_AMOP;
2814
2815 case AccessMethodProcedureRelationId:
2816 return OCLASS_AMPROC;
2817
2818 case RewriteRelationId:
2819 return OCLASS_REWRITE;
2820
2821 case TriggerRelationId:
2822 return OCLASS_TRIGGER;
2823
2824 case NamespaceRelationId:
2825 return OCLASS_SCHEMA;
2826
2827 case StatisticExtRelationId:
2828 return OCLASS_STATISTIC_EXT;
2829
2830 case TSParserRelationId:
2831 return OCLASS_TSPARSER;
2832
2833 case TSDictionaryRelationId:
2834 return OCLASS_TSDICT;
2835
2836 case TSTemplateRelationId:
2837 return OCLASS_TSTEMPLATE;
2838
2839 case TSConfigRelationId:
2840 return OCLASS_TSCONFIG;
2841
2842 case AuthIdRelationId:
2843 return OCLASS_ROLE;
2844
2845 case DatabaseRelationId:
2846 return OCLASS_DATABASE;
2847
2848 case TableSpaceRelationId:
2849 return OCLASS_TBLSPACE;
2850
2851 case ForeignDataWrapperRelationId:
2852 return OCLASS_FDW;
2853
2854 case ForeignServerRelationId:
2855 return OCLASS_FOREIGN_SERVER;
2856
2857 case UserMappingRelationId:
2858 return OCLASS_USER_MAPPING;
2859
2860 case DefaultAclRelationId:
2861 return OCLASS_DEFACL;
2862
2863 case ExtensionRelationId:
2864 return OCLASS_EXTENSION;
2865
2866 case EventTriggerRelationId:
2867 return OCLASS_EVENT_TRIGGER;
2868
2869 case PolicyRelationId:
2870 return OCLASS_POLICY;
2871
2872 case PublicationRelationId:
2873 return OCLASS_PUBLICATION;
2874
2875 case PublicationRelRelationId:
2876 return OCLASS_PUBLICATION_REL;
2877
2878 case SubscriptionRelationId:
2879 return OCLASS_SUBSCRIPTION;
2880
2881 case TransformRelationId:
2882 return OCLASS_TRANSFORM;
2883 }
2884
2885 /* shouldn't get here */
2886 elog(ERROR, "unrecognized object class: %u", object->classId);
2887 return OCLASS_CLASS; /* keep compiler quiet */
2888 }
2889
2890 /*
2891 * delete initial ACL for extension objects
2892 */
2893 static void
DeleteInitPrivs(const ObjectAddress * object)2894 DeleteInitPrivs(const ObjectAddress *object)
2895 {
2896 Relation relation;
2897 ScanKeyData key[3];
2898 SysScanDesc scan;
2899 HeapTuple oldtuple;
2900
2901 relation = table_open(InitPrivsRelationId, RowExclusiveLock);
2902
2903 ScanKeyInit(&key[0],
2904 Anum_pg_init_privs_objoid,
2905 BTEqualStrategyNumber, F_OIDEQ,
2906 ObjectIdGetDatum(object->objectId));
2907 ScanKeyInit(&key[1],
2908 Anum_pg_init_privs_classoid,
2909 BTEqualStrategyNumber, F_OIDEQ,
2910 ObjectIdGetDatum(object->classId));
2911 ScanKeyInit(&key[2],
2912 Anum_pg_init_privs_objsubid,
2913 BTEqualStrategyNumber, F_INT4EQ,
2914 Int32GetDatum(object->objectSubId));
2915
2916 scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
2917 NULL, 3, key);
2918
2919 while (HeapTupleIsValid(oldtuple = systable_getnext(scan)))
2920 CatalogTupleDelete(relation, &oldtuple->t_self);
2921
2922 systable_endscan(scan);
2923
2924 table_close(relation, RowExclusiveLock);
2925 }
2926