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