Header And Logo

PostgreSQL
| The world's most advanced open source database.

dependency.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * dependency.c
00004  *    Routines to support inter-object dependencies.
00005  *
00006  *
00007  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00008  * Portions Copyright (c) 1994, Regents of the University of California
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/catalog/dependency.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "access/htup_details.h"
00018 #include "access/xact.h"
00019 #include "catalog/dependency.h"
00020 #include "catalog/heap.h"
00021 #include "catalog/index.h"
00022 #include "catalog/objectaccess.h"
00023 #include "catalog/pg_amop.h"
00024 #include "catalog/pg_amproc.h"
00025 #include "catalog/pg_attrdef.h"
00026 #include "catalog/pg_authid.h"
00027 #include "catalog/pg_cast.h"
00028 #include "catalog/pg_collation.h"
00029 #include "catalog/pg_collation_fn.h"
00030 #include "catalog/pg_constraint.h"
00031 #include "catalog/pg_conversion.h"
00032 #include "catalog/pg_conversion_fn.h"
00033 #include "catalog/pg_database.h"
00034 #include "catalog/pg_default_acl.h"
00035 #include "catalog/pg_depend.h"
00036 #include "catalog/pg_event_trigger.h"
00037 #include "catalog/pg_extension.h"
00038 #include "catalog/pg_foreign_data_wrapper.h"
00039 #include "catalog/pg_foreign_server.h"
00040 #include "catalog/pg_language.h"
00041 #include "catalog/pg_largeobject.h"
00042 #include "catalog/pg_namespace.h"
00043 #include "catalog/pg_opclass.h"
00044 #include "catalog/pg_operator.h"
00045 #include "catalog/pg_opfamily.h"
00046 #include "catalog/pg_proc.h"
00047 #include "catalog/pg_rewrite.h"
00048 #include "catalog/pg_tablespace.h"
00049 #include "catalog/pg_trigger.h"
00050 #include "catalog/pg_ts_config.h"
00051 #include "catalog/pg_ts_dict.h"
00052 #include "catalog/pg_ts_parser.h"
00053 #include "catalog/pg_ts_template.h"
00054 #include "catalog/pg_type.h"
00055 #include "catalog/pg_user_mapping.h"
00056 #include "commands/comment.h"
00057 #include "commands/defrem.h"
00058 #include "commands/event_trigger.h"
00059 #include "commands/extension.h"
00060 #include "commands/proclang.h"
00061 #include "commands/schemacmds.h"
00062 #include "commands/seclabel.h"
00063 #include "commands/trigger.h"
00064 #include "commands/typecmds.h"
00065 #include "nodes/nodeFuncs.h"
00066 #include "parser/parsetree.h"
00067 #include "rewrite/rewriteRemove.h"
00068 #include "storage/lmgr.h"
00069 #include "utils/fmgroids.h"
00070 #include "utils/guc.h"
00071 #include "utils/lsyscache.h"
00072 #include "utils/syscache.h"
00073 #include "utils/tqual.h"
00074 
00075 
00076 /*
00077  * Deletion processing requires additional state for each ObjectAddress that
00078  * it's planning to delete.  For simplicity and code-sharing we make the
00079  * ObjectAddresses code support arrays with or without this extra state.
00080  */
00081 typedef struct
00082 {
00083     int         flags;          /* bitmask, see bit definitions below */
00084     ObjectAddress dependee;     /* object whose deletion forced this one */
00085 } ObjectAddressExtra;
00086 
00087 /* ObjectAddressExtra flag bits */
00088 #define DEPFLAG_ORIGINAL    0x0001      /* an original deletion target */
00089 #define DEPFLAG_NORMAL      0x0002      /* reached via normal dependency */
00090 #define DEPFLAG_AUTO        0x0004      /* reached via auto dependency */
00091 #define DEPFLAG_INTERNAL    0x0008      /* reached via internal dependency */
00092 #define DEPFLAG_EXTENSION   0x0010      /* reached via extension dependency */
00093 #define DEPFLAG_REVERSE     0x0020      /* reverse internal/extension link */
00094 
00095 
00096 /* expansible list of ObjectAddresses */
00097 struct ObjectAddresses
00098 {
00099     ObjectAddress *refs;        /* => palloc'd array */
00100     ObjectAddressExtra *extras; /* => palloc'd array, or NULL if not used */
00101     int         numrefs;        /* current number of references */
00102     int         maxrefs;        /* current size of palloc'd array(s) */
00103 };
00104 
00105 /* typedef ObjectAddresses appears in dependency.h */
00106 
00107 /* threaded list of ObjectAddresses, for recursion detection */
00108 typedef struct ObjectAddressStack
00109 {
00110     const ObjectAddress *object;    /* object being visited */
00111     int         flags;          /* its current flag bits */
00112     struct ObjectAddressStack *next;    /* next outer stack level */
00113 } ObjectAddressStack;
00114 
00115 /* for find_expr_references_walker */
00116 typedef struct
00117 {
00118     ObjectAddresses *addrs;     /* addresses being accumulated */
00119     List       *rtables;        /* list of rangetables to resolve Vars */
00120 } find_expr_references_context;
00121 
00122 /*
00123  * This constant table maps ObjectClasses to the corresponding catalog OIDs.
00124  * See also getObjectClass().
00125  */
00126 static const Oid object_classes[MAX_OCLASS] = {
00127     RelationRelationId,         /* OCLASS_CLASS */
00128     ProcedureRelationId,        /* OCLASS_PROC */
00129     TypeRelationId,             /* OCLASS_TYPE */
00130     CastRelationId,             /* OCLASS_CAST */
00131     CollationRelationId,        /* OCLASS_COLLATION */
00132     ConstraintRelationId,       /* OCLASS_CONSTRAINT */
00133     ConversionRelationId,       /* OCLASS_CONVERSION */
00134     AttrDefaultRelationId,      /* OCLASS_DEFAULT */
00135     LanguageRelationId,         /* OCLASS_LANGUAGE */
00136     LargeObjectRelationId,      /* OCLASS_LARGEOBJECT */
00137     OperatorRelationId,         /* OCLASS_OPERATOR */
00138     OperatorClassRelationId,    /* OCLASS_OPCLASS */
00139     OperatorFamilyRelationId,   /* OCLASS_OPFAMILY */
00140     AccessMethodOperatorRelationId,     /* OCLASS_AMOP */
00141     AccessMethodProcedureRelationId,    /* OCLASS_AMPROC */
00142     RewriteRelationId,          /* OCLASS_REWRITE */
00143     TriggerRelationId,          /* OCLASS_TRIGGER */
00144     NamespaceRelationId,        /* OCLASS_SCHEMA */
00145     TSParserRelationId,         /* OCLASS_TSPARSER */
00146     TSDictionaryRelationId,     /* OCLASS_TSDICT */
00147     TSTemplateRelationId,       /* OCLASS_TSTEMPLATE */
00148     TSConfigRelationId,         /* OCLASS_TSCONFIG */
00149     AuthIdRelationId,           /* OCLASS_ROLE */
00150     DatabaseRelationId,         /* OCLASS_DATABASE */
00151     TableSpaceRelationId,       /* OCLASS_TBLSPACE */
00152     ForeignDataWrapperRelationId,       /* OCLASS_FDW */
00153     ForeignServerRelationId,    /* OCLASS_FOREIGN_SERVER */
00154     UserMappingRelationId,      /* OCLASS_USER_MAPPING */
00155     DefaultAclRelationId,       /* OCLASS_DEFACL */
00156     ExtensionRelationId,        /* OCLASS_EXTENSION */
00157     EventTriggerRelationId      /* OCLASS_EVENT_TRIGGER */
00158 };
00159 
00160 
00161 static void findDependentObjects(const ObjectAddress *object,
00162                      int flags,
00163                      ObjectAddressStack *stack,
00164                      ObjectAddresses *targetObjects,
00165                      const ObjectAddresses *pendingObjects,
00166                      Relation *depRel);
00167 static void reportDependentObjects(const ObjectAddresses *targetObjects,
00168                        DropBehavior behavior,
00169                        int msglevel,
00170                        const ObjectAddress *origObject);
00171 static void deleteOneObject(const ObjectAddress *object,
00172                 Relation *depRel, int32 flags);
00173 static void doDeletion(const ObjectAddress *object, int flags);
00174 static void AcquireDeletionLock(const ObjectAddress *object, int flags);
00175 static void ReleaseDeletionLock(const ObjectAddress *object);
00176 static bool find_expr_references_walker(Node *node,
00177                             find_expr_references_context *context);
00178 static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
00179 static int  object_address_comparator(const void *a, const void *b);
00180 static void add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
00181                    ObjectAddresses *addrs);
00182 static void add_exact_object_address_extra(const ObjectAddress *object,
00183                                const ObjectAddressExtra *extra,
00184                                ObjectAddresses *addrs);
00185 static bool object_address_present_add_flags(const ObjectAddress *object,
00186                                  int flags,
00187                                  ObjectAddresses *addrs);
00188 static bool stack_address_present_add_flags(const ObjectAddress *object,
00189                                 int flags,
00190                                 ObjectAddressStack *stack);
00191 
00192 
00193 /*
00194  * Go through the objects given running the final actions on them, and execute
00195  * the actual deletion.
00196  */
00197 static void
00198 deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel,
00199                     int flags)
00200 {
00201     int     i;
00202 
00203     /*
00204      * Keep track of objects for event triggers, if necessary.
00205      */
00206     if (trackDroppedObjectsNeeded())
00207     {
00208         for (i = 0; i < targetObjects->numrefs; i++)
00209         {
00210             ObjectAddress *thisobj = targetObjects->refs + i;
00211 
00212             if ((!(flags & PERFORM_DELETION_INTERNAL)) &&
00213                 EventTriggerSupportsObjectClass(getObjectClass(thisobj)))
00214             {
00215                 EventTriggerSQLDropAddObject(thisobj);
00216             }
00217         }
00218     }
00219 
00220     /*
00221      * Delete all the objects in the proper order.
00222      */
00223     for (i = 0; i < targetObjects->numrefs; i++)
00224     {
00225         ObjectAddress *thisobj = targetObjects->refs + i;
00226 
00227         deleteOneObject(thisobj, depRel, flags);
00228     }
00229 }
00230 
00231 /*
00232  * performDeletion: attempt to drop the specified object.  If CASCADE
00233  * behavior is specified, also drop any dependent objects (recursively).
00234  * If RESTRICT behavior is specified, error out if there are any dependent
00235  * objects, except for those that should be implicitly dropped anyway
00236  * according to the dependency type.
00237  *
00238  * This is the outer control routine for all forms of DROP that drop objects
00239  * that can participate in dependencies.  Note that the next two routines
00240  * are variants on the same theme; if you change anything here you'll likely
00241  * need to fix them too.
00242  *
00243  * flags should include PERFORM_DELETION_INTERNAL when the drop operation is
00244  * not the direct result of a user-initiated action.  For example, when a
00245  * temporary schema is cleaned out so that a new backend can use it, or when
00246  * a column default is dropped as an intermediate step while adding a new one,
00247  * that's an internal operation.  On the other hand, when the we drop something
00248  * because the user issued a DROP statement against it, that's not internal.
00249  */
00250 void
00251 performDeletion(const ObjectAddress *object,
00252                 DropBehavior behavior, int flags)
00253 {
00254     Relation    depRel;
00255     ObjectAddresses *targetObjects;
00256 
00257     /*
00258      * We save some cycles by opening pg_depend just once and passing the
00259      * Relation pointer down to all the recursive deletion steps.
00260      */
00261     depRel = heap_open(DependRelationId, RowExclusiveLock);
00262 
00263     /*
00264      * Acquire deletion lock on the target object.  (Ideally the caller has
00265      * done this already, but many places are sloppy about it.)
00266      */
00267     AcquireDeletionLock(object, 0);
00268 
00269     /*
00270      * Construct a list of objects to delete (ie, the given object plus
00271      * everything directly or indirectly dependent on it).
00272      */
00273     targetObjects = new_object_addresses();
00274 
00275     findDependentObjects(object,
00276                          DEPFLAG_ORIGINAL,
00277                          NULL,  /* empty stack */
00278                          targetObjects,
00279                          NULL,  /* no pendingObjects */
00280                          &depRel);
00281 
00282     /*
00283      * Check if deletion is allowed, and report about cascaded deletes.
00284      */
00285     reportDependentObjects(targetObjects,
00286                            behavior,
00287                            NOTICE,
00288                            object);
00289 
00290     /* do the deed */
00291     deleteObjectsInList(targetObjects, &depRel, flags);
00292 
00293     /* And clean up */
00294     free_object_addresses(targetObjects);
00295 
00296     heap_close(depRel, RowExclusiveLock);
00297 }
00298 
00299 /*
00300  * performMultipleDeletions: Similar to performDeletion, but act on multiple
00301  * objects at once.
00302  *
00303  * The main difference from issuing multiple performDeletion calls is that the
00304  * list of objects that would be implicitly dropped, for each object to be
00305  * dropped, is the union of the implicit-object list for all objects.  This
00306  * makes each check be more relaxed.
00307  */
00308 void
00309 performMultipleDeletions(const ObjectAddresses *objects,
00310                          DropBehavior behavior, int flags)
00311 {
00312     Relation    depRel;
00313     ObjectAddresses *targetObjects;
00314     int         i;
00315 
00316     /* No work if no objects... */
00317     if (objects->numrefs <= 0)
00318         return;
00319 
00320     /*
00321      * We save some cycles by opening pg_depend just once and passing the
00322      * Relation pointer down to all the recursive deletion steps.
00323      */
00324     depRel = heap_open(DependRelationId, RowExclusiveLock);
00325 
00326     /*
00327      * Construct a list of objects to delete (ie, the given objects plus
00328      * everything directly or indirectly dependent on them).  Note that
00329      * because we pass the whole objects list as pendingObjects context, we
00330      * won't get a failure from trying to delete an object that is internally
00331      * dependent on another one in the list; we'll just skip that object and
00332      * delete it when we reach its owner.
00333      */
00334     targetObjects = new_object_addresses();
00335 
00336     for (i = 0; i < objects->numrefs; i++)
00337     {
00338         const ObjectAddress *thisobj = objects->refs + i;
00339 
00340         /*
00341          * Acquire deletion lock on each target object.  (Ideally the caller
00342          * has done this already, but many places are sloppy about it.)
00343          */
00344         AcquireDeletionLock(thisobj, flags);
00345 
00346         findDependentObjects(thisobj,
00347                              DEPFLAG_ORIGINAL,
00348                              NULL,      /* empty stack */
00349                              targetObjects,
00350                              objects,
00351                              &depRel);
00352     }
00353 
00354     /*
00355      * Check if deletion is allowed, and report about cascaded deletes.
00356      *
00357      * If there's exactly one object being deleted, report it the same way as
00358      * in performDeletion(), else we have to be vaguer.
00359      */
00360     reportDependentObjects(targetObjects,
00361                            behavior,
00362                            NOTICE,
00363                            (objects->numrefs == 1 ? objects->refs : NULL));
00364 
00365     /* do the deed */
00366     deleteObjectsInList(targetObjects, &depRel, flags);
00367 
00368     /* And clean up */
00369     free_object_addresses(targetObjects);
00370 
00371     heap_close(depRel, RowExclusiveLock);
00372 }
00373 
00374 /*
00375  * deleteWhatDependsOn: attempt to drop everything that depends on the
00376  * specified object, though not the object itself.  Behavior is always
00377  * CASCADE.
00378  *
00379  * This is currently used only to clean out the contents of a schema
00380  * (namespace): the passed object is a namespace.  We normally want this
00381  * to be done silently, so there's an option to suppress NOTICE messages.
00382  *
00383  * Note we don't fire object drop event triggers here; it would be wrong to do
00384  * so for the current only use of this function, but if more callers are added
00385  * this might need to be reconsidered.
00386  */
00387 void
00388 deleteWhatDependsOn(const ObjectAddress *object,
00389                     bool showNotices)
00390 {
00391     Relation    depRel;
00392     ObjectAddresses *targetObjects;
00393     int         i;
00394 
00395     /*
00396      * We save some cycles by opening pg_depend just once and passing the
00397      * Relation pointer down to all the recursive deletion steps.
00398      */
00399     depRel = heap_open(DependRelationId, RowExclusiveLock);
00400 
00401     /*
00402      * Acquire deletion lock on the target object.  (Ideally the caller has
00403      * done this already, but many places are sloppy about it.)
00404      */
00405     AcquireDeletionLock(object, 0);
00406 
00407     /*
00408      * Construct a list of objects to delete (ie, the given object plus
00409      * everything directly or indirectly dependent on it).
00410      */
00411     targetObjects = new_object_addresses();
00412 
00413     findDependentObjects(object,
00414                          DEPFLAG_ORIGINAL,
00415                          NULL,  /* empty stack */
00416                          targetObjects,
00417                          NULL,  /* no pendingObjects */
00418                          &depRel);
00419 
00420     /*
00421      * Check if deletion is allowed, and report about cascaded deletes.
00422      */
00423     reportDependentObjects(targetObjects,
00424                            DROP_CASCADE,
00425                            showNotices ? NOTICE : DEBUG2,
00426                            object);
00427 
00428     /*
00429      * Delete all the objects in the proper order, except we skip the original
00430      * object.
00431      */
00432     for (i = 0; i < targetObjects->numrefs; i++)
00433     {
00434         ObjectAddress *thisobj = targetObjects->refs + i;
00435         ObjectAddressExtra *thisextra = targetObjects->extras + i;
00436 
00437         if (thisextra->flags & DEPFLAG_ORIGINAL)
00438             continue;
00439 
00440         /*
00441          * Since this function is currently only used to clean out temporary
00442          * schemas, we pass PERFORM_DELETION_INTERNAL here, indicating that
00443          * the operation is an automatic system operation rather than a user
00444          * action.  If, in the future, this function is used for other
00445          * purposes, we might need to revisit this.
00446          */
00447         deleteOneObject(thisobj, &depRel, PERFORM_DELETION_INTERNAL);
00448     }
00449 
00450     /* And clean up */
00451     free_object_addresses(targetObjects);
00452 
00453     heap_close(depRel, RowExclusiveLock);
00454 }
00455 
00456 /*
00457  * findDependentObjects - find all objects that depend on 'object'
00458  *
00459  * For every object that depends on the starting object, acquire a deletion
00460  * lock on the object, add it to targetObjects (if not already there),
00461  * and recursively find objects that depend on it.  An object's dependencies
00462  * will be placed into targetObjects before the object itself; this means
00463  * that the finished list's order represents a safe deletion order.
00464  *
00465  * The caller must already have a deletion lock on 'object' itself,
00466  * but must not have added it to targetObjects.  (Note: there are corner
00467  * cases where we won't add the object either, and will also release the
00468  * caller-taken lock.  This is a bit ugly, but the API is set up this way
00469  * to allow easy rechecking of an object's liveness after we lock it.  See
00470  * notes within the function.)
00471  *
00472  * When dropping a whole object (subId = 0), we find dependencies for
00473  * its sub-objects too.
00474  *
00475  *  object: the object to add to targetObjects and find dependencies on
00476  *  flags: flags to be ORed into the object's targetObjects entry
00477  *  stack: list of objects being visited in current recursion; topmost item
00478  *          is the object that we recursed from (NULL for external callers)
00479  *  targetObjects: list of objects that are scheduled to be deleted
00480  *  pendingObjects: list of other objects slated for destruction, but
00481  *          not necessarily in targetObjects yet (can be NULL if none)
00482  *  *depRel: already opened pg_depend relation
00483  */
00484 static void
00485 findDependentObjects(const ObjectAddress *object,
00486                      int flags,
00487                      ObjectAddressStack *stack,
00488                      ObjectAddresses *targetObjects,
00489                      const ObjectAddresses *pendingObjects,
00490                      Relation *depRel)
00491 {
00492     ScanKeyData key[3];
00493     int         nkeys;
00494     SysScanDesc scan;
00495     HeapTuple   tup;
00496     ObjectAddress otherObject;
00497     ObjectAddressStack mystack;
00498     ObjectAddressExtra extra;
00499 
00500     /*
00501      * If the target object is already being visited in an outer recursion
00502      * level, just report the current flags back to that level and exit. This
00503      * is needed to avoid infinite recursion in the face of circular
00504      * dependencies.
00505      *
00506      * The stack check alone would result in dependency loops being broken at
00507      * an arbitrary point, ie, the first member object of the loop to be
00508      * visited is the last one to be deleted.  This is obviously unworkable.
00509      * However, the check for internal dependency below guarantees that we
00510      * will not break a loop at an internal dependency: if we enter the loop
00511      * at an "owned" object we will switch and start at the "owning" object
00512      * instead.  We could probably hack something up to avoid breaking at an
00513      * auto dependency, too, if we had to.  However there are no known cases
00514      * where that would be necessary.
00515      */
00516     if (stack_address_present_add_flags(object, flags, stack))
00517         return;
00518 
00519     /*
00520      * It's also possible that the target object has already been completely
00521      * processed and put into targetObjects.  If so, again we just add the
00522      * specified flags to its entry and return.
00523      *
00524      * (Note: in these early-exit cases we could release the caller-taken
00525      * lock, since the object is presumably now locked multiple times; but it
00526      * seems not worth the cycles.)
00527      */
00528     if (object_address_present_add_flags(object, flags, targetObjects))
00529         return;
00530 
00531     /*
00532      * The target object might be internally dependent on some other object
00533      * (its "owner"), and/or be a member of an extension (also considered its
00534      * owner).  If so, and if we aren't recursing from the owning object, we
00535      * have to transform this deletion request into a deletion request of the
00536      * owning object.  (We'll eventually recurse back to this object, but the
00537      * owning object has to be visited first so it will be deleted after.) The
00538      * way to find out about this is to scan the pg_depend entries that show
00539      * what this object depends on.
00540      */
00541     ScanKeyInit(&key[0],
00542                 Anum_pg_depend_classid,
00543                 BTEqualStrategyNumber, F_OIDEQ,
00544                 ObjectIdGetDatum(object->classId));
00545     ScanKeyInit(&key[1],
00546                 Anum_pg_depend_objid,
00547                 BTEqualStrategyNumber, F_OIDEQ,
00548                 ObjectIdGetDatum(object->objectId));
00549     if (object->objectSubId != 0)
00550     {
00551         ScanKeyInit(&key[2],
00552                     Anum_pg_depend_objsubid,
00553                     BTEqualStrategyNumber, F_INT4EQ,
00554                     Int32GetDatum(object->objectSubId));
00555         nkeys = 3;
00556     }
00557     else
00558         nkeys = 2;
00559 
00560     scan = systable_beginscan(*depRel, DependDependerIndexId, true,
00561                               SnapshotNow, nkeys, key);
00562 
00563     while (HeapTupleIsValid(tup = systable_getnext(scan)))
00564     {
00565         Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
00566 
00567         otherObject.classId = foundDep->refclassid;
00568         otherObject.objectId = foundDep->refobjid;
00569         otherObject.objectSubId = foundDep->refobjsubid;
00570 
00571         switch (foundDep->deptype)
00572         {
00573             case DEPENDENCY_NORMAL:
00574             case DEPENDENCY_AUTO:
00575                 /* no problem */
00576                 break;
00577             case DEPENDENCY_INTERNAL:
00578             case DEPENDENCY_EXTENSION:
00579 
00580                 /*
00581                  * This object is part of the internal implementation of
00582                  * another object, or is part of the extension that is the
00583                  * other object.  We have three cases:
00584                  *
00585                  * 1. At the outermost recursion level, we normally disallow
00586                  * the DROP.  (We just ereport here, rather than proceeding,
00587                  * since no other dependencies are likely to be interesting.)
00588                  * However, there are exceptions.
00589                  */
00590                 if (stack == NULL)
00591                 {
00592                     char       *otherObjDesc;
00593 
00594                     /*
00595                      * Exception 1a: if the owning object is listed in
00596                      * pendingObjects, just release the caller's lock and
00597                      * return.  We'll eventually complete the DROP when we
00598                      * reach that entry in the pending list.
00599                      */
00600                     if (pendingObjects &&
00601                         object_address_present(&otherObject, pendingObjects))
00602                     {
00603                         systable_endscan(scan);
00604                         /* need to release caller's lock; see notes below */
00605                         ReleaseDeletionLock(object);
00606                         return;
00607                     }
00608 
00609                     /*
00610                      * Exception 1b: if the owning object is the extension
00611                      * currently being created/altered, it's okay to continue
00612                      * with the deletion.  This allows dropping of an
00613                      * extension's objects within the extension's scripts, as
00614                      * well as corner cases such as dropping a transient
00615                      * object created within such a script.
00616                      */
00617                     if (creating_extension &&
00618                         otherObject.classId == ExtensionRelationId &&
00619                         otherObject.objectId == CurrentExtensionObject)
00620                         break;
00621 
00622                     /* No exception applies, so throw the error */
00623                     otherObjDesc = getObjectDescription(&otherObject);
00624                     ereport(ERROR,
00625                             (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00626                              errmsg("cannot drop %s because %s requires it",
00627                                     getObjectDescription(object),
00628                                     otherObjDesc),
00629                              errhint("You can drop %s instead.",
00630                                      otherObjDesc)));
00631                 }
00632 
00633                 /*
00634                  * 2. When recursing from the other end of this dependency,
00635                  * it's okay to continue with the deletion.  This holds when
00636                  * recursing from a whole object that includes the nominal
00637                  * other end as a component, too.  Since there can be more
00638                  * than one "owning" object, we have to allow matches that are
00639                  * more than one level down in the stack.
00640                  */
00641                 if (stack_address_present_add_flags(&otherObject, 0, stack))
00642                     break;
00643 
00644                 /*
00645                  * 3. Not all the owning objects have been visited, so
00646                  * transform this deletion request into a delete of this
00647                  * owning object.
00648                  *
00649                  * First, release caller's lock on this object and get
00650                  * deletion lock on the owning object.  (We must release
00651                  * caller's lock to avoid deadlock against a concurrent
00652                  * deletion of the owning object.)
00653                  */
00654                 ReleaseDeletionLock(object);
00655                 AcquireDeletionLock(&otherObject, 0);
00656 
00657                 /*
00658                  * The owning object might have been deleted while we waited
00659                  * to lock it; if so, neither it nor the current object are
00660                  * interesting anymore.  We test this by checking the
00661                  * pg_depend entry (see notes below).
00662                  */
00663                 if (!systable_recheck_tuple(scan, tup))
00664                 {
00665                     systable_endscan(scan);
00666                     ReleaseDeletionLock(&otherObject);
00667                     return;
00668                 }
00669 
00670                 /*
00671                  * Okay, recurse to the owning object instead of proceeding.
00672                  *
00673                  * We do not need to stack the current object; we want the
00674                  * traversal order to be as if the original reference had
00675                  * linked to the owning object instead of this one.
00676                  *
00677                  * The dependency type is a "reverse" dependency: we need to
00678                  * delete the owning object if this one is to be deleted, but
00679                  * this linkage is never a reason for an automatic deletion.
00680                  */
00681                 findDependentObjects(&otherObject,
00682                                      DEPFLAG_REVERSE,
00683                                      stack,
00684                                      targetObjects,
00685                                      pendingObjects,
00686                                      depRel);
00687                 /* And we're done here. */
00688                 systable_endscan(scan);
00689                 return;
00690             case DEPENDENCY_PIN:
00691 
00692                 /*
00693                  * Should not happen; PIN dependencies should have zeroes in
00694                  * the depender fields...
00695                  */
00696                 elog(ERROR, "incorrect use of PIN dependency with %s",
00697                      getObjectDescription(object));
00698                 break;
00699             default:
00700                 elog(ERROR, "unrecognized dependency type '%c' for %s",
00701                      foundDep->deptype, getObjectDescription(object));
00702                 break;
00703         }
00704     }
00705 
00706     systable_endscan(scan);
00707 
00708     /*
00709      * Now recurse to any dependent objects.  We must visit them first since
00710      * they have to be deleted before the current object.
00711      */
00712     mystack.object = object;    /* set up a new stack level */
00713     mystack.flags = flags;
00714     mystack.next = stack;
00715 
00716     ScanKeyInit(&key[0],
00717                 Anum_pg_depend_refclassid,
00718                 BTEqualStrategyNumber, F_OIDEQ,
00719                 ObjectIdGetDatum(object->classId));
00720     ScanKeyInit(&key[1],
00721                 Anum_pg_depend_refobjid,
00722                 BTEqualStrategyNumber, F_OIDEQ,
00723                 ObjectIdGetDatum(object->objectId));
00724     if (object->objectSubId != 0)
00725     {
00726         ScanKeyInit(&key[2],
00727                     Anum_pg_depend_refobjsubid,
00728                     BTEqualStrategyNumber, F_INT4EQ,
00729                     Int32GetDatum(object->objectSubId));
00730         nkeys = 3;
00731     }
00732     else
00733         nkeys = 2;
00734 
00735     scan = systable_beginscan(*depRel, DependReferenceIndexId, true,
00736                               SnapshotNow, nkeys, key);
00737 
00738     while (HeapTupleIsValid(tup = systable_getnext(scan)))
00739     {
00740         Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
00741         int         subflags;
00742 
00743         otherObject.classId = foundDep->classid;
00744         otherObject.objectId = foundDep->objid;
00745         otherObject.objectSubId = foundDep->objsubid;
00746 
00747         /*
00748          * Must lock the dependent object before recursing to it.
00749          */
00750         AcquireDeletionLock(&otherObject, 0);
00751 
00752         /*
00753          * The dependent object might have been deleted while we waited to
00754          * lock it; if so, we don't need to do anything more with it. We can
00755          * test this cheaply and independently of the object's type by seeing
00756          * if the pg_depend tuple we are looking at is still live. (If the
00757          * object got deleted, the tuple would have been deleted too.)
00758          */
00759         if (!systable_recheck_tuple(scan, tup))
00760         {
00761             /* release the now-useless lock */
00762             ReleaseDeletionLock(&otherObject);
00763             /* and continue scanning for dependencies */
00764             continue;
00765         }
00766 
00767         /* Recurse, passing flags indicating the dependency type */
00768         switch (foundDep->deptype)
00769         {
00770             case DEPENDENCY_NORMAL:
00771                 subflags = DEPFLAG_NORMAL;
00772                 break;
00773             case DEPENDENCY_AUTO:
00774                 subflags = DEPFLAG_AUTO;
00775                 break;
00776             case DEPENDENCY_INTERNAL:
00777                 subflags = DEPFLAG_INTERNAL;
00778                 break;
00779             case DEPENDENCY_EXTENSION:
00780                 subflags = DEPFLAG_EXTENSION;
00781                 break;
00782             case DEPENDENCY_PIN:
00783 
00784                 /*
00785                  * For a PIN dependency we just ereport immediately; there
00786                  * won't be any others to report.
00787                  */
00788                 ereport(ERROR,
00789                         (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00790                          errmsg("cannot drop %s because it is required by the database system",
00791                                 getObjectDescription(object))));
00792                 subflags = 0;   /* keep compiler quiet */
00793                 break;
00794             default:
00795                 elog(ERROR, "unrecognized dependency type '%c' for %s",
00796                      foundDep->deptype, getObjectDescription(object));
00797                 subflags = 0;   /* keep compiler quiet */
00798                 break;
00799         }
00800 
00801         findDependentObjects(&otherObject,
00802                              subflags,
00803                              &mystack,
00804                              targetObjects,
00805                              pendingObjects,
00806                              depRel);
00807     }
00808 
00809     systable_endscan(scan);
00810 
00811     /*
00812      * Finally, we can add the target object to targetObjects.  Be careful to
00813      * include any flags that were passed back down to us from inner recursion
00814      * levels.
00815      */
00816     extra.flags = mystack.flags;
00817     if (stack)
00818         extra.dependee = *stack->object;
00819     else
00820         memset(&extra.dependee, 0, sizeof(extra.dependee));
00821     add_exact_object_address_extra(object, &extra, targetObjects);
00822 }
00823 
00824 /*
00825  * reportDependentObjects - report about dependencies, and fail if RESTRICT
00826  *
00827  * Tell the user about dependent objects that we are going to delete
00828  * (or would need to delete, but are prevented by RESTRICT mode);
00829  * then error out if there are any and it's not CASCADE mode.
00830  *
00831  *  targetObjects: list of objects that are scheduled to be deleted
00832  *  behavior: RESTRICT or CASCADE
00833  *  msglevel: elog level for non-error report messages
00834  *  origObject: base object of deletion, or NULL if not available
00835  *      (the latter case occurs in DROP OWNED)
00836  */
00837 static void
00838 reportDependentObjects(const ObjectAddresses *targetObjects,
00839                        DropBehavior behavior,
00840                        int msglevel,
00841                        const ObjectAddress *origObject)
00842 {
00843     bool        ok = true;
00844     StringInfoData clientdetail;
00845     StringInfoData logdetail;
00846     int         numReportedClient = 0;
00847     int         numNotReportedClient = 0;
00848     int         i;
00849 
00850     /*
00851      * If no error is to be thrown, and the msglevel is too low to be shown to
00852      * either client or server log, there's no need to do any of the work.
00853      *
00854      * Note: this code doesn't know all there is to be known about elog
00855      * levels, but it works for NOTICE and DEBUG2, which are the only values
00856      * msglevel can currently have.  We also assume we are running in a normal
00857      * operating environment.
00858      */
00859     if (behavior == DROP_CASCADE &&
00860         msglevel < client_min_messages &&
00861         (msglevel < log_min_messages || log_min_messages == LOG))
00862         return;
00863 
00864     /*
00865      * We limit the number of dependencies reported to the client to
00866      * MAX_REPORTED_DEPS, since client software may not deal well with
00867      * enormous error strings.  The server log always gets a full report.
00868      */
00869 #define MAX_REPORTED_DEPS 100
00870 
00871     initStringInfo(&clientdetail);
00872     initStringInfo(&logdetail);
00873 
00874     /*
00875      * We process the list back to front (ie, in dependency order not deletion
00876      * order), since this makes for a more understandable display.
00877      */
00878     for (i = targetObjects->numrefs - 1; i >= 0; i--)
00879     {
00880         const ObjectAddress *obj = &targetObjects->refs[i];
00881         const ObjectAddressExtra *extra = &targetObjects->extras[i];
00882         char       *objDesc;
00883 
00884         /* Ignore the original deletion target(s) */
00885         if (extra->flags & DEPFLAG_ORIGINAL)
00886             continue;
00887 
00888         objDesc = getObjectDescription(obj);
00889 
00890         /*
00891          * If, at any stage of the recursive search, we reached the object via
00892          * an AUTO, INTERNAL, or EXTENSION dependency, then it's okay to
00893          * delete it even in RESTRICT mode.
00894          */
00895         if (extra->flags & (DEPFLAG_AUTO |
00896                             DEPFLAG_INTERNAL |
00897                             DEPFLAG_EXTENSION))
00898         {
00899             /*
00900              * auto-cascades are reported at DEBUG2, not msglevel.  We don't
00901              * try to combine them with the regular message because the
00902              * results are too confusing when client_min_messages and
00903              * log_min_messages are different.
00904              */
00905             ereport(DEBUG2,
00906                     (errmsg("drop auto-cascades to %s",
00907                             objDesc)));
00908         }
00909         else if (behavior == DROP_RESTRICT)
00910         {
00911             char       *otherDesc = getObjectDescription(&extra->dependee);
00912 
00913             if (numReportedClient < MAX_REPORTED_DEPS)
00914             {
00915                 /* separate entries with a newline */
00916                 if (clientdetail.len != 0)
00917                     appendStringInfoChar(&clientdetail, '\n');
00918                 appendStringInfo(&clientdetail, _("%s depends on %s"),
00919                                  objDesc, otherDesc);
00920                 numReportedClient++;
00921             }
00922             else
00923                 numNotReportedClient++;
00924             /* separate entries with a newline */
00925             if (logdetail.len != 0)
00926                 appendStringInfoChar(&logdetail, '\n');
00927             appendStringInfo(&logdetail, _("%s depends on %s"),
00928                              objDesc, otherDesc);
00929             pfree(otherDesc);
00930             ok = false;
00931         }
00932         else
00933         {
00934             if (numReportedClient < MAX_REPORTED_DEPS)
00935             {
00936                 /* separate entries with a newline */
00937                 if (clientdetail.len != 0)
00938                     appendStringInfoChar(&clientdetail, '\n');
00939                 appendStringInfo(&clientdetail, _("drop cascades to %s"),
00940                                  objDesc);
00941                 numReportedClient++;
00942             }
00943             else
00944                 numNotReportedClient++;
00945             /* separate entries with a newline */
00946             if (logdetail.len != 0)
00947                 appendStringInfoChar(&logdetail, '\n');
00948             appendStringInfo(&logdetail, _("drop cascades to %s"),
00949                              objDesc);
00950         }
00951 
00952         pfree(objDesc);
00953     }
00954 
00955     if (numNotReportedClient > 0)
00956         appendStringInfo(&clientdetail, ngettext("\nand %d other object "
00957                                                  "(see server log for list)",
00958                                                  "\nand %d other objects "
00959                                                  "(see server log for list)",
00960                                                  numNotReportedClient),
00961                          numNotReportedClient);
00962 
00963     if (!ok)
00964     {
00965         if (origObject)
00966             ereport(ERROR,
00967                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00968                   errmsg("cannot drop %s because other objects depend on it",
00969                          getObjectDescription(origObject)),
00970                      errdetail("%s", clientdetail.data),
00971                      errdetail_log("%s", logdetail.data),
00972                      errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
00973         else
00974             ereport(ERROR,
00975                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00976                      errmsg("cannot drop desired object(s) because other objects depend on them"),
00977                      errdetail("%s", clientdetail.data),
00978                      errdetail_log("%s", logdetail.data),
00979                      errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
00980     }
00981     else if (numReportedClient > 1)
00982     {
00983         ereport(msglevel,
00984         /* translator: %d always has a value larger than 1 */
00985                 (errmsg_plural("drop cascades to %d other object",
00986                                "drop cascades to %d other objects",
00987                                numReportedClient + numNotReportedClient,
00988                                numReportedClient + numNotReportedClient),
00989                  errdetail("%s", clientdetail.data),
00990                  errdetail_log("%s", logdetail.data)));
00991     }
00992     else if (numReportedClient == 1)
00993     {
00994         /* we just use the single item as-is */
00995         ereport(msglevel,
00996                 (errmsg_internal("%s", clientdetail.data)));
00997     }
00998 
00999     pfree(clientdetail.data);
01000     pfree(logdetail.data);
01001 }
01002 
01003 /*
01004  * deleteOneObject: delete a single object for performDeletion.
01005  *
01006  * *depRel is the already-open pg_depend relation.
01007  */
01008 static void
01009 deleteOneObject(const ObjectAddress *object, Relation *depRel, int flags)
01010 {
01011     ScanKeyData key[3];
01012     int         nkeys;
01013     SysScanDesc scan;
01014     HeapTuple   tup;
01015 
01016     /* DROP hook of the objects being removed */
01017     InvokeObjectDropHookArg(object->classId, object->objectId,
01018                             object->objectSubId, flags);
01019 
01020     /*
01021      * Close depRel if we are doing a drop concurrently.  The object deletion
01022      * subroutine will commit the current transaction, so we can't keep the
01023      * relation open across doDeletion().
01024      */
01025     if (flags & PERFORM_DELETION_CONCURRENTLY)
01026         heap_close(*depRel, RowExclusiveLock);
01027 
01028     /*
01029      * Delete the object itself, in an object-type-dependent way.
01030      *
01031      * We used to do this after removing the outgoing dependency links, but it
01032      * seems just as reasonable to do it beforehand.  In the concurrent case
01033      * we *must* do it in this order, because we can't make any transactional
01034      * updates before calling doDeletion() --- they'd get committed right
01035      * away, which is not cool if the deletion then fails.
01036      */
01037     doDeletion(object, flags);
01038 
01039     /*
01040      * Reopen depRel if we closed it above
01041      */
01042     if (flags & PERFORM_DELETION_CONCURRENTLY)
01043         *depRel = heap_open(DependRelationId, RowExclusiveLock);
01044 
01045     /*
01046      * Now remove any pg_depend records that link from this object to others.
01047      * (Any records linking to this object should be gone already.)
01048      *
01049      * When dropping a whole object (subId = 0), remove all pg_depend records
01050      * for its sub-objects too.
01051      */
01052     ScanKeyInit(&key[0],
01053                 Anum_pg_depend_classid,
01054                 BTEqualStrategyNumber, F_OIDEQ,
01055                 ObjectIdGetDatum(object->classId));
01056     ScanKeyInit(&key[1],
01057                 Anum_pg_depend_objid,
01058                 BTEqualStrategyNumber, F_OIDEQ,
01059                 ObjectIdGetDatum(object->objectId));
01060     if (object->objectSubId != 0)
01061     {
01062         ScanKeyInit(&key[2],
01063                     Anum_pg_depend_objsubid,
01064                     BTEqualStrategyNumber, F_INT4EQ,
01065                     Int32GetDatum(object->objectSubId));
01066         nkeys = 3;
01067     }
01068     else
01069         nkeys = 2;
01070 
01071     scan = systable_beginscan(*depRel, DependDependerIndexId, true,
01072                               SnapshotNow, nkeys, key);
01073 
01074     while (HeapTupleIsValid(tup = systable_getnext(scan)))
01075     {
01076         simple_heap_delete(*depRel, &tup->t_self);
01077     }
01078 
01079     systable_endscan(scan);
01080 
01081     /*
01082      * Delete shared dependency references related to this object.  Again, if
01083      * subId = 0, remove records for sub-objects too.
01084      */
01085     deleteSharedDependencyRecordsFor(object->classId, object->objectId,
01086                                      object->objectSubId);
01087 
01088 
01089     /*
01090      * Delete any comments or security labels associated with this object.
01091      * (This is a convenient place to do these things, rather than having
01092      * every object type know to do it.)
01093      */
01094     DeleteComments(object->objectId, object->classId, object->objectSubId);
01095     DeleteSecurityLabel(object);
01096 
01097     /*
01098      * CommandCounterIncrement here to ensure that preceding changes are all
01099      * visible to the next deletion step.
01100      */
01101     CommandCounterIncrement();
01102 
01103     /*
01104      * And we're done!
01105      */
01106 }
01107 
01108 /*
01109  * doDeletion: actually delete a single object
01110  */
01111 static void
01112 doDeletion(const ObjectAddress *object, int flags)
01113 {
01114     switch (getObjectClass(object))
01115     {
01116         case OCLASS_CLASS:
01117             {
01118                 char        relKind = get_rel_relkind(object->objectId);
01119 
01120                 if (relKind == RELKIND_INDEX)
01121                 {
01122                     bool        concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY)
01123                                            == PERFORM_DELETION_CONCURRENTLY);
01124 
01125                     Assert(object->objectSubId == 0);
01126                     index_drop(object->objectId, concurrent);
01127                 }
01128                 else
01129                 {
01130                     if (object->objectSubId != 0)
01131                         RemoveAttributeById(object->objectId,
01132                                             object->objectSubId);
01133                     else
01134                         heap_drop_with_catalog(object->objectId);
01135                 }
01136                 break;
01137             }
01138 
01139         case OCLASS_PROC:
01140             RemoveFunctionById(object->objectId);
01141             break;
01142 
01143         case OCLASS_TYPE:
01144             RemoveTypeById(object->objectId);
01145             break;
01146 
01147         case OCLASS_CAST:
01148             DropCastById(object->objectId);
01149             break;
01150 
01151         case OCLASS_COLLATION:
01152             RemoveCollationById(object->objectId);
01153             break;
01154 
01155         case OCLASS_CONSTRAINT:
01156             RemoveConstraintById(object->objectId);
01157             break;
01158 
01159         case OCLASS_CONVERSION:
01160             RemoveConversionById(object->objectId);
01161             break;
01162 
01163         case OCLASS_DEFAULT:
01164             RemoveAttrDefaultById(object->objectId);
01165             break;
01166 
01167         case OCLASS_LANGUAGE:
01168             DropProceduralLanguageById(object->objectId);
01169             break;
01170 
01171         case OCLASS_LARGEOBJECT:
01172             LargeObjectDrop(object->objectId);
01173             break;
01174 
01175         case OCLASS_OPERATOR:
01176             RemoveOperatorById(object->objectId);
01177             break;
01178 
01179         case OCLASS_OPCLASS:
01180             RemoveOpClassById(object->objectId);
01181             break;
01182 
01183         case OCLASS_OPFAMILY:
01184             RemoveOpFamilyById(object->objectId);
01185             break;
01186 
01187         case OCLASS_AMOP:
01188             RemoveAmOpEntryById(object->objectId);
01189             break;
01190 
01191         case OCLASS_AMPROC:
01192             RemoveAmProcEntryById(object->objectId);
01193             break;
01194 
01195         case OCLASS_REWRITE:
01196             RemoveRewriteRuleById(object->objectId);
01197             break;
01198 
01199         case OCLASS_TRIGGER:
01200             RemoveTriggerById(object->objectId);
01201             break;
01202 
01203         case OCLASS_SCHEMA:
01204             RemoveSchemaById(object->objectId);
01205             break;
01206 
01207         case OCLASS_TSPARSER:
01208             RemoveTSParserById(object->objectId);
01209             break;
01210 
01211         case OCLASS_TSDICT:
01212             RemoveTSDictionaryById(object->objectId);
01213             break;
01214 
01215         case OCLASS_TSTEMPLATE:
01216             RemoveTSTemplateById(object->objectId);
01217             break;
01218 
01219         case OCLASS_TSCONFIG:
01220             RemoveTSConfigurationById(object->objectId);
01221             break;
01222 
01223             /*
01224              * OCLASS_ROLE, OCLASS_DATABASE, OCLASS_TBLSPACE intentionally not
01225              * handled here
01226              */
01227 
01228         case OCLASS_FDW:
01229             RemoveForeignDataWrapperById(object->objectId);
01230             break;
01231 
01232         case OCLASS_FOREIGN_SERVER:
01233             RemoveForeignServerById(object->objectId);
01234             break;
01235 
01236         case OCLASS_USER_MAPPING:
01237             RemoveUserMappingById(object->objectId);
01238             break;
01239 
01240         case OCLASS_DEFACL:
01241             RemoveDefaultACLById(object->objectId);
01242             break;
01243 
01244         case OCLASS_EXTENSION:
01245             RemoveExtensionById(object->objectId);
01246             break;
01247 
01248         case OCLASS_EVENT_TRIGGER:
01249             RemoveEventTriggerById(object->objectId);
01250             break;
01251 
01252         default:
01253             elog(ERROR, "unrecognized object class: %u",
01254                  object->classId);
01255     }
01256 }
01257 
01258 /*
01259  * AcquireDeletionLock - acquire a suitable lock for deleting an object
01260  *
01261  * We use LockRelation for relations, LockDatabaseObject for everything
01262  * else.  Note that dependency.c is not concerned with deleting any kind of
01263  * shared-across-databases object, so we have no need for LockSharedObject.
01264  */
01265 static void
01266 AcquireDeletionLock(const ObjectAddress *object, int flags)
01267 {
01268     if (object->classId == RelationRelationId)
01269     {
01270         /*
01271          * In DROP INDEX CONCURRENTLY, take only ShareUpdateExclusiveLock on
01272          * the index for the moment.  index_drop() will promote the lock once
01273          * it's safe to do so.  In all other cases we need full exclusive
01274          * lock.
01275          */
01276         if (flags & PERFORM_DELETION_CONCURRENTLY)
01277             LockRelationOid(object->objectId, ShareUpdateExclusiveLock);
01278         else
01279             LockRelationOid(object->objectId, AccessExclusiveLock);
01280     }
01281     else
01282     {
01283         /* assume we should lock the whole object not a sub-object */
01284         LockDatabaseObject(object->classId, object->objectId, 0,
01285                            AccessExclusiveLock);
01286     }
01287 }
01288 
01289 /*
01290  * ReleaseDeletionLock - release an object deletion lock
01291  */
01292 static void
01293 ReleaseDeletionLock(const ObjectAddress *object)
01294 {
01295     if (object->classId == RelationRelationId)
01296         UnlockRelationOid(object->objectId, AccessExclusiveLock);
01297     else
01298         /* assume we should lock the whole object not a sub-object */
01299         UnlockDatabaseObject(object->classId, object->objectId, 0,
01300                              AccessExclusiveLock);
01301 }
01302 
01303 /*
01304  * recordDependencyOnExpr - find expression dependencies
01305  *
01306  * This is used to find the dependencies of rules, constraint expressions,
01307  * etc.
01308  *
01309  * Given an expression or query in node-tree form, find all the objects
01310  * it refers to (tables, columns, operators, functions, etc).  Record
01311  * a dependency of the specified type from the given depender object
01312  * to each object mentioned in the expression.
01313  *
01314  * rtable is the rangetable to be used to interpret Vars with varlevelsup=0.
01315  * It can be NIL if no such variables are expected.
01316  */
01317 void
01318 recordDependencyOnExpr(const ObjectAddress *depender,
01319                        Node *expr, List *rtable,
01320                        DependencyType behavior)
01321 {
01322     find_expr_references_context context;
01323 
01324     context.addrs = new_object_addresses();
01325 
01326     /* Set up interpretation for Vars at varlevelsup = 0 */
01327     context.rtables = list_make1(rtable);
01328 
01329     /* Scan the expression tree for referenceable objects */
01330     find_expr_references_walker(expr, &context);
01331 
01332     /* Remove any duplicates */
01333     eliminate_duplicate_dependencies(context.addrs);
01334 
01335     /* And record 'em */
01336     recordMultipleDependencies(depender,
01337                                context.addrs->refs, context.addrs->numrefs,
01338                                behavior);
01339 
01340     free_object_addresses(context.addrs);
01341 }
01342 
01343 /*
01344  * recordDependencyOnSingleRelExpr - find expression dependencies
01345  *
01346  * As above, but only one relation is expected to be referenced (with
01347  * varno = 1 and varlevelsup = 0).  Pass the relation OID instead of a
01348  * range table.  An additional frammish is that dependencies on that
01349  * relation (or its component columns) will be marked with 'self_behavior',
01350  * whereas 'behavior' is used for everything else.
01351  *
01352  * NOTE: the caller should ensure that a whole-table dependency on the
01353  * specified relation is created separately, if one is needed.  In particular,
01354  * a whole-row Var "relation.*" will not cause this routine to emit any
01355  * dependency item.  This is appropriate behavior for subexpressions of an
01356  * ordinary query, so other cases need to cope as necessary.
01357  */
01358 void
01359 recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
01360                                 Node *expr, Oid relId,
01361                                 DependencyType behavior,
01362                                 DependencyType self_behavior)
01363 {
01364     find_expr_references_context context;
01365     RangeTblEntry rte;
01366 
01367     context.addrs = new_object_addresses();
01368 
01369     /* We gin up a rather bogus rangetable list to handle Vars */
01370     MemSet(&rte, 0, sizeof(rte));
01371     rte.type = T_RangeTblEntry;
01372     rte.rtekind = RTE_RELATION;
01373     rte.relid = relId;
01374     rte.relkind = RELKIND_RELATION;     /* no need for exactness here */
01375 
01376     context.rtables = list_make1(list_make1(&rte));
01377 
01378     /* Scan the expression tree for referenceable objects */
01379     find_expr_references_walker(expr, &context);
01380 
01381     /* Remove any duplicates */
01382     eliminate_duplicate_dependencies(context.addrs);
01383 
01384     /* Separate self-dependencies if necessary */
01385     if (behavior != self_behavior && context.addrs->numrefs > 0)
01386     {
01387         ObjectAddresses *self_addrs;
01388         ObjectAddress *outobj;
01389         int         oldref,
01390                     outrefs;
01391 
01392         self_addrs = new_object_addresses();
01393 
01394         outobj = context.addrs->refs;
01395         outrefs = 0;
01396         for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
01397         {
01398             ObjectAddress *thisobj = context.addrs->refs + oldref;
01399 
01400             if (thisobj->classId == RelationRelationId &&
01401                 thisobj->objectId == relId)
01402             {
01403                 /* Move this ref into self_addrs */
01404                 add_exact_object_address(thisobj, self_addrs);
01405             }
01406             else
01407             {
01408                 /* Keep it in context.addrs */
01409                 *outobj = *thisobj;
01410                 outobj++;
01411                 outrefs++;
01412             }
01413         }
01414         context.addrs->numrefs = outrefs;
01415 
01416         /* Record the self-dependencies */
01417         recordMultipleDependencies(depender,
01418                                    self_addrs->refs, self_addrs->numrefs,
01419                                    self_behavior);
01420 
01421         free_object_addresses(self_addrs);
01422     }
01423 
01424     /* Record the external dependencies */
01425     recordMultipleDependencies(depender,
01426                                context.addrs->refs, context.addrs->numrefs,
01427                                behavior);
01428 
01429     free_object_addresses(context.addrs);
01430 }
01431 
01432 /*
01433  * Recursively search an expression tree for object references.
01434  *
01435  * Note: we avoid creating references to columns of tables that participate
01436  * in an SQL JOIN construct, but are not actually used anywhere in the query.
01437  * To do so, we do not scan the joinaliasvars list of a join RTE while
01438  * scanning the query rangetable, but instead scan each individual entry
01439  * of the alias list when we find a reference to it.
01440  *
01441  * Note: in many cases we do not need to create dependencies on the datatypes
01442  * involved in an expression, because we'll have an indirect dependency via
01443  * some other object.  For instance Var nodes depend on a column which depends
01444  * on the datatype, and OpExpr nodes depend on the operator which depends on
01445  * the datatype.  However we do need a type dependency if there is no such
01446  * indirect dependency, as for example in Const and CoerceToDomain nodes.
01447  *
01448  * Similarly, we don't need to create dependencies on collations except where
01449  * the collation is being freshly introduced to the expression.
01450  */
01451 static bool
01452 find_expr_references_walker(Node *node,
01453                             find_expr_references_context *context)
01454 {
01455     if (node == NULL)
01456         return false;
01457     if (IsA(node, Var))
01458     {
01459         Var        *var = (Var *) node;
01460         List       *rtable;
01461         RangeTblEntry *rte;
01462 
01463         /* Find matching rtable entry, or complain if not found */
01464         if (var->varlevelsup >= list_length(context->rtables))
01465             elog(ERROR, "invalid varlevelsup %d", var->varlevelsup);
01466         rtable = (List *) list_nth(context->rtables, var->varlevelsup);
01467         if (var->varno <= 0 || var->varno > list_length(rtable))
01468             elog(ERROR, "invalid varno %d", var->varno);
01469         rte = rt_fetch(var->varno, rtable);
01470 
01471         /*
01472          * A whole-row Var references no specific columns, so adds no new
01473          * dependency.  (We assume that there is a whole-table dependency
01474          * arising from each underlying rangetable entry.  While we could
01475          * record such a dependency when finding a whole-row Var that
01476          * references a relation directly, it's quite unclear how to extend
01477          * that to whole-row Vars for JOINs, so it seems better to leave the
01478          * responsibility with the range table.  Note that this poses some
01479          * risks for identifying dependencies of stand-alone expressions:
01480          * whole-table references may need to be created separately.)
01481          */
01482         if (var->varattno == InvalidAttrNumber)
01483             return false;
01484         if (rte->rtekind == RTE_RELATION)
01485         {
01486             /* If it's a plain relation, reference this column */
01487             add_object_address(OCLASS_CLASS, rte->relid, var->varattno,
01488                                context->addrs);
01489         }
01490         else if (rte->rtekind == RTE_JOIN)
01491         {
01492             /* Scan join output column to add references to join inputs */
01493             List       *save_rtables;
01494 
01495             /* We must make the context appropriate for join's level */
01496             save_rtables = context->rtables;
01497             context->rtables = list_copy_tail(context->rtables,
01498                                               var->varlevelsup);
01499             if (var->varattno <= 0 ||
01500                 var->varattno > list_length(rte->joinaliasvars))
01501                 elog(ERROR, "invalid varattno %d", var->varattno);
01502             find_expr_references_walker((Node *) list_nth(rte->joinaliasvars,
01503                                                           var->varattno - 1),
01504                                         context);
01505             list_free(context->rtables);
01506             context->rtables = save_rtables;
01507         }
01508         return false;
01509     }
01510     else if (IsA(node, Const))
01511     {
01512         Const      *con = (Const *) node;
01513         Oid         objoid;
01514 
01515         /* A constant must depend on the constant's datatype */
01516         add_object_address(OCLASS_TYPE, con->consttype, 0,
01517                            context->addrs);
01518 
01519         /*
01520          * We must also depend on the constant's collation: it could be
01521          * different from the datatype's, if a CollateExpr was const-folded to
01522          * a simple constant.  However we can save work in the most common
01523          * case where the collation is "default", since we know that's pinned.
01524          */
01525         if (OidIsValid(con->constcollid) &&
01526             con->constcollid != DEFAULT_COLLATION_OID)
01527             add_object_address(OCLASS_COLLATION, con->constcollid, 0,
01528                                context->addrs);
01529 
01530         /*
01531          * If it's a regclass or similar literal referring to an existing
01532          * object, add a reference to that object.  (Currently, only the
01533          * regclass and regconfig cases have any likely use, but we may as
01534          * well handle all the OID-alias datatypes consistently.)
01535          */
01536         if (!con->constisnull)
01537         {
01538             switch (con->consttype)
01539             {
01540                 case REGPROCOID:
01541                 case REGPROCEDUREOID:
01542                     objoid = DatumGetObjectId(con->constvalue);
01543                     if (SearchSysCacheExists1(PROCOID,
01544                                               ObjectIdGetDatum(objoid)))
01545                         add_object_address(OCLASS_PROC, objoid, 0,
01546                                            context->addrs);
01547                     break;
01548                 case REGOPEROID:
01549                 case REGOPERATOROID:
01550                     objoid = DatumGetObjectId(con->constvalue);
01551                     if (SearchSysCacheExists1(OPEROID,
01552                                               ObjectIdGetDatum(objoid)))
01553                         add_object_address(OCLASS_OPERATOR, objoid, 0,
01554                                            context->addrs);
01555                     break;
01556                 case REGCLASSOID:
01557                     objoid = DatumGetObjectId(con->constvalue);
01558                     if (SearchSysCacheExists1(RELOID,
01559                                               ObjectIdGetDatum(objoid)))
01560                         add_object_address(OCLASS_CLASS, objoid, 0,
01561                                            context->addrs);
01562                     break;
01563                 case REGTYPEOID:
01564                     objoid = DatumGetObjectId(con->constvalue);
01565                     if (SearchSysCacheExists1(TYPEOID,
01566                                               ObjectIdGetDatum(objoid)))
01567                         add_object_address(OCLASS_TYPE, objoid, 0,
01568                                            context->addrs);
01569                     break;
01570                 case REGCONFIGOID:
01571                     objoid = DatumGetObjectId(con->constvalue);
01572                     if (SearchSysCacheExists1(TSCONFIGOID,
01573                                               ObjectIdGetDatum(objoid)))
01574                         add_object_address(OCLASS_TSCONFIG, objoid, 0,
01575                                            context->addrs);
01576                     break;
01577                 case REGDICTIONARYOID:
01578                     objoid = DatumGetObjectId(con->constvalue);
01579                     if (SearchSysCacheExists1(TSDICTOID,
01580                                               ObjectIdGetDatum(objoid)))
01581                         add_object_address(OCLASS_TSDICT, objoid, 0,
01582                                            context->addrs);
01583                     break;
01584             }
01585         }
01586         return false;
01587     }
01588     else if (IsA(node, Param))
01589     {
01590         Param      *param = (Param *) node;
01591 
01592         /* A parameter must depend on the parameter's datatype */
01593         add_object_address(OCLASS_TYPE, param->paramtype, 0,
01594                            context->addrs);
01595         /* and its collation, just as for Consts */
01596         if (OidIsValid(param->paramcollid) &&
01597             param->paramcollid != DEFAULT_COLLATION_OID)
01598             add_object_address(OCLASS_COLLATION, param->paramcollid, 0,
01599                                context->addrs);
01600     }
01601     else if (IsA(node, FuncExpr))
01602     {
01603         FuncExpr   *funcexpr = (FuncExpr *) node;
01604 
01605         add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
01606                            context->addrs);
01607         /* fall through to examine arguments */
01608     }
01609     else if (IsA(node, OpExpr))
01610     {
01611         OpExpr     *opexpr = (OpExpr *) node;
01612 
01613         add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
01614                            context->addrs);
01615         /* fall through to examine arguments */
01616     }
01617     else if (IsA(node, DistinctExpr))
01618     {
01619         DistinctExpr *distinctexpr = (DistinctExpr *) node;
01620 
01621         add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
01622                            context->addrs);
01623         /* fall through to examine arguments */
01624     }
01625     else if (IsA(node, NullIfExpr))
01626     {
01627         NullIfExpr *nullifexpr = (NullIfExpr *) node;
01628 
01629         add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
01630                            context->addrs);
01631         /* fall through to examine arguments */
01632     }
01633     else if (IsA(node, ScalarArrayOpExpr))
01634     {
01635         ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
01636 
01637         add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
01638                            context->addrs);
01639         /* fall through to examine arguments */
01640     }
01641     else if (IsA(node, Aggref))
01642     {
01643         Aggref     *aggref = (Aggref *) node;
01644 
01645         add_object_address(OCLASS_PROC, aggref->aggfnoid, 0,
01646                            context->addrs);
01647         /* fall through to examine arguments */
01648     }
01649     else if (IsA(node, WindowFunc))
01650     {
01651         WindowFunc *wfunc = (WindowFunc *) node;
01652 
01653         add_object_address(OCLASS_PROC, wfunc->winfnoid, 0,
01654                            context->addrs);
01655         /* fall through to examine arguments */
01656     }
01657     else if (IsA(node, SubPlan))
01658     {
01659         /* Extra work needed here if we ever need this case */
01660         elog(ERROR, "already-planned subqueries not supported");
01661     }
01662     else if (IsA(node, RelabelType))
01663     {
01664         RelabelType *relab = (RelabelType *) node;
01665 
01666         /* since there is no function dependency, need to depend on type */
01667         add_object_address(OCLASS_TYPE, relab->resulttype, 0,
01668                            context->addrs);
01669         /* the collation might not be referenced anywhere else, either */
01670         if (OidIsValid(relab->resultcollid) &&
01671             relab->resultcollid != DEFAULT_COLLATION_OID)
01672             add_object_address(OCLASS_COLLATION, relab->resultcollid, 0,
01673                                context->addrs);
01674     }
01675     else if (IsA(node, CoerceViaIO))
01676     {
01677         CoerceViaIO *iocoerce = (CoerceViaIO *) node;
01678 
01679         /* since there is no exposed function, need to depend on type */
01680         add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0,
01681                            context->addrs);
01682     }
01683     else if (IsA(node, ArrayCoerceExpr))
01684     {
01685         ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
01686 
01687         if (OidIsValid(acoerce->elemfuncid))
01688             add_object_address(OCLASS_PROC, acoerce->elemfuncid, 0,
01689                                context->addrs);
01690         add_object_address(OCLASS_TYPE, acoerce->resulttype, 0,
01691                            context->addrs);
01692         /* fall through to examine arguments */
01693     }
01694     else if (IsA(node, ConvertRowtypeExpr))
01695     {
01696         ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node;
01697 
01698         /* since there is no function dependency, need to depend on type */
01699         add_object_address(OCLASS_TYPE, cvt->resulttype, 0,
01700                            context->addrs);
01701     }
01702     else if (IsA(node, CollateExpr))
01703     {
01704         CollateExpr *coll = (CollateExpr *) node;
01705 
01706         add_object_address(OCLASS_COLLATION, coll->collOid, 0,
01707                            context->addrs);
01708     }
01709     else if (IsA(node, RowExpr))
01710     {
01711         RowExpr    *rowexpr = (RowExpr *) node;
01712 
01713         add_object_address(OCLASS_TYPE, rowexpr->row_typeid, 0,
01714                            context->addrs);
01715     }
01716     else if (IsA(node, RowCompareExpr))
01717     {
01718         RowCompareExpr *rcexpr = (RowCompareExpr *) node;
01719         ListCell   *l;
01720 
01721         foreach(l, rcexpr->opnos)
01722         {
01723             add_object_address(OCLASS_OPERATOR, lfirst_oid(l), 0,
01724                                context->addrs);
01725         }
01726         foreach(l, rcexpr->opfamilies)
01727         {
01728             add_object_address(OCLASS_OPFAMILY, lfirst_oid(l), 0,
01729                                context->addrs);
01730         }
01731         /* fall through to examine arguments */
01732     }
01733     else if (IsA(node, CoerceToDomain))
01734     {
01735         CoerceToDomain *cd = (CoerceToDomain *) node;
01736 
01737         add_object_address(OCLASS_TYPE, cd->resulttype, 0,
01738                            context->addrs);
01739     }
01740     else if (IsA(node, SortGroupClause))
01741     {
01742         SortGroupClause *sgc = (SortGroupClause *) node;
01743 
01744         add_object_address(OCLASS_OPERATOR, sgc->eqop, 0,
01745                            context->addrs);
01746         if (OidIsValid(sgc->sortop))
01747             add_object_address(OCLASS_OPERATOR, sgc->sortop, 0,
01748                                context->addrs);
01749         return false;
01750     }
01751     else if (IsA(node, Query))
01752     {
01753         /* Recurse into RTE subquery or not-yet-planned sublink subquery */
01754         Query      *query = (Query *) node;
01755         ListCell   *lc;
01756         bool        result;
01757 
01758         /*
01759          * Add whole-relation refs for each plain relation mentioned in the
01760          * subquery's rtable, as well as refs for any datatypes and collations
01761          * used in a RECORD function's output.
01762          *
01763          * Note: query_tree_walker takes care of recursing into RTE_FUNCTION
01764          * RTEs, subqueries, etc, so no need to do that here.  But keep it
01765          * from looking at join alias lists.
01766          *
01767          * Note: we don't need to worry about collations mentioned in
01768          * RTE_VALUES or RTE_CTE RTEs, because those must just duplicate
01769          * collations referenced in other parts of the Query.
01770          */
01771         foreach(lc, query->rtable)
01772         {
01773             RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
01774             ListCell   *ct;
01775 
01776             switch (rte->rtekind)
01777             {
01778                 case RTE_RELATION:
01779                     add_object_address(OCLASS_CLASS, rte->relid, 0,
01780                                        context->addrs);
01781                     break;
01782                 case RTE_FUNCTION:
01783                     foreach(ct, rte->funccoltypes)
01784                     {
01785                         add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0,
01786                                            context->addrs);
01787                     }
01788                     foreach(ct, rte->funccolcollations)
01789                     {
01790                         Oid         collid = lfirst_oid(ct);
01791 
01792                         if (OidIsValid(collid) &&
01793                             collid != DEFAULT_COLLATION_OID)
01794                             add_object_address(OCLASS_COLLATION, collid, 0,
01795                                                context->addrs);
01796                     }
01797                     break;
01798                 default:
01799                     break;
01800             }
01801         }
01802 
01803         /*
01804          * If the query is an INSERT or UPDATE, we should create a dependency
01805          * on each target column, to prevent the specific target column from
01806          * being dropped.  Although we will visit the TargetEntry nodes again
01807          * during query_tree_walker, we won't have enough context to do this
01808          * conveniently, so do it here.
01809          */
01810         if (query->commandType == CMD_INSERT ||
01811             query->commandType == CMD_UPDATE)
01812         {
01813             RangeTblEntry *rte;
01814 
01815             if (query->resultRelation <= 0 ||
01816                 query->resultRelation > list_length(query->rtable))
01817                 elog(ERROR, "invalid resultRelation %d",
01818                      query->resultRelation);
01819             rte = rt_fetch(query->resultRelation, query->rtable);
01820             if (rte->rtekind == RTE_RELATION)
01821             {
01822                 foreach(lc, query->targetList)
01823                 {
01824                     TargetEntry *tle = (TargetEntry *) lfirst(lc);
01825 
01826                     if (tle->resjunk)
01827                         continue;       /* ignore junk tlist items */
01828                     add_object_address(OCLASS_CLASS, rte->relid, tle->resno,
01829                                        context->addrs);
01830                 }
01831             }
01832         }
01833 
01834         /*
01835          * Add dependencies on constraints listed in query's constraintDeps
01836          */
01837         foreach(lc, query->constraintDeps)
01838         {
01839             add_object_address(OCLASS_CONSTRAINT, lfirst_oid(lc), 0,
01840                                context->addrs);
01841         }
01842 
01843         /* query_tree_walker ignores ORDER BY etc, but we need those opers */
01844         find_expr_references_walker((Node *) query->sortClause, context);
01845         find_expr_references_walker((Node *) query->groupClause, context);
01846         find_expr_references_walker((Node *) query->windowClause, context);
01847         find_expr_references_walker((Node *) query->distinctClause, context);
01848 
01849         /* Examine substructure of query */
01850         context->rtables = lcons(query->rtable, context->rtables);
01851         result = query_tree_walker(query,
01852                                    find_expr_references_walker,
01853                                    (void *) context,
01854                                    QTW_IGNORE_JOINALIASES);
01855         context->rtables = list_delete_first(context->rtables);
01856         return result;
01857     }
01858     else if (IsA(node, SetOperationStmt))
01859     {
01860         SetOperationStmt *setop = (SetOperationStmt *) node;
01861 
01862         /* we need to look at the groupClauses for operator references */
01863         find_expr_references_walker((Node *) setop->groupClauses, context);
01864         /* fall through to examine child nodes */
01865     }
01866 
01867     return expression_tree_walker(node, find_expr_references_walker,
01868                                   (void *) context);
01869 }
01870 
01871 /*
01872  * Given an array of dependency references, eliminate any duplicates.
01873  */
01874 static void
01875 eliminate_duplicate_dependencies(ObjectAddresses *addrs)
01876 {
01877     ObjectAddress *priorobj;
01878     int         oldref,
01879                 newrefs;
01880 
01881     /*
01882      * We can't sort if the array has "extra" data, because there's no way to
01883      * keep it in sync.  Fortunately that combination of features is not
01884      * needed.
01885      */
01886     Assert(!addrs->extras);
01887 
01888     if (addrs->numrefs <= 1)
01889         return;                 /* nothing to do */
01890 
01891     /* Sort the refs so that duplicates are adjacent */
01892     qsort((void *) addrs->refs, addrs->numrefs, sizeof(ObjectAddress),
01893           object_address_comparator);
01894 
01895     /* Remove dups */
01896     priorobj = addrs->refs;
01897     newrefs = 1;
01898     for (oldref = 1; oldref < addrs->numrefs; oldref++)
01899     {
01900         ObjectAddress *thisobj = addrs->refs + oldref;
01901 
01902         if (priorobj->classId == thisobj->classId &&
01903             priorobj->objectId == thisobj->objectId)
01904         {
01905             if (priorobj->objectSubId == thisobj->objectSubId)
01906                 continue;       /* identical, so drop thisobj */
01907 
01908             /*
01909              * If we have a whole-object reference and a reference to a part
01910              * of the same object, we don't need the whole-object reference
01911              * (for example, we don't need to reference both table foo and
01912              * column foo.bar).  The whole-object reference will always appear
01913              * first in the sorted list.
01914              */
01915             if (priorobj->objectSubId == 0)
01916             {
01917                 /* replace whole ref with partial */
01918                 priorobj->objectSubId = thisobj->objectSubId;
01919                 continue;
01920             }
01921         }
01922         /* Not identical, so add thisobj to output set */
01923         priorobj++;
01924         *priorobj = *thisobj;
01925         newrefs++;
01926     }
01927 
01928     addrs->numrefs = newrefs;
01929 }
01930 
01931 /*
01932  * qsort comparator for ObjectAddress items
01933  */
01934 static int
01935 object_address_comparator(const void *a, const void *b)
01936 {
01937     const ObjectAddress *obja = (const ObjectAddress *) a;
01938     const ObjectAddress *objb = (const ObjectAddress *) b;
01939 
01940     if (obja->classId < objb->classId)
01941         return -1;
01942     if (obja->classId > objb->classId)
01943         return 1;
01944     if (obja->objectId < objb->objectId)
01945         return -1;
01946     if (obja->objectId > objb->objectId)
01947         return 1;
01948 
01949     /*
01950      * We sort the subId as an unsigned int so that 0 will come first. See
01951      * logic in eliminate_duplicate_dependencies.
01952      */
01953     if ((unsigned int) obja->objectSubId < (unsigned int) objb->objectSubId)
01954         return -1;
01955     if ((unsigned int) obja->objectSubId > (unsigned int) objb->objectSubId)
01956         return 1;
01957     return 0;
01958 }
01959 
01960 /*
01961  * Routines for handling an expansible array of ObjectAddress items.
01962  *
01963  * new_object_addresses: create a new ObjectAddresses array.
01964  */
01965 ObjectAddresses *
01966 new_object_addresses(void)
01967 {
01968     ObjectAddresses *addrs;
01969 
01970     addrs = palloc(sizeof(ObjectAddresses));
01971 
01972     addrs->numrefs = 0;
01973     addrs->maxrefs = 32;
01974     addrs->refs = (ObjectAddress *)
01975         palloc(addrs->maxrefs * sizeof(ObjectAddress));
01976     addrs->extras = NULL;       /* until/unless needed */
01977 
01978     return addrs;
01979 }
01980 
01981 /*
01982  * Add an entry to an ObjectAddresses array.
01983  *
01984  * It is convenient to specify the class by ObjectClass rather than directly
01985  * by catalog OID.
01986  */
01987 static void
01988 add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
01989                    ObjectAddresses *addrs)
01990 {
01991     ObjectAddress *item;
01992 
01993     /* enlarge array if needed */
01994     if (addrs->numrefs >= addrs->maxrefs)
01995     {
01996         addrs->maxrefs *= 2;
01997         addrs->refs = (ObjectAddress *)
01998             repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
01999         Assert(!addrs->extras);
02000     }
02001     /* record this item */
02002     item = addrs->refs + addrs->numrefs;
02003     item->classId = object_classes[oclass];
02004     item->objectId = objectId;
02005     item->objectSubId = subId;
02006     addrs->numrefs++;
02007 }
02008 
02009 /*
02010  * Add an entry to an ObjectAddresses array.
02011  *
02012  * As above, but specify entry exactly.
02013  */
02014 void
02015 add_exact_object_address(const ObjectAddress *object,
02016                          ObjectAddresses *addrs)
02017 {
02018     ObjectAddress *item;
02019 
02020     /* enlarge array if needed */
02021     if (addrs->numrefs >= addrs->maxrefs)
02022     {
02023         addrs->maxrefs *= 2;
02024         addrs->refs = (ObjectAddress *)
02025             repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
02026         Assert(!addrs->extras);
02027     }
02028     /* record this item */
02029     item = addrs->refs + addrs->numrefs;
02030     *item = *object;
02031     addrs->numrefs++;
02032 }
02033 
02034 /*
02035  * Add an entry to an ObjectAddresses array.
02036  *
02037  * As above, but specify entry exactly and provide some "extra" data too.
02038  */
02039 static void
02040 add_exact_object_address_extra(const ObjectAddress *object,
02041                                const ObjectAddressExtra *extra,
02042                                ObjectAddresses *addrs)
02043 {
02044     ObjectAddress *item;
02045     ObjectAddressExtra *itemextra;
02046 
02047     /* allocate extra space if first time */
02048     if (!addrs->extras)
02049         addrs->extras = (ObjectAddressExtra *)
02050             palloc(addrs->maxrefs * sizeof(ObjectAddressExtra));
02051 
02052     /* enlarge array if needed */
02053     if (addrs->numrefs >= addrs->maxrefs)
02054     {
02055         addrs->maxrefs *= 2;
02056         addrs->refs = (ObjectAddress *)
02057             repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
02058         addrs->extras = (ObjectAddressExtra *)
02059             repalloc(addrs->extras, addrs->maxrefs * sizeof(ObjectAddressExtra));
02060     }
02061     /* record this item */
02062     item = addrs->refs + addrs->numrefs;
02063     *item = *object;
02064     itemextra = addrs->extras + addrs->numrefs;
02065     *itemextra = *extra;
02066     addrs->numrefs++;
02067 }
02068 
02069 /*
02070  * Test whether an object is present in an ObjectAddresses array.
02071  *
02072  * We return "true" if object is a subobject of something in the array, too.
02073  */
02074 bool
02075 object_address_present(const ObjectAddress *object,
02076                        const ObjectAddresses *addrs)
02077 {
02078     int         i;
02079 
02080     for (i = addrs->numrefs - 1; i >= 0; i--)
02081     {
02082         const ObjectAddress *thisobj = addrs->refs + i;
02083 
02084         if (object->classId == thisobj->classId &&
02085             object->objectId == thisobj->objectId)
02086         {
02087             if (object->objectSubId == thisobj->objectSubId ||
02088                 thisobj->objectSubId == 0)
02089                 return true;
02090         }
02091     }
02092 
02093     return false;
02094 }
02095 
02096 /*
02097  * As above, except that if the object is present then also OR the given
02098  * flags into its associated extra data (which must exist).
02099  */
02100 static bool
02101 object_address_present_add_flags(const ObjectAddress *object,
02102                                  int flags,
02103                                  ObjectAddresses *addrs)
02104 {
02105     int         i;
02106 
02107     for (i = addrs->numrefs - 1; i >= 0; i--)
02108     {
02109         ObjectAddress *thisobj = addrs->refs + i;
02110 
02111         if (object->classId == thisobj->classId &&
02112             object->objectId == thisobj->objectId)
02113         {
02114             if (object->objectSubId == thisobj->objectSubId)
02115             {
02116                 ObjectAddressExtra *thisextra = addrs->extras + i;
02117 
02118                 thisextra->flags |= flags;
02119                 return true;
02120             }
02121             if (thisobj->objectSubId == 0)
02122             {
02123                 /*
02124                  * We get here if we find a need to delete a column after
02125                  * having already decided to drop its whole table.  Obviously
02126                  * we no longer need to drop the column.  But don't plaster
02127                  * its flags on the table.
02128                  */
02129                 return true;
02130             }
02131         }
02132     }
02133 
02134     return false;
02135 }
02136 
02137 /*
02138  * Similar to above, except we search an ObjectAddressStack.
02139  */
02140 static bool
02141 stack_address_present_add_flags(const ObjectAddress *object,
02142                                 int flags,
02143                                 ObjectAddressStack *stack)
02144 {
02145     ObjectAddressStack *stackptr;
02146 
02147     for (stackptr = stack; stackptr; stackptr = stackptr->next)
02148     {
02149         const ObjectAddress *thisobj = stackptr->object;
02150 
02151         if (object->classId == thisobj->classId &&
02152             object->objectId == thisobj->objectId)
02153         {
02154             if (object->objectSubId == thisobj->objectSubId)
02155             {
02156                 stackptr->flags |= flags;
02157                 return true;
02158             }
02159 
02160             /*
02161              * Could visit column with whole table already on stack; this is
02162              * the same case noted in object_address_present_add_flags(), and
02163              * as in that case, we don't propagate flags for the component to
02164              * the whole object.
02165              */
02166             if (thisobj->objectSubId == 0)
02167                 return true;
02168         }
02169     }
02170 
02171     return false;
02172 }
02173 
02174 /*
02175  * Record multiple dependencies from an ObjectAddresses array, after first
02176  * removing any duplicates.
02177  */
02178 void
02179 record_object_address_dependencies(const ObjectAddress *depender,
02180                                    ObjectAddresses *referenced,
02181                                    DependencyType behavior)
02182 {
02183     eliminate_duplicate_dependencies(referenced);
02184     recordMultipleDependencies(depender,
02185                                referenced->refs, referenced->numrefs,
02186                                behavior);
02187 }
02188 
02189 /*
02190  * Clean up when done with an ObjectAddresses array.
02191  */
02192 void
02193 free_object_addresses(ObjectAddresses *addrs)
02194 {
02195     pfree(addrs->refs);
02196     if (addrs->extras)
02197         pfree(addrs->extras);
02198     pfree(addrs);
02199 }
02200 
02201 /*
02202  * Determine the class of a given object identified by objectAddress.
02203  *
02204  * This function is essentially the reverse mapping for the object_classes[]
02205  * table.  We implement it as a function because the OIDs aren't consecutive.
02206  */
02207 ObjectClass
02208 getObjectClass(const ObjectAddress *object)
02209 {
02210     /* only pg_class entries can have nonzero objectSubId */
02211     if (object->classId != RelationRelationId &&
02212         object->objectSubId != 0)
02213         elog(ERROR, "invalid non-zero objectSubId for object class %u",
02214              object->classId);
02215 
02216     switch (object->classId)
02217     {
02218         case RelationRelationId:
02219             /* caller must check objectSubId */
02220             return OCLASS_CLASS;
02221 
02222         case ProcedureRelationId:
02223             return OCLASS_PROC;
02224 
02225         case TypeRelationId:
02226             return OCLASS_TYPE;
02227 
02228         case CastRelationId:
02229             return OCLASS_CAST;
02230 
02231         case CollationRelationId:
02232             return OCLASS_COLLATION;
02233 
02234         case ConstraintRelationId:
02235             return OCLASS_CONSTRAINT;
02236 
02237         case ConversionRelationId:
02238             return OCLASS_CONVERSION;
02239 
02240         case AttrDefaultRelationId:
02241             return OCLASS_DEFAULT;
02242 
02243         case LanguageRelationId:
02244             return OCLASS_LANGUAGE;
02245 
02246         case LargeObjectRelationId:
02247             return OCLASS_LARGEOBJECT;
02248 
02249         case OperatorRelationId:
02250             return OCLASS_OPERATOR;
02251 
02252         case OperatorClassRelationId:
02253             return OCLASS_OPCLASS;
02254 
02255         case OperatorFamilyRelationId:
02256             return OCLASS_OPFAMILY;
02257 
02258         case AccessMethodOperatorRelationId:
02259             return OCLASS_AMOP;
02260 
02261         case AccessMethodProcedureRelationId:
02262             return OCLASS_AMPROC;
02263 
02264         case RewriteRelationId:
02265             return OCLASS_REWRITE;
02266 
02267         case TriggerRelationId:
02268             return OCLASS_TRIGGER;
02269 
02270         case NamespaceRelationId:
02271             return OCLASS_SCHEMA;
02272 
02273         case TSParserRelationId:
02274             return OCLASS_TSPARSER;
02275 
02276         case TSDictionaryRelationId:
02277             return OCLASS_TSDICT;
02278 
02279         case TSTemplateRelationId:
02280             return OCLASS_TSTEMPLATE;
02281 
02282         case TSConfigRelationId:
02283             return OCLASS_TSCONFIG;
02284 
02285         case AuthIdRelationId:
02286             return OCLASS_ROLE;
02287 
02288         case DatabaseRelationId:
02289             return OCLASS_DATABASE;
02290 
02291         case TableSpaceRelationId:
02292             return OCLASS_TBLSPACE;
02293 
02294         case ForeignDataWrapperRelationId:
02295             return OCLASS_FDW;
02296 
02297         case ForeignServerRelationId:
02298             return OCLASS_FOREIGN_SERVER;
02299 
02300         case UserMappingRelationId:
02301             return OCLASS_USER_MAPPING;
02302 
02303         case DefaultAclRelationId:
02304             return OCLASS_DEFACL;
02305 
02306         case ExtensionRelationId:
02307             return OCLASS_EXTENSION;
02308 
02309         case EventTriggerRelationId:
02310             return OCLASS_EVENT_TRIGGER;
02311     }
02312 
02313     /* shouldn't get here */
02314     elog(ERROR, "unrecognized object class: %u", object->classId);
02315     return OCLASS_CLASS;        /* keep compiler quiet */
02316 }