@@ -168,14 +168,15 @@ static const Oid object_classes[] = {
168168
169169
170170static void findDependentObjects (const ObjectAddress * object ,
171+ int objflags ,
171172 int flags ,
172173 ObjectAddressStack * stack ,
173174 ObjectAddresses * targetObjects ,
174175 const ObjectAddresses * pendingObjects ,
175176 Relation * depRel );
176177static void reportDependentObjects (const ObjectAddresses * targetObjects ,
177178 DropBehavior behavior ,
178- int msglevel ,
179+ int flags ,
179180 const ObjectAddress * origObject );
180181static void deleteOneObject (const ObjectAddress * object ,
181182 Relation * depRel , int32 flags );
@@ -237,11 +238,17 @@ deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel,
237238 }
238239
239240 /*
240- * Delete all the objects in the proper order.
241+ * Delete all the objects in the proper order, except that if told to, we
242+ * should skip the original object(s).
241243 */
242244 for (i = 0 ; i < targetObjects -> numrefs ; i ++ )
243245 {
244246 ObjectAddress * thisobj = targetObjects -> refs + i ;
247+ ObjectAddressExtra * thisextra = targetObjects -> extras + i ;
248+
249+ if ((flags & PERFORM_DELETION_SKIP_ORIGINAL ) &&
250+ (thisextra -> flags & DEPFLAG_ORIGINAL ))
251+ continue ;
245252
246253 deleteOneObject (thisobj , depRel , flags );
247254 }
@@ -255,16 +262,32 @@ deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel,
255262 * according to the dependency type.
256263 *
257264 * This is the outer control routine for all forms of DROP that drop objects
258- * that can participate in dependencies. Note that the next two routines
259- * are variants on the same theme; if you change anything here you'll likely
260- * need to fix them too.
265+ * that can participate in dependencies. Note that performMultipleDeletions
266+ * is a variant on the same theme; if you change anything here you'll likely
267+ * need to fix that too.
268+ *
269+ * Bits in the flags argument can include:
270+ *
271+ * PERFORM_DELETION_INTERNAL: indicates that the drop operation is not the
272+ * direct result of a user-initiated action. For example, when a temporary
273+ * schema is cleaned out so that a new backend can use it, or when a column
274+ * default is dropped as an intermediate step while adding a new one, that's
275+ * an internal operation. On the other hand, when we drop something because
276+ * the user issued a DROP statement against it, that's not internal. Currently
277+ * this suppresses calling event triggers and making some permissions checks.
261278 *
262- * flags should include PERFORM_DELETION_INTERNAL when the drop operation is
263- * not the direct result of a user-initiated action. For example, when a
264- * temporary schema is cleaned out so that a new backend can use it, or when
265- * a column default is dropped as an intermediate step while adding a new one,
266- * that's an internal operation. On the other hand, when we drop something
267- * because the user issued a DROP statement against it, that's not internal.
279+ * PERFORM_DELETION_CONCURRENTLY: perform the drop concurrently. This does
280+ * not currently work for anything except dropping indexes; don't set it for
281+ * other object types or you may get strange results.
282+ *
283+ * PERFORM_DELETION_QUIETLY: reduce message level from NOTICE to DEBUG2.
284+ *
285+ * PERFORM_DELETION_SKIP_ORIGINAL: do not delete the specified object(s),
286+ * but only what depends on it/them.
287+ *
288+ * PERFORM_DELETION_SKIP_EXTENSIONS: do not delete extensions, even when
289+ * deleting objects that are part of an extension. This should generally
290+ * be used only when dropping temporary objects.
268291 */
269292void
270293performDeletion (const ObjectAddress * object ,
@@ -293,6 +316,7 @@ performDeletion(const ObjectAddress *object,
293316
294317 findDependentObjects (object ,
295318 DEPFLAG_ORIGINAL ,
319+ flags ,
296320 NULL , /* empty stack */
297321 targetObjects ,
298322 NULL , /* no pendingObjects */
@@ -303,7 +327,7 @@ performDeletion(const ObjectAddress *object,
303327 */
304328 reportDependentObjects (targetObjects ,
305329 behavior ,
306- NOTICE ,
330+ flags ,
307331 object );
308332
309333 /* do the deed */
@@ -364,6 +388,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
364388
365389 findDependentObjects (thisobj ,
366390 DEPFLAG_ORIGINAL ,
391+ flags ,
367392 NULL , /* empty stack */
368393 targetObjects ,
369394 objects ,
@@ -378,7 +403,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
378403 */
379404 reportDependentObjects (targetObjects ,
380405 behavior ,
381- NOTICE ,
406+ flags ,
382407 (objects -> numrefs == 1 ? objects -> refs : NULL ));
383408
384409 /* do the deed */
@@ -390,88 +415,6 @@ performMultipleDeletions(const ObjectAddresses *objects,
390415 heap_close (depRel , RowExclusiveLock );
391416}
392417
393- /*
394- * deleteWhatDependsOn: attempt to drop everything that depends on the
395- * specified object, though not the object itself. Behavior is always
396- * CASCADE.
397- *
398- * This is currently used only to clean out the contents of a schema
399- * (namespace): the passed object is a namespace. We normally want this
400- * to be done silently, so there's an option to suppress NOTICE messages.
401- *
402- * Note we don't fire object drop event triggers here; it would be wrong to do
403- * so for the current only use of this function, but if more callers are added
404- * this might need to be reconsidered.
405- */
406- void
407- deleteWhatDependsOn (const ObjectAddress * object ,
408- bool showNotices )
409- {
410- Relation depRel ;
411- ObjectAddresses * targetObjects ;
412- int i ;
413-
414- /*
415- * We save some cycles by opening pg_depend just once and passing the
416- * Relation pointer down to all the recursive deletion steps.
417- */
418- depRel = heap_open (DependRelationId , RowExclusiveLock );
419-
420- /*
421- * Acquire deletion lock on the target object. (Ideally the caller has
422- * done this already, but many places are sloppy about it.)
423- */
424- AcquireDeletionLock (object , 0 );
425-
426- /*
427- * Construct a list of objects to delete (ie, the given object plus
428- * everything directly or indirectly dependent on it).
429- */
430- targetObjects = new_object_addresses ();
431-
432- findDependentObjects (object ,
433- DEPFLAG_ORIGINAL ,
434- NULL , /* empty stack */
435- targetObjects ,
436- NULL , /* no pendingObjects */
437- & depRel );
438-
439- /*
440- * Check if deletion is allowed, and report about cascaded deletes.
441- */
442- reportDependentObjects (targetObjects ,
443- DROP_CASCADE ,
444- showNotices ? NOTICE : DEBUG2 ,
445- object );
446-
447- /*
448- * Delete all the objects in the proper order, except we skip the original
449- * object.
450- */
451- for (i = 0 ; i < targetObjects -> numrefs ; i ++ )
452- {
453- ObjectAddress * thisobj = targetObjects -> refs + i ;
454- ObjectAddressExtra * thisextra = targetObjects -> extras + i ;
455-
456- if (thisextra -> flags & DEPFLAG_ORIGINAL )
457- continue ;
458-
459- /*
460- * Since this function is currently only used to clean out temporary
461- * schemas, we pass PERFORM_DELETION_INTERNAL here, indicating that
462- * the operation is an automatic system operation rather than a user
463- * action. If, in the future, this function is used for other
464- * purposes, we might need to revisit this.
465- */
466- deleteOneObject (thisobj , & depRel , PERFORM_DELETION_INTERNAL );
467- }
468-
469- /* And clean up */
470- free_object_addresses (targetObjects );
471-
472- heap_close (depRel , RowExclusiveLock );
473- }
474-
475418/*
476419 * findDependentObjects - find all objects that depend on 'object'
477420 *
@@ -492,16 +435,22 @@ deleteWhatDependsOn(const ObjectAddress *object,
492435 * its sub-objects too.
493436 *
494437 * object: the object to add to targetObjects and find dependencies on
495- * flags: flags to be ORed into the object's targetObjects entry
438+ * objflags: flags to be ORed into the object's targetObjects entry
439+ * flags: PERFORM_DELETION_xxx flags for the deletion operation as a whole
496440 * stack: list of objects being visited in current recursion; topmost item
497441 * is the object that we recursed from (NULL for external callers)
498442 * targetObjects: list of objects that are scheduled to be deleted
499443 * pendingObjects: list of other objects slated for destruction, but
500444 * not necessarily in targetObjects yet (can be NULL if none)
501445 * *depRel: already opened pg_depend relation
446+ *
447+ * Note: objflags describes the reason for visiting this particular object
448+ * at this time, and is not passed down when recursing. The flags argument
449+ * is passed down, since it describes what we're doing overall.
502450 */
503451static void
504452findDependentObjects (const ObjectAddress * object ,
453+ int objflags ,
505454 int flags ,
506455 ObjectAddressStack * stack ,
507456 ObjectAddresses * targetObjects ,
@@ -518,8 +467,8 @@ findDependentObjects(const ObjectAddress *object,
518467
519468 /*
520469 * If the target object is already being visited in an outer recursion
521- * level, just report the current flags back to that level and exit. This
522- * is needed to avoid infinite recursion in the face of circular
470+ * level, just report the current objflags back to that level and exit.
471+ * This is needed to avoid infinite recursion in the face of circular
523472 * dependencies.
524473 *
525474 * The stack check alone would result in dependency loops being broken at
@@ -532,19 +481,19 @@ findDependentObjects(const ObjectAddress *object,
532481 * auto dependency, too, if we had to. However there are no known cases
533482 * where that would be necessary.
534483 */
535- if (stack_address_present_add_flags (object , flags , stack ))
484+ if (stack_address_present_add_flags (object , objflags , stack ))
536485 return ;
537486
538487 /*
539488 * It's also possible that the target object has already been completely
540489 * processed and put into targetObjects. If so, again we just add the
541- * specified flags to its entry and return.
490+ * specified objflags to its entry and return.
542491 *
543492 * (Note: in these early-exit cases we could release the caller-taken
544493 * lock, since the object is presumably now locked multiple times; but it
545494 * seems not worth the cycles.)
546495 */
547- if (object_address_present_add_flags (object , flags , targetObjects ))
496+ if (object_address_present_add_flags (object , objflags , targetObjects ))
548497 return ;
549498
550499 /*
@@ -597,6 +546,15 @@ findDependentObjects(const ObjectAddress *object,
597546
598547 case DEPENDENCY_EXTENSION :
599548
549+ /*
550+ * If told to, ignore EXTENSION dependencies altogether. This
551+ * flag is normally used to prevent dropping extensions during
552+ * temporary-object cleanup, even if a temp object was created
553+ * during an extension script.
554+ */
555+ if (flags & PERFORM_DELETION_SKIP_EXTENSIONS )
556+ break ;
557+
600558 /*
601559 * If the other object is the extension currently being
602560 * created/altered, ignore this dependency and continue with
@@ -699,6 +657,7 @@ findDependentObjects(const ObjectAddress *object,
699657 */
700658 findDependentObjects (& otherObject ,
701659 DEPFLAG_REVERSE ,
660+ flags ,
702661 stack ,
703662 targetObjects ,
704663 pendingObjects ,
@@ -729,7 +688,7 @@ findDependentObjects(const ObjectAddress *object,
729688 * they have to be deleted before the current object.
730689 */
731690 mystack .object = object ; /* set up a new stack level */
732- mystack .flags = flags ;
691+ mystack .flags = objflags ;
733692 mystack .next = stack ;
734693
735694 ScanKeyInit (& key [0 ],
@@ -783,7 +742,7 @@ findDependentObjects(const ObjectAddress *object,
783742 continue ;
784743 }
785744
786- /* Recurse, passing flags indicating the dependency type */
745+ /* Recurse, passing objflags indicating the dependency type */
787746 switch (foundDep -> deptype )
788747 {
789748 case DEPENDENCY_NORMAL :
@@ -820,6 +779,7 @@ findDependentObjects(const ObjectAddress *object,
820779
821780 findDependentObjects (& otherObject ,
822781 subflags ,
782+ flags ,
823783 & mystack ,
824784 targetObjects ,
825785 pendingObjects ,
@@ -850,16 +810,17 @@ findDependentObjects(const ObjectAddress *object,
850810 *
851811 * targetObjects: list of objects that are scheduled to be deleted
852812 * behavior: RESTRICT or CASCADE
853- * msglevel: elog level for non-error report messages
813+ * flags: other flags for the deletion operation
854814 * origObject: base object of deletion, or NULL if not available
855815 * (the latter case occurs in DROP OWNED)
856816 */
857817static void
858818reportDependentObjects (const ObjectAddresses * targetObjects ,
859819 DropBehavior behavior ,
860- int msglevel ,
820+ int flags ,
861821 const ObjectAddress * origObject )
862822{
823+ int msglevel = (flags & PERFORM_DELETION_QUIETLY ) ? DEBUG2 : NOTICE ;
863824 bool ok = true;
864825 StringInfoData clientdetail ;
865826 StringInfoData logdetail ;
@@ -1140,8 +1101,7 @@ doDeletion(const ObjectAddress *object, int flags)
11401101
11411102 if (relKind == RELKIND_INDEX )
11421103 {
1143- bool concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY )
1144- == PERFORM_DELETION_CONCURRENTLY );
1104+ bool concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY ) != 0 );
11451105
11461106 Assert (object -> objectSubId == 0 );
11471107 index_drop (object -> objectId , concurrent );
0 commit comments