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