1/*-------------------------------------------------------------------------
4 * Routines to support inter-object dependencies.
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/catalog/dependency.c
13 *-------------------------------------------------------------------------
84#include "utils/fmgroids.h"
90 * Deletion processing requires additional state for each ObjectAddress that
91 * it's planning to delete. For simplicity and code-sharing we make the
92 * ObjectAddresses code support arrays with or without this extra state.
96 int flags;
/* bitmask, see bit definitions below */
100/* ObjectAddressExtra flag bits */
101 #define DEPFLAG_ORIGINAL 0x0001 /* an original deletion target */
102 #define DEPFLAG_NORMAL 0x0002 /* reached via normal dependency */
103 #define DEPFLAG_AUTO 0x0004 /* reached via auto dependency */
104 #define DEPFLAG_INTERNAL 0x0008 /* reached via internal dependency */
105 #define DEPFLAG_PARTITION 0x0010 /* reached via partition dependency */
106 #define DEPFLAG_EXTENSION 0x0020 /* reached via extension dependency */
107 #define DEPFLAG_REVERSE 0x0040 /* reverse internal/extension link */
108 #define DEPFLAG_IS_PART 0x0080 /* has a partition dependency */
109 #define DEPFLAG_SUBOBJECT 0x0100 /* subobject of another deletable object */
112/* expansible list of ObjectAddresses */
117 int numrefs;
/* current number of references */
118 int maxrefs;
/* current size of palloc'd array(s) */
121/* typedef ObjectAddresses appears in dependency.h */
123/* threaded list of ObjectAddresses, for recursion detection */
127 int flags;
/* its current flag bits */
131/* temporary storage in findDependentObjects */
135 int subflags;
/* flags to pass down when recursing to obj */
138/* for find_expr_references_walker */
181 * Go through the objects given running the final actions on them, and execute
182 * the actual deletion.
191 * Keep track of objects for event triggers, if necessary.
199 bool original =
false;
217 * Delete all the objects in the proper order, except that if told to, we
218 * should skip the original object(s).
234 * performDeletion: attempt to drop the specified object. If CASCADE
235 * behavior is specified, also drop any dependent objects (recursively).
236 * If RESTRICT behavior is specified, error out if there are any dependent
237 * objects, except for those that should be implicitly dropped anyway
238 * according to the dependency type.
240 * This is the outer control routine for all forms of DROP that drop objects
241 * that can participate in dependencies. Note that performMultipleDeletions
242 * is a variant on the same theme; if you change anything here you'll likely
243 * need to fix that too.
245 * Bits in the flags argument can include:
247 * PERFORM_DELETION_INTERNAL: indicates that the drop operation is not the
248 * direct result of a user-initiated action. For example, when a temporary
249 * schema is cleaned out so that a new backend can use it, or when a column
250 * default is dropped as an intermediate step while adding a new one, that's
251 * an internal operation. On the other hand, when we drop something because
252 * the user issued a DROP statement against it, that's not internal. Currently
253 * this suppresses calling event triggers and making some permissions checks.
255 * PERFORM_DELETION_CONCURRENTLY: perform the drop concurrently. This does
256 * not currently work for anything except dropping indexes; don't set it for
257 * other object types or you may get strange results.
259 * PERFORM_DELETION_QUIETLY: reduce message level from NOTICE to DEBUG2.
261 * PERFORM_DELETION_SKIP_ORIGINAL: do not delete the specified object(s),
262 * but only what depends on it/them.
264 * PERFORM_DELETION_SKIP_EXTENSIONS: do not delete extensions, even when
265 * deleting objects that are part of an extension. This should generally
266 * be used only when dropping temporary objects.
268 * PERFORM_DELETION_CONCURRENT_LOCK: perform the drop normally but with a lock
269 * as if it were concurrent. This is used by REINDEX CONCURRENTLY.
280 * We save some cycles by opening pg_depend just once and passing the
281 * Relation pointer down to all the recursive deletion steps.
286 * Acquire deletion lock on the target object. (Ideally the caller has
287 * done this already, but many places are sloppy about it.)
292 * Construct a list of objects to delete (ie, the given object plus
293 * everything directly or indirectly dependent on it).
300 NULL,
/* empty stack */
302 NULL,
/* no pendingObjects */
306 * Check if deletion is allowed, and report about cascaded deletes.
323 * performMultipleDeletions: Similar to performDeletion, but act on multiple
326 * The main difference from issuing multiple performDeletion calls is that the
327 * list of objects that would be implicitly dropped, for each object to be
328 * dropped, is the union of the implicit-object list for all objects. This
329 * makes each check be more relaxed.
339 /* No work if no objects... */
344 * We save some cycles by opening pg_depend just once and passing the
345 * Relation pointer down to all the recursive deletion steps.
350 * Construct a list of objects to delete (ie, the given objects plus
351 * everything directly or indirectly dependent on them). Note that
352 * because we pass the whole objects list as pendingObjects context, we
353 * won't get a failure from trying to delete an object that is internally
354 * dependent on another one in the list; we'll just skip that object and
355 * delete it when we reach its owner.
364 * Acquire deletion lock on each target object. (Ideally the caller
365 * has done this already, but many places are sloppy about it.)
372 NULL,
/* empty stack */
379 * Check if deletion is allowed, and report about cascaded deletes.
381 * If there's exactly one object being deleted, report it the same way as
382 * in performDeletion(), else we have to be vaguer.
399 * findDependentObjects - find all objects that depend on 'object'
401 * For every object that depends on the starting object, acquire a deletion
402 * lock on the object, add it to targetObjects (if not already there),
403 * and recursively find objects that depend on it. An object's dependencies
404 * will be placed into targetObjects before the object itself; this means
405 * that the finished list's order represents a safe deletion order.
407 * The caller must already have a deletion lock on 'object' itself,
408 * but must not have added it to targetObjects. (Note: there are corner
409 * cases where we won't add the object either, and will also release the
410 * caller-taken lock. This is a bit ugly, but the API is set up this way
411 * to allow easy rechecking of an object's liveness after we lock it. See
412 * notes within the function.)
414 * When dropping a whole object (subId = 0), we find dependencies for
415 * its sub-objects too.
417 * object: the object to add to targetObjects and find dependencies on
418 * objflags: flags to be ORed into the object's targetObjects entry
419 * flags: PERFORM_DELETION_xxx flags for the deletion operation as a whole
420 * stack: list of objects being visited in current recursion; topmost item
421 * is the object that we recursed from (NULL for external callers)
422 * targetObjects: list of objects that are scheduled to be deleted
423 * pendingObjects: list of other objects slated for destruction, but
424 * not necessarily in targetObjects yet (can be NULL if none)
425 * *depRel: already opened pg_depend relation
427 * Note: objflags describes the reason for visiting this particular object
428 * at this time, and is not passed down when recursing. The flags argument
429 * is passed down, since it describes what we're doing overall.
448 int numDependentObjects;
449 int maxDependentObjects;
454 * If the target object is already being visited in an outer recursion
455 * level, just report the current objflags back to that level and exit.
456 * This is needed to avoid infinite recursion in the face of circular
459 * The stack check alone would result in dependency loops being broken at
460 * an arbitrary point, ie, the first member object of the loop to be
461 * visited is the last one to be deleted. This is obviously unworkable.
462 * However, the check for internal dependency below guarantees that we
463 * will not break a loop at an internal dependency: if we enter the loop
464 * at an "owned" object we will switch and start at the "owning" object
465 * instead. We could probably hack something up to avoid breaking at an
466 * auto dependency, too, if we had to. However there are no known cases
467 * where that would be necessary.
473 * since this function recurses, it could be driven to stack overflow,
474 * because of the deep dependency tree, not only due to dependency loops.
479 * It's also possible that the target object has already been completely
480 * processed and put into targetObjects. If so, again we just add the
481 * specified objflags to its entry and return.
483 * (Note: in these early-exit cases we could release the caller-taken
484 * lock, since the object is presumably now locked multiple times; but it
485 * seems not worth the cycles.)
491 * If the target object is pinned, we can just error out immediately; it
492 * won't have any objects recorded as depending on it.
496 (
errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
497 errmsg(
"cannot drop %s because it is required by the database system",
501 * The target object might be internally dependent on some other object
502 * (its "owner"), and/or be a member of an extension (also considered its
503 * owner). If so, and if we aren't recursing from the owning object, we
504 * have to transform this deletion request into a deletion request of the
505 * owning object. (We'll eventually recurse back to this object, but the
506 * owning object has to be visited first so it will be deleted after.) The
507 * way to find out about this is to scan the pg_depend entries that show
508 * what this object depends on.
511 Anum_pg_depend_classid,
515 Anum_pg_depend_objid,
520 /* Consider only dependencies of this sub-object */
522 Anum_pg_depend_objsubid,
529 /* Consider dependencies of this object and any sub-objects it has */
536 /* initialize variables that loop may fill */
537 memset(&owningObject, 0,
sizeof(owningObject));
538 memset(&partitionObject, 0,
sizeof(partitionObject));
544 otherObject.
classId = foundDep->refclassid;
545 otherObject.
objectId = foundDep->refobjid;
549 * When scanning dependencies of a whole object, we may find rows
550 * linking sub-objects of the object to the object itself. (Normally,
551 * such a dependency is implicit, but we must make explicit ones in
552 * some cases involving partitioning.) We must ignore such rows to
553 * avoid infinite recursion.
560 switch (foundDep->deptype)
571 * If told to, ignore EXTENSION dependencies altogether. This
572 * flag is normally used to prevent dropping extensions during
573 * temporary-object cleanup, even if a temp object was created
574 * during an extension script.
580 * If the other object is the extension currently being
581 * created/altered, ignore this dependency and continue with
582 * the deletion. This allows dropping of an extension's
583 * objects within the extension's scripts, as well as corner
584 * cases such as dropping a transient object created within
588 otherObject.
classId == ExtensionRelationId &&
592 /* Otherwise, treat this like an internal dependency */
598 * This object is part of the internal implementation of
599 * another object, or is part of the extension that is the
600 * other object. We have three cases:
602 * 1. At the outermost recursion level, we must disallow the
603 * DROP. However, if the owning object is listed in
604 * pendingObjects, just release the caller's lock and return;
605 * we'll eventually complete the DROP when we reach that entry
606 * in the pending list.
608 * Note: the above statement is true only if this pg_depend
609 * entry still exists by then; in principle, therefore, we
610 * could miss deleting an item the user told us to delete.
611 * However, no inconsistency can result: since we're at outer
612 * level, there is no object depending on this one.
616 if (pendingObjects &&
620 /* need to release caller's lock; see notes below */
626 * We postpone actually issuing the error message until
627 * after this loop, so that we can make the behavior
628 * independent of the ordering of pg_depend entries, at
629 * least if there's not more than one INTERNAL and one
630 * EXTENSION dependency. (If there's more, we'll complain
631 * about a random one of them.) Prefer to complain about
632 * EXTENSION, since that's generally a more important
637 owningObject = otherObject;
642 * 2. When recursing from the other end of this dependency,
643 * it's okay to continue with the deletion. This holds when
644 * recursing from a whole object that includes the nominal
645 * other end as a component, too. Since there can be more
646 * than one "owning" object, we have to allow matches that are
647 * more than one level down in the stack.
653 * 3. Not all the owning objects have been visited, so
654 * transform this deletion request into a delete of this
657 * First, release caller's lock on this object and get
658 * deletion lock on the owning object. (We must release
659 * caller's lock to avoid deadlock against a concurrent
660 * deletion of the owning object.)
666 * The owning object might have been deleted while we waited
667 * to lock it; if so, neither it nor the current object are
668 * interesting anymore. We test this by checking the
669 * pg_depend entry (see notes below).
679 * One way or the other, we're done with the scan; might as
680 * well close it down before recursing, to reduce peak
681 * resource consumption.
686 * Okay, recurse to the owning object instead of proceeding.
688 * We do not need to stack the current object; we want the
689 * traversal order to be as if the original reference had
690 * linked to the owning object instead of this one.
692 * The dependency type is a "reverse" dependency: we need to
693 * delete the owning object if this one is to be deleted, but
694 * this linkage is never a reason for an automatic deletion.
705 * The current target object should have been added to
706 * targetObjects while processing the owning object; but it
707 * probably got only the flag bits associated with the
708 * dependency we're looking at. We need to add the objflags
709 * that were passed to this recursion level, too, else we may
710 * get a bogus failure in reportDependentObjects (if, for
711 * example, we were called due to a partition dependency).
713 * If somehow the current object didn't get scheduled for
714 * deletion, bleat. (That would imply that somebody deleted
715 * this dependency record before the recursion got to it.)
716 * Another idea would be to reacquire lock on the current
717 * object and resume trying to delete it, but it seems not
718 * worth dealing with the race conditions inherent in that.
722 elog(
ERROR,
"deletion of owning object %s failed to delete %s",
726 /* And we're done here. */
732 * Remember that this object has a partition-type dependency.
733 * After the dependency scan, we'll complain if we didn't find
734 * a reason to delete one of its partition dependencies.
739 * Also remember the primary partition owner, for error
740 * messages. If there are multiple primary owners (which
741 * there should not be), we'll report a random one of them.
743 partitionObject = otherObject;
749 * Only use secondary partition owners in error messages if we
750 * find no primary owner (which probably shouldn't happen).
753 partitionObject = otherObject;
756 * Remember that this object has a partition-type dependency.
757 * After the dependency scan, we'll complain if we didn't find
758 * a reason to delete one of its partition dependencies.
764 elog(
ERROR,
"unrecognized dependency type '%c' for %s",
773 * If we found an INTERNAL or EXTENSION dependency when we're at outer
774 * level, complain about it now. If we also found a PARTITION dependency,
775 * we prefer to report the PARTITION dependency. This is arbitrary but
776 * seems to be more useful in practice.
788 (
errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
789 errmsg(
"cannot drop %s because %s requires it",
791 errhint(
"You can drop %s instead.", otherObjDesc)));
795 * Next, identify all objects that directly depend on the current object.
796 * To ensure predictable deletion order, we collect them up in
797 * dependentObjects and sort the list before actually recursing. (The
798 * deletion order would be valid in any case, but doing this ensures
799 * consistent output from DROP CASCADE commands, which is helpful for
800 * regression testing.)
802 maxDependentObjects = 128;
/* arbitrary initial allocation */
805 numDependentObjects = 0;
808 Anum_pg_depend_refclassid,
812 Anum_pg_depend_refobjid,
818 Anum_pg_depend_refobjsubid,
834 otherObject.
classId = foundDep->classid;
835 otherObject.
objectId = foundDep->objid;
839 * If what we found is a sub-object of the current object, just ignore
840 * it. (Normally, such a dependency is implicit, but we must make
841 * explicit ones in some cases involving partitioning.)
849 * Must lock the dependent object before recursing to it.
854 * The dependent object might have been deleted while we waited to
855 * lock it; if so, we don't need to do anything more with it. We can
856 * test this cheaply and independently of the object's type by seeing
857 * if the pg_depend tuple we are looking at is still live. (If the
858 * object got deleted, the tuple would have been deleted too.)
862 /* release the now-useless lock */
864 /* and continue scanning for dependencies */
869 * We do need to delete it, so identify objflags to be passed down,
870 * which depend on the dependency type.
872 switch (foundDep->deptype)
892 elog(
ERROR,
"unrecognized dependency type '%c' for %s",
894 subflags = 0;
/* keep compiler quiet */
898 /* And add it to the pending-objects list */
899 if (numDependentObjects >= maxDependentObjects)
901 /* enlarge array if needed */
902 maxDependentObjects *= 2;
908 dependentObjects[numDependentObjects].
obj = otherObject;
909 dependentObjects[numDependentObjects].
subflags = subflags;
910 numDependentObjects++;
916 * Now we can sort the dependent objects into a stable visitation order.
917 * It's safe to use object_address_comparator here since the obj field is
918 * first within ObjectAddressAndFlags.
920 if (numDependentObjects > 1)
921 qsort(dependentObjects, numDependentObjects,
926 * Now recurse to the dependent objects. We must visit them first since
927 * they have to be deleted before the current object.
930 mystack.
flags = objflags;
931 mystack.
next = stack;
933 for (
int i = 0;
i < numDependentObjects;
i++)
946 pfree(dependentObjects);
949 * Finally, we can add the target object to targetObjects. Be careful to
950 * include any flags that were passed back down to us from inner recursion
951 * levels. Record the "dependee" as being either the most important
952 * partition owner if there is one, else the object we recursed from, if
953 * any. (The logic in reportDependentObjects() is such that it can only
954 * need one of those objects.)
967 * reportDependentObjects - report about dependencies, and fail if RESTRICT
969 * Tell the user about dependent objects that we are going to delete
970 * (or would need to delete, but are prevented by RESTRICT mode);
971 * then error out if there are any and it's not CASCADE mode.
973 * targetObjects: list of objects that are scheduled to be deleted
974 * behavior: RESTRICT or CASCADE
975 * flags: other flags for the deletion operation
976 * origObject: base object of deletion, or NULL if not available
977 * (the latter case occurs in DROP OWNED)
989 int numReportedClient = 0;
990 int numNotReportedClient = 0;
994 * If we need to delete any partition-dependent objects, make sure that
995 * we're deleting at least one of their partition dependencies, too. That
996 * can be detected by checking that we reached them by a PARTITION
997 * dependency at some point.
999 * We just report the first such object, as in most cases the only way to
1000 * trigger this complaint is to explicitly try to delete one partition of
1001 * a partitioned object.
1015 (
errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1016 errmsg(
"cannot drop %s because %s requires it",
1018 errhint(
"You can drop %s instead.", otherObjDesc)));
1023 * If no error is to be thrown, and the msglevel is too low to be shown to
1024 * either client or server log, there's no need to do any of the rest of
1032 * We limit the number of dependencies reported to the client to
1033 * MAX_REPORTED_DEPS, since client software may not deal well with
1034 * enormous error strings. The server log always gets a full report.
1036#define MAX_REPORTED_DEPS 100
1042 * We process the list back to front (ie, in dependency order not deletion
1043 * order), since this makes for a more understandable display.
1045 for (
i = targetObjects->
numrefs - 1;
i >= 0;
i--)
1051 /* Ignore the original deletion target(s) */
1055 /* Also ignore sub-objects; we'll report the whole object elsewhere */
1061 /* An object being dropped concurrently doesn't need to be reported */
1062 if (objDesc == NULL)
1066 * If, at any stage of the recursive search, we reached the object via
1067 * an AUTO, INTERNAL, PARTITION, or EXTENSION dependency, then it's
1068 * okay to delete it even in RESTRICT mode.
1076 * auto-cascades are reported at DEBUG2, not msglevel. We don't
1077 * try to combine them with the regular message because the
1078 * results are too confusing when client_min_messages and
1079 * log_min_messages are different.
1094 /* separate entries with a newline */
1095 if (clientdetail.
len != 0)
1098 objDesc, otherDesc);
1099 numReportedClient++;
1102 numNotReportedClient++;
1103 /* separate entries with a newline */
1104 if (logdetail.
len != 0)
1107 objDesc, otherDesc);
1111 numNotReportedClient++;
1118 /* separate entries with a newline */
1119 if (clientdetail.
len != 0)
1123 numReportedClient++;
1126 numNotReportedClient++;
1127 /* separate entries with a newline */
1128 if (logdetail.
len != 0)
1137 if (numNotReportedClient > 0)
1139 "(see server log for list)",
1140 "\nand %d other objects "
1141 "(see server log for list)",
1142 numNotReportedClient),
1143 numNotReportedClient);
1149 (
errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1150 errmsg(
"cannot drop %s because other objects depend on it",
1154 errhint(
"Use DROP ... CASCADE to drop the dependent objects too.")));
1157 (
errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1158 errmsg(
"cannot drop desired object(s) because other objects depend on them"),
1161 errhint(
"Use DROP ... CASCADE to drop the dependent objects too.")));
1163 else if (numReportedClient > 1)
1167 "drop cascades to %d other objects",
1168 numReportedClient + numNotReportedClient,
1169 numReportedClient + numNotReportedClient),
1173 else if (numReportedClient == 1)
1175 /* we just use the single item as-is */
1185 * Drop an object by OID. Works for most catalogs, if no special processing
1200 * Use the system cache for the oid column, if one exists.
1206 elog(
ERROR,
"cache lookup failed for %s %u",
1226 /* we expect exactly one match */
1229 elog(
ERROR,
"could not find tuple for %s %u",
1241 * deleteOneObject: delete a single object for performDeletion.
1243 * *depRel is the already-open pg_depend relation.
1253 /* DROP hook of the objects being removed */
1258 * Close depRel if we are doing a drop concurrently. The object deletion
1259 * subroutine will commit the current transaction, so we can't keep the
1260 * relation open across doDeletion().
1266 * Delete the object itself, in an object-type-dependent way.
1268 * We used to do this after removing the outgoing dependency links, but it
1269 * seems just as reasonable to do it beforehand. In the concurrent case
1270 * we *must* do it in this order, because we can't make any transactional
1271 * updates before calling doDeletion() --- they'd get committed right
1272 * away, which is not cool if the deletion then fails.
1277 * Reopen depRel if we closed it above
1283 * Now remove any pg_depend records that link from this object to others.
1284 * (Any records linking to this object should be gone already.)
1286 * When dropping a whole object (subId = 0), remove all pg_depend records
1287 * for its sub-objects too.
1290 Anum_pg_depend_classid,
1294 Anum_pg_depend_objid,
1300 Anum_pg_depend_objsubid,
1319 * Delete shared dependency references related to this object. Again, if
1320 * subId = 0, remove records for sub-objects too.
1327 * Delete any comments, security labels, or initial privileges associated
1328 * with this object. (This is a convenient place to do these things,
1329 * rather than having every object type know to do it.) As above, all
1330 * these functions must remove records for sub-objects too if the subid is
1338 * CommandCounterIncrement here to ensure that preceding changes are all
1339 * visible to the next deletion step.
1349 * doDeletion: actually delete a single object
1356 case RelationRelationId:
1360 if (relKind == RELKIND_INDEX ||
1361 relKind == RELKIND_PARTITIONED_INDEX)
1379 * for a sequence, in addition to dropping the heap, also
1380 * delete pg_sequence tuple
1382 if (relKind == RELKIND_SEQUENCE)
1387 case ProcedureRelationId:
1391 case TypeRelationId:
1395 case ConstraintRelationId:
1399 case AttrDefaultRelationId:
1403 case LargeObjectRelationId:
1407 case OperatorRelationId:
1411 case RewriteRelationId:
1415 case TriggerRelationId:
1419 case StatisticExtRelationId:
1423 case TSConfigRelationId:
1427 case ExtensionRelationId:
1431 case PolicyRelationId:
1435 case PublicationNamespaceRelationId:
1439 case PublicationRelRelationId:
1443 case PublicationRelationId:
1447 case CastRelationId:
1448 case CollationRelationId:
1449 case ConversionRelationId:
1450 case LanguageRelationId:
1451 case OperatorClassRelationId:
1452 case OperatorFamilyRelationId:
1453 case AccessMethodRelationId:
1454 case AccessMethodOperatorRelationId:
1455 case AccessMethodProcedureRelationId:
1456 case NamespaceRelationId:
1457 case TSParserRelationId:
1458 case TSDictionaryRelationId:
1459 case TSTemplateRelationId:
1460 case ForeignDataWrapperRelationId:
1461 case ForeignServerRelationId:
1462 case UserMappingRelationId:
1463 case DefaultAclRelationId:
1464 case EventTriggerRelationId:
1465 case TransformRelationId:
1466 case AuthMemRelationId:
1471 * These global object types are not supported here.
1473 case AuthIdRelationId:
1474 case DatabaseRelationId:
1475 case TableSpaceRelationId:
1476 case SubscriptionRelationId:
1477 case ParameterAclRelationId:
1478 elog(
ERROR,
"global objects cannot be deleted by doDeletion");
1487 * AcquireDeletionLock - acquire a suitable lock for deleting an object
1489 * Accepts the same flags as performDeletion (though currently only
1490 * PERFORM_DELETION_CONCURRENTLY does anything).
1492 * We use LockRelation for relations, and otherwise LockSharedObject or
1493 * LockDatabaseObject as appropriate for the object type.
1501 * In DROP INDEX CONCURRENTLY, take only ShareUpdateExclusiveLock on
1502 * the index for the moment. index_drop() will promote the lock once
1503 * it's safe to do so. In all other cases we need full exclusive
1516 /* assume we should lock the whole object not a sub-object */
1523 * ReleaseDeletionLock - release an object deletion lock
1525 * Companion to AcquireDeletionLock.
1533 /* assume we should lock the whole object not a sub-object */
1539 * recordDependencyOnExpr - find expression dependencies
1541 * This is used to find the dependencies of rules, constraint expressions,
1544 * Given an expression or query in node-tree form, find all the objects
1545 * it refers to (tables, columns, operators, functions, etc). Record
1546 * a dependency of the specified type from the given depender object
1547 * to each object mentioned in the expression.
1549 * rtable is the rangetable to be used to interpret Vars with varlevelsup=0.
1550 * It can be NIL if no such variables are expected.
1561 /* Set up interpretation for Vars at varlevelsup = 0 */
1564 /* Scan the expression tree for referenceable objects */
1567 /* Remove any duplicates */
1570 /* And record 'em */
1579 * recordDependencyOnSingleRelExpr - find expression dependencies
1581 * As above, but only one relation is expected to be referenced (with
1582 * varno = 1 and varlevelsup = 0). Pass the relation OID instead of a
1583 * range table. An additional frammish is that dependencies on that
1584 * relation's component columns will be marked with 'self_behavior',
1585 * whereas 'behavior' is used for everything else; also, if 'reverse_self'
1586 * is true, those dependencies are reversed so that the columns are made
1587 * to depend on the table not vice versa.
1589 * NOTE: the caller should ensure that a whole-table dependency on the
1590 * specified relation is created separately, if one is needed. In particular,
1591 * a whole-row Var "relation.*" will not cause this routine to emit any
1592 * dependency item. This is appropriate behavior for subexpressions of an
1593 * ordinary query, so other cases need to cope as necessary.
1607 /* We gin up a rather bogus rangetable list to handle Vars */
1608 rte.type = T_RangeTblEntry;
1611 rte.relkind = RELKIND_RELATION;
/* no need for exactness here */
1616 /* Scan the expression tree for referenceable objects */
1619 /* Remove any duplicates */
1622 /* Separate self-dependencies if necessary */
1623 if ((behavior != self_behavior || reverse_self) &&
1635 for (oldref = 0; oldref < context.
addrs->
numrefs; oldref++)
1639 if (thisobj->
classId == RelationRelationId &&
1642 /* Move this ref into self_addrs */
1647 /* Keep it in context.addrs */
1655 /* Record the self-dependencies with the appropriate direction */
1662 /* Can't use recordMultipleDependencies, so do it the hard way */
1665 for (selfref = 0; selfref < self_addrs->
numrefs; selfref++)
1676 /* Record the external dependencies */
1685 * Recursively search an expression tree for object references.
1687 * Note: in many cases we do not need to create dependencies on the datatypes
1688 * involved in an expression, because we'll have an indirect dependency via
1689 * some other object. For instance Var nodes depend on a column which depends
1690 * on the datatype, and OpExpr nodes depend on the operator which depends on
1691 * the datatype. However we do need a type dependency if there is no such
1692 * indirect dependency, as for example in Const and CoerceToDomain nodes.
1694 * Similarly, we don't need to create dependencies on collations except where
1695 * the collation is being freshly introduced to the expression.
1709 /* Find matching rtable entry, or complain if not found */
1718 * A whole-row Var references no specific columns, so adds no new
1719 * dependency. (We assume that there is a whole-table dependency
1720 * arising from each underlying rangetable entry. While we could
1721 * record such a dependency when finding a whole-row Var that
1722 * references a relation directly, it's quite unclear how to extend
1723 * that to whole-row Vars for JOINs, so it seems better to leave the
1724 * responsibility with the range table. Note that this poses some
1725 * risks for identifying dependencies of stand-alone expressions:
1726 * whole-table references may need to be created separately.)
1732 /* If it's a plain relation, reference this column */
1738 /* Might need to add a dependency on a composite type's column */
1739 /* (done out of line, because it's a bit bulky) */
1744 * Vars referencing other RTE types require no additional work. In
1745 * particular, a join alias Var can be ignored, because it must
1746 * reference a merged USING column. The relevant join input columns
1747 * will also be referenced in the join qual, and any type coercion
1748 * functions involved in the alias expression will be dealt with when
1749 * we scan the RTE itself.
1758 /* A constant must depend on the constant's datatype */
1763 * We must also depend on the constant's collation: it could be
1764 * different from the datatype's, if a CollateExpr was const-folded to
1765 * a simple constant. However we can save work in the most common
1766 * case where the collation is "default", since we know that's pinned.
1769 con->constcollid != DEFAULT_COLLATION_OID)
1774 * If it's a regclass or similar literal referring to an existing
1775 * object, add a reference to that object. (Currently, only the
1776 * regclass and regconfig cases have any likely use, but we may as
1777 * well handle all the OID-alias datatypes consistently.)
1779 if (!con->constisnull)
1784 case REGPROCEDUREOID:
1792 case REGOPERATOROID:
1813 case REGCOLLATIONOID:
1827 case REGDICTIONARYOID:
1835 case REGNAMESPACEOID:
1844 * Dependencies for regrole should be shared among all
1845 * databases, so explicitly inhibit to have dependencies.
1849 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1850 errmsg(
"constant of the type %s cannot be used here",
1855 * Dependencies for regdatabase should be shared among all
1856 * databases, so explicitly inhibit to have dependencies.
1858 case REGDATABASEOID:
1860 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1861 errmsg(
"constant of the type %s cannot be used here",
1872 /* A parameter must depend on the parameter's datatype */
1875 /* and its collation, just as for Consts */
1887 /* fall through to examine arguments */
1895 /* fall through to examine arguments */
1903 /* fall through to examine arguments */
1911 /* fall through to examine arguments */
1919 /* fall through to examine arguments */
1927 /* fall through to examine arguments */
1935 /* fall through to examine arguments */
1942 * The refexpr should provide adequate dependency on refcontainertype,
1943 * and that type in turn depends on refelemtype. However, a custom
1944 * subscripting handler might set refrestype to something different
1945 * from either of those, in which case we'd better record it.
1947 if (sbsref->refrestype != sbsref->refcontainertype &&
1948 sbsref->refrestype != sbsref->refelemtype)
1951 /* fall through to examine arguments */
1955 /* Extra work needed here if we ever need this case */
1956 elog(
ERROR,
"already-planned subqueries not supported");
1965 * We need a dependency on the specific column named in FieldSelect,
1966 * assuming we can identify the pg_class OID for it. (Probably we
1967 * always can at the moment, but in future it might be possible for
1968 * argtype to be RECORDOID.) If we can make a column dependency then
1969 * we shouldn't need a dependency on the column's type; but if we
1970 * can't, make a dependency on the type, as it might not appear
1971 * anywhere else in the expression.
1979 /* the collation might not be referenced anywhere else, either */
1981 fselect->resultcollid != DEFAULT_COLLATION_OID)
1990 /* similar considerations to FieldSelect, but multiple column(s) */
1995 foreach(l, fstore->fieldnums)
2007 /* since there is no function dependency, need to depend on type */
2010 /* the collation might not be referenced anywhere else, either */
2012 relab->resultcollid != DEFAULT_COLLATION_OID)
2020 /* since there is no exposed function, need to depend on type */
2023 /* the collation might not be referenced anywhere else, either */
2025 iocoerce->resultcollid != DEFAULT_COLLATION_OID)
2033 /* as above, depend on type */
2036 /* the collation might not be referenced anywhere else, either */
2038 acoerce->resultcollid != DEFAULT_COLLATION_OID)
2041 /* fall through to examine arguments */
2047 /* since there is no function dependency, need to depend on type */
2070 foreach(l, rcexpr->opnos)
2075 foreach(l, rcexpr->opfamilies)
2080 /* fall through to examine arguments */
2103 /* fall through to examine arguments */
2127 wc->inRangeColl != DEFAULT_COLLATION_OID)
2130 /* fall through to examine substructure */
2145 /* fall through to examine substructure */
2149 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
2155 * Add whole-relation refs for each plain relation mentioned in the
2156 * subquery's rtable, and ensure we add refs for any type-coercion
2157 * functions used in join alias lists.
2159 * Note: query_tree_walker takes care of recursing into RTE_FUNCTION
2160 * RTEs, subqueries, etc, so no need to do that here. But we must
2161 * tell it not to visit join alias lists, or we'll add refs for join
2162 * input columns whether or not they are actually used in our query.
2164 * Note: we don't need to worry about collations mentioned in
2165 * RTE_VALUES or RTE_CTE RTEs, because those must just duplicate
2166 * collations referenced in other parts of the Query. We do have to
2167 * worry about collations mentioned in RTE_FUNCTION, but we take care
2168 * of those when we recurse to the RangeTblFunction node(s).
2170 foreach(lc, query->
rtable)
2183 * Examine joinaliasvars entries only for merged JOIN
2184 * USING columns. Only those entries could contain
2185 * type-coercion functions. Also, their join input
2186 * columns must be referenced in the join quals, so this
2187 * won't accidentally add refs to otherwise-unused join
2188 * input columns. (We want to ref the type coercion
2189 * functions even if the merged column isn't explicitly
2190 * used anywhere, to protect possible expansion of the
2191 * join RTE as a whole-row var, and because it seems like
2192 * a bad idea to allow dropping a function that's present
2193 * in our query tree, whether or not it could get called.)
2196 for (
int i = 0;
i < rte->joinmergedcols;
i++)
2208 * Cataloged objects cannot depend on tuplestores, because
2209 * those have no cataloged representation. For now we can
2210 * call the tuplestore a "transition table" because that's
2211 * the only kind exposed to SQL, but someday we might have
2215 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2216 errmsg(
"transition table \"%s\" cannot be referenced in a persistent object",
2217 rte->eref->aliasname)));
2220 /* Other RTE types can be ignored here */
2226 * If the query is an INSERT or UPDATE, we should create a dependency
2227 * on each target column, to prevent the specific target column from
2228 * being dropped. Although we will visit the TargetEntry nodes again
2229 * during query_tree_walker, we won't have enough context to do this
2230 * conveniently, so do it here.
2237 if (query->resultRelation <= 0 ||
2239 elog(
ERROR,
"invalid resultRelation %d",
2240 query->resultRelation);
2249 continue;
/* ignore junk tlist items */
2257 * Add dependencies on constraints listed in query's constraintDeps
2259 foreach(lc, query->constraintDeps)
2265 /* Examine substructure of query */
2279 /* we need to look at the groupClauses for operator references */
2281 /* fall through to examine child nodes */
2289 * Add refs for any datatypes and collations used in a column
2290 * definition list for a RECORD function. (For other cases, it should
2291 * be enough to depend on the function itself.)
2293 foreach(ct, rtfunc->funccoltypes)
2298 foreach(ct, rtfunc->funccolcollations)
2313 * Add refs for the datatypes and collations used in the TableFunc.
2315 foreach(ct, tf->coltypes)
2320 foreach(ct, tf->colcollations)
2335 /* fall through to examine arguments */
2343 * find_expr_references_walker subroutine: handle a Var reference
2344 * to an RTE_FUNCTION RTE
2354 * Identify which RangeTblFunction produces this attnum, and see if it
2355 * returns a composite type. If so, we'd better make a dependency on the
2356 * referenced column of the composite type (or actually, of its associated
2363 if (
attnum > atts_done &&
2364 attnum <= atts_done + rtfunc->funccolcount)
2368 /* If it has a coldeflist, it certainly returns RECORD */
2369 if (rtfunc->funccolnames !=
NIL)
2370 tupdesc = NULL;
/* no need to work hard */
2373 if (tupdesc && tupdesc->
tdtypeid != RECORDOID)
2376 * Named composite type, so individual columns could get
2377 * dropped. Make a dependency on this specific column.
2382 if (
OidIsValid(reltype))
/* can this fail? */
2388 /* Nothing to do; function's result type is handled elsewhere */
2391 atts_done += rtfunc->funccolcount;
2394 /* If we get here, must be looking for the ordinality column */
2398 /* this probably can't happen ... */
2400 (
errcode(ERRCODE_UNDEFINED_COLUMN),
2401 errmsg(
"column %d of relation \"%s\" does not exist",
2402 attnum, rte->eref->aliasname)));
2406 * Given an array of dependency references, eliminate any duplicates.
2416 * We can't sort if the array has "extra" data, because there's no way to
2417 * keep it in sync. Fortunately that combination of features is not
2423 return;
/* nothing to do */
2425 /* Sort the refs so that duplicates are adjacent */
2430 priorobj = addrs->
refs;
2432 for (oldref = 1; oldref < addrs->
numrefs; oldref++)
2440 continue;
/* identical, so drop thisobj */
2443 * If we have a whole-object reference and a reference to a part
2444 * of the same object, we don't need the whole-object reference
2445 * (for example, we don't need to reference both table foo and
2446 * column foo.bar). The whole-object reference will always appear
2447 * first in the sorted list.
2451 /* replace whole ref with partial */
2456 /* Not identical, so add thisobj to output set */
2458 *priorobj = *thisobj;
2466 * qsort comparator for ObjectAddress items
2475 * Primary sort key is OID descending. Most of the time, this will result
2476 * in putting newer objects before older ones, which is likely to be the
2477 * right order to delete in.
2485 * Next sort on catalog ID, in case identical OIDs appear in different
2486 * catalogs. Sort direction is pretty arbitrary here.
2494 * Last, sort on object subId.
2496 * We sort the subId as an unsigned int so that 0 (the whole object) will
2497 * come first. This is essential for eliminate_duplicate_dependencies,
2498 * and is also the best order for findDependentObjects.
2508 * Routines for handling an expansible array of ObjectAddress items.
2510 * new_object_addresses: create a new ObjectAddresses array.
2523 addrs->
extras = NULL;
/* until/unless needed */
2529 * Add an entry to an ObjectAddresses array.
2537 /* enlarge array if needed */
2545 /* record this item */
2554 * Add an entry to an ObjectAddresses array.
2556 * As above, but specify entry exactly.
2564 /* enlarge array if needed */
2572 /* record this item */
2579 * Add an entry to an ObjectAddresses array.
2581 * As above, but specify entry exactly and provide some "extra" data too.
2591 /* allocate extra space if first time */
2596 /* enlarge array if needed */
2605 /* record this item */
2609 *itemextra = *extra;
2614 * Test whether an object is present in an ObjectAddresses array.
2616 * We return "true" if object is a subobject of something in the array, too.
2641 * As above, except that if the object is present then also OR the given
2642 * flags into its associated extra data (which must exist).
2649 bool result =
false;
2669 * We get here if we find a need to delete a column after
2670 * having already decided to drop its whole table. Obviously
2671 * we no longer need to drop the subobject, so report that we
2672 * found the subobject in the array. But don't plaster its
2673 * flags on the whole object.
2680 * We get here if we find a need to delete a whole table after
2681 * having already decided to drop one of its columns. We
2682 * can't report that the whole object is in the array, but we
2683 * should mark the subobject with the whole object's flags.
2685 * It might seem attractive to physically delete the column's
2686 * array entry, or at least mark it as no longer needing
2687 * separate deletion. But that could lead to, e.g., dropping
2688 * the column's datatype before we drop the table, which does
2689 * not seem like a good idea. This is a very rare situation
2690 * in practice, so we just take the hit of doing a separate
2691 * DROP COLUMN action even though we know we're gonna delete
2694 * What we can do, though, is mark this as a subobject so that
2695 * we don't report it separately, which is confusing because
2696 * it's unpredictable whether it happens or not. But do so
2697 * only if flags != 0 (flags == 0 is a read-only probe).
2699 * Because there could be other subobjects of this object in
2700 * the array, this case means we always have to loop through
2701 * the whole array; we cannot exit early on a match.
2715 * Similar to above, except we search an ObjectAddressStack.
2722 bool result =
false;
2725 for (stackptr = stack; stackptr; stackptr = stackptr->
next)
2740 * We're visiting a column with whole table already on stack.
2741 * As in object_address_present_add_flags(), we can skip
2742 * further processing of the subobject, but we don't want to
2743 * propagate flags for the subobject to the whole object.
2750 * We're visiting a table with column already on stack. As in
2751 * object_address_present_add_flags(), we should propagate
2752 * flags for the whole object to each of its subobjects.
2764 * Record multiple dependencies from an ObjectAddresses array, after first
2765 * removing any duplicates.
2779 * Sort the items in an ObjectAddresses array.
2781 * The major sort key is OID-descending, so that newer objects will be listed
2782 * first in most cases. This is primarily useful for ensuring stable outputs
2783 * from regression tests; it's not recommended if the order of the objects is
2784 * determined by user input, such as the order of targets in a DROP command.
2796 * Clean up when done with an ObjectAddresses array.
2808 * delete initial ACL for extension objects
2822 Anum_pg_init_privs_objoid,
2826 Anum_pg_init_privs_classoid,
2832 Anum_pg_init_privs_objsubid,
#define InvalidAttrNumber
#define ngettext(s, p, n)
#define OidIsValid(objectId)
bool IsPinnedObject(Oid classId, Oid objectId)
void DeleteSequenceTuple(Oid relid)
static bool object_address_present_add_flags(const ObjectAddress *object, int flags, ObjectAddresses *addrs)
#define DEPFLAG_PARTITION
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
struct ObjectAddressStack ObjectAddressStack
static void add_exact_object_address_extra(const ObjectAddress *object, const ObjectAddressExtra *extra, ObjectAddresses *addrs)
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
static void DropObjectById(const ObjectAddress *object)
static int object_address_comparator(const void *a, const void *b)
void sort_object_addresses(ObjectAddresses *addrs)
static void doDeletion(const ObjectAddress *object, int flags)
static bool stack_address_present_add_flags(const ObjectAddress *object, int flags, ObjectAddressStack *stack)
static void add_object_address(Oid classId, Oid objectId, int32 subId, ObjectAddresses *addrs)
static bool find_expr_references_walker(Node *node, find_expr_references_context *context)
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs)
void AcquireDeletionLock(const ObjectAddress *object, int flags)
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
static void deleteOneObject(const ObjectAddress *object, Relation *depRel, int32 flags)
static void DeleteInitPrivs(const ObjectAddress *object)
#define MAX_REPORTED_DEPS
static void process_function_rte_ref(RangeTblEntry *rte, AttrNumber attnum, find_expr_references_context *context)
static void reportDependentObjects(const ObjectAddresses *targetObjects, DropBehavior behavior, int flags, const ObjectAddress *origObject)
void ReleaseDeletionLock(const ObjectAddress *object)
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
static void findDependentObjects(const ObjectAddress *object, int objflags, int flags, ObjectAddressStack *stack, ObjectAddresses *targetObjects, const ObjectAddresses *pendingObjects, Relation *depRel)
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
#define DEPFLAG_SUBOBJECT
#define DEPFLAG_EXTENSION
static void deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, int flags)
void free_object_addresses(ObjectAddresses *addrs)
#define PERFORM_DELETION_CONCURRENTLY
#define PERFORM_DELETION_SKIP_EXTENSIONS
@ DEPENDENCY_AUTO_EXTENSION
@ DEPENDENCY_PARTITION_PRI
@ DEPENDENCY_PARTITION_SEC
#define PERFORM_DELETION_CONCURRENT_LOCK
#define PERFORM_DELETION_QUIETLY
#define PERFORM_DELETION_SKIP_ORIGINAL
#define PERFORM_DELETION_INTERNAL
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
int errmsg_internal(const char *fmt,...)
int errdetail_internal(const char *fmt,...)
int errhint(const char *fmt,...)
bool message_level_is_interesting(int elevel)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
int errdetail_log(const char *fmt,...)
#define ereport(elevel,...)
void EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool normal)
bool trackDroppedObjectsNeeded(void)
bool EventTriggerSupportsObject(const ObjectAddress *object)
Oid CurrentExtensionObject
void RemoveExtensionById(Oid extId)
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
void RemoveFunctionById(Oid funcOid)
void systable_endscan(SysScanDesc sysscan)
bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
HeapTuple systable_getnext(SysScanDesc sysscan)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Assert(PointerIsAligned(start, uint64))
void RemoveAttributeById(Oid relid, AttrNumber attnum)
void heap_drop_with_catalog(Oid relid)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
void index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
List * list_delete_first(List *list)
List * lcons(void *datum, List *list)
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
void LockRelationOid(Oid relid, LOCKMODE lockmode)
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
#define AccessExclusiveLock
#define ShareUpdateExclusiveLock
char get_rel_relkind(Oid relid)
Oid get_typ_typrelid(Oid typid)
Oid getBaseType(Oid typid)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
Oid exprType(const Node *expr)
#define query_tree_walker(q, w, c, f)
#define QTW_EXAMINE_SORTGROUP
#define expression_tree_walker(n, w, c)
#define QTW_IGNORE_JOINALIASES
#define IsA(nodeptr, _type_)
#define InvokeObjectDropHookArg(classId, objectId, subId, dropflags)
AttrNumber get_object_attnum_oid(Oid class_id)
const char * get_object_class_descr(Oid class_id)
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
int get_object_catcache_oid(Oid class_id)
Oid get_object_oid_index(Oid class_id)
void RemoveOperatorById(Oid operOid)
#define rt_fetch(rangetable_index, rangetable)
void RemoveAttrDefaultById(Oid attrdefId)
void RemoveConstraintById(Oid conId)
void recordMultipleDependencies(const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
FormData_pg_depend * Form_pg_depend
void LargeObjectDrop(Oid loid)
static int list_length(const List *l)
static void * list_nth(const List *list, int n)
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
void RemovePolicyById(Oid policy_id)
#define qsort(a, b, c, d)
static Oid DatumGetObjectId(Datum X)
static Datum ObjectIdGetDatum(Oid X)
static Datum Int32GetDatum(int32 X)
void RemovePublicationSchemaById(Oid psoid)
void RemovePublicationById(Oid pubid)
void RemovePublicationRelById(Oid proid)
void RemoveRewriteRuleById(Oid ruleOid)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
void DeleteSecurityLabel(const ObjectAddress *object)
void check_stack_depth(void)
void RemoveStatisticsById(Oid statsOid)
#define BTEqualStrategyNumber
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
const ObjectAddress * object
struct ObjectAddressStack * next
ObjectAddressExtra * extras
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define SearchSysCacheExists1(cacheId, key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
void RemoveTriggerById(Oid trigOid)
void RemoveTSConfigurationById(Oid cfgId)
void RemoveTypeById(Oid typeOid)
void CommandCounterIncrement(void)