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