1 /*-------------------------------------------------------------------------
4 * Routines to support inter-object dependencies.
7 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.52 2006/04/29 16:43:54 momjian Exp $
13 *-------------------------------------------------------------------------
17 #include "access/genam.h"
18 #include "access/heapam.h"
19 #include "catalog/dependency.h"
20 #include "catalog/heap.h"
21 #include "catalog/index.h"
22 #include "catalog/indexing.h"
23 #include "catalog/namespace.h"
24 #include "catalog/pg_attrdef.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/pg_cast.h"
27 #include "catalog/pg_constraint.h"
28 #include "catalog/pg_conversion.h"
29 #include "catalog/pg_database.h"
30 #include "catalog/pg_depend.h"
31 #include "catalog/pg_language.h"
32 #include "catalog/pg_namespace.h"
33 #include "catalog/pg_opclass.h"
34 #include "catalog/pg_operator.h"
35 #include "catalog/pg_proc.h"
36 #include "catalog/pg_rewrite.h"
37 #include "catalog/pg_tablespace.h"
38 #include "catalog/pg_trigger.h"
39 #include "catalog/pg_type.h"
40 #include "commands/comment.h"
41 #include "commands/dbcommands.h"
42 #include "commands/defrem.h"
43 #include "commands/proclang.h"
44 #include "commands/schemacmds.h"
45 #include "commands/tablespace.h"
46 #include "commands/trigger.h"
47 #include "commands/typecmds.h"
48 #include "lib/stringinfo.h"
49 #include "miscadmin.h"
50 #include "optimizer/clauses.h"
51 #include "parser/parsetree.h"
52 #include "rewrite/rewriteRemove.h"
53 #include "utils/builtins.h"
54 #include "utils/fmgroids.h"
55 #include "utils/lsyscache.h"
56 #include "utils/syscache.h"
59 /* expansible list of ObjectAddresses */
62 ObjectAddress *refs; /* => palloc'd array */
63 int numrefs; /* current number of references */
64 int maxrefs; /* current size of palloc'd array */
67 /* for find_expr_references_walker */
70 ObjectAddresses addrs; /* addresses being accumulated */
71 List *rtables; /* list of rangetables to resolve Vars */
72 } find_expr_references_context;
75 * This constant table maps ObjectClasses to the corresponding catalog OIDs.
76 * See also getObjectClass().
78 static const Oid object_classes[MAX_OCLASS] = {
79 RelationRelationId, /* OCLASS_CLASS */
80 ProcedureRelationId, /* OCLASS_PROC */
81 TypeRelationId, /* OCLASS_TYPE */
82 CastRelationId, /* OCLASS_CAST */
83 ConstraintRelationId, /* OCLASS_CONSTRAINT */
84 ConversionRelationId, /* OCLASS_CONVERSION */
85 AttrDefaultRelationId, /* OCLASS_DEFAULT */
86 LanguageRelationId, /* OCLASS_LANGUAGE */
87 OperatorRelationId, /* OCLASS_OPERATOR */
88 OperatorClassRelationId, /* OCLASS_OPCLASS */
89 RewriteRelationId, /* OCLASS_REWRITE */
90 TriggerRelationId, /* OCLASS_TRIGGER */
91 NamespaceRelationId /* OCLASS_SCHEMA */
95 static void findAutoDeletableObjects(const ObjectAddress *object,
96 ObjectAddresses *oktodelete,
98 static bool recursiveDeletion(const ObjectAddress *object,
99 DropBehavior behavior,
101 const ObjectAddress *callingObject,
102 ObjectAddresses *oktodelete,
104 static bool deleteDependentObjects(const ObjectAddress *object,
105 const char *objDescription,
106 DropBehavior behavior,
108 ObjectAddresses *oktodelete,
110 static void doDeletion(const ObjectAddress *object);
111 static bool find_expr_references_walker(Node *node,
112 find_expr_references_context *context);
113 static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
114 static int object_address_comparator(const void *a, const void *b);
115 static void init_object_addresses(ObjectAddresses *addrs);
116 static void add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
117 ObjectAddresses *addrs);
118 static void add_exact_object_address(const ObjectAddress *object,
119 ObjectAddresses *addrs);
120 static bool object_address_present(const ObjectAddress *object,
121 ObjectAddresses *addrs);
122 static void term_object_addresses(ObjectAddresses *addrs);
123 static void getRelationDescription(StringInfo buffer, Oid relid);
127 * performDeletion: attempt to drop the specified object. If CASCADE
128 * behavior is specified, also drop any dependent objects (recursively).
129 * If RESTRICT behavior is specified, error out if there are any dependent
130 * objects, except for those that should be implicitly dropped anyway
131 * according to the dependency type.
133 * This is the outer control routine for all forms of DROP that drop objects
134 * that can participate in dependencies.
137 performDeletion(const ObjectAddress *object,
138 DropBehavior behavior)
140 char *objDescription;
142 ObjectAddresses oktodelete;
145 * Get object description for possible use in failure message. Must do
146 * this before deleting it ...
148 objDescription = getObjectDescription(object);
151 * We save some cycles by opening pg_depend just once and passing the
152 * Relation pointer down to all the recursive deletion steps.
154 depRel = heap_open(DependRelationId, RowExclusiveLock);
157 * Construct a list of objects that are reachable by AUTO or INTERNAL
158 * dependencies from the target object. These should be deleted silently,
159 * even if the actual deletion pass first reaches one of them via a
160 * non-auto dependency.
162 init_object_addresses(&oktodelete);
164 findAutoDeletableObjects(object, &oktodelete, depRel);
166 if (!recursiveDeletion(object, behavior, NOTICE,
167 NULL, &oktodelete, depRel))
169 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
170 errmsg("cannot drop %s because other objects depend on it",
172 errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
174 term_object_addresses(&oktodelete);
176 heap_close(depRel, RowExclusiveLock);
178 pfree(objDescription);
183 * deleteWhatDependsOn: attempt to drop everything that depends on the
184 * specified object, though not the object itself. Behavior is always
187 * This is currently used only to clean out the contents of a schema
188 * (namespace): the passed object is a namespace. We normally want this
189 * to be done silently, so there's an option to suppress NOTICE messages.
192 deleteWhatDependsOn(const ObjectAddress *object,
195 char *objDescription;
197 ObjectAddresses oktodelete;
200 * Get object description for possible use in failure messages
202 objDescription = getObjectDescription(object);
205 * We save some cycles by opening pg_depend just once and passing the
206 * Relation pointer down to all the recursive deletion steps.
208 depRel = heap_open(DependRelationId, RowExclusiveLock);
211 * Construct a list of objects that are reachable by AUTO or INTERNAL
212 * dependencies from the target object. These should be deleted silently,
213 * even if the actual deletion pass first reaches one of them via a
214 * non-auto dependency.
216 init_object_addresses(&oktodelete);
218 findAutoDeletableObjects(object, &oktodelete, depRel);
221 * Now invoke only step 2 of recursiveDeletion: just recurse to the stuff
222 * dependent on the given object.
224 if (!deleteDependentObjects(object, objDescription,
226 showNotices ? NOTICE : DEBUG2,
227 &oktodelete, depRel))
229 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
230 errmsg("failed to drop all objects depending on %s",
234 * We do not need CommandCounterIncrement here, since if step 2 did
235 * anything then each recursive call will have ended with one.
238 term_object_addresses(&oktodelete);
240 heap_close(depRel, RowExclusiveLock);
242 pfree(objDescription);
247 * findAutoDeletableObjects: find all objects that are reachable by AUTO or
248 * INTERNAL dependency paths from the given object. Add them all to the
249 * oktodelete list. Note that the originally given object will also be
252 * depRel is the already-open pg_depend relation.
255 findAutoDeletableObjects(const ObjectAddress *object,
256 ObjectAddresses *oktodelete,
263 ObjectAddress otherObject;
266 * If this object is already in oktodelete, then we already visited it;
267 * don't do so again (this prevents infinite recursion if there's a loop
268 * in pg_depend). Otherwise, add it.
270 if (object_address_present(object, oktodelete))
272 add_exact_object_address(object, oktodelete);
275 * Scan pg_depend records that link to this object, showing the things
276 * that depend on it. For each one that is AUTO or INTERNAL, visit the
277 * referencing object.
279 * When dropping a whole object (subId = 0), find pg_depend records for
280 * its sub-objects too.
283 Anum_pg_depend_refclassid,
284 BTEqualStrategyNumber, F_OIDEQ,
285 ObjectIdGetDatum(object->classId));
287 Anum_pg_depend_refobjid,
288 BTEqualStrategyNumber, F_OIDEQ,
289 ObjectIdGetDatum(object->objectId));
290 if (object->objectSubId != 0)
293 Anum_pg_depend_refobjsubid,
294 BTEqualStrategyNumber, F_INT4EQ,
295 Int32GetDatum(object->objectSubId));
301 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
302 SnapshotNow, nkeys, key);
304 while (HeapTupleIsValid(tup = systable_getnext(scan)))
306 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
308 switch (foundDep->deptype)
310 case DEPENDENCY_NORMAL:
313 case DEPENDENCY_AUTO:
314 case DEPENDENCY_INTERNAL:
316 otherObject.classId = foundDep->classid;
317 otherObject.objectId = foundDep->objid;
318 otherObject.objectSubId = foundDep->objsubid;
319 findAutoDeletableObjects(&otherObject, oktodelete, depRel);
324 * For a PIN dependency we just ereport immediately; there
325 * won't be any others to examine, and we aren't ever going to
326 * let the user delete it.
329 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
330 errmsg("cannot drop %s because it is required by the database system",
331 getObjectDescription(object))));
334 elog(ERROR, "unrecognized dependency type '%c' for %s",
335 foundDep->deptype, getObjectDescription(object));
340 systable_endscan(scan);
345 * recursiveDeletion: delete a single object for performDeletion, plus
346 * (recursively) anything that depends on it.
348 * Returns TRUE if successful, FALSE if not.
350 * callingObject is NULL at the outer level, else identifies the object that
351 * we recursed from (the reference object that someone else needs to delete).
353 * oktodelete is a list of objects verified deletable (ie, reachable by one
354 * or more AUTO or INTERNAL dependencies from the original target).
356 * depRel is the already-open pg_depend relation.
359 * In RESTRICT mode, we perform all the deletions anyway, but ereport a message
360 * and return FALSE if we find a restriction violation. performDeletion
361 * will then abort the transaction to nullify the deletions. We have to
362 * do it this way to (a) report all the direct and indirect dependencies
363 * while (b) not going into infinite recursion if there's a cycle.
365 * This is even more complex than one could wish, because it is possible for
366 * the same pair of objects to be related by both NORMAL and AUTO/INTERNAL
367 * dependencies. Also, we might have a situation where we've been asked to
368 * delete object A, and objects B and C both have AUTO dependencies on A,
369 * but B also has a NORMAL dependency on C. (Since any of these paths might
370 * be indirect, we can't prevent these scenarios, but must cope instead.)
371 * If we visit C before B then we would mistakenly decide that the B->C link
372 * should prevent the restricted drop from occurring. To handle this, we make
373 * a pre-scan to find all the objects that are auto-deletable from A. If we
374 * visit C first, but B is present in the oktodelete list, then we make no
375 * complaint but recurse to delete B anyway. (Note that in general we must
376 * delete B before deleting C; the drop routine for B may try to access C.)
378 * Note: in the case where the path to B is traversed first, we will not
379 * see the NORMAL dependency when we reach C, because of the pg_depend
380 * removals done in step 1. The oktodelete list is necessary just
381 * to make the behavior independent of the order in which pg_depend
382 * entries are visited.
385 recursiveDeletion(const ObjectAddress *object,
386 DropBehavior behavior,
388 const ObjectAddress *callingObject,
389 ObjectAddresses *oktodelete,
393 char *objDescription;
398 ObjectAddress otherObject;
399 ObjectAddress owningObject;
400 bool amOwned = false;
403 * Get object description for possible use in messages. Must do this
404 * before deleting it ...
406 objDescription = getObjectDescription(object);
409 * Step 1: find and remove pg_depend records that link from this object to
410 * others. We have to do this anyway, and doing it first ensures that we
411 * avoid infinite recursion in the case of cycles. Also, some dependency
412 * types require extra processing here.
414 * When dropping a whole object (subId = 0), remove all pg_depend records
415 * for its sub-objects too.
418 Anum_pg_depend_classid,
419 BTEqualStrategyNumber, F_OIDEQ,
420 ObjectIdGetDatum(object->classId));
422 Anum_pg_depend_objid,
423 BTEqualStrategyNumber, F_OIDEQ,
424 ObjectIdGetDatum(object->objectId));
425 if (object->objectSubId != 0)
428 Anum_pg_depend_objsubid,
429 BTEqualStrategyNumber, F_INT4EQ,
430 Int32GetDatum(object->objectSubId));
436 scan = systable_beginscan(depRel, DependDependerIndexId, true,
437 SnapshotNow, nkeys, key);
439 while (HeapTupleIsValid(tup = systable_getnext(scan)))
441 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
443 otherObject.classId = foundDep->refclassid;
444 otherObject.objectId = foundDep->refobjid;
445 otherObject.objectSubId = foundDep->refobjsubid;
447 switch (foundDep->deptype)
449 case DEPENDENCY_NORMAL:
450 case DEPENDENCY_AUTO:
453 case DEPENDENCY_INTERNAL:
456 * This object is part of the internal implementation of
457 * another object. We have three cases:
459 * 1. At the outermost recursion level, disallow the DROP. (We
460 * just ereport here, rather than proceeding, since no other
461 * dependencies are likely to be interesting.)
463 if (callingObject == NULL)
465 char *otherObjDesc = getObjectDescription(&otherObject);
468 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
469 errmsg("cannot drop %s because %s requires it",
470 objDescription, otherObjDesc),
471 errhint("You may drop %s instead.",
476 * 2. When recursing from the other end of this dependency,
477 * it's okay to continue with the deletion. This holds when
478 * recursing from a whole object that includes the nominal
479 * other end as a component, too.
481 if (callingObject->classId == otherObject.classId &&
482 callingObject->objectId == otherObject.objectId &&
483 (callingObject->objectSubId == otherObject.objectSubId ||
484 callingObject->objectSubId == 0))
488 * 3. When recursing from anyplace else, transform this
489 * deletion request into a delete of the other object. (This
490 * will be an error condition iff RESTRICT mode.) In this case
491 * we finish deleting my dependencies except for the INTERNAL
492 * link, which will be needed to cause the owning object to
493 * recurse back to me.
495 if (amOwned) /* shouldn't happen */
496 elog(ERROR, "multiple INTERNAL dependencies for %s",
498 owningObject = otherObject;
500 /* "continue" bypasses the simple_heap_delete call below */
505 * Should not happen; PIN dependencies should have zeroes in
506 * the depender fields...
508 elog(ERROR, "incorrect use of PIN dependency with %s",
512 elog(ERROR, "unrecognized dependency type '%c' for %s",
513 foundDep->deptype, objDescription);
517 /* delete the pg_depend tuple */
518 simple_heap_delete(depRel, &tup->t_self);
521 systable_endscan(scan);
524 * CommandCounterIncrement here to ensure that preceding changes are all
525 * visible; in particular, that the above deletions of pg_depend entries
526 * are visible. That prevents infinite recursion in case of a dependency
527 * loop (which is perfectly legal).
529 CommandCounterIncrement();
532 * If we found we are owned by another object, ask it to delete itself
533 * instead of proceeding. Complain if RESTRICT mode, unless the other
534 * object is in oktodelete.
538 if (object_address_present(&owningObject, oktodelete))
540 (errmsg("drop auto-cascades to %s",
541 getObjectDescription(&owningObject))));
542 else if (behavior == DROP_RESTRICT)
545 (errmsg("%s depends on %s",
546 getObjectDescription(&owningObject),
552 (errmsg("drop cascades to %s",
553 getObjectDescription(&owningObject))));
555 if (!recursiveDeletion(&owningObject, behavior, msglevel,
556 object, oktodelete, depRel))
559 pfree(objDescription);
565 * Step 2: scan pg_depend records that link to this object, showing the
566 * things that depend on it. Recursively delete those things. Note it's
567 * important to delete the dependent objects before the referenced one,
568 * since the deletion routines might do things like try to update the
569 * pg_class record when deleting a check constraint.
571 if (!deleteDependentObjects(object, objDescription,
577 * We do not need CommandCounterIncrement here, since if step 2 did
578 * anything then each recursive call will have ended with one.
582 * Step 3: delete the object itself.
587 * Delete any comments associated with this object. (This is a convenient
588 * place to do it instead of having every object type know to do it.)
590 DeleteComments(object->objectId, object->classId, object->objectSubId);
593 * Delete shared dependency references related to this object. Sub-objects
594 * (columns) don't have dependencies on global objects, so skip them.
596 if (object->objectSubId == 0)
597 deleteSharedDependencyRecordsFor(object->classId, object->objectId);
600 * CommandCounterIncrement here to ensure that preceding changes are all
603 CommandCounterIncrement();
608 pfree(objDescription);
615 * deleteDependentObjects - find and delete objects that depend on 'object'
617 * Scan pg_depend records that link to the given object, showing
618 * the things that depend on it. Recursively delete those things. (We
619 * don't delete the pg_depend records here, as the recursive call will
620 * do that.) Note it's important to delete the dependent objects
621 * before the referenced one, since the deletion routines might do
622 * things like try to update the pg_class record when deleting a check
625 * When dropping a whole object (subId = 0), find pg_depend records for
626 * its sub-objects too.
628 * object: the object to find dependencies on
629 * objDescription: description of object (only used for error messages)
630 * behavior: desired drop behavior
631 * oktodelete: stuff that's AUTO-deletable
632 * depRel: already opened pg_depend relation
634 * Returns TRUE if all is well, false if any problem found.
636 * NOTE: because we are using SnapshotNow, if a recursive call deletes
637 * any pg_depend tuples that our scan hasn't yet visited, we will not
638 * see them as good when we do visit them. This is essential for
639 * correct behavior if there are multiple dependency paths between two
640 * objects --- else we might try to delete an already-deleted object.
643 deleteDependentObjects(const ObjectAddress *object,
644 const char *objDescription,
645 DropBehavior behavior,
647 ObjectAddresses *oktodelete,
655 ObjectAddress otherObject;
658 Anum_pg_depend_refclassid,
659 BTEqualStrategyNumber, F_OIDEQ,
660 ObjectIdGetDatum(object->classId));
662 Anum_pg_depend_refobjid,
663 BTEqualStrategyNumber, F_OIDEQ,
664 ObjectIdGetDatum(object->objectId));
665 if (object->objectSubId != 0)
668 Anum_pg_depend_refobjsubid,
669 BTEqualStrategyNumber, F_INT4EQ,
670 Int32GetDatum(object->objectSubId));
676 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
677 SnapshotNow, nkeys, key);
679 while (HeapTupleIsValid(tup = systable_getnext(scan)))
681 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
683 otherObject.classId = foundDep->classid;
684 otherObject.objectId = foundDep->objid;
685 otherObject.objectSubId = foundDep->objsubid;
687 switch (foundDep->deptype)
689 case DEPENDENCY_NORMAL:
692 * Perhaps there was another dependency path that would have
693 * allowed silent deletion of the otherObject, had we only
694 * taken that path first. In that case, act like this link is
697 if (object_address_present(&otherObject, oktodelete))
699 (errmsg("drop auto-cascades to %s",
700 getObjectDescription(&otherObject))));
701 else if (behavior == DROP_RESTRICT)
704 (errmsg("%s depends on %s",
705 getObjectDescription(&otherObject),
711 (errmsg("drop cascades to %s",
712 getObjectDescription(&otherObject))));
714 if (!recursiveDeletion(&otherObject, behavior, msglevel,
715 object, oktodelete, depRel))
718 case DEPENDENCY_AUTO:
719 case DEPENDENCY_INTERNAL:
722 * We propagate the DROP without complaint even in the
723 * RESTRICT case. (However, normal dependencies on the
724 * component object could still cause failure.)
727 (errmsg("drop auto-cascades to %s",
728 getObjectDescription(&otherObject))));
730 if (!recursiveDeletion(&otherObject, behavior, msglevel,
731 object, oktodelete, depRel))
737 * For a PIN dependency we just ereport immediately; there
738 * won't be any others to report.
741 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
742 errmsg("cannot drop %s because it is required by the database system",
746 elog(ERROR, "unrecognized dependency type '%c' for %s",
747 foundDep->deptype, objDescription);
752 systable_endscan(scan);
759 * doDeletion: actually delete a single object
762 doDeletion(const ObjectAddress *object)
764 switch (getObjectClass(object))
768 char relKind = get_rel_relkind(object->objectId);
770 if (relKind == RELKIND_INDEX)
772 Assert(object->objectSubId == 0);
773 index_drop(object->objectId);
777 if (object->objectSubId != 0)
778 RemoveAttributeById(object->objectId,
779 object->objectSubId);
781 heap_drop_with_catalog(object->objectId);
787 RemoveFunctionById(object->objectId);
791 RemoveTypeById(object->objectId);
795 DropCastById(object->objectId);
798 case OCLASS_CONSTRAINT:
799 RemoveConstraintById(object->objectId);
802 case OCLASS_CONVERSION:
803 RemoveConversionById(object->objectId);
807 RemoveAttrDefaultById(object->objectId);
810 case OCLASS_LANGUAGE:
811 DropProceduralLanguageById(object->objectId);
814 case OCLASS_OPERATOR:
815 RemoveOperatorById(object->objectId);
819 RemoveOpClassById(object->objectId);
823 RemoveRewriteRuleById(object->objectId);
827 RemoveTriggerById(object->objectId);
831 RemoveSchemaById(object->objectId);
835 elog(ERROR, "unrecognized object class: %u",
841 * recordDependencyOnExpr - find expression dependencies
843 * This is used to find the dependencies of rules, constraint expressions,
846 * Given an expression or query in node-tree form, find all the objects
847 * it refers to (tables, columns, operators, functions, etc). Record
848 * a dependency of the specified type from the given depender object
849 * to each object mentioned in the expression.
851 * rtable is the rangetable to be used to interpret Vars with varlevelsup=0.
852 * It can be NIL if no such variables are expected.
855 recordDependencyOnExpr(const ObjectAddress *depender,
856 Node *expr, List *rtable,
857 DependencyType behavior)
859 find_expr_references_context context;
861 init_object_addresses(&context.addrs);
863 /* Set up interpretation for Vars at varlevelsup = 0 */
864 context.rtables = list_make1(rtable);
866 /* Scan the expression tree for referenceable objects */
867 find_expr_references_walker(expr, &context);
869 /* Remove any duplicates */
870 eliminate_duplicate_dependencies(&context.addrs);
873 recordMultipleDependencies(depender,
874 context.addrs.refs, context.addrs.numrefs,
877 term_object_addresses(&context.addrs);
881 * recordDependencyOnSingleRelExpr - find expression dependencies
883 * As above, but only one relation is expected to be referenced (with
884 * varno = 1 and varlevelsup = 0). Pass the relation OID instead of a
885 * range table. An additional frammish is that dependencies on that
886 * relation (or its component columns) will be marked with 'self_behavior',
887 * whereas 'behavior' is used for everything else.
890 recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
891 Node *expr, Oid relId,
892 DependencyType behavior,
893 DependencyType self_behavior)
895 find_expr_references_context context;
898 init_object_addresses(&context.addrs);
900 /* We gin up a rather bogus rangetable list to handle Vars */
901 MemSet(&rte, 0, sizeof(rte));
902 rte.type = T_RangeTblEntry;
903 rte.rtekind = RTE_RELATION;
906 context.rtables = list_make1(list_make1(&rte));
908 /* Scan the expression tree for referenceable objects */
909 find_expr_references_walker(expr, &context);
911 /* Remove any duplicates */
912 eliminate_duplicate_dependencies(&context.addrs);
914 /* Separate self-dependencies if necessary */
915 if (behavior != self_behavior && context.addrs.numrefs > 0)
917 ObjectAddresses self_addrs;
918 ObjectAddress *outobj;
922 init_object_addresses(&self_addrs);
924 outobj = context.addrs.refs;
926 for (oldref = 0; oldref < context.addrs.numrefs; oldref++)
928 ObjectAddress *thisobj = context.addrs.refs + oldref;
930 if (thisobj->classId == RelationRelationId &&
931 thisobj->objectId == relId)
933 /* Move this ref into self_addrs */
934 add_object_address(OCLASS_CLASS, relId, thisobj->objectSubId,
939 /* Keep it in context.addrs */
940 outobj->classId = thisobj->classId;
941 outobj->objectId = thisobj->objectId;
942 outobj->objectSubId = thisobj->objectSubId;
947 context.addrs.numrefs = outrefs;
949 /* Record the self-dependencies */
950 recordMultipleDependencies(depender,
951 self_addrs.refs, self_addrs.numrefs,
954 term_object_addresses(&self_addrs);
957 /* Record the external dependencies */
958 recordMultipleDependencies(depender,
959 context.addrs.refs, context.addrs.numrefs,
962 term_object_addresses(&context.addrs);
966 * Recursively search an expression tree for object references.
968 * Note: we avoid creating references to columns of tables that participate
969 * in an SQL JOIN construct, but are not actually used anywhere in the query.
970 * To do so, we do not scan the joinaliasvars list of a join RTE while
971 * scanning the query rangetable, but instead scan each individual entry
972 * of the alias list when we find a reference to it.
974 * Note: in many cases we do not need to create dependencies on the datatypes
975 * involved in an expression, because we'll have an indirect dependency via
976 * some other object. For instance Var nodes depend on a column which depends
977 * on the datatype, and OpExpr nodes depend on the operator which depends on
978 * the datatype. However we do need a type dependency if there is no such
979 * indirect dependency, as for example in Const and CoerceToDomain nodes.
982 find_expr_references_walker(Node *node,
983 find_expr_references_context *context)
989 Var *var = (Var *) node;
993 /* Find matching rtable entry, or complain if not found */
994 if (var->varlevelsup >= list_length(context->rtables))
995 elog(ERROR, "invalid varlevelsup %d", var->varlevelsup);
996 rtable = (List *) list_nth(context->rtables, var->varlevelsup);
997 if (var->varno <= 0 || var->varno > list_length(rtable))
998 elog(ERROR, "invalid varno %d", var->varno);
999 rte = rt_fetch(var->varno, rtable);
1002 * A whole-row Var references no specific columns, so adds no new
1005 if (var->varattno == InvalidAttrNumber)
1007 if (rte->rtekind == RTE_RELATION)
1009 /* If it's a plain relation, reference this column */
1010 add_object_address(OCLASS_CLASS, rte->relid, var->varattno,
1013 else if (rte->rtekind == RTE_JOIN)
1015 /* Scan join output column to add references to join inputs */
1018 /* We must make the context appropriate for join's level */
1019 save_rtables = context->rtables;
1020 context->rtables = list_copy_tail(context->rtables,
1022 if (var->varattno <= 0 ||
1023 var->varattno > list_length(rte->joinaliasvars))
1024 elog(ERROR, "invalid varattno %d", var->varattno);
1025 find_expr_references_walker((Node *) list_nth(rte->joinaliasvars,
1028 list_free(context->rtables);
1029 context->rtables = save_rtables;
1033 if (IsA(node, Const))
1035 Const *con = (Const *) node;
1038 /* A constant must depend on the constant's datatype */
1039 add_object_address(OCLASS_TYPE, con->consttype, 0,
1043 * If it's a regclass or similar literal referring to an existing
1044 * object, add a reference to that object. (Currently, only the
1045 * regclass case has any likely use, but we may as well handle all the
1046 * OID-alias datatypes consistently.)
1048 if (!con->constisnull)
1050 switch (con->consttype)
1053 case REGPROCEDUREOID:
1054 objoid = DatumGetObjectId(con->constvalue);
1055 if (SearchSysCacheExists(PROCOID,
1056 ObjectIdGetDatum(objoid),
1058 add_object_address(OCLASS_PROC, objoid, 0,
1062 case REGOPERATOROID:
1063 objoid = DatumGetObjectId(con->constvalue);
1064 if (SearchSysCacheExists(OPEROID,
1065 ObjectIdGetDatum(objoid),
1067 add_object_address(OCLASS_OPERATOR, objoid, 0,
1071 objoid = DatumGetObjectId(con->constvalue);
1072 if (SearchSysCacheExists(RELOID,
1073 ObjectIdGetDatum(objoid),
1075 add_object_address(OCLASS_CLASS, objoid, 0,
1079 objoid = DatumGetObjectId(con->constvalue);
1080 if (SearchSysCacheExists(TYPEOID,
1081 ObjectIdGetDatum(objoid),
1083 add_object_address(OCLASS_TYPE, objoid, 0,
1090 if (IsA(node, Param))
1092 Param *param = (Param *) node;
1094 /* A parameter must depend on the parameter's datatype */
1095 add_object_address(OCLASS_TYPE, param->paramtype, 0,
1098 if (IsA(node, FuncExpr))
1100 FuncExpr *funcexpr = (FuncExpr *) node;
1102 add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
1104 /* fall through to examine arguments */
1106 if (IsA(node, OpExpr))
1108 OpExpr *opexpr = (OpExpr *) node;
1110 add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
1112 /* fall through to examine arguments */
1114 if (IsA(node, DistinctExpr))
1116 DistinctExpr *distinctexpr = (DistinctExpr *) node;
1118 add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
1120 /* fall through to examine arguments */
1122 if (IsA(node, ScalarArrayOpExpr))
1124 ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
1126 add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
1128 /* fall through to examine arguments */
1130 if (IsA(node, NullIfExpr))
1132 NullIfExpr *nullifexpr = (NullIfExpr *) node;
1134 add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
1136 /* fall through to examine arguments */
1138 if (IsA(node, Aggref))
1140 Aggref *aggref = (Aggref *) node;
1142 add_object_address(OCLASS_PROC, aggref->aggfnoid, 0,
1144 /* fall through to examine arguments */
1146 if (is_subplan(node))
1148 /* Extra work needed here if we ever need this case */
1149 elog(ERROR, "already-planned subqueries not supported");
1151 if (IsA(node, RelabelType))
1153 RelabelType *relab = (RelabelType *) node;
1155 /* since there is no function dependency, need to depend on type */
1156 add_object_address(OCLASS_TYPE, relab->resulttype, 0,
1159 if (IsA(node, ConvertRowtypeExpr))
1161 ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node;
1163 /* since there is no function dependency, need to depend on type */
1164 add_object_address(OCLASS_TYPE, cvt->resulttype, 0,
1167 if (IsA(node, RowExpr))
1169 RowExpr *rowexpr = (RowExpr *) node;
1171 add_object_address(OCLASS_TYPE, rowexpr->row_typeid, 0,
1174 if (IsA(node, RowCompareExpr))
1176 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1179 foreach(l, rcexpr->opnos)
1181 add_object_address(OCLASS_OPERATOR, lfirst_oid(l), 0,
1184 foreach(l, rcexpr->opclasses)
1186 add_object_address(OCLASS_OPCLASS, lfirst_oid(l), 0,
1189 /* fall through to examine arguments */
1191 if (IsA(node, CoerceToDomain))
1193 CoerceToDomain *cd = (CoerceToDomain *) node;
1195 add_object_address(OCLASS_TYPE, cd->resulttype, 0,
1198 if (IsA(node, Query))
1200 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1201 Query *query = (Query *) node;
1206 * Add whole-relation refs for each plain relation mentioned in the
1207 * subquery's rtable, as well as datatype refs for any datatypes used
1208 * as a RECORD function's output. (Note: query_tree_walker takes care
1209 * of recursing into RTE_FUNCTION and RTE_SUBQUERY RTEs, so no need to
1210 * do that here. But keep it from looking at join alias lists.)
1212 foreach(rtable, query->rtable)
1214 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtable);
1217 switch (rte->rtekind)
1220 add_object_address(OCLASS_CLASS, rte->relid, 0,
1224 foreach(ct, rte->funccoltypes)
1226 add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0,
1235 /* Examine substructure of query */
1236 context->rtables = lcons(query->rtable, context->rtables);
1237 result = query_tree_walker(query,
1238 find_expr_references_walker,
1240 QTW_IGNORE_JOINALIASES);
1241 context->rtables = list_delete_first(context->rtables);
1244 return expression_tree_walker(node, find_expr_references_walker,
1249 * Given an array of dependency references, eliminate any duplicates.
1252 eliminate_duplicate_dependencies(ObjectAddresses *addrs)
1254 ObjectAddress *priorobj;
1258 if (addrs->numrefs <= 1)
1259 return; /* nothing to do */
1261 /* Sort the refs so that duplicates are adjacent */
1262 qsort((void *) addrs->refs, addrs->numrefs, sizeof(ObjectAddress),
1263 object_address_comparator);
1266 priorobj = addrs->refs;
1268 for (oldref = 1; oldref < addrs->numrefs; oldref++)
1270 ObjectAddress *thisobj = addrs->refs + oldref;
1272 if (priorobj->classId == thisobj->classId &&
1273 priorobj->objectId == thisobj->objectId)
1275 if (priorobj->objectSubId == thisobj->objectSubId)
1276 continue; /* identical, so drop thisobj */
1279 * If we have a whole-object reference and a reference to a part
1280 * of the same object, we don't need the whole-object reference
1281 * (for example, we don't need to reference both table foo and
1282 * column foo.bar). The whole-object reference will always appear
1283 * first in the sorted list.
1285 if (priorobj->objectSubId == 0)
1287 /* replace whole ref with partial */
1288 priorobj->objectSubId = thisobj->objectSubId;
1292 /* Not identical, so add thisobj to output set */
1294 priorobj->classId = thisobj->classId;
1295 priorobj->objectId = thisobj->objectId;
1296 priorobj->objectSubId = thisobj->objectSubId;
1300 addrs->numrefs = newrefs;
1304 * qsort comparator for ObjectAddress items
1307 object_address_comparator(const void *a, const void *b)
1309 const ObjectAddress *obja = (const ObjectAddress *) a;
1310 const ObjectAddress *objb = (const ObjectAddress *) b;
1312 if (obja->classId < objb->classId)
1314 if (obja->classId > objb->classId)
1316 if (obja->objectId < objb->objectId)
1318 if (obja->objectId > objb->objectId)
1322 * We sort the subId as an unsigned int so that 0 will come first. See
1323 * logic in eliminate_duplicate_dependencies.
1325 if ((unsigned int) obja->objectSubId < (unsigned int) objb->objectSubId)
1327 if ((unsigned int) obja->objectSubId > (unsigned int) objb->objectSubId)
1333 * Routines for handling an expansible array of ObjectAddress items.
1335 * init_object_addresses: initialize an ObjectAddresses array.
1338 init_object_addresses(ObjectAddresses *addrs)
1340 /* Initialize array to empty */
1342 addrs->maxrefs = 32; /* arbitrary initial array size */
1343 addrs->refs = (ObjectAddress *)
1344 palloc(addrs->maxrefs * sizeof(ObjectAddress));
1348 * Add an entry to an ObjectAddresses array.
1350 * It is convenient to specify the class by ObjectClass rather than directly
1354 add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
1355 ObjectAddresses *addrs)
1357 ObjectAddress *item;
1359 /* enlarge array if needed */
1360 if (addrs->numrefs >= addrs->maxrefs)
1362 addrs->maxrefs *= 2;
1363 addrs->refs = (ObjectAddress *)
1364 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
1366 /* record this item */
1367 item = addrs->refs + addrs->numrefs;
1368 item->classId = object_classes[oclass];
1369 item->objectId = objectId;
1370 item->objectSubId = subId;
1375 * Add an entry to an ObjectAddresses array.
1377 * As above, but specify entry exactly.
1380 add_exact_object_address(const ObjectAddress *object,
1381 ObjectAddresses *addrs)
1383 ObjectAddress *item;
1385 /* enlarge array if needed */
1386 if (addrs->numrefs >= addrs->maxrefs)
1388 addrs->maxrefs *= 2;
1389 addrs->refs = (ObjectAddress *)
1390 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
1392 /* record this item */
1393 item = addrs->refs + addrs->numrefs;
1399 * Test whether an object is present in an ObjectAddresses array.
1401 * We return "true" if object is a subobject of something in the array, too.
1404 object_address_present(const ObjectAddress *object,
1405 ObjectAddresses *addrs)
1409 for (i = addrs->numrefs - 1; i >= 0; i--)
1411 ObjectAddress *thisobj = addrs->refs + i;
1413 if (object->classId == thisobj->classId &&
1414 object->objectId == thisobj->objectId)
1416 if (object->objectSubId == thisobj->objectSubId ||
1417 thisobj->objectSubId == 0)
1426 * Clean up when done with an ObjectAddresses array.
1429 term_object_addresses(ObjectAddresses *addrs)
1435 * Determine the class of a given object identified by objectAddress.
1437 * This function is essentially the reverse mapping for the object_classes[]
1438 * table. We implement it as a function because the OIDs aren't consecutive.
1441 getObjectClass(const ObjectAddress *object)
1443 switch (object->classId)
1445 case RelationRelationId:
1446 /* caller must check objectSubId */
1447 return OCLASS_CLASS;
1449 case ProcedureRelationId:
1450 Assert(object->objectSubId == 0);
1453 case TypeRelationId:
1454 Assert(object->objectSubId == 0);
1457 case CastRelationId:
1458 Assert(object->objectSubId == 0);
1461 case ConstraintRelationId:
1462 Assert(object->objectSubId == 0);
1463 return OCLASS_CONSTRAINT;
1465 case ConversionRelationId:
1466 Assert(object->objectSubId == 0);
1467 return OCLASS_CONVERSION;
1469 case AttrDefaultRelationId:
1470 Assert(object->objectSubId == 0);
1471 return OCLASS_DEFAULT;
1473 case LanguageRelationId:
1474 Assert(object->objectSubId == 0);
1475 return OCLASS_LANGUAGE;
1477 case OperatorRelationId:
1478 Assert(object->objectSubId == 0);
1479 return OCLASS_OPERATOR;
1481 case OperatorClassRelationId:
1482 Assert(object->objectSubId == 0);
1483 return OCLASS_OPCLASS;
1485 case RewriteRelationId:
1486 Assert(object->objectSubId == 0);
1487 return OCLASS_REWRITE;
1489 case TriggerRelationId:
1490 Assert(object->objectSubId == 0);
1491 return OCLASS_TRIGGER;
1493 case NamespaceRelationId:
1494 Assert(object->objectSubId == 0);
1495 return OCLASS_SCHEMA;
1497 case AuthIdRelationId:
1498 Assert(object->objectSubId == 0);
1501 case DatabaseRelationId:
1502 Assert(object->objectSubId == 0);
1503 return OCLASS_DATABASE;
1505 case TableSpaceRelationId:
1506 Assert(object->objectSubId == 0);
1507 return OCLASS_TBLSPACE;
1510 /* shouldn't get here */
1511 elog(ERROR, "unrecognized object class: %u", object->classId);
1512 return OCLASS_CLASS; /* keep compiler quiet */
1516 * getObjectDescription: build an object description for messages
1518 * The result is a palloc'd string.
1521 getObjectDescription(const ObjectAddress *object)
1523 StringInfoData buffer;
1525 initStringInfo(&buffer);
1527 switch (getObjectClass(object))
1530 getRelationDescription(&buffer, object->objectId);
1531 if (object->objectSubId != 0)
1532 appendStringInfo(&buffer, _(" column %s"),
1533 get_relid_attribute_name(object->objectId,
1534 object->objectSubId));
1538 appendStringInfo(&buffer, _("function %s"),
1539 format_procedure(object->objectId));
1543 appendStringInfo(&buffer, _("type %s"),
1544 format_type_be(object->objectId));
1550 ScanKeyData skey[1];
1553 Form_pg_cast castForm;
1555 castDesc = heap_open(CastRelationId, AccessShareLock);
1557 ScanKeyInit(&skey[0],
1558 ObjectIdAttributeNumber,
1559 BTEqualStrategyNumber, F_OIDEQ,
1560 ObjectIdGetDatum(object->objectId));
1562 rcscan = systable_beginscan(castDesc, CastOidIndexId, true,
1563 SnapshotNow, 1, skey);
1565 tup = systable_getnext(rcscan);
1567 if (!HeapTupleIsValid(tup))
1568 elog(ERROR, "could not find tuple for cast %u",
1571 castForm = (Form_pg_cast) GETSTRUCT(tup);
1573 appendStringInfo(&buffer, _("cast from %s to %s"),
1574 format_type_be(castForm->castsource),
1575 format_type_be(castForm->casttarget));
1577 systable_endscan(rcscan);
1578 heap_close(castDesc, AccessShareLock);
1582 case OCLASS_CONSTRAINT:
1585 ScanKeyData skey[1];
1588 Form_pg_constraint con;
1590 conDesc = heap_open(ConstraintRelationId, AccessShareLock);
1592 ScanKeyInit(&skey[0],
1593 ObjectIdAttributeNumber,
1594 BTEqualStrategyNumber, F_OIDEQ,
1595 ObjectIdGetDatum(object->objectId));
1597 rcscan = systable_beginscan(conDesc, ConstraintOidIndexId, true,
1598 SnapshotNow, 1, skey);
1600 tup = systable_getnext(rcscan);
1602 if (!HeapTupleIsValid(tup))
1603 elog(ERROR, "could not find tuple for constraint %u",
1606 con = (Form_pg_constraint) GETSTRUCT(tup);
1608 if (OidIsValid(con->conrelid))
1610 appendStringInfo(&buffer, _("constraint %s on "),
1611 NameStr(con->conname));
1612 getRelationDescription(&buffer, con->conrelid);
1616 appendStringInfo(&buffer, _("constraint %s"),
1617 NameStr(con->conname));
1620 systable_endscan(rcscan);
1621 heap_close(conDesc, AccessShareLock);
1625 case OCLASS_CONVERSION:
1629 conTup = SearchSysCache(CONOID,
1630 ObjectIdGetDatum(object->objectId),
1632 if (!HeapTupleIsValid(conTup))
1633 elog(ERROR, "cache lookup failed for conversion %u",
1635 appendStringInfo(&buffer, _("conversion %s"),
1636 NameStr(((Form_pg_conversion) GETSTRUCT(conTup))->conname));
1637 ReleaseSysCache(conTup);
1641 case OCLASS_DEFAULT:
1643 Relation attrdefDesc;
1644 ScanKeyData skey[1];
1647 Form_pg_attrdef attrdef;
1648 ObjectAddress colobject;
1650 attrdefDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
1652 ScanKeyInit(&skey[0],
1653 ObjectIdAttributeNumber,
1654 BTEqualStrategyNumber, F_OIDEQ,
1655 ObjectIdGetDatum(object->objectId));
1657 adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndexId,
1658 true, SnapshotNow, 1, skey);
1660 tup = systable_getnext(adscan);
1662 if (!HeapTupleIsValid(tup))
1663 elog(ERROR, "could not find tuple for attrdef %u",
1666 attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
1668 colobject.classId = RelationRelationId;
1669 colobject.objectId = attrdef->adrelid;
1670 colobject.objectSubId = attrdef->adnum;
1672 appendStringInfo(&buffer, _("default for %s"),
1673 getObjectDescription(&colobject));
1675 systable_endscan(adscan);
1676 heap_close(attrdefDesc, AccessShareLock);
1680 case OCLASS_LANGUAGE:
1684 langTup = SearchSysCache(LANGOID,
1685 ObjectIdGetDatum(object->objectId),
1687 if (!HeapTupleIsValid(langTup))
1688 elog(ERROR, "cache lookup failed for language %u",
1690 appendStringInfo(&buffer, _("language %s"),
1691 NameStr(((Form_pg_language) GETSTRUCT(langTup))->lanname));
1692 ReleaseSysCache(langTup);
1696 case OCLASS_OPERATOR:
1697 appendStringInfo(&buffer, _("operator %s"),
1698 format_operator(object->objectId));
1701 case OCLASS_OPCLASS:
1704 Form_pg_opclass opcForm;
1709 opcTup = SearchSysCache(CLAOID,
1710 ObjectIdGetDatum(object->objectId),
1712 if (!HeapTupleIsValid(opcTup))
1713 elog(ERROR, "cache lookup failed for opclass %u",
1715 opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
1717 amTup = SearchSysCache(AMOID,
1718 ObjectIdGetDatum(opcForm->opcamid),
1720 if (!HeapTupleIsValid(amTup))
1721 elog(ERROR, "cache lookup failed for access method %u",
1723 amForm = (Form_pg_am) GETSTRUCT(amTup);
1725 /* Qualify the name if not visible in search path */
1726 if (OpclassIsVisible(object->objectId))
1729 nspname = get_namespace_name(opcForm->opcnamespace);
1731 appendStringInfo(&buffer, _("operator class %s for access method %s"),
1732 quote_qualified_identifier(nspname,
1733 NameStr(opcForm->opcname)),
1734 NameStr(amForm->amname));
1736 ReleaseSysCache(amTup);
1737 ReleaseSysCache(opcTup);
1741 case OCLASS_REWRITE:
1744 ScanKeyData skey[1];
1747 Form_pg_rewrite rule;
1749 ruleDesc = heap_open(RewriteRelationId, AccessShareLock);
1751 ScanKeyInit(&skey[0],
1752 ObjectIdAttributeNumber,
1753 BTEqualStrategyNumber, F_OIDEQ,
1754 ObjectIdGetDatum(object->objectId));
1756 rcscan = systable_beginscan(ruleDesc, RewriteOidIndexId, true,
1757 SnapshotNow, 1, skey);
1759 tup = systable_getnext(rcscan);
1761 if (!HeapTupleIsValid(tup))
1762 elog(ERROR, "could not find tuple for rule %u",
1765 rule = (Form_pg_rewrite) GETSTRUCT(tup);
1767 appendStringInfo(&buffer, _("rule %s on "),
1768 NameStr(rule->rulename));
1769 getRelationDescription(&buffer, rule->ev_class);
1771 systable_endscan(rcscan);
1772 heap_close(ruleDesc, AccessShareLock);
1776 case OCLASS_TRIGGER:
1779 ScanKeyData skey[1];
1782 Form_pg_trigger trig;
1784 trigDesc = heap_open(TriggerRelationId, AccessShareLock);
1786 ScanKeyInit(&skey[0],
1787 ObjectIdAttributeNumber,
1788 BTEqualStrategyNumber, F_OIDEQ,
1789 ObjectIdGetDatum(object->objectId));
1791 tgscan = systable_beginscan(trigDesc, TriggerOidIndexId, true,
1792 SnapshotNow, 1, skey);
1794 tup = systable_getnext(tgscan);
1796 if (!HeapTupleIsValid(tup))
1797 elog(ERROR, "could not find tuple for trigger %u",
1800 trig = (Form_pg_trigger) GETSTRUCT(tup);
1802 appendStringInfo(&buffer, _("trigger %s on "),
1803 NameStr(trig->tgname));
1804 getRelationDescription(&buffer, trig->tgrelid);
1806 systable_endscan(tgscan);
1807 heap_close(trigDesc, AccessShareLock);
1815 nspname = get_namespace_name(object->objectId);
1817 elog(ERROR, "cache lookup failed for namespace %u",
1819 appendStringInfo(&buffer, _("schema %s"), nspname);
1825 appendStringInfo(&buffer, _("role %s"),
1826 GetUserNameFromId(object->objectId));
1830 case OCLASS_DATABASE:
1834 datname = get_database_name(object->objectId);
1836 elog(ERROR, "cache lookup failed for database %u",
1838 appendStringInfo(&buffer, _("database %s"), datname);
1842 case OCLASS_TBLSPACE:
1846 tblspace = get_tablespace_name(object->objectId);
1848 elog(ERROR, "cache lookup failed for tablespace %u",
1850 appendStringInfo(&buffer, _("tablespace %s"), tblspace);
1855 appendStringInfo(&buffer, "unrecognized object %u %u %d",
1858 object->objectSubId);
1866 * subroutine for getObjectDescription: describe a relation
1869 getRelationDescription(StringInfo buffer, Oid relid)
1872 Form_pg_class relForm;
1876 relTup = SearchSysCache(RELOID,
1877 ObjectIdGetDatum(relid),
1879 if (!HeapTupleIsValid(relTup))
1880 elog(ERROR, "cache lookup failed for relation %u", relid);
1881 relForm = (Form_pg_class) GETSTRUCT(relTup);
1883 /* Qualify the name if not visible in search path */
1884 if (RelationIsVisible(relid))
1887 nspname = get_namespace_name(relForm->relnamespace);
1889 relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
1891 switch (relForm->relkind)
1893 case RELKIND_RELATION:
1894 appendStringInfo(buffer, _("table %s"),
1898 appendStringInfo(buffer, _("index %s"),
1901 case RELKIND_SPECIAL:
1902 appendStringInfo(buffer, _("special system relation %s"),
1905 case RELKIND_SEQUENCE:
1906 appendStringInfo(buffer, _("sequence %s"),
1909 case RELKIND_UNCATALOGED:
1910 appendStringInfo(buffer, _("uncataloged table %s"),
1913 case RELKIND_TOASTVALUE:
1914 appendStringInfo(buffer, _("toast table %s"),
1918 appendStringInfo(buffer, _("view %s"),
1921 case RELKIND_COMPOSITE_TYPE:
1922 appendStringInfo(buffer, _("composite type %s"),
1926 /* shouldn't get here */
1927 appendStringInfo(buffer, _("relation %s"),
1932 ReleaseSysCache(relTup);
1935 /* Recursively travel and search for the default sequence. Finally detach it */
1937 void performSequenceDefaultDeletion(const ObjectAddress *object,
1938 DropBehavior behavior, int deleteFlag)
1945 ObjectAddress otherObject;
1948 depRel = heap_open(DependRelationId, RowExclusiveLock);
1950 ScanKeyInit(&key[0],
1951 Anum_pg_depend_classid,
1952 BTEqualStrategyNumber, F_OIDEQ,
1953 ObjectIdGetDatum(object->classId));
1954 ScanKeyInit(&key[1],
1955 Anum_pg_depend_objid,
1956 BTEqualStrategyNumber, F_OIDEQ,
1957 ObjectIdGetDatum(object->objectId));
1958 if (object->objectSubId != 0)
1960 ScanKeyInit(&key[2],
1961 Anum_pg_depend_objsubid,
1962 BTEqualStrategyNumber, F_INT4EQ,
1963 Int32GetDatum(object->objectSubId));
1969 scan = systable_beginscan(depRel, DependDependerIndexId, true,
1970 SnapshotNow, nkeys, key);
1972 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1975 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
1977 otherObject.classId = foundDep->refclassid;
1978 otherObject.objectId = foundDep->refobjid;
1979 otherObject.objectSubId = foundDep->refobjsubid;
1981 /* Detach the default sequence from the relation */
1984 simple_heap_delete(depRel, &tup->t_self);
1988 switch (foundDep->deptype)
1990 case DEPENDENCY_NORMAL:
1993 if(getObjectClass(&otherObject) == OCLASS_CLASS)
1995 /* Dont allow to change the default sequence */
1998 systable_endscan(scan);
1999 heap_close(depRel, RowExclusiveLock);
2000 elog(ERROR, "%s is a SERIAL sequence. Can't alter the relation", getObjectDescription(&otherObject));
2003 else /* Detach the default sequence from the relation */
2005 performSequenceDefaultDeletion(&otherObject, behavior, 1);
2006 systable_endscan(scan);
2007 heap_close(depRel, RowExclusiveLock);
2016 systable_endscan(scan);
2017 heap_close(depRel, RowExclusiveLock);