Coverage Report

Created: 2025-07-03 06:49

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