]> granicus.if.org Git - postgresql/blob - src/backend/catalog/dependency.c
Disallow changing DEFAULT expression of a SERIAL column.
[postgresql] / src / backend / catalog / dependency.c
1 /*-------------------------------------------------------------------------
2  *
3  * dependency.c
4  *        Routines to support inter-object dependencies.
5  *
6  *
7  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.52 2006/04/29 16:43:54 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/genam.h"
18 #include "access/heapam.h"
19 #include "catalog/dependency.h"
20 #include "catalog/heap.h"
21 #include "catalog/index.h"
22 #include "catalog/indexing.h"
23 #include "catalog/namespace.h"
24 #include "catalog/pg_attrdef.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/pg_cast.h"
27 #include "catalog/pg_constraint.h"
28 #include "catalog/pg_conversion.h"
29 #include "catalog/pg_database.h"
30 #include "catalog/pg_depend.h"
31 #include "catalog/pg_language.h"
32 #include "catalog/pg_namespace.h"
33 #include "catalog/pg_opclass.h"
34 #include "catalog/pg_operator.h"
35 #include "catalog/pg_proc.h"
36 #include "catalog/pg_rewrite.h"
37 #include "catalog/pg_tablespace.h"
38 #include "catalog/pg_trigger.h"
39 #include "catalog/pg_type.h"
40 #include "commands/comment.h"
41 #include "commands/dbcommands.h"
42 #include "commands/defrem.h"
43 #include "commands/proclang.h"
44 #include "commands/schemacmds.h"
45 #include "commands/tablespace.h"
46 #include "commands/trigger.h"
47 #include "commands/typecmds.h"
48 #include "lib/stringinfo.h"
49 #include "miscadmin.h"
50 #include "optimizer/clauses.h"
51 #include "parser/parsetree.h"
52 #include "rewrite/rewriteRemove.h"
53 #include "utils/builtins.h"
54 #include "utils/fmgroids.h"
55 #include "utils/lsyscache.h"
56 #include "utils/syscache.h"
57
58
59 /* expansible list of ObjectAddresses */
60 typedef struct
61 {
62         ObjectAddress *refs;            /* => palloc'd array */
63         int                     numrefs;                /* current number of references */
64         int                     maxrefs;                /* current size of palloc'd array */
65 } ObjectAddresses;
66
67 /* for find_expr_references_walker */
68 typedef struct
69 {
70         ObjectAddresses addrs;          /* addresses being accumulated */
71         List       *rtables;            /* list of rangetables to resolve Vars */
72 } find_expr_references_context;
73
74 /*
75  * This constant table maps ObjectClasses to the corresponding catalog OIDs.
76  * See also getObjectClass().
77  */
78 static const Oid object_classes[MAX_OCLASS] = {
79         RelationRelationId,                     /* OCLASS_CLASS */
80         ProcedureRelationId,            /* OCLASS_PROC */
81         TypeRelationId,                         /* OCLASS_TYPE */
82         CastRelationId,                         /* OCLASS_CAST */
83         ConstraintRelationId,           /* OCLASS_CONSTRAINT */
84         ConversionRelationId,           /* OCLASS_CONVERSION */
85         AttrDefaultRelationId,          /* OCLASS_DEFAULT */
86         LanguageRelationId,                     /* OCLASS_LANGUAGE */
87         OperatorRelationId,                     /* OCLASS_OPERATOR */
88         OperatorClassRelationId,        /* OCLASS_OPCLASS */
89         RewriteRelationId,                      /* OCLASS_REWRITE */
90         TriggerRelationId,                      /* OCLASS_TRIGGER */
91         NamespaceRelationId                     /* OCLASS_SCHEMA */
92 };
93
94
95 static void findAutoDeletableObjects(const ObjectAddress *object,
96                                                  ObjectAddresses *oktodelete,
97                                                  Relation depRel);
98 static bool recursiveDeletion(const ObjectAddress *object,
99                                   DropBehavior behavior,
100                                   int msglevel,
101                                   const ObjectAddress *callingObject,
102                                   ObjectAddresses *oktodelete,
103                                   Relation depRel);
104 static bool deleteDependentObjects(const ObjectAddress *object,
105                                            const char *objDescription,
106                                            DropBehavior behavior,
107                                            int msglevel,
108                                            ObjectAddresses *oktodelete,
109                                            Relation depRel);
110 static void doDeletion(const ObjectAddress *object);
111 static bool find_expr_references_walker(Node *node,
112                                                         find_expr_references_context *context);
113 static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
114 static int      object_address_comparator(const void *a, const void *b);
115 static void init_object_addresses(ObjectAddresses *addrs);
116 static void add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
117                                    ObjectAddresses *addrs);
118 static void add_exact_object_address(const ObjectAddress *object,
119                                                  ObjectAddresses *addrs);
120 static bool object_address_present(const ObjectAddress *object,
121                                            ObjectAddresses *addrs);
122 static void term_object_addresses(ObjectAddresses *addrs);
123 static void getRelationDescription(StringInfo buffer, Oid relid);
124
125
126 /*
127  * performDeletion: attempt to drop the specified object.  If CASCADE
128  * behavior is specified, also drop any dependent objects (recursively).
129  * If RESTRICT behavior is specified, error out if there are any dependent
130  * objects, except for those that should be implicitly dropped anyway
131  * according to the dependency type.
132  *
133  * This is the outer control routine for all forms of DROP that drop objects
134  * that can participate in dependencies.
135  */
136 void
137 performDeletion(const ObjectAddress *object,
138                                 DropBehavior behavior)
139 {
140         char       *objDescription;
141         Relation        depRel;
142         ObjectAddresses oktodelete;
143
144         /*
145          * Get object description for possible use in failure message. Must do
146          * this before deleting it ...
147          */
148         objDescription = getObjectDescription(object);
149
150         /*
151          * We save some cycles by opening pg_depend just once and passing the
152          * Relation pointer down to all the recursive deletion steps.
153          */
154         depRel = heap_open(DependRelationId, RowExclusiveLock);
155
156         /*
157          * Construct a list of objects that are reachable by AUTO or INTERNAL
158          * dependencies from the target object.  These should be deleted silently,
159          * even if the actual deletion pass first reaches one of them via a
160          * non-auto dependency.
161          */
162         init_object_addresses(&oktodelete);
163
164         findAutoDeletableObjects(object, &oktodelete, depRel);
165
166         if (!recursiveDeletion(object, behavior, NOTICE,
167                                                    NULL, &oktodelete, depRel))
168                 ereport(ERROR,
169                                 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
170                                  errmsg("cannot drop %s because other objects depend on it",
171                                                 objDescription),
172                 errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
173
174         term_object_addresses(&oktodelete);
175
176         heap_close(depRel, RowExclusiveLock);
177
178         pfree(objDescription);
179 }
180
181
182 /*
183  * deleteWhatDependsOn: attempt to drop everything that depends on the
184  * specified object, though not the object itself.      Behavior is always
185  * CASCADE.
186  *
187  * This is currently used only to clean out the contents of a schema
188  * (namespace): the passed object is a namespace.  We normally want this
189  * to be done silently, so there's an option to suppress NOTICE messages.
190  */
191 void
192 deleteWhatDependsOn(const ObjectAddress *object,
193                                         bool showNotices)
194 {
195         char       *objDescription;
196         Relation        depRel;
197         ObjectAddresses oktodelete;
198
199         /*
200          * Get object description for possible use in failure messages
201          */
202         objDescription = getObjectDescription(object);
203
204         /*
205          * We save some cycles by opening pg_depend just once and passing the
206          * Relation pointer down to all the recursive deletion steps.
207          */
208         depRel = heap_open(DependRelationId, RowExclusiveLock);
209
210         /*
211          * Construct a list of objects that are reachable by AUTO or INTERNAL
212          * dependencies from the target object.  These should be deleted silently,
213          * even if the actual deletion pass first reaches one of them via a
214          * non-auto dependency.
215          */
216         init_object_addresses(&oktodelete);
217
218         findAutoDeletableObjects(object, &oktodelete, depRel);
219
220         /*
221          * Now invoke only step 2 of recursiveDeletion: just recurse to the stuff
222          * dependent on the given object.
223          */
224         if (!deleteDependentObjects(object, objDescription,
225                                                                 DROP_CASCADE,
226                                                                 showNotices ? NOTICE : DEBUG2,
227                                                                 &oktodelete, depRel))
228                 ereport(ERROR,
229                                 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
230                                  errmsg("failed to drop all objects depending on %s",
231                                                 objDescription)));
232
233         /*
234          * We do not need CommandCounterIncrement here, since if step 2 did
235          * anything then each recursive call will have ended with one.
236          */
237
238         term_object_addresses(&oktodelete);
239
240         heap_close(depRel, RowExclusiveLock);
241
242         pfree(objDescription);
243 }
244
245
246 /*
247  * findAutoDeletableObjects: find all objects that are reachable by AUTO or
248  * INTERNAL dependency paths from the given object.  Add them all to the
249  * oktodelete list.  Note that the originally given object will also be
250  * added to the list.
251  *
252  * depRel is the already-open pg_depend relation.
253  */
254 static void
255 findAutoDeletableObjects(const ObjectAddress *object,
256                                                  ObjectAddresses *oktodelete,
257                                                  Relation depRel)
258 {
259         ScanKeyData key[3];
260         int                     nkeys;
261         SysScanDesc scan;
262         HeapTuple       tup;
263         ObjectAddress otherObject;
264
265         /*
266          * If this object is already in oktodelete, then we already visited it;
267          * don't do so again (this prevents infinite recursion if there's a loop
268          * in pg_depend).  Otherwise, add it.
269          */
270         if (object_address_present(object, oktodelete))
271                 return;
272         add_exact_object_address(object, oktodelete);
273
274         /*
275          * Scan pg_depend records that link to this object, showing the things
276          * that depend on it.  For each one that is AUTO or INTERNAL, visit the
277          * referencing object.
278          *
279          * When dropping a whole object (subId = 0), find pg_depend records for
280          * its sub-objects too.
281          */
282         ScanKeyInit(&key[0],
283                                 Anum_pg_depend_refclassid,
284                                 BTEqualStrategyNumber, F_OIDEQ,
285                                 ObjectIdGetDatum(object->classId));
286         ScanKeyInit(&key[1],
287                                 Anum_pg_depend_refobjid,
288                                 BTEqualStrategyNumber, F_OIDEQ,
289                                 ObjectIdGetDatum(object->objectId));
290         if (object->objectSubId != 0)
291         {
292                 ScanKeyInit(&key[2],
293                                         Anum_pg_depend_refobjsubid,
294                                         BTEqualStrategyNumber, F_INT4EQ,
295                                         Int32GetDatum(object->objectSubId));
296                 nkeys = 3;
297         }
298         else
299                 nkeys = 2;
300
301         scan = systable_beginscan(depRel, DependReferenceIndexId, true,
302                                                           SnapshotNow, nkeys, key);
303
304         while (HeapTupleIsValid(tup = systable_getnext(scan)))
305         {
306                 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
307
308                 switch (foundDep->deptype)
309                 {
310                         case DEPENDENCY_NORMAL:
311                                 /* ignore */
312                                 break;
313                         case DEPENDENCY_AUTO:
314                         case DEPENDENCY_INTERNAL:
315                                 /* recurse */
316                                 otherObject.classId = foundDep->classid;
317                                 otherObject.objectId = foundDep->objid;
318                                 otherObject.objectSubId = foundDep->objsubid;
319                                 findAutoDeletableObjects(&otherObject, oktodelete, depRel);
320                                 break;
321                         case DEPENDENCY_PIN:
322
323                                 /*
324                                  * For a PIN dependency we just ereport immediately; there
325                                  * won't be any others to examine, and we aren't ever going to
326                                  * let the user delete it.
327                                  */
328                                 ereport(ERROR,
329                                                 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
330                                                  errmsg("cannot drop %s because it is required by the database system",
331                                                                 getObjectDescription(object))));
332                                 break;
333                         default:
334                                 elog(ERROR, "unrecognized dependency type '%c' for %s",
335                                          foundDep->deptype, getObjectDescription(object));
336                                 break;
337                 }
338         }
339
340         systable_endscan(scan);
341 }
342
343
344 /*
345  * recursiveDeletion: delete a single object for performDeletion, plus
346  * (recursively) anything that depends on it.
347  *
348  * Returns TRUE if successful, FALSE if not.
349  *
350  * callingObject is NULL at the outer level, else identifies the object that
351  * we recursed from (the reference object that someone else needs to delete).
352  *
353  * oktodelete is a list of objects verified deletable (ie, reachable by one
354  * or more AUTO or INTERNAL dependencies from the original target).
355  *
356  * depRel is the already-open pg_depend relation.
357  *
358  *
359  * In RESTRICT mode, we perform all the deletions anyway, but ereport a message
360  * and return FALSE if we find a restriction violation.  performDeletion
361  * will then abort the transaction to nullify the deletions.  We have to
362  * do it this way to (a) report all the direct and indirect dependencies
363  * while (b) not going into infinite recursion if there's a cycle.
364  *
365  * This is even more complex than one could wish, because it is possible for
366  * the same pair of objects to be related by both NORMAL and AUTO/INTERNAL
367  * dependencies.  Also, we might have a situation where we've been asked to
368  * delete object A, and objects B and C both have AUTO dependencies on A,
369  * but B also has a NORMAL dependency on C.  (Since any of these paths might
370  * be indirect, we can't prevent these scenarios, but must cope instead.)
371  * If we visit C before B then we would mistakenly decide that the B->C link
372  * should prevent the restricted drop from occurring.  To handle this, we make
373  * a pre-scan to find all the objects that are auto-deletable from A.  If we
374  * visit C first, but B is present in the oktodelete list, then we make no
375  * complaint but recurse to delete B anyway.  (Note that in general we must
376  * delete B before deleting C; the drop routine for B may try to access C.)
377  *
378  * Note: in the case where the path to B is traversed first, we will not
379  * see the NORMAL dependency when we reach C, because of the pg_depend
380  * removals done in step 1.  The oktodelete list is necessary just
381  * to make the behavior independent of the order in which pg_depend
382  * entries are visited.
383  */
384 static bool
385 recursiveDeletion(const ObjectAddress *object,
386                                   DropBehavior behavior,
387                                   int msglevel,
388                                   const ObjectAddress *callingObject,
389                                   ObjectAddresses *oktodelete,
390                                   Relation depRel)
391 {
392         bool            ok = true;
393         char       *objDescription;
394         ScanKeyData key[3];
395         int                     nkeys;
396         SysScanDesc scan;
397         HeapTuple       tup;
398         ObjectAddress otherObject;
399         ObjectAddress owningObject;
400         bool            amOwned = false;
401
402         /*
403          * Get object description for possible use in messages.  Must do this
404          * before deleting it ...
405          */
406         objDescription = getObjectDescription(object);
407
408         /*
409          * Step 1: find and remove pg_depend records that link from this object to
410          * others.      We have to do this anyway, and doing it first ensures that we
411          * avoid infinite recursion in the case of cycles. Also, some dependency
412          * types require extra processing here.
413          *
414          * When dropping a whole object (subId = 0), remove all pg_depend records
415          * for its sub-objects too.
416          */
417         ScanKeyInit(&key[0],
418                                 Anum_pg_depend_classid,
419                                 BTEqualStrategyNumber, F_OIDEQ,
420                                 ObjectIdGetDatum(object->classId));
421         ScanKeyInit(&key[1],
422                                 Anum_pg_depend_objid,
423                                 BTEqualStrategyNumber, F_OIDEQ,
424                                 ObjectIdGetDatum(object->objectId));
425         if (object->objectSubId != 0)
426         {
427                 ScanKeyInit(&key[2],
428                                         Anum_pg_depend_objsubid,
429                                         BTEqualStrategyNumber, F_INT4EQ,
430                                         Int32GetDatum(object->objectSubId));
431                 nkeys = 3;
432         }
433         else
434                 nkeys = 2;
435
436         scan = systable_beginscan(depRel, DependDependerIndexId, true,
437                                                           SnapshotNow, nkeys, key);
438
439         while (HeapTupleIsValid(tup = systable_getnext(scan)))
440         {
441                 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
442
443                 otherObject.classId = foundDep->refclassid;
444                 otherObject.objectId = foundDep->refobjid;
445                 otherObject.objectSubId = foundDep->refobjsubid;
446
447                 switch (foundDep->deptype)
448                 {
449                         case DEPENDENCY_NORMAL:
450                         case DEPENDENCY_AUTO:
451                                 /* no problem */
452                                 break;
453                         case DEPENDENCY_INTERNAL:
454
455                                 /*
456                                  * This object is part of the internal implementation of
457                                  * another object.      We have three cases:
458                                  *
459                                  * 1. At the outermost recursion level, disallow the DROP. (We
460                                  * just ereport here, rather than proceeding, since no other
461                                  * dependencies are likely to be interesting.)
462                                  */
463                                 if (callingObject == NULL)
464                                 {
465                                         char       *otherObjDesc = getObjectDescription(&otherObject);
466
467                                         ereport(ERROR,
468                                                         (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
469                                                          errmsg("cannot drop %s because %s requires it",
470                                                                         objDescription, otherObjDesc),
471                                                          errhint("You may drop %s instead.",
472                                                                          otherObjDesc)));
473                                 }
474
475                                 /*
476                                  * 2. When recursing from the other end of this dependency,
477                                  * it's okay to continue with the deletion. This holds when
478                                  * recursing from a whole object that includes the nominal
479                                  * other end as a component, too.
480                                  */
481                                 if (callingObject->classId == otherObject.classId &&
482                                         callingObject->objectId == otherObject.objectId &&
483                                         (callingObject->objectSubId == otherObject.objectSubId ||
484                                          callingObject->objectSubId == 0))
485                                         break;
486
487                                 /*
488                                  * 3. When recursing from anyplace else, transform this
489                                  * deletion request into a delete of the other object. (This
490                                  * will be an error condition iff RESTRICT mode.) In this case
491                                  * we finish deleting my dependencies except for the INTERNAL
492                                  * link, which will be needed to cause the owning object to
493                                  * recurse back to me.
494                                  */
495                                 if (amOwned)    /* shouldn't happen */
496                                         elog(ERROR, "multiple INTERNAL dependencies for %s",
497                                                  objDescription);
498                                 owningObject = otherObject;
499                                 amOwned = true;
500                                 /* "continue" bypasses the simple_heap_delete call below */
501                                 continue;
502                         case DEPENDENCY_PIN:
503
504                                 /*
505                                  * Should not happen; PIN dependencies should have zeroes in
506                                  * the depender fields...
507                                  */
508                                 elog(ERROR, "incorrect use of PIN dependency with %s",
509                                          objDescription);
510                                 break;
511                         default:
512                                 elog(ERROR, "unrecognized dependency type '%c' for %s",
513                                          foundDep->deptype, objDescription);
514                                 break;
515                 }
516
517                 /* delete the pg_depend tuple */
518                 simple_heap_delete(depRel, &tup->t_self);
519         }
520
521         systable_endscan(scan);
522
523         /*
524          * CommandCounterIncrement here to ensure that preceding changes are all
525          * visible; in particular, that the above deletions of pg_depend entries
526          * are visible.  That prevents infinite recursion in case of a dependency
527          * loop (which is perfectly legal).
528          */
529         CommandCounterIncrement();
530
531         /*
532          * If we found we are owned by another object, ask it to delete itself
533          * instead of proceeding.  Complain if RESTRICT mode, unless the other
534          * object is in oktodelete.
535          */
536         if (amOwned)
537         {
538                 if (object_address_present(&owningObject, oktodelete))
539                         ereport(DEBUG2,
540                                         (errmsg("drop auto-cascades to %s",
541                                                         getObjectDescription(&owningObject))));
542                 else if (behavior == DROP_RESTRICT)
543                 {
544                         ereport(msglevel,
545                                         (errmsg("%s depends on %s",
546                                                         getObjectDescription(&owningObject),
547                                                         objDescription)));
548                         ok = false;
549                 }
550                 else
551                         ereport(msglevel,
552                                         (errmsg("drop cascades to %s",
553                                                         getObjectDescription(&owningObject))));
554
555                 if (!recursiveDeletion(&owningObject, behavior, msglevel,
556                                                            object, oktodelete, depRel))
557                         ok = false;
558
559                 pfree(objDescription);
560
561                 return ok;
562         }
563
564         /*
565          * Step 2: scan pg_depend records that link to this object, showing the
566          * things that depend on it.  Recursively delete those things. Note it's
567          * important to delete the dependent objects before the referenced one,
568          * since the deletion routines might do things like try to update the
569          * pg_class record when deleting a check constraint.
570          */
571         if (!deleteDependentObjects(object, objDescription,
572                                                                 behavior, msglevel,
573                                                                 oktodelete, depRel))
574                 ok = false;
575
576         /*
577          * We do not need CommandCounterIncrement here, since if step 2 did
578          * anything then each recursive call will have ended with one.
579          */
580
581         /*
582          * Step 3: delete the object itself.
583          */
584         doDeletion(object);
585
586         /*
587          * Delete any comments associated with this object.  (This is a convenient
588          * place to do it instead of having every object type know to do it.)
589          */
590         DeleteComments(object->objectId, object->classId, object->objectSubId);
591
592         /*
593          * Delete shared dependency references related to this object. Sub-objects
594          * (columns) don't have dependencies on global objects, so skip them.
595          */
596         if (object->objectSubId == 0)
597                 deleteSharedDependencyRecordsFor(object->classId, object->objectId);
598
599         /*
600          * CommandCounterIncrement here to ensure that preceding changes are all
601          * visible.
602          */
603         CommandCounterIncrement();
604
605         /*
606          * And we're done!
607          */
608         pfree(objDescription);
609
610         return ok;
611 }
612
613
614 /*
615  * deleteDependentObjects - find and delete objects that depend on 'object'
616  *
617  * Scan pg_depend records that link to the given object, showing
618  * the things that depend on it.  Recursively delete those things. (We
619  * don't delete the pg_depend records here, as the recursive call will
620  * do that.)  Note it's important to delete the dependent objects
621  * before the referenced one, since the deletion routines might do
622  * things like try to update the pg_class record when deleting a check
623  * constraint.
624  *
625  * When dropping a whole object (subId = 0), find pg_depend records for
626  * its sub-objects too.
627  *
628  *      object: the object to find dependencies on
629  *      objDescription: description of object (only used for error messages)
630  *      behavior: desired drop behavior
631  *      oktodelete: stuff that's AUTO-deletable
632  *      depRel: already opened pg_depend relation
633  *
634  * Returns TRUE if all is well, false if any problem found.
635  *
636  * NOTE: because we are using SnapshotNow, if a recursive call deletes
637  * any pg_depend tuples that our scan hasn't yet visited, we will not
638  * see them as good when we do visit them.      This is essential for
639  * correct behavior if there are multiple dependency paths between two
640  * objects --- else we might try to delete an already-deleted object.
641  */
642 static bool
643 deleteDependentObjects(const ObjectAddress *object,
644                                            const char *objDescription,
645                                            DropBehavior behavior,
646                                            int msglevel,
647                                            ObjectAddresses *oktodelete,
648                                            Relation depRel)
649 {
650         bool            ok = true;
651         ScanKeyData key[3];
652         int                     nkeys;
653         SysScanDesc scan;
654         HeapTuple       tup;
655         ObjectAddress otherObject;
656
657         ScanKeyInit(&key[0],
658                                 Anum_pg_depend_refclassid,
659                                 BTEqualStrategyNumber, F_OIDEQ,
660                                 ObjectIdGetDatum(object->classId));
661         ScanKeyInit(&key[1],
662                                 Anum_pg_depend_refobjid,
663                                 BTEqualStrategyNumber, F_OIDEQ,
664                                 ObjectIdGetDatum(object->objectId));
665         if (object->objectSubId != 0)
666         {
667                 ScanKeyInit(&key[2],
668                                         Anum_pg_depend_refobjsubid,
669                                         BTEqualStrategyNumber, F_INT4EQ,
670                                         Int32GetDatum(object->objectSubId));
671                 nkeys = 3;
672         }
673         else
674                 nkeys = 2;
675
676         scan = systable_beginscan(depRel, DependReferenceIndexId, true,
677                                                           SnapshotNow, nkeys, key);
678
679         while (HeapTupleIsValid(tup = systable_getnext(scan)))
680         {
681                 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
682
683                 otherObject.classId = foundDep->classid;
684                 otherObject.objectId = foundDep->objid;
685                 otherObject.objectSubId = foundDep->objsubid;
686
687                 switch (foundDep->deptype)
688                 {
689                         case DEPENDENCY_NORMAL:
690
691                                 /*
692                                  * Perhaps there was another dependency path that would have
693                                  * allowed silent deletion of the otherObject, had we only
694                                  * taken that path first. In that case, act like this link is
695                                  * AUTO, too.
696                                  */
697                                 if (object_address_present(&otherObject, oktodelete))
698                                         ereport(DEBUG2,
699                                                         (errmsg("drop auto-cascades to %s",
700                                                                         getObjectDescription(&otherObject))));
701                                 else if (behavior == DROP_RESTRICT)
702                                 {
703                                         ereport(msglevel,
704                                                         (errmsg("%s depends on %s",
705                                                                         getObjectDescription(&otherObject),
706                                                                         objDescription)));
707                                         ok = false;
708                                 }
709                                 else
710                                         ereport(msglevel,
711                                                         (errmsg("drop cascades to %s",
712                                                                         getObjectDescription(&otherObject))));
713
714                                 if (!recursiveDeletion(&otherObject, behavior, msglevel,
715                                                                            object, oktodelete, depRel))
716                                         ok = false;
717                                 break;
718                         case DEPENDENCY_AUTO:
719                         case DEPENDENCY_INTERNAL:
720
721                                 /*
722                                  * We propagate the DROP without complaint even in the
723                                  * RESTRICT case.  (However, normal dependencies on the
724                                  * component object could still cause failure.)
725                                  */
726                                 ereport(DEBUG2,
727                                                 (errmsg("drop auto-cascades to %s",
728                                                                 getObjectDescription(&otherObject))));
729
730                                 if (!recursiveDeletion(&otherObject, behavior, msglevel,
731                                                                            object, oktodelete, depRel))
732                                         ok = false;
733                                 break;
734                         case DEPENDENCY_PIN:
735
736                                 /*
737                                  * For a PIN dependency we just ereport immediately; there
738                                  * won't be any others to report.
739                                  */
740                                 ereport(ERROR,
741                                                 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
742                                                  errmsg("cannot drop %s because it is required by the database system",
743                                                                 objDescription)));
744                                 break;
745                         default:
746                                 elog(ERROR, "unrecognized dependency type '%c' for %s",
747                                          foundDep->deptype, objDescription);
748                                 break;
749                 }
750         }
751
752         systable_endscan(scan);
753
754         return ok;
755 }
756
757
758 /*
759  * doDeletion: actually delete a single object
760  */
761 static void
762 doDeletion(const ObjectAddress *object)
763 {
764         switch (getObjectClass(object))
765         {
766                 case OCLASS_CLASS:
767                         {
768                                 char            relKind = get_rel_relkind(object->objectId);
769
770                                 if (relKind == RELKIND_INDEX)
771                                 {
772                                         Assert(object->objectSubId == 0);
773                                         index_drop(object->objectId);
774                                 }
775                                 else
776                                 {
777                                         if (object->objectSubId != 0)
778                                                 RemoveAttributeById(object->objectId,
779                                                                                         object->objectSubId);
780                                         else
781                                                 heap_drop_with_catalog(object->objectId);
782                                 }
783                                 break;
784                         }
785
786                 case OCLASS_PROC:
787                         RemoveFunctionById(object->objectId);
788                         break;
789
790                 case OCLASS_TYPE:
791                         RemoveTypeById(object->objectId);
792                         break;
793
794                 case OCLASS_CAST:
795                         DropCastById(object->objectId);
796                         break;
797
798                 case OCLASS_CONSTRAINT:
799                         RemoveConstraintById(object->objectId);
800                         break;
801
802                 case OCLASS_CONVERSION:
803                         RemoveConversionById(object->objectId);
804                         break;
805
806                 case OCLASS_DEFAULT:
807                         RemoveAttrDefaultById(object->objectId);
808                         break;
809
810                 case OCLASS_LANGUAGE:
811                         DropProceduralLanguageById(object->objectId);
812                         break;
813
814                 case OCLASS_OPERATOR:
815                         RemoveOperatorById(object->objectId);
816                         break;
817
818                 case OCLASS_OPCLASS:
819                         RemoveOpClassById(object->objectId);
820                         break;
821
822                 case OCLASS_REWRITE:
823                         RemoveRewriteRuleById(object->objectId);
824                         break;
825
826                 case OCLASS_TRIGGER:
827                         RemoveTriggerById(object->objectId);
828                         break;
829
830                 case OCLASS_SCHEMA:
831                         RemoveSchemaById(object->objectId);
832                         break;
833
834                 default:
835                         elog(ERROR, "unrecognized object class: %u",
836                                  object->classId);
837         }
838 }
839
840 /*
841  * recordDependencyOnExpr - find expression dependencies
842  *
843  * This is used to find the dependencies of rules, constraint expressions,
844  * etc.
845  *
846  * Given an expression or query in node-tree form, find all the objects
847  * it refers to (tables, columns, operators, functions, etc).  Record
848  * a dependency of the specified type from the given depender object
849  * to each object mentioned in the expression.
850  *
851  * rtable is the rangetable to be used to interpret Vars with varlevelsup=0.
852  * It can be NIL if no such variables are expected.
853  */
854 void
855 recordDependencyOnExpr(const ObjectAddress *depender,
856                                            Node *expr, List *rtable,
857                                            DependencyType behavior)
858 {
859         find_expr_references_context context;
860
861         init_object_addresses(&context.addrs);
862
863         /* Set up interpretation for Vars at varlevelsup = 0 */
864         context.rtables = list_make1(rtable);
865
866         /* Scan the expression tree for referenceable objects */
867         find_expr_references_walker(expr, &context);
868
869         /* Remove any duplicates */
870         eliminate_duplicate_dependencies(&context.addrs);
871
872         /* And record 'em */
873         recordMultipleDependencies(depender,
874                                                            context.addrs.refs, context.addrs.numrefs,
875                                                            behavior);
876
877         term_object_addresses(&context.addrs);
878 }
879
880 /*
881  * recordDependencyOnSingleRelExpr - find expression dependencies
882  *
883  * As above, but only one relation is expected to be referenced (with
884  * varno = 1 and varlevelsup = 0).      Pass the relation OID instead of a
885  * range table.  An additional frammish is that dependencies on that
886  * relation (or its component columns) will be marked with 'self_behavior',
887  * whereas 'behavior' is used for everything else.
888  */
889 void
890 recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
891                                                                 Node *expr, Oid relId,
892                                                                 DependencyType behavior,
893                                                                 DependencyType self_behavior)
894 {
895         find_expr_references_context context;
896         RangeTblEntry rte;
897
898         init_object_addresses(&context.addrs);
899
900         /* We gin up a rather bogus rangetable list to handle Vars */
901         MemSet(&rte, 0, sizeof(rte));
902         rte.type = T_RangeTblEntry;
903         rte.rtekind = RTE_RELATION;
904         rte.relid = relId;
905
906         context.rtables = list_make1(list_make1(&rte));
907
908         /* Scan the expression tree for referenceable objects */
909         find_expr_references_walker(expr, &context);
910
911         /* Remove any duplicates */
912         eliminate_duplicate_dependencies(&context.addrs);
913
914         /* Separate self-dependencies if necessary */
915         if (behavior != self_behavior && context.addrs.numrefs > 0)
916         {
917                 ObjectAddresses self_addrs;
918                 ObjectAddress *outobj;
919                 int                     oldref,
920                                         outrefs;
921
922                 init_object_addresses(&self_addrs);
923
924                 outobj = context.addrs.refs;
925                 outrefs = 0;
926                 for (oldref = 0; oldref < context.addrs.numrefs; oldref++)
927                 {
928                         ObjectAddress *thisobj = context.addrs.refs + oldref;
929
930                         if (thisobj->classId == RelationRelationId &&
931                                 thisobj->objectId == relId)
932                         {
933                                 /* Move this ref into self_addrs */
934                                 add_object_address(OCLASS_CLASS, relId, thisobj->objectSubId,
935                                                                    &self_addrs);
936                         }
937                         else
938                         {
939                                 /* Keep it in context.addrs */
940                                 outobj->classId = thisobj->classId;
941                                 outobj->objectId = thisobj->objectId;
942                                 outobj->objectSubId = thisobj->objectSubId;
943                                 outobj++;
944                                 outrefs++;
945                         }
946                 }
947                 context.addrs.numrefs = outrefs;
948
949                 /* Record the self-dependencies */
950                 recordMultipleDependencies(depender,
951                                                                    self_addrs.refs, self_addrs.numrefs,
952                                                                    self_behavior);
953
954                 term_object_addresses(&self_addrs);
955         }
956
957         /* Record the external dependencies */
958         recordMultipleDependencies(depender,
959                                                            context.addrs.refs, context.addrs.numrefs,
960                                                            behavior);
961
962         term_object_addresses(&context.addrs);
963 }
964
965 /*
966  * Recursively search an expression tree for object references.
967  *
968  * Note: we avoid creating references to columns of tables that participate
969  * in an SQL JOIN construct, but are not actually used anywhere in the query.
970  * To do so, we do not scan the joinaliasvars list of a join RTE while
971  * scanning the query rangetable, but instead scan each individual entry
972  * of the alias list when we find a reference to it.
973  *
974  * Note: in many cases we do not need to create dependencies on the datatypes
975  * involved in an expression, because we'll have an indirect dependency via
976  * some other object.  For instance Var nodes depend on a column which depends
977  * on the datatype, and OpExpr nodes depend on the operator which depends on
978  * the datatype.  However we do need a type dependency if there is no such
979  * indirect dependency, as for example in Const and CoerceToDomain nodes.
980  */
981 static bool
982 find_expr_references_walker(Node *node,
983                                                         find_expr_references_context *context)
984 {
985         if (node == NULL)
986                 return false;
987         if (IsA(node, Var))
988         {
989                 Var                *var = (Var *) node;
990                 List       *rtable;
991                 RangeTblEntry *rte;
992
993                 /* Find matching rtable entry, or complain if not found */
994                 if (var->varlevelsup >= list_length(context->rtables))
995                         elog(ERROR, "invalid varlevelsup %d", var->varlevelsup);
996                 rtable = (List *) list_nth(context->rtables, var->varlevelsup);
997                 if (var->varno <= 0 || var->varno > list_length(rtable))
998                         elog(ERROR, "invalid varno %d", var->varno);
999                 rte = rt_fetch(var->varno, rtable);
1000
1001                 /*
1002                  * A whole-row Var references no specific columns, so adds no new
1003                  * dependency.
1004                  */
1005                 if (var->varattno == InvalidAttrNumber)
1006                         return false;
1007                 if (rte->rtekind == RTE_RELATION)
1008                 {
1009                         /* If it's a plain relation, reference this column */
1010                         add_object_address(OCLASS_CLASS, rte->relid, var->varattno,
1011                                                            &context->addrs);
1012                 }
1013                 else if (rte->rtekind == RTE_JOIN)
1014                 {
1015                         /* Scan join output column to add references to join inputs */
1016                         List       *save_rtables;
1017
1018                         /* We must make the context appropriate for join's level */
1019                         save_rtables = context->rtables;
1020                         context->rtables = list_copy_tail(context->rtables,
1021                                                                                           var->varlevelsup);
1022                         if (var->varattno <= 0 ||
1023                                 var->varattno > list_length(rte->joinaliasvars))
1024                                 elog(ERROR, "invalid varattno %d", var->varattno);
1025                         find_expr_references_walker((Node *) list_nth(rte->joinaliasvars,
1026                                                                                                                   var->varattno - 1),
1027                                                                                 context);
1028                         list_free(context->rtables);
1029                         context->rtables = save_rtables;
1030                 }
1031                 return false;
1032         }
1033         if (IsA(node, Const))
1034         {
1035                 Const      *con = (Const *) node;
1036                 Oid                     objoid;
1037
1038                 /* A constant must depend on the constant's datatype */
1039                 add_object_address(OCLASS_TYPE, con->consttype, 0,
1040                                                    &context->addrs);
1041
1042                 /*
1043                  * If it's a regclass or similar literal referring to an existing
1044                  * object, add a reference to that object.      (Currently, only the
1045                  * regclass case has any likely use, but we may as well handle all the
1046                  * OID-alias datatypes consistently.)
1047                  */
1048                 if (!con->constisnull)
1049                 {
1050                         switch (con->consttype)
1051                         {
1052                                 case REGPROCOID:
1053                                 case REGPROCEDUREOID:
1054                                         objoid = DatumGetObjectId(con->constvalue);
1055                                         if (SearchSysCacheExists(PROCOID,
1056                                                                                          ObjectIdGetDatum(objoid),
1057                                                                                          0, 0, 0))
1058                                                 add_object_address(OCLASS_PROC, objoid, 0,
1059                                                                                    &context->addrs);
1060                                         break;
1061                                 case REGOPEROID:
1062                                 case REGOPERATOROID:
1063                                         objoid = DatumGetObjectId(con->constvalue);
1064                                         if (SearchSysCacheExists(OPEROID,
1065                                                                                          ObjectIdGetDatum(objoid),
1066                                                                                          0, 0, 0))
1067                                                 add_object_address(OCLASS_OPERATOR, objoid, 0,
1068                                                                                    &context->addrs);
1069                                         break;
1070                                 case REGCLASSOID:
1071                                         objoid = DatumGetObjectId(con->constvalue);
1072                                         if (SearchSysCacheExists(RELOID,
1073                                                                                          ObjectIdGetDatum(objoid),
1074                                                                                          0, 0, 0))
1075                                                 add_object_address(OCLASS_CLASS, objoid, 0,
1076                                                                                    &context->addrs);
1077                                         break;
1078                                 case REGTYPEOID:
1079                                         objoid = DatumGetObjectId(con->constvalue);
1080                                         if (SearchSysCacheExists(TYPEOID,
1081                                                                                          ObjectIdGetDatum(objoid),
1082                                                                                          0, 0, 0))
1083                                                 add_object_address(OCLASS_TYPE, objoid, 0,
1084                                                                                    &context->addrs);
1085                                         break;
1086                         }
1087                 }
1088                 return false;
1089         }
1090         if (IsA(node, Param))
1091         {
1092                 Param      *param = (Param *) node;
1093
1094                 /* A parameter must depend on the parameter's datatype */
1095                 add_object_address(OCLASS_TYPE, param->paramtype, 0,
1096                                                    &context->addrs);
1097         }
1098         if (IsA(node, FuncExpr))
1099         {
1100                 FuncExpr   *funcexpr = (FuncExpr *) node;
1101
1102                 add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
1103                                                    &context->addrs);
1104                 /* fall through to examine arguments */
1105         }
1106         if (IsA(node, OpExpr))
1107         {
1108                 OpExpr     *opexpr = (OpExpr *) node;
1109
1110                 add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
1111                                                    &context->addrs);
1112                 /* fall through to examine arguments */
1113         }
1114         if (IsA(node, DistinctExpr))
1115         {
1116                 DistinctExpr *distinctexpr = (DistinctExpr *) node;
1117
1118                 add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
1119                                                    &context->addrs);
1120                 /* fall through to examine arguments */
1121         }
1122         if (IsA(node, ScalarArrayOpExpr))
1123         {
1124                 ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
1125
1126                 add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
1127                                                    &context->addrs);
1128                 /* fall through to examine arguments */
1129         }
1130         if (IsA(node, NullIfExpr))
1131         {
1132                 NullIfExpr *nullifexpr = (NullIfExpr *) node;
1133
1134                 add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
1135                                                    &context->addrs);
1136                 /* fall through to examine arguments */
1137         }
1138         if (IsA(node, Aggref))
1139         {
1140                 Aggref     *aggref = (Aggref *) node;
1141
1142                 add_object_address(OCLASS_PROC, aggref->aggfnoid, 0,
1143                                                    &context->addrs);
1144                 /* fall through to examine arguments */
1145         }
1146         if (is_subplan(node))
1147         {
1148                 /* Extra work needed here if we ever need this case */
1149                 elog(ERROR, "already-planned subqueries not supported");
1150         }
1151         if (IsA(node, RelabelType))
1152         {
1153                 RelabelType        *relab = (RelabelType *) node;
1154
1155                 /* since there is no function dependency, need to depend on type */
1156                 add_object_address(OCLASS_TYPE, relab->resulttype, 0,
1157                                                    &context->addrs);
1158         }
1159         if (IsA(node, ConvertRowtypeExpr))
1160         {
1161                 ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node;
1162
1163                 /* since there is no function dependency, need to depend on type */
1164                 add_object_address(OCLASS_TYPE, cvt->resulttype, 0,
1165                                                    &context->addrs);
1166         }
1167         if (IsA(node, RowExpr))
1168         {
1169                 RowExpr    *rowexpr = (RowExpr *) node;
1170
1171                 add_object_address(OCLASS_TYPE, rowexpr->row_typeid, 0,
1172                                                    &context->addrs);
1173         }
1174         if (IsA(node, RowCompareExpr))
1175         {
1176                 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1177                 ListCell   *l;
1178
1179                 foreach(l, rcexpr->opnos)
1180                 {
1181                         add_object_address(OCLASS_OPERATOR, lfirst_oid(l), 0,
1182                                                            &context->addrs);
1183                 }
1184                 foreach(l, rcexpr->opclasses)
1185                 {
1186                         add_object_address(OCLASS_OPCLASS, lfirst_oid(l), 0,
1187                                                            &context->addrs);
1188                 }
1189                 /* fall through to examine arguments */
1190         }
1191         if (IsA(node, CoerceToDomain))
1192         {
1193                 CoerceToDomain *cd = (CoerceToDomain *) node;
1194
1195                 add_object_address(OCLASS_TYPE, cd->resulttype, 0,
1196                                                    &context->addrs);
1197         }
1198         if (IsA(node, Query))
1199         {
1200                 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1201                 Query      *query = (Query *) node;
1202                 ListCell   *rtable;
1203                 bool            result;
1204
1205                 /*
1206                  * Add whole-relation refs for each plain relation mentioned in the
1207                  * subquery's rtable, as well as datatype refs for any datatypes used
1208                  * as a RECORD function's output.  (Note: query_tree_walker takes care
1209                  * of recursing into RTE_FUNCTION and RTE_SUBQUERY RTEs, so no need to
1210                  * do that here.  But keep it from looking at join alias lists.)
1211                  */
1212                 foreach(rtable, query->rtable)
1213                 {
1214                         RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtable);
1215                         ListCell   *ct;
1216
1217                         switch (rte->rtekind)
1218                         {
1219                                 case RTE_RELATION:
1220                                         add_object_address(OCLASS_CLASS, rte->relid, 0,
1221                                                                            &context->addrs);
1222                                         break;
1223                                 case RTE_FUNCTION:
1224                                         foreach(ct, rte->funccoltypes)
1225                                         {
1226                                                 add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0,
1227                                                                                    &context->addrs);
1228                                         }
1229                                         break;
1230                                 default:
1231                                         break;
1232                         }
1233                 }
1234
1235                 /* Examine substructure of query */
1236                 context->rtables = lcons(query->rtable, context->rtables);
1237                 result = query_tree_walker(query,
1238                                                                    find_expr_references_walker,
1239                                                                    (void *) context,
1240                                                                    QTW_IGNORE_JOINALIASES);
1241                 context->rtables = list_delete_first(context->rtables);
1242                 return result;
1243         }
1244         return expression_tree_walker(node, find_expr_references_walker,
1245                                                                   (void *) context);
1246 }
1247
1248 /*
1249  * Given an array of dependency references, eliminate any duplicates.
1250  */
1251 static void
1252 eliminate_duplicate_dependencies(ObjectAddresses *addrs)
1253 {
1254         ObjectAddress *priorobj;
1255         int                     oldref,
1256                                 newrefs;
1257
1258         if (addrs->numrefs <= 1)
1259                 return;                                 /* nothing to do */
1260
1261         /* Sort the refs so that duplicates are adjacent */
1262         qsort((void *) addrs->refs, addrs->numrefs, sizeof(ObjectAddress),
1263                   object_address_comparator);
1264
1265         /* Remove dups */
1266         priorobj = addrs->refs;
1267         newrefs = 1;
1268         for (oldref = 1; oldref < addrs->numrefs; oldref++)
1269         {
1270                 ObjectAddress *thisobj = addrs->refs + oldref;
1271
1272                 if (priorobj->classId == thisobj->classId &&
1273                         priorobj->objectId == thisobj->objectId)
1274                 {
1275                         if (priorobj->objectSubId == thisobj->objectSubId)
1276                                 continue;               /* identical, so drop thisobj */
1277
1278                         /*
1279                          * If we have a whole-object reference and a reference to a part
1280                          * of the same object, we don't need the whole-object reference
1281                          * (for example, we don't need to reference both table foo and
1282                          * column foo.bar).  The whole-object reference will always appear
1283                          * first in the sorted list.
1284                          */
1285                         if (priorobj->objectSubId == 0)
1286                         {
1287                                 /* replace whole ref with partial */
1288                                 priorobj->objectSubId = thisobj->objectSubId;
1289                                 continue;
1290                         }
1291                 }
1292                 /* Not identical, so add thisobj to output set */
1293                 priorobj++;
1294                 priorobj->classId = thisobj->classId;
1295                 priorobj->objectId = thisobj->objectId;
1296                 priorobj->objectSubId = thisobj->objectSubId;
1297                 newrefs++;
1298         }
1299
1300         addrs->numrefs = newrefs;
1301 }
1302
1303 /*
1304  * qsort comparator for ObjectAddress items
1305  */
1306 static int
1307 object_address_comparator(const void *a, const void *b)
1308 {
1309         const ObjectAddress *obja = (const ObjectAddress *) a;
1310         const ObjectAddress *objb = (const ObjectAddress *) b;
1311
1312         if (obja->classId < objb->classId)
1313                 return -1;
1314         if (obja->classId > objb->classId)
1315                 return 1;
1316         if (obja->objectId < objb->objectId)
1317                 return -1;
1318         if (obja->objectId > objb->objectId)
1319                 return 1;
1320
1321         /*
1322          * We sort the subId as an unsigned int so that 0 will come first. See
1323          * logic in eliminate_duplicate_dependencies.
1324          */
1325         if ((unsigned int) obja->objectSubId < (unsigned int) objb->objectSubId)
1326                 return -1;
1327         if ((unsigned int) obja->objectSubId > (unsigned int) objb->objectSubId)
1328                 return 1;
1329         return 0;
1330 }
1331
1332 /*
1333  * Routines for handling an expansible array of ObjectAddress items.
1334  *
1335  * init_object_addresses: initialize an ObjectAddresses array.
1336  */
1337 static void
1338 init_object_addresses(ObjectAddresses *addrs)
1339 {
1340         /* Initialize array to empty */
1341         addrs->numrefs = 0;
1342         addrs->maxrefs = 32;            /* arbitrary initial array size */
1343         addrs->refs = (ObjectAddress *)
1344                 palloc(addrs->maxrefs * sizeof(ObjectAddress));
1345 }
1346
1347 /*
1348  * Add an entry to an ObjectAddresses array.
1349  *
1350  * It is convenient to specify the class by ObjectClass rather than directly
1351  * by catalog OID.
1352  */
1353 static void
1354 add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
1355                                    ObjectAddresses *addrs)
1356 {
1357         ObjectAddress *item;
1358
1359         /* enlarge array if needed */
1360         if (addrs->numrefs >= addrs->maxrefs)
1361         {
1362                 addrs->maxrefs *= 2;
1363                 addrs->refs = (ObjectAddress *)
1364                         repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
1365         }
1366         /* record this item */
1367         item = addrs->refs + addrs->numrefs;
1368         item->classId = object_classes[oclass];
1369         item->objectId = objectId;
1370         item->objectSubId = subId;
1371         addrs->numrefs++;
1372 }
1373
1374 /*
1375  * Add an entry to an ObjectAddresses array.
1376  *
1377  * As above, but specify entry exactly.
1378  */
1379 static void
1380 add_exact_object_address(const ObjectAddress *object,
1381                                                  ObjectAddresses *addrs)
1382 {
1383         ObjectAddress *item;
1384
1385         /* enlarge array if needed */
1386         if (addrs->numrefs >= addrs->maxrefs)
1387         {
1388                 addrs->maxrefs *= 2;
1389                 addrs->refs = (ObjectAddress *)
1390                         repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
1391         }
1392         /* record this item */
1393         item = addrs->refs + addrs->numrefs;
1394         *item = *object;
1395         addrs->numrefs++;
1396 }
1397
1398 /*
1399  * Test whether an object is present in an ObjectAddresses array.
1400  *
1401  * We return "true" if object is a subobject of something in the array, too.
1402  */
1403 static bool
1404 object_address_present(const ObjectAddress *object,
1405                                            ObjectAddresses *addrs)
1406 {
1407         int                     i;
1408
1409         for (i = addrs->numrefs - 1; i >= 0; i--)
1410         {
1411                 ObjectAddress *thisobj = addrs->refs + i;
1412
1413                 if (object->classId == thisobj->classId &&
1414                         object->objectId == thisobj->objectId)
1415                 {
1416                         if (object->objectSubId == thisobj->objectSubId ||
1417                                 thisobj->objectSubId == 0)
1418                                 return true;
1419                 }
1420         }
1421
1422         return false;
1423 }
1424
1425 /*
1426  * Clean up when done with an ObjectAddresses array.
1427  */
1428 static void
1429 term_object_addresses(ObjectAddresses *addrs)
1430 {
1431         pfree(addrs->refs);
1432 }
1433
1434 /*
1435  * Determine the class of a given object identified by objectAddress.
1436  *
1437  * This function is essentially the reverse mapping for the object_classes[]
1438  * table.  We implement it as a function because the OIDs aren't consecutive.
1439  */
1440 ObjectClass
1441 getObjectClass(const ObjectAddress *object)
1442 {
1443         switch (object->classId)
1444         {
1445                 case RelationRelationId:
1446                         /* caller must check objectSubId */
1447                         return OCLASS_CLASS;
1448
1449                 case ProcedureRelationId:
1450                         Assert(object->objectSubId == 0);
1451                         return OCLASS_PROC;
1452
1453                 case TypeRelationId:
1454                         Assert(object->objectSubId == 0);
1455                         return OCLASS_TYPE;
1456
1457                 case CastRelationId:
1458                         Assert(object->objectSubId == 0);
1459                         return OCLASS_CAST;
1460
1461                 case ConstraintRelationId:
1462                         Assert(object->objectSubId == 0);
1463                         return OCLASS_CONSTRAINT;
1464
1465                 case ConversionRelationId:
1466                         Assert(object->objectSubId == 0);
1467                         return OCLASS_CONVERSION;
1468
1469                 case AttrDefaultRelationId:
1470                         Assert(object->objectSubId == 0);
1471                         return OCLASS_DEFAULT;
1472
1473                 case LanguageRelationId:
1474                         Assert(object->objectSubId == 0);
1475                         return OCLASS_LANGUAGE;
1476
1477                 case OperatorRelationId:
1478                         Assert(object->objectSubId == 0);
1479                         return OCLASS_OPERATOR;
1480
1481                 case OperatorClassRelationId:
1482                         Assert(object->objectSubId == 0);
1483                         return OCLASS_OPCLASS;
1484
1485                 case RewriteRelationId:
1486                         Assert(object->objectSubId == 0);
1487                         return OCLASS_REWRITE;
1488
1489                 case TriggerRelationId:
1490                         Assert(object->objectSubId == 0);
1491                         return OCLASS_TRIGGER;
1492
1493                 case NamespaceRelationId:
1494                         Assert(object->objectSubId == 0);
1495                         return OCLASS_SCHEMA;
1496
1497                 case AuthIdRelationId:
1498                         Assert(object->objectSubId == 0);
1499                         return OCLASS_ROLE;
1500
1501                 case DatabaseRelationId:
1502                         Assert(object->objectSubId == 0);
1503                         return OCLASS_DATABASE;
1504
1505                 case TableSpaceRelationId:
1506                         Assert(object->objectSubId == 0);
1507                         return OCLASS_TBLSPACE;
1508         }
1509
1510         /* shouldn't get here */
1511         elog(ERROR, "unrecognized object class: %u", object->classId);
1512         return OCLASS_CLASS;            /* keep compiler quiet */
1513 }
1514
1515 /*
1516  * getObjectDescription: build an object description for messages
1517  *
1518  * The result is a palloc'd string.
1519  */
1520 char *
1521 getObjectDescription(const ObjectAddress *object)
1522 {
1523         StringInfoData buffer;
1524
1525         initStringInfo(&buffer);
1526
1527         switch (getObjectClass(object))
1528         {
1529                 case OCLASS_CLASS:
1530                         getRelationDescription(&buffer, object->objectId);
1531                         if (object->objectSubId != 0)
1532                                 appendStringInfo(&buffer, _(" column %s"),
1533                                                                  get_relid_attribute_name(object->objectId,
1534                                                                                                            object->objectSubId));
1535                         break;
1536
1537                 case OCLASS_PROC:
1538                         appendStringInfo(&buffer, _("function %s"),
1539                                                          format_procedure(object->objectId));
1540                         break;
1541
1542                 case OCLASS_TYPE:
1543                         appendStringInfo(&buffer, _("type %s"),
1544                                                          format_type_be(object->objectId));
1545                         break;
1546
1547                 case OCLASS_CAST:
1548                         {
1549                                 Relation        castDesc;
1550                                 ScanKeyData skey[1];
1551                                 SysScanDesc rcscan;
1552                                 HeapTuple       tup;
1553                                 Form_pg_cast castForm;
1554
1555                                 castDesc = heap_open(CastRelationId, AccessShareLock);
1556
1557                                 ScanKeyInit(&skey[0],
1558                                                         ObjectIdAttributeNumber,
1559                                                         BTEqualStrategyNumber, F_OIDEQ,
1560                                                         ObjectIdGetDatum(object->objectId));
1561
1562                                 rcscan = systable_beginscan(castDesc, CastOidIndexId, true,
1563                                                                                         SnapshotNow, 1, skey);
1564
1565                                 tup = systable_getnext(rcscan);
1566
1567                                 if (!HeapTupleIsValid(tup))
1568                                         elog(ERROR, "could not find tuple for cast %u",
1569                                                  object->objectId);
1570
1571                                 castForm = (Form_pg_cast) GETSTRUCT(tup);
1572
1573                                 appendStringInfo(&buffer, _("cast from %s to %s"),
1574                                                                  format_type_be(castForm->castsource),
1575                                                                  format_type_be(castForm->casttarget));
1576
1577                                 systable_endscan(rcscan);
1578                                 heap_close(castDesc, AccessShareLock);
1579                                 break;
1580                         }
1581
1582                 case OCLASS_CONSTRAINT:
1583                         {
1584                                 Relation        conDesc;
1585                                 ScanKeyData skey[1];
1586                                 SysScanDesc rcscan;
1587                                 HeapTuple       tup;
1588                                 Form_pg_constraint con;
1589
1590                                 conDesc = heap_open(ConstraintRelationId, AccessShareLock);
1591
1592                                 ScanKeyInit(&skey[0],
1593                                                         ObjectIdAttributeNumber,
1594                                                         BTEqualStrategyNumber, F_OIDEQ,
1595                                                         ObjectIdGetDatum(object->objectId));
1596
1597                                 rcscan = systable_beginscan(conDesc, ConstraintOidIndexId, true,
1598                                                                                         SnapshotNow, 1, skey);
1599
1600                                 tup = systable_getnext(rcscan);
1601
1602                                 if (!HeapTupleIsValid(tup))
1603                                         elog(ERROR, "could not find tuple for constraint %u",
1604                                                  object->objectId);
1605
1606                                 con = (Form_pg_constraint) GETSTRUCT(tup);
1607
1608                                 if (OidIsValid(con->conrelid))
1609                                 {
1610                                         appendStringInfo(&buffer, _("constraint %s on "),
1611                                                                          NameStr(con->conname));
1612                                         getRelationDescription(&buffer, con->conrelid);
1613                                 }
1614                                 else
1615                                 {
1616                                         appendStringInfo(&buffer, _("constraint %s"),
1617                                                                          NameStr(con->conname));
1618                                 }
1619
1620                                 systable_endscan(rcscan);
1621                                 heap_close(conDesc, AccessShareLock);
1622                                 break;
1623                         }
1624
1625                 case OCLASS_CONVERSION:
1626                         {
1627                                 HeapTuple       conTup;
1628
1629                                 conTup = SearchSysCache(CONOID,
1630                                                                                 ObjectIdGetDatum(object->objectId),
1631                                                                                 0, 0, 0);
1632                                 if (!HeapTupleIsValid(conTup))
1633                                         elog(ERROR, "cache lookup failed for conversion %u",
1634                                                  object->objectId);
1635                                 appendStringInfo(&buffer, _("conversion %s"),
1636                                  NameStr(((Form_pg_conversion) GETSTRUCT(conTup))->conname));
1637                                 ReleaseSysCache(conTup);
1638                                 break;
1639                         }
1640
1641                 case OCLASS_DEFAULT:
1642                         {
1643                                 Relation        attrdefDesc;
1644                                 ScanKeyData skey[1];
1645                                 SysScanDesc adscan;
1646                                 HeapTuple       tup;
1647                                 Form_pg_attrdef attrdef;
1648                                 ObjectAddress colobject;
1649
1650                                 attrdefDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
1651
1652                                 ScanKeyInit(&skey[0],
1653                                                         ObjectIdAttributeNumber,
1654                                                         BTEqualStrategyNumber, F_OIDEQ,
1655                                                         ObjectIdGetDatum(object->objectId));
1656
1657                                 adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndexId,
1658                                                                                         true, SnapshotNow, 1, skey);
1659
1660                                 tup = systable_getnext(adscan);
1661
1662                                 if (!HeapTupleIsValid(tup))
1663                                         elog(ERROR, "could not find tuple for attrdef %u",
1664                                                  object->objectId);
1665
1666                                 attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
1667
1668                                 colobject.classId = RelationRelationId;
1669                                 colobject.objectId = attrdef->adrelid;
1670                                 colobject.objectSubId = attrdef->adnum;
1671
1672                                 appendStringInfo(&buffer, _("default for %s"),
1673                                                                  getObjectDescription(&colobject));
1674
1675                                 systable_endscan(adscan);
1676                                 heap_close(attrdefDesc, AccessShareLock);
1677                                 break;
1678                         }
1679
1680                 case OCLASS_LANGUAGE:
1681                         {
1682                                 HeapTuple       langTup;
1683
1684                                 langTup = SearchSysCache(LANGOID,
1685                                                                                  ObjectIdGetDatum(object->objectId),
1686                                                                                  0, 0, 0);
1687                                 if (!HeapTupleIsValid(langTup))
1688                                         elog(ERROR, "cache lookup failed for language %u",
1689                                                  object->objectId);
1690                                 appendStringInfo(&buffer, _("language %s"),
1691                                   NameStr(((Form_pg_language) GETSTRUCT(langTup))->lanname));
1692                                 ReleaseSysCache(langTup);
1693                                 break;
1694                         }
1695
1696                 case OCLASS_OPERATOR:
1697                         appendStringInfo(&buffer, _("operator %s"),
1698                                                          format_operator(object->objectId));
1699                         break;
1700
1701                 case OCLASS_OPCLASS:
1702                         {
1703                                 HeapTuple       opcTup;
1704                                 Form_pg_opclass opcForm;
1705                                 HeapTuple       amTup;
1706                                 Form_pg_am      amForm;
1707                                 char       *nspname;
1708
1709                                 opcTup = SearchSysCache(CLAOID,
1710                                                                                 ObjectIdGetDatum(object->objectId),
1711                                                                                 0, 0, 0);
1712                                 if (!HeapTupleIsValid(opcTup))
1713                                         elog(ERROR, "cache lookup failed for opclass %u",
1714                                                  object->objectId);
1715                                 opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
1716
1717                                 amTup = SearchSysCache(AMOID,
1718                                                                            ObjectIdGetDatum(opcForm->opcamid),
1719                                                                            0, 0, 0);
1720                                 if (!HeapTupleIsValid(amTup))
1721                                         elog(ERROR, "cache lookup failed for access method %u",
1722                                                  opcForm->opcamid);
1723                                 amForm = (Form_pg_am) GETSTRUCT(amTup);
1724
1725                                 /* Qualify the name if not visible in search path */
1726                                 if (OpclassIsVisible(object->objectId))
1727                                         nspname = NULL;
1728                                 else
1729                                         nspname = get_namespace_name(opcForm->opcnamespace);
1730
1731                                 appendStringInfo(&buffer, _("operator class %s for access method %s"),
1732                                                                  quote_qualified_identifier(nspname,
1733                                                                                                   NameStr(opcForm->opcname)),
1734                                                                  NameStr(amForm->amname));
1735
1736                                 ReleaseSysCache(amTup);
1737                                 ReleaseSysCache(opcTup);
1738                                 break;
1739                         }
1740
1741                 case OCLASS_REWRITE:
1742                         {
1743                                 Relation        ruleDesc;
1744                                 ScanKeyData skey[1];
1745                                 SysScanDesc rcscan;
1746                                 HeapTuple       tup;
1747                                 Form_pg_rewrite rule;
1748
1749                                 ruleDesc = heap_open(RewriteRelationId, AccessShareLock);
1750
1751                                 ScanKeyInit(&skey[0],
1752                                                         ObjectIdAttributeNumber,
1753                                                         BTEqualStrategyNumber, F_OIDEQ,
1754                                                         ObjectIdGetDatum(object->objectId));
1755
1756                                 rcscan = systable_beginscan(ruleDesc, RewriteOidIndexId, true,
1757                                                                                         SnapshotNow, 1, skey);
1758
1759                                 tup = systable_getnext(rcscan);
1760
1761                                 if (!HeapTupleIsValid(tup))
1762                                         elog(ERROR, "could not find tuple for rule %u",
1763                                                  object->objectId);
1764
1765                                 rule = (Form_pg_rewrite) GETSTRUCT(tup);
1766
1767                                 appendStringInfo(&buffer, _("rule %s on "),
1768                                                                  NameStr(rule->rulename));
1769                                 getRelationDescription(&buffer, rule->ev_class);
1770
1771                                 systable_endscan(rcscan);
1772                                 heap_close(ruleDesc, AccessShareLock);
1773                                 break;
1774                         }
1775
1776                 case OCLASS_TRIGGER:
1777                         {
1778                                 Relation        trigDesc;
1779                                 ScanKeyData skey[1];
1780                                 SysScanDesc tgscan;
1781                                 HeapTuple       tup;
1782                                 Form_pg_trigger trig;
1783
1784                                 trigDesc = heap_open(TriggerRelationId, AccessShareLock);
1785
1786                                 ScanKeyInit(&skey[0],
1787                                                         ObjectIdAttributeNumber,
1788                                                         BTEqualStrategyNumber, F_OIDEQ,
1789                                                         ObjectIdGetDatum(object->objectId));
1790
1791                                 tgscan = systable_beginscan(trigDesc, TriggerOidIndexId, true,
1792                                                                                         SnapshotNow, 1, skey);
1793
1794                                 tup = systable_getnext(tgscan);
1795
1796                                 if (!HeapTupleIsValid(tup))
1797                                         elog(ERROR, "could not find tuple for trigger %u",
1798                                                  object->objectId);
1799
1800                                 trig = (Form_pg_trigger) GETSTRUCT(tup);
1801
1802                                 appendStringInfo(&buffer, _("trigger %s on "),
1803                                                                  NameStr(trig->tgname));
1804                                 getRelationDescription(&buffer, trig->tgrelid);
1805
1806                                 systable_endscan(tgscan);
1807                                 heap_close(trigDesc, AccessShareLock);
1808                                 break;
1809                         }
1810
1811                 case OCLASS_SCHEMA:
1812                         {
1813                                 char       *nspname;
1814
1815                                 nspname = get_namespace_name(object->objectId);
1816                                 if (!nspname)
1817                                         elog(ERROR, "cache lookup failed for namespace %u",
1818                                                  object->objectId);
1819                                 appendStringInfo(&buffer, _("schema %s"), nspname);
1820                                 break;
1821                         }
1822
1823                 case OCLASS_ROLE:
1824                         {
1825                                 appendStringInfo(&buffer, _("role %s"),
1826                                                                  GetUserNameFromId(object->objectId));
1827                                 break;
1828                         }
1829
1830                 case OCLASS_DATABASE:
1831                         {
1832                                 char       *datname;
1833
1834                                 datname = get_database_name(object->objectId);
1835                                 if (!datname)
1836                                         elog(ERROR, "cache lookup failed for database %u",
1837                                                  object->objectId);
1838                                 appendStringInfo(&buffer, _("database %s"), datname);
1839                                 break;
1840                         }
1841
1842                 case OCLASS_TBLSPACE:
1843                         {
1844                                 char       *tblspace;
1845
1846                                 tblspace = get_tablespace_name(object->objectId);
1847                                 if (!tblspace)
1848                                         elog(ERROR, "cache lookup failed for tablespace %u",
1849                                                  object->objectId);
1850                                 appendStringInfo(&buffer, _("tablespace %s"), tblspace);
1851                                 break;
1852                         }
1853
1854                 default:
1855                         appendStringInfo(&buffer, "unrecognized object %u %u %d",
1856                                                          object->classId,
1857                                                          object->objectId,
1858                                                          object->objectSubId);
1859                         break;
1860         }
1861
1862         return buffer.data;
1863 }
1864
1865 /*
1866  * subroutine for getObjectDescription: describe a relation
1867  */
1868 static void
1869 getRelationDescription(StringInfo buffer, Oid relid)
1870 {
1871         HeapTuple       relTup;
1872         Form_pg_class relForm;
1873         char       *nspname;
1874         char       *relname;
1875
1876         relTup = SearchSysCache(RELOID,
1877                                                         ObjectIdGetDatum(relid),
1878                                                         0, 0, 0);
1879         if (!HeapTupleIsValid(relTup))
1880                 elog(ERROR, "cache lookup failed for relation %u", relid);
1881         relForm = (Form_pg_class) GETSTRUCT(relTup);
1882
1883         /* Qualify the name if not visible in search path */
1884         if (RelationIsVisible(relid))
1885                 nspname = NULL;
1886         else
1887                 nspname = get_namespace_name(relForm->relnamespace);
1888
1889         relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
1890
1891         switch (relForm->relkind)
1892         {
1893                 case RELKIND_RELATION:
1894                         appendStringInfo(buffer, _("table %s"),
1895                                                          relname);
1896                         break;
1897                 case RELKIND_INDEX:
1898                         appendStringInfo(buffer, _("index %s"),
1899                                                          relname);
1900                         break;
1901                 case RELKIND_SPECIAL:
1902                         appendStringInfo(buffer, _("special system relation %s"),
1903                                                          relname);
1904                         break;
1905                 case RELKIND_SEQUENCE:
1906                         appendStringInfo(buffer, _("sequence %s"),
1907                                                          relname);
1908                         break;
1909                 case RELKIND_UNCATALOGED:
1910                         appendStringInfo(buffer, _("uncataloged table %s"),
1911                                                          relname);
1912                         break;
1913                 case RELKIND_TOASTVALUE:
1914                         appendStringInfo(buffer, _("toast table %s"),
1915                                                          relname);
1916                         break;
1917                 case RELKIND_VIEW:
1918                         appendStringInfo(buffer, _("view %s"),
1919                                                          relname);
1920                         break;
1921                 case RELKIND_COMPOSITE_TYPE:
1922                         appendStringInfo(buffer, _("composite type %s"),
1923                                                          relname);
1924                         break;
1925                 default:
1926                         /* shouldn't get here */
1927                         appendStringInfo(buffer, _("relation %s"),
1928                                                          relname);
1929                         break;
1930         }
1931
1932         ReleaseSysCache(relTup);
1933 }
1934
1935 /* Recursively travel and search for the default sequence. Finally detach it */
1936
1937 void performSequenceDefaultDeletion(const ObjectAddress *object,
1938                                         DropBehavior behavior, int deleteFlag)
1939 {        
1940         
1941         ScanKeyData key[3];
1942         int                     nkeys;
1943         SysScanDesc scan;
1944         HeapTuple       tup;
1945         ObjectAddress otherObject;            
1946           Relation      depRel;
1947         
1948           depRel = heap_open(DependRelationId, RowExclusiveLock);
1949
1950         ScanKeyInit(&key[0],
1951                                 Anum_pg_depend_classid,
1952                                 BTEqualStrategyNumber, F_OIDEQ,
1953                                 ObjectIdGetDatum(object->classId));
1954         ScanKeyInit(&key[1],
1955                                 Anum_pg_depend_objid,
1956                                 BTEqualStrategyNumber, F_OIDEQ,
1957                                 ObjectIdGetDatum(object->objectId));
1958         if (object->objectSubId != 0)
1959         {
1960                ScanKeyInit(&key[2],
1961                                         Anum_pg_depend_objsubid,
1962                                         BTEqualStrategyNumber, F_INT4EQ,
1963                                         Int32GetDatum(object->objectSubId));
1964                 nkeys = 3;
1965         }
1966         else
1967                 nkeys = 2;
1968
1969         scan = systable_beginscan(depRel, DependDependerIndexId, true,
1970                                                           SnapshotNow, nkeys, key);
1971
1972         while (HeapTupleIsValid(tup = systable_getnext(scan)))
1973         {
1974                 
1975                 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
1976
1977                 otherObject.classId = foundDep->refclassid;
1978                 otherObject.objectId = foundDep->refobjid;
1979                 otherObject.objectSubId = foundDep->refobjsubid;
1980
1981                   /* Detach the default sequence from the relation */
1982                   if(deleteFlag == 1)   
1983                   {     
1984                         simple_heap_delete(depRel, &tup->t_self);       
1985                         break;
1986                   }
1987
1988                 switch (foundDep->deptype)
1989                 {
1990                         case DEPENDENCY_NORMAL:                        
1991                         {
1992
1993                                 if(getObjectClass(&otherObject) == OCLASS_CLASS)
1994                                 {
1995                                         /* Dont allow to change the default sequence */
1996                                         if(deleteFlag == 2)     
1997                                         { 
1998                                                 systable_endscan(scan);
1999                                                 heap_close(depRel, RowExclusiveLock);
2000                                                 elog(ERROR, "%s is a SERIAL sequence. Can't alter the relation", getObjectDescription(&otherObject));
2001                                                 return;
2002                                         }
2003                                         else /* Detach the default sequence from the relation */
2004                                         {
2005                                                 performSequenceDefaultDeletion(&otherObject, behavior, 1);
2006                                                 systable_endscan(scan);
2007                                                 heap_close(depRel, RowExclusiveLock);
2008                                                 return;                                 
2009                                         }
2010                                 }
2011                         }
2012                                 
2013                 }
2014         }
2015
2016         systable_endscan(scan);
2017         heap_close(depRel, RowExclusiveLock);   
2018
2019 }