#include "catalog/objectaddress.h"
Go to the source code of this file.
#define PERFORM_DELETION_CONCURRENTLY 0x0002 |
Definition at line 157 of file dependency.h.
Referenced by AcquireDeletionLock(), deleteOneObject(), and doDeletion().
#define PERFORM_DELETION_INTERNAL 0x0001 |
Definition at line 156 of file dependency.h.
Referenced by ATPostAlterTypeCleanup(), DefineQueryRewrite(), deleteObjectsInList(), deleteWhatDependsOn(), do_autovacuum(), finish_heap_swap(), PreCommit_on_commit_actions(), RemoveAttrDefault(), and sepgsql_object_access().
typedef enum DependencyType DependencyType |
typedef struct ObjectAddresses ObjectAddresses |
Definition at line 111 of file dependency.h.
typedef enum ObjectClass ObjectClass |
typedef enum SharedDependencyType SharedDependencyType |
enum DependencyType |
DEPENDENCY_NORMAL | |
DEPENDENCY_AUTO | |
DEPENDENCY_INTERNAL | |
DEPENDENCY_EXTENSION | |
DEPENDENCY_PIN |
Definition at line 67 of file dependency.h.
{ DEPENDENCY_NORMAL = 'n', DEPENDENCY_AUTO = 'a', DEPENDENCY_INTERNAL = 'i', DEPENDENCY_EXTENSION = 'e', DEPENDENCY_PIN = 'p' } DependencyType;
enum ObjectClass |
Definition at line 117 of file dependency.h.
{ OCLASS_CLASS, /* pg_class */ OCLASS_PROC, /* pg_proc */ OCLASS_TYPE, /* pg_type */ OCLASS_CAST, /* pg_cast */ OCLASS_COLLATION, /* pg_collation */ OCLASS_CONSTRAINT, /* pg_constraint */ OCLASS_CONVERSION, /* pg_conversion */ OCLASS_DEFAULT, /* pg_attrdef */ OCLASS_LANGUAGE, /* pg_language */ OCLASS_LARGEOBJECT, /* pg_largeobject */ OCLASS_OPERATOR, /* pg_operator */ OCLASS_OPCLASS, /* pg_opclass */ OCLASS_OPFAMILY, /* pg_opfamily */ OCLASS_AMOP, /* pg_amop */ OCLASS_AMPROC, /* pg_amproc */ OCLASS_REWRITE, /* pg_rewrite */ OCLASS_TRIGGER, /* pg_trigger */ OCLASS_SCHEMA, /* pg_namespace */ OCLASS_TSPARSER, /* pg_ts_parser */ OCLASS_TSDICT, /* pg_ts_dict */ OCLASS_TSTEMPLATE, /* pg_ts_template */ OCLASS_TSCONFIG, /* pg_ts_config */ OCLASS_ROLE, /* pg_authid */ OCLASS_DATABASE, /* pg_database */ OCLASS_TBLSPACE, /* pg_tablespace */ OCLASS_FDW, /* pg_foreign_data_wrapper */ OCLASS_FOREIGN_SERVER, /* pg_foreign_server */ OCLASS_USER_MAPPING, /* pg_user_mapping */ OCLASS_DEFACL, /* pg_default_acl */ OCLASS_EXTENSION, /* pg_extension */ OCLASS_EVENT_TRIGGER, /* pg_event_trigger */ MAX_OCLASS /* MUST BE LAST */ } ObjectClass;
enum SharedDependencyType |
SHARED_DEPENDENCY_PIN | |
SHARED_DEPENDENCY_OWNER | |
SHARED_DEPENDENCY_ACL | |
SHARED_DEPENDENCY_INVALID |
Definition at line 102 of file dependency.h.
{ SHARED_DEPENDENCY_PIN = 'p', SHARED_DEPENDENCY_OWNER = 'o', SHARED_DEPENDENCY_ACL = 'a', SHARED_DEPENDENCY_INVALID = 0 } SharedDependencyType;
void add_exact_object_address | ( | const ObjectAddress * | object, | |
ObjectAddresses * | addrs | |||
) |
Definition at line 2015 of file dependency.c.
References Assert, ObjectAddresses::extras, ObjectAddresses::maxrefs, ObjectAddresses::numrefs, ObjectAddresses::refs, and repalloc().
Referenced by AlterConstraintNamespaces(), AlterIndexNamespaces(), AlterRelationNamespaceInternal(), AlterTypeNamespaceInternal(), makeConfigurationDependencies(), recordDependencyOnSingleRelExpr(), RemoveObjects(), RemoveRelations(), and shdepDropOwned().
{ ObjectAddress *item; /* enlarge array if needed */ if (addrs->numrefs >= addrs->maxrefs) { addrs->maxrefs *= 2; addrs->refs = (ObjectAddress *) repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress)); Assert(!addrs->extras); } /* record this item */ item = addrs->refs + addrs->numrefs; *item = *object; addrs->numrefs++; }
long changeDependencyFor | ( | Oid | classId, | |
Oid | objectId, | |||
Oid | refClassId, | |||
Oid | oldRefObjectId, | |||
Oid | newRefObjectId | |||
) |
Definition at line 297 of file pg_depend.c.
References Anum_pg_depend_classid, Anum_pg_depend_objid, BTEqualStrategyNumber, CatalogUpdateIndexes(), ObjectAddress::classId, DependDependerIndexId, DependRelationId, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, heap_close, heap_copytuple(), heap_freetuple(), heap_open(), HeapTupleIsValid, isObjectPinned(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), simple_heap_update(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by AlterExtensionNamespace(), AlterObjectNamespace_internal(), AlterRelationNamespaceInternal(), and AlterTypeNamespaceInternal().
{ long count = 0; Relation depRel; ScanKeyData key[2]; SysScanDesc scan; HeapTuple tup; ObjectAddress objAddr; bool newIsPinned; depRel = heap_open(DependRelationId, RowExclusiveLock); /* * If oldRefObjectId is pinned, there won't be any dependency entries on * it --- we can't cope in that case. (This isn't really worth expending * code to fix, in current usage; it just means you can't rename stuff out * of pg_catalog, which would likely be a bad move anyway.) */ objAddr.classId = refClassId; objAddr.objectId = oldRefObjectId; objAddr.objectSubId = 0; if (isObjectPinned(&objAddr, depRel)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot remove dependency on %s because it is a system object", getObjectDescription(&objAddr)))); /* * We can handle adding a dependency on something pinned, though, since * that just means deleting the dependency entry. */ objAddr.objectId = newRefObjectId; newIsPinned = isObjectPinned(&objAddr, depRel); /* Now search for dependency records */ ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(classId)); ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(objectId)); scan = systable_beginscan(depRel, DependDependerIndexId, true, SnapshotNow, 2, key); while (HeapTupleIsValid((tup = systable_getnext(scan)))) { Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup); if (depform->refclassid == refClassId && depform->refobjid == oldRefObjectId) { if (newIsPinned) simple_heap_delete(depRel, &tup->t_self); else { /* make a modifiable copy */ tup = heap_copytuple(tup); depform = (Form_pg_depend) GETSTRUCT(tup); depform->refobjid = newRefObjectId; simple_heap_update(depRel, &tup->t_self, tup); CatalogUpdateIndexes(depRel, tup); heap_freetuple(tup); } count++; } } systable_endscan(scan); heap_close(depRel, RowExclusiveLock); return count; }
Definition at line 301 of file pg_shdepend.c.
References AuthIdRelationId, heap_close, heap_open(), RowExclusiveLock, SHARED_DEPENDENCY_ACL, SHARED_DEPENDENCY_OWNER, SharedDependRelationId, shdepChangeDep(), and shdepDropDependency().
Referenced by AlterDatabaseOwner(), AlterEventTriggerOwner_internal(), AlterForeignDataWrapperOwner_internal(), AlterForeignServerOwner_internal(), AlterObjectOwner_internal(), AlterSchemaOwner_internal(), AlterTypeOwner(), AlterTypeOwnerInternal(), and ATExecChangeOwner().
{ Relation sdepRel; sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock); /* Adjust the SHARED_DEPENDENCY_OWNER entry */ shdepChangeDep(sdepRel, classId, objectId, 0, AuthIdRelationId, newOwnerId, SHARED_DEPENDENCY_OWNER); /*---------- * There should never be a SHARED_DEPENDENCY_ACL entry for the owner, * so get rid of it if there is one. This can happen if the new owner * was previously granted some rights to the object. * * This step is analogous to aclnewowner's removal of duplicate entries * in the ACL. We have to do it to handle this scenario: * A grants some rights on an object to B * ALTER OWNER changes the object's owner to B * ALTER OWNER changes the object's owner to C * The third step would remove all mention of B from the object's ACL, * but we'd still have a SHARED_DEPENDENCY_ACL for B if we did not do * things this way. * * The rule against having a SHARED_DEPENDENCY_ACL entry for the owner * allows us to fix things up in just this one place, without having * to make the various ALTER OWNER routines each know about it. *---------- */ shdepDropDependency(sdepRel, classId, objectId, 0, true, AuthIdRelationId, newOwnerId, SHARED_DEPENDENCY_ACL); heap_close(sdepRel, RowExclusiveLock); }
bool checkSharedDependencies | ( | Oid | classId, | |
Oid | objectId, | |||
char ** | detail_msg, | |||
char ** | detail_log_msg | |||
) |
Definition at line 519 of file pg_shdepend.c.
References AccessShareLock, Anum_pg_shdepend_refclassid, Anum_pg_shdepend_refobjid, appendStringInfo(), BTEqualStrategyNumber, remoteDep::count, StringInfoData::data, remoteDep::dbOid, ereport, errcode(), errmsg(), ERROR, getObjectDescription(), GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, initStringInfo(), InvalidOid, lappend(), StringInfoData::len, lfirst, list_free_deep(), LOCAL_OBJECT, MAX_REPORTED_DEPS, MyDatabaseId, ngettext, ObjectIdGetDatum, palloc(), pfree(), REMOTE_OBJECT, ScanKeyInit(), SHARED_DEPENDENCY_INVALID, SHARED_DEPENDENCY_PIN, SHARED_OBJECT, SharedDependReferenceIndexId, SharedDependRelationId, SnapshotNow, storeObjectDescription(), systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by DropRole().
{ Relation sdepRel; ScanKeyData key[2]; SysScanDesc scan; HeapTuple tup; int numReportedDeps = 0; int numNotReportedDeps = 0; int numNotReportedDbs = 0; List *remDeps = NIL; ListCell *cell; ObjectAddress object; StringInfoData descs; StringInfoData alldescs; /* * We limit the number of dependencies reported to the client to * MAX_REPORTED_DEPS, since client software may not deal well with * enormous error strings. The server log always gets a full report. */ #define MAX_REPORTED_DEPS 100 initStringInfo(&descs); initStringInfo(&alldescs); sdepRel = heap_open(SharedDependRelationId, AccessShareLock); ScanKeyInit(&key[0], Anum_pg_shdepend_refclassid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(classId)); ScanKeyInit(&key[1], Anum_pg_shdepend_refobjid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(objectId)); scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true, SnapshotNow, 2, key); while (HeapTupleIsValid(tup = systable_getnext(scan))) { Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tup); /* This case can be dispatched quickly */ if (sdepForm->deptype == SHARED_DEPENDENCY_PIN) { object.classId = classId; object.objectId = objectId; object.objectSubId = 0; ereport(ERROR, (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), errmsg("cannot drop %s because it is required by the database system", getObjectDescription(&object)))); } object.classId = sdepForm->classid; object.objectId = sdepForm->objid; object.objectSubId = sdepForm->objsubid; /* * If it's a dependency local to this database or it's a shared * object, describe it. * * If it's a remote dependency, keep track of it so we can report the * number of them later. */ if (sdepForm->dbid == MyDatabaseId) { if (numReportedDeps < MAX_REPORTED_DEPS) { numReportedDeps++; storeObjectDescription(&descs, LOCAL_OBJECT, &object, sdepForm->deptype, 0); } else numNotReportedDeps++; storeObjectDescription(&alldescs, LOCAL_OBJECT, &object, sdepForm->deptype, 0); } else if (sdepForm->dbid == InvalidOid) { if (numReportedDeps < MAX_REPORTED_DEPS) { numReportedDeps++; storeObjectDescription(&descs, SHARED_OBJECT, &object, sdepForm->deptype, 0); } else numNotReportedDeps++; storeObjectDescription(&alldescs, SHARED_OBJECT, &object, sdepForm->deptype, 0); } else { /* It's not local nor shared, so it must be remote. */ remoteDep *dep; bool stored = false; /* * XXX this info is kept on a simple List. Maybe it's not good * for performance, but using a hash table seems needlessly * complex. The expected number of databases is not high anyway, * I suppose. */ foreach(cell, remDeps) { dep = lfirst(cell); if (dep->dbOid == sdepForm->dbid) { dep->count++; stored = true; break; } } if (!stored) { dep = (remoteDep *) palloc(sizeof(remoteDep)); dep->dbOid = sdepForm->dbid; dep->count = 1; remDeps = lappend(remDeps, dep); } } } systable_endscan(scan); heap_close(sdepRel, AccessShareLock); /* * Summarize dependencies in remote databases. */ foreach(cell, remDeps) { remoteDep *dep = lfirst(cell); object.classId = DatabaseRelationId; object.objectId = dep->dbOid; object.objectSubId = 0; if (numReportedDeps < MAX_REPORTED_DEPS) { numReportedDeps++; storeObjectDescription(&descs, REMOTE_OBJECT, &object, SHARED_DEPENDENCY_INVALID, dep->count); } else numNotReportedDbs++; storeObjectDescription(&alldescs, REMOTE_OBJECT, &object, SHARED_DEPENDENCY_INVALID, dep->count); } list_free_deep(remDeps); if (descs.len == 0) { pfree(descs.data); pfree(alldescs.data); *detail_msg = *detail_log_msg = NULL; return false; } if (numNotReportedDeps > 0) appendStringInfo(&descs, ngettext("\nand %d other object " "(see server log for list)", "\nand %d other objects " "(see server log for list)", numNotReportedDeps), numNotReportedDeps); if (numNotReportedDbs > 0) appendStringInfo(&descs, ngettext("\nand objects in %d other database " "(see server log for list)", "\nand objects in %d other databases " "(see server log for list)", numNotReportedDbs), numNotReportedDbs); *detail_msg = descs.data; *detail_log_msg = alldescs.data; return true; }
Definition at line 708 of file pg_shdepend.c.
References Anum_pg_shdepend_dbid, BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogIndexInsert(), CatalogOpenIndexes(), heap_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RelationGetDescr, RowExclusiveLock, ScanKeyInit(), SharedDependDependerIndexId, SharedDependRelationId, simple_heap_insert(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and values.
Referenced by createdb().
{ Relation sdepRel; TupleDesc sdepDesc; ScanKeyData key[1]; SysScanDesc scan; HeapTuple tup; CatalogIndexState indstate; Datum values[Natts_pg_shdepend]; bool nulls[Natts_pg_shdepend]; bool replace[Natts_pg_shdepend]; sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock); sdepDesc = RelationGetDescr(sdepRel); indstate = CatalogOpenIndexes(sdepRel); /* Scan all entries with dbid = templateDbId */ ScanKeyInit(&key[0], Anum_pg_shdepend_dbid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(templateDbId)); scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true, SnapshotNow, 1, key); /* Set up to copy the tuples except for inserting newDbId */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); memset(replace, false, sizeof(replace)); replace[Anum_pg_shdepend_dbid - 1] = true; values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId); /* * Copy the entries of the original database, changing the database Id to * that of the new database. Note that because we are not copying rows * with dbId == 0 (ie, rows describing dependent shared objects) we won't * copy the ownership dependency of the template database itself; this is * what we want. */ while (HeapTupleIsValid(tup = systable_getnext(scan))) { HeapTuple newtup; newtup = heap_modify_tuple(tup, sdepDesc, values, nulls, replace); simple_heap_insert(sdepRel, newtup); /* Keep indexes current */ CatalogIndexInsert(indstate, newtup); heap_freetuple(newtup); } systable_endscan(scan); CatalogCloseIndexes(indstate); heap_close(sdepRel, RowExclusiveLock); }
Definition at line 193 of file pg_depend.c.
References Anum_pg_depend_classid, Anum_pg_depend_objid, BTEqualStrategyNumber, DependDependerIndexId, DEPENDENCY_EXTENSION, DependRelationId, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by create_proc_lang(), DefineQueryRewrite(), GenerateTypeDependencies(), InsertRule(), makeConfigurationDependencies(), makeOperatorDependencies(), ProcedureCreate(), and swap_relation_files().
{ long count = 0; Relation depRel; ScanKeyData key[2]; SysScanDesc scan; HeapTuple tup; depRel = heap_open(DependRelationId, RowExclusiveLock); ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(classId)); ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(objectId)); scan = systable_beginscan(depRel, DependDependerIndexId, true, SnapshotNow, 2, key); while (HeapTupleIsValid(tup = systable_getnext(scan))) { if (skipExtensionDeps && ((Form_pg_depend) GETSTRUCT(tup))->deptype == DEPENDENCY_EXTENSION) continue; simple_heap_delete(depRel, &tup->t_self); count++; } systable_endscan(scan); heap_close(depRel, RowExclusiveLock); return count; }
Definition at line 243 of file pg_depend.c.
References Anum_pg_depend_classid, Anum_pg_depend_objid, BTEqualStrategyNumber, DependDependerIndexId, DependRelationId, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by AlterForeignDataWrapper(), ApplyExtensionUpdates(), ExecAlterExtensionContentsStmt(), index_constraint_create(), and markSequenceUnowned().
{ long count = 0; Relation depRel; ScanKeyData key[2]; SysScanDesc scan; HeapTuple tup; depRel = heap_open(DependRelationId, RowExclusiveLock); ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(classId)); ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(objectId)); scan = systable_beginscan(depRel, DependDependerIndexId, true, SnapshotNow, 2, key); while (HeapTupleIsValid(tup = systable_getnext(scan))) { Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup); if (depform->refclassid == refclassId && depform->deptype == deptype) { simple_heap_delete(depRel, &tup->t_self); count++; } } systable_endscan(scan); heap_close(depRel, RowExclusiveLock); return count; }
Definition at line 823 of file pg_shdepend.c.
References heap_close, heap_open(), InvalidOid, RowExclusiveLock, SHARED_DEPENDENCY_INVALID, SharedDependRelationId, and shdepDropDependency().
Referenced by deleteOneObject(), DropTableSpace(), GenerateTypeDependencies(), makeConfigurationDependencies(), and makeOperatorDependencies().
{ Relation sdepRel; sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock); shdepDropDependency(sdepRel, classId, objectId, objectSubId, (objectSubId == 0), InvalidOid, InvalidOid, SHARED_DEPENDENCY_INVALID); heap_close(sdepRel, RowExclusiveLock); }
void deleteWhatDependsOn | ( | const ObjectAddress * | object, | |
bool | showNotices | |||
) |
Definition at line 388 of file dependency.c.
References AcquireDeletionLock(), DEBUG2, deleteOneObject(), DependRelationId, DEPFLAG_ORIGINAL, DROP_CASCADE, ObjectAddresses::extras, findDependentObjects(), ObjectAddressExtra::flags, free_object_addresses(), heap_close, heap_open(), i, new_object_addresses(), NOTICE, NULL, ObjectAddresses::numrefs, PERFORM_DELETION_INTERNAL, ObjectAddresses::refs, reportDependentObjects(), and RowExclusiveLock.
Referenced by RemoveTempRelations().
{ Relation depRel; ObjectAddresses *targetObjects; int i; /* * We save some cycles by opening pg_depend just once and passing the * Relation pointer down to all the recursive deletion steps. */ depRel = heap_open(DependRelationId, RowExclusiveLock); /* * Acquire deletion lock on the target object. (Ideally the caller has * done this already, but many places are sloppy about it.) */ AcquireDeletionLock(object, 0); /* * Construct a list of objects to delete (ie, the given object plus * everything directly or indirectly dependent on it). */ targetObjects = new_object_addresses(); findDependentObjects(object, DEPFLAG_ORIGINAL, NULL, /* empty stack */ targetObjects, NULL, /* no pendingObjects */ &depRel); /* * Check if deletion is allowed, and report about cascaded deletes. */ reportDependentObjects(targetObjects, DROP_CASCADE, showNotices ? NOTICE : DEBUG2, object); /* * Delete all the objects in the proper order, except we skip the original * object. */ for (i = 0; i < targetObjects->numrefs; i++) { ObjectAddress *thisobj = targetObjects->refs + i; ObjectAddressExtra *thisextra = targetObjects->extras + i; if (thisextra->flags & DEPFLAG_ORIGINAL) continue; /* * Since this function is currently only used to clean out temporary * schemas, we pass PERFORM_DELETION_INTERNAL here, indicating that * the operation is an automatic system operation rather than a user * action. If, in the future, this function is used for other * purposes, we might need to revisit this. */ deleteOneObject(thisobj, &depRel, PERFORM_DELETION_INTERNAL); } /* And clean up */ free_object_addresses(targetObjects); heap_close(depRel, RowExclusiveLock); }
void dropDatabaseDependencies | ( | Oid | databaseId | ) |
Definition at line 775 of file pg_shdepend.c.
References Anum_pg_shdepend_dbid, BTEqualStrategyNumber, DatabaseRelationId, heap_close, heap_open(), HeapTupleIsValid, InvalidOid, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_INVALID, SharedDependDependerIndexId, SharedDependRelationId, shdepDropDependency(), simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by dropdb().
{ Relation sdepRel; ScanKeyData key[1]; SysScanDesc scan; HeapTuple tup; sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock); /* * First, delete all the entries that have the database Oid in the dbid * field. */ ScanKeyInit(&key[0], Anum_pg_shdepend_dbid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(databaseId)); /* We leave the other index fields unspecified */ scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true, SnapshotNow, 1, key); while (HeapTupleIsValid(tup = systable_getnext(scan))) { simple_heap_delete(sdepRel, &tup->t_self); } systable_endscan(scan); /* Now delete all entries corresponding to the database itself */ shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true, InvalidOid, InvalidOid, SHARED_DEPENDENCY_INVALID); heap_close(sdepRel, RowExclusiveLock); }
void free_object_addresses | ( | ObjectAddresses * | addrs | ) |
Definition at line 2193 of file dependency.c.
References ObjectAddresses::extras, pfree(), and ObjectAddresses::refs.
Referenced by AlterTableNamespace(), AlterTypeNamespace(), deleteWhatDependsOn(), makeConfigurationDependencies(), performDeletion(), performMultipleDeletions(), recordDependencyOnExpr(), recordDependencyOnSingleRelExpr(), RemoveObjects(), RemoveRelations(), and shdepDropOwned().
Definition at line 621 of file pg_depend.c.
References AccessShareLock, Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, Anum_pg_depend_refobjsubid, BTEqualStrategyNumber, ConstraintRelationId, DEPENDENCY_INTERNAL, DependReferenceIndexId, DependRelationId, get_rel_relkind(), GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, Int32GetDatum, ObjectIdGetDatum, RelationRelationId, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by ATPostAlterTypeParse(), and pg_get_constraintdef_worker().
{ Oid indexId = InvalidOid; Relation depRel; ScanKeyData key[3]; SysScanDesc scan; HeapTuple tup; /* Search the dependency table for the dependent index */ depRel = heap_open(DependRelationId, AccessShareLock); ScanKeyInit(&key[0], Anum_pg_depend_refclassid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(ConstraintRelationId)); ScanKeyInit(&key[1], Anum_pg_depend_refobjid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(constraintId)); ScanKeyInit(&key[2], Anum_pg_depend_refobjsubid, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(0)); scan = systable_beginscan(depRel, DependReferenceIndexId, true, SnapshotNow, 3, key); while (HeapTupleIsValid(tup = systable_getnext(scan))) { Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup); /* * We assume any internal dependency of an index on the constraint * must be what we are looking for. (The relkind test is just * paranoia; there shouldn't be any such dependencies otherwise.) */ if (deprec->classid == RelationRelationId && deprec->objsubid == 0 && deprec->deptype == DEPENDENCY_INTERNAL && get_rel_relkind(deprec->objid) == RELKIND_INDEX) { indexId = deprec->objid; break; } } systable_endscan(scan); heap_close(depRel, AccessShareLock); return indexId; }
Definition at line 679 of file pg_depend.c.
References AccessShareLock, Anum_pg_depend_classid, Anum_pg_depend_objid, Anum_pg_depend_objsubid, BTEqualStrategyNumber, ConstraintRelationId, DependDependerIndexId, DEPENDENCY_INTERNAL, DependRelationId, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, Int32GetDatum, ObjectIdGetDatum, RelationRelationId, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by generateClonedIndexStmt(), RenameRelationInternal(), and transformIndexConstraint().
{ Oid constraintId = InvalidOid; Relation depRel; ScanKeyData key[3]; SysScanDesc scan; HeapTuple tup; /* Search the dependency table for the index */ depRel = heap_open(DependRelationId, AccessShareLock); ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationRelationId)); ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(indexId)); ScanKeyInit(&key[2], Anum_pg_depend_objsubid, BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(0)); scan = systable_beginscan(depRel, DependDependerIndexId, true, SnapshotNow, 3, key); while (HeapTupleIsValid(tup = systable_getnext(scan))) { Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup); /* * We assume any internal dependency on a constraint must be what we * are looking for. */ if (deprec->refclassid == ConstraintRelationId && deprec->refobjsubid == 0 && deprec->deptype == DEPENDENCY_INTERNAL) { constraintId = deprec->refobjid; break; } } systable_endscan(scan); heap_close(depRel, AccessShareLock); return constraintId; }
Definition at line 450 of file pg_depend.c.
References AccessShareLock, Anum_pg_depend_classid, Anum_pg_depend_objid, BTEqualStrategyNumber, DependDependerIndexId, DEPENDENCY_EXTENSION, DependRelationId, ExtensionRelationId, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by AlterExtensionNamespace(), ExecAlterExtensionContentsStmt(), pg_extension_config_dump(), and recordDependencyOnCurrentExtension().
{ Oid result = InvalidOid; Relation depRel; ScanKeyData key[2]; SysScanDesc scan; HeapTuple tup; depRel = heap_open(DependRelationId, AccessShareLock); ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(classId)); ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(objectId)); scan = systable_beginscan(depRel, DependDependerIndexId, true, SnapshotNow, 2, key); while (HeapTupleIsValid((tup = systable_getnext(scan)))) { Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup); if (depform->refclassid == ExtensionRelationId && depform->deptype == DEPENDENCY_EXTENSION) { result = depform->refobjid; break; /* no need to keep scanning */ } } systable_endscan(scan); heap_close(depRel, AccessShareLock); return result; }
ObjectClass getObjectClass | ( | const ObjectAddress * | object | ) |
Definition at line 2208 of file dependency.c.
References AccessMethodOperatorRelationId, AccessMethodProcedureRelationId, AttrDefaultRelationId, AuthIdRelationId, CastRelationId, ObjectAddress::classId, CollationRelationId, ConstraintRelationId, ConversionRelationId, DatabaseRelationId, DefaultAclRelationId, elog, ERROR, EventTriggerRelationId, ExtensionRelationId, ForeignDataWrapperRelationId, ForeignServerRelationId, LanguageRelationId, LargeObjectRelationId, NamespaceRelationId, ObjectAddress::objectSubId, OperatorClassRelationId, OperatorFamilyRelationId, OperatorRelationId, ProcedureRelationId, RelationRelationId, RewriteRelationId, TableSpaceRelationId, TriggerRelationId, TSConfigRelationId, TSDictionaryRelationId, TSParserRelationId, TSTemplateRelationId, TypeRelationId, and UserMappingRelationId.
Referenced by AlterObjectNamespace_oid(), ATExecAlterColumnType(), deleteObjectsInList(), doDeletion(), EventTriggerSQLDropAddObject(), getObjectDescription(), getObjectIdentity(), and getObjectTypeDescription().
{ /* only pg_class entries can have nonzero objectSubId */ if (object->classId != RelationRelationId && object->objectSubId != 0) elog(ERROR, "invalid non-zero objectSubId for object class %u", object->classId); switch (object->classId) { case RelationRelationId: /* caller must check objectSubId */ return OCLASS_CLASS; case ProcedureRelationId: return OCLASS_PROC; case TypeRelationId: return OCLASS_TYPE; case CastRelationId: return OCLASS_CAST; case CollationRelationId: return OCLASS_COLLATION; case ConstraintRelationId: return OCLASS_CONSTRAINT; case ConversionRelationId: return OCLASS_CONVERSION; case AttrDefaultRelationId: return OCLASS_DEFAULT; case LanguageRelationId: return OCLASS_LANGUAGE; case LargeObjectRelationId: return OCLASS_LARGEOBJECT; case OperatorRelationId: return OCLASS_OPERATOR; case OperatorClassRelationId: return OCLASS_OPCLASS; case OperatorFamilyRelationId: return OCLASS_OPFAMILY; case AccessMethodOperatorRelationId: return OCLASS_AMOP; case AccessMethodProcedureRelationId: return OCLASS_AMPROC; case RewriteRelationId: return OCLASS_REWRITE; case TriggerRelationId: return OCLASS_TRIGGER; case NamespaceRelationId: return OCLASS_SCHEMA; case TSParserRelationId: return OCLASS_TSPARSER; case TSDictionaryRelationId: return OCLASS_TSDICT; case TSTemplateRelationId: return OCLASS_TSTEMPLATE; case TSConfigRelationId: return OCLASS_TSCONFIG; case AuthIdRelationId: return OCLASS_ROLE; case DatabaseRelationId: return OCLASS_DATABASE; case TableSpaceRelationId: return OCLASS_TBLSPACE; case ForeignDataWrapperRelationId: return OCLASS_FDW; case ForeignServerRelationId: return OCLASS_FOREIGN_SERVER; case UserMappingRelationId: return OCLASS_USER_MAPPING; case DefaultAclRelationId: return OCLASS_DEFACL; case ExtensionRelationId: return OCLASS_EXTENSION; case EventTriggerRelationId: return OCLASS_EVENT_TRIGGER; } /* shouldn't get here */ elog(ERROR, "unrecognized object class: %u", object->classId); return OCLASS_CLASS; /* keep compiler quiet */ }
Definition at line 563 of file pg_depend.c.
References AccessShareLock, Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, BTEqualStrategyNumber, DEPENDENCY_AUTO, DependReferenceIndexId, DependRelationId, get_rel_relkind(), GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, lappend_oid(), ObjectIdGetDatum, RelationRelationId, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by ExecuteTruncate().
{ List *result = NIL; Relation depRel; ScanKeyData key[2]; SysScanDesc scan; HeapTuple tup; depRel = heap_open(DependRelationId, AccessShareLock); ScanKeyInit(&key[0], Anum_pg_depend_refclassid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationRelationId)); ScanKeyInit(&key[1], Anum_pg_depend_refobjid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(relid)); scan = systable_beginscan(depRel, DependReferenceIndexId, true, SnapshotNow, 2, key); while (HeapTupleIsValid(tup = systable_getnext(scan))) { Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup); /* * We assume any auto dependency of a sequence on a column must be * what we are looking for. (We need the relkind test because indexes * can also have auto dependencies on columns.) */ if (deprec->classid == RelationRelationId && deprec->objsubid == 0 && deprec->refobjsubid != 0 && deprec->deptype == DEPENDENCY_AUTO && get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE) { result = lappend_oid(result, deprec->objid); } } systable_endscan(scan); heap_close(depRel, AccessShareLock); return result; }
void markSequenceUnowned | ( | Oid | seqId | ) |
Definition at line 553 of file pg_depend.c.
References deleteDependencyRecordsForClass(), DEPENDENCY_AUTO, and RelationRelationId.
Referenced by process_owned_by().
ObjectAddresses* new_object_addresses | ( | void | ) |
Definition at line 1966 of file dependency.c.
References ObjectAddresses::extras, ObjectAddresses::maxrefs, ObjectAddresses::numrefs, palloc(), and ObjectAddresses::refs.
Referenced by AlterExtensionNamespace(), AlterTableNamespace(), AlterTypeNamespace(), deleteWhatDependsOn(), makeConfigurationDependencies(), performDeletion(), performMultipleDeletions(), recordDependencyOnExpr(), recordDependencyOnSingleRelExpr(), RemoveObjects(), RemoveRelations(), and shdepDropOwned().
{ ObjectAddresses *addrs; addrs = palloc(sizeof(ObjectAddresses)); addrs->numrefs = 0; addrs->maxrefs = 32; addrs->refs = (ObjectAddress *) palloc(addrs->maxrefs * sizeof(ObjectAddress)); addrs->extras = NULL; /* until/unless needed */ return addrs; }
bool object_address_present | ( | const ObjectAddress * | object, | |
const ObjectAddresses * | addrs | |||
) |
Definition at line 2075 of file dependency.c.
References ObjectAddress::classId, i, ObjectAddresses::numrefs, ObjectAddress::objectId, ObjectAddress::objectSubId, and ObjectAddresses::refs.
Referenced by AlterConstraintNamespaces(), AlterIndexNamespaces(), AlterRelationNamespaceInternal(), AlterTypeNamespaceInternal(), and findDependentObjects().
{ int i; for (i = addrs->numrefs - 1; i >= 0; i--) { const ObjectAddress *thisobj = addrs->refs + i; if (object->classId == thisobj->classId && object->objectId == thisobj->objectId) { if (object->objectSubId == thisobj->objectSubId || thisobj->objectSubId == 0) return true; } } return false; }
void performDeletion | ( | const ObjectAddress * | object, | |
DropBehavior | behavior, | |||
int | flags | |||
) |
Definition at line 251 of file dependency.c.
References AcquireDeletionLock(), deleteObjectsInList(), DependRelationId, DEPFLAG_ORIGINAL, findDependentObjects(), free_object_addresses(), heap_close, heap_open(), new_object_addresses(), NOTICE, NULL, reportDependentObjects(), and RowExclusiveLock.
Referenced by AlterDomainDropConstraint(), ATExecDropColumn(), ATExecDropConstraint(), ATPostAlterTypeCleanup(), DefineQueryRewrite(), do_autovacuum(), dropOperators(), dropProcedures(), finish_heap_swap(), inv_drop(), PreCommit_on_commit_actions(), RemoveAttrDefault(), RemoveUserMapping(), and SetDefaultACL().
{ Relation depRel; ObjectAddresses *targetObjects; /* * We save some cycles by opening pg_depend just once and passing the * Relation pointer down to all the recursive deletion steps. */ depRel = heap_open(DependRelationId, RowExclusiveLock); /* * Acquire deletion lock on the target object. (Ideally the caller has * done this already, but many places are sloppy about it.) */ AcquireDeletionLock(object, 0); /* * Construct a list of objects to delete (ie, the given object plus * everything directly or indirectly dependent on it). */ targetObjects = new_object_addresses(); findDependentObjects(object, DEPFLAG_ORIGINAL, NULL, /* empty stack */ targetObjects, NULL, /* no pendingObjects */ &depRel); /* * Check if deletion is allowed, and report about cascaded deletes. */ reportDependentObjects(targetObjects, behavior, NOTICE, object); /* do the deed */ deleteObjectsInList(targetObjects, &depRel, flags); /* And clean up */ free_object_addresses(targetObjects); heap_close(depRel, RowExclusiveLock); }
void performMultipleDeletions | ( | const ObjectAddresses * | objects, | |
DropBehavior | behavior, | |||
int | flags | |||
) |
Definition at line 309 of file dependency.c.
References AcquireDeletionLock(), deleteObjectsInList(), DependRelationId, DEPFLAG_ORIGINAL, findDependentObjects(), free_object_addresses(), heap_close, heap_open(), i, new_object_addresses(), NOTICE, NULL, ObjectAddresses::numrefs, ObjectAddresses::refs, reportDependentObjects(), and RowExclusiveLock.
Referenced by RemoveObjects(), RemoveRelations(), and shdepDropOwned().
{ Relation depRel; ObjectAddresses *targetObjects; int i; /* No work if no objects... */ if (objects->numrefs <= 0) return; /* * We save some cycles by opening pg_depend just once and passing the * Relation pointer down to all the recursive deletion steps. */ depRel = heap_open(DependRelationId, RowExclusiveLock); /* * Construct a list of objects to delete (ie, the given objects plus * everything directly or indirectly dependent on them). Note that * because we pass the whole objects list as pendingObjects context, we * won't get a failure from trying to delete an object that is internally * dependent on another one in the list; we'll just skip that object and * delete it when we reach its owner. */ targetObjects = new_object_addresses(); for (i = 0; i < objects->numrefs; i++) { const ObjectAddress *thisobj = objects->refs + i; /* * Acquire deletion lock on each target object. (Ideally the caller * has done this already, but many places are sloppy about it.) */ AcquireDeletionLock(thisobj, flags); findDependentObjects(thisobj, DEPFLAG_ORIGINAL, NULL, /* empty stack */ targetObjects, objects, &depRel); } /* * Check if deletion is allowed, and report about cascaded deletes. * * If there's exactly one object being deleted, report it the same way as * in performDeletion(), else we have to be vaguer. */ reportDependentObjects(targetObjects, behavior, NOTICE, (objects->numrefs == 1 ? objects->refs : NULL)); /* do the deed */ deleteObjectsInList(targetObjects, &depRel, flags); /* And clean up */ free_object_addresses(targetObjects); heap_close(depRel, RowExclusiveLock); }
void record_object_address_dependencies | ( | const ObjectAddress * | depender, | |
ObjectAddresses * | referenced, | |||
DependencyType | behavior | |||
) |
Definition at line 2179 of file dependency.c.
References eliminate_duplicate_dependencies(), ObjectAddresses::numrefs, recordMultipleDependencies(), and ObjectAddresses::refs.
Referenced by makeConfigurationDependencies().
{ eliminate_duplicate_dependencies(referenced); recordMultipleDependencies(depender, referenced->refs, referenced->numrefs, behavior); }
void recordDependencyOn | ( | const ObjectAddress * | depender, | |
const ObjectAddress * | referenced, | |||
DependencyType | behavior | |||
) |
Definition at line 44 of file pg_depend.c.
References recordMultipleDependencies().
Referenced by add_column_collation_dependency(), add_column_datatype_dependency(), AddNewAttributeTuples(), AggregateCreate(), AlterForeignDataWrapper(), ApplyExtensionUpdates(), ATExecAddOf(), CollationCreate(), ConversionCreate(), create_proc_lang(), create_toast_table(), CreateCast(), CreateConstraintEntry(), CreateForeignDataWrapper(), CreateForeignServer(), CreateForeignTable(), CreateOpFamily(), CreateTrigger(), CreateUserMapping(), DefineOpClass(), ExecAlterExtensionContentsStmt(), GenerateTypeDependencies(), heap_create_with_catalog(), index_constraint_create(), index_create(), insert_event_trigger_tuple(), InsertExtensionTuple(), InsertRule(), makeDictionaryDependencies(), makeOperatorDependencies(), makeParserDependencies(), makeRangeConstructors(), makeTSTemplateDependencies(), ProcedureCreate(), process_owned_by(), RangeCreate(), recordDependencyOnCurrentExtension(), SetDefaultACL(), StoreAttrDefault(), StoreCatalogInheritance1(), storeOperators(), storeProcedures(), and swap_relation_files().
{ recordMultipleDependencies(depender, referenced, 1, behavior); }
void recordDependencyOnCurrentExtension | ( | const ObjectAddress * | object, | |
bool | isReplace | |||
) |
Definition at line 141 of file pg_depend.c.
References Assert, ObjectAddress::classId, creating_extension, CurrentExtensionObject, DEPENDENCY_EXTENSION, ereport, errcode(), errmsg(), ERROR, get_extension_name(), getExtensionOfObject(), getObjectDescription(), ObjectAddress::objectId, ObjectAddress::objectSubId, OidIsValid, and recordDependencyOn().
Referenced by CollationCreate(), ConversionCreate(), create_proc_lang(), CreateCast(), CreateForeignDataWrapper(), CreateForeignServer(), CreateOpFamily(), CreateUserMapping(), DefineOpClass(), GenerateTypeDependencies(), heap_create_with_catalog(), makeConfigurationDependencies(), makeDictionaryDependencies(), makeOperatorDependencies(), makeParserDependencies(), makeTSTemplateDependencies(), NamespaceCreate(), and ProcedureCreate().
{ /* Only whole objects can be extension members */ Assert(object->objectSubId == 0); if (creating_extension) { ObjectAddress extension; /* Only need to check for existing membership if isReplace */ if (isReplace) { Oid oldext; oldext = getExtensionOfObject(object->classId, object->objectId); if (OidIsValid(oldext)) { /* If already a member of this extension, nothing to do */ if (oldext == CurrentExtensionObject) return; /* Already a member of some other extension, so reject */ ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("%s is already a member of extension \"%s\"", getObjectDescription(object), get_extension_name(oldext)))); } } /* OK, record it as a member of CurrentExtensionObject */ extension.classId = ExtensionRelationId; extension.objectId = CurrentExtensionObject; extension.objectSubId = 0; recordDependencyOn(object, &extension, DEPENDENCY_EXTENSION); } }
void recordDependencyOnExpr | ( | const ObjectAddress * | depender, | |
Node * | expr, | |||
List * | rtable, | |||
DependencyType | behavior | |||
) |
Definition at line 1318 of file dependency.c.
References find_expr_references_context::addrs, eliminate_duplicate_dependencies(), find_expr_references_walker(), free_object_addresses(), list_make1, new_object_addresses(), ObjectAddresses::numrefs, recordMultipleDependencies(), ObjectAddresses::refs, and find_expr_references_context::rtables.
Referenced by CreateTrigger(), GenerateTypeDependencies(), InsertRule(), ProcedureCreate(), and StoreAttrDefault().
{ find_expr_references_context context; context.addrs = new_object_addresses(); /* Set up interpretation for Vars at varlevelsup = 0 */ context.rtables = list_make1(rtable); /* Scan the expression tree for referenceable objects */ find_expr_references_walker(expr, &context); /* Remove any duplicates */ eliminate_duplicate_dependencies(context.addrs); /* And record 'em */ recordMultipleDependencies(depender, context.addrs->refs, context.addrs->numrefs, behavior); free_object_addresses(context.addrs); }
Definition at line 150 of file pg_shdepend.c.
References ObjectAddress::classId, ObjectAddress::objectId, ObjectAddress::objectSubId, recordSharedDependencyOn(), and SHARED_DEPENDENCY_OWNER.
Referenced by CollationCreate(), ConversionCreate(), create_proc_lang(), createdb(), CreateForeignDataWrapper(), CreateForeignServer(), CreateOpFamily(), CreateTableSpace(), CreateUserMapping(), DefineOpClass(), GenerateTypeDependencies(), heap_create_with_catalog(), insert_event_trigger_tuple(), InsertExtensionTuple(), inv_create(), makeConfigurationDependencies(), makeDictionaryDependencies(), makeOperatorDependencies(), NamespaceCreate(), ProcedureCreate(), and SetDefaultACL().
{ ObjectAddress myself, referenced; myself.classId = classId; myself.objectId = objectId; myself.objectSubId = 0; referenced.classId = AuthIdRelationId; referenced.objectId = owner; referenced.objectSubId = 0; recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_OWNER); }
void recordDependencyOnSingleRelExpr | ( | const ObjectAddress * | depender, | |
Node * | expr, | |||
Oid | relId, | |||
DependencyType | behavior, | |||
DependencyType | self_behavior | |||
) |
Definition at line 1359 of file dependency.c.
References add_exact_object_address(), find_expr_references_context::addrs, ObjectAddress::classId, eliminate_duplicate_dependencies(), find_expr_references_walker(), free_object_addresses(), list_make1, MemSet, new_object_addresses(), ObjectAddresses::numrefs, ObjectAddress::objectId, recordMultipleDependencies(), ObjectAddresses::refs, RelationRelationId, RangeTblEntry::relid, RangeTblEntry::relkind, find_expr_references_context::rtables, RangeTblEntry::rtekind, and RangeTblEntry::type.
Referenced by CreateConstraintEntry(), and index_create().
{ find_expr_references_context context; RangeTblEntry rte; context.addrs = new_object_addresses(); /* We gin up a rather bogus rangetable list to handle Vars */ MemSet(&rte, 0, sizeof(rte)); rte.type = T_RangeTblEntry; rte.rtekind = RTE_RELATION; rte.relid = relId; rte.relkind = RELKIND_RELATION; /* no need for exactness here */ context.rtables = list_make1(list_make1(&rte)); /* Scan the expression tree for referenceable objects */ find_expr_references_walker(expr, &context); /* Remove any duplicates */ eliminate_duplicate_dependencies(context.addrs); /* Separate self-dependencies if necessary */ if (behavior != self_behavior && context.addrs->numrefs > 0) { ObjectAddresses *self_addrs; ObjectAddress *outobj; int oldref, outrefs; self_addrs = new_object_addresses(); outobj = context.addrs->refs; outrefs = 0; for (oldref = 0; oldref < context.addrs->numrefs; oldref++) { ObjectAddress *thisobj = context.addrs->refs + oldref; if (thisobj->classId == RelationRelationId && thisobj->objectId == relId) { /* Move this ref into self_addrs */ add_exact_object_address(thisobj, self_addrs); } else { /* Keep it in context.addrs */ *outobj = *thisobj; outobj++; outrefs++; } } context.addrs->numrefs = outrefs; /* Record the self-dependencies */ recordMultipleDependencies(depender, self_addrs->refs, self_addrs->numrefs, self_behavior); free_object_addresses(self_addrs); } /* Record the external dependencies */ recordMultipleDependencies(depender, context.addrs->refs, context.addrs->numrefs, behavior); free_object_addresses(context.addrs); }
void recordMultipleDependencies | ( | const ObjectAddress * | depender, | |
const ObjectAddress * | referenced, | |||
int | nreferenced, | |||
DependencyType | behavior | |||
) |
Definition at line 56 of file pg_depend.c.
References Anum_pg_depend_classid, Anum_pg_depend_deptype, Anum_pg_depend_objid, Anum_pg_depend_objsubid, Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, Anum_pg_depend_refobjsubid, CatalogCloseIndexes(), CatalogIndexInsert(), CatalogOpenIndexes(), CharGetDatum, ObjectAddress::classId, DependRelationId, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), i, Int32GetDatum, IsBootstrapProcessingMode, isObjectPinned(), NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, RelationData::rd_att, RowExclusiveLock, simple_heap_insert(), and values.
Referenced by record_object_address_dependencies(), recordDependencyOn(), recordDependencyOnExpr(), and recordDependencyOnSingleRelExpr().
{ Relation dependDesc; CatalogIndexState indstate; HeapTuple tup; int i; bool nulls[Natts_pg_depend]; Datum values[Natts_pg_depend]; if (nreferenced <= 0) return; /* nothing to do */ /* * During bootstrap, do nothing since pg_depend may not exist yet. initdb * will fill in appropriate pg_depend entries after bootstrap. */ if (IsBootstrapProcessingMode()) return; dependDesc = heap_open(DependRelationId, RowExclusiveLock); /* Don't open indexes unless we need to make an update */ indstate = NULL; memset(nulls, false, sizeof(nulls)); for (i = 0; i < nreferenced; i++, referenced++) { /* * If the referenced object is pinned by the system, there's no real * need to record dependencies on it. This saves lots of space in * pg_depend, so it's worth the time taken to check. */ if (!isObjectPinned(referenced, dependDesc)) { /* * Record the Dependency. Note we don't bother to check for * duplicate dependencies; there's no harm in them. */ values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); tup = heap_form_tuple(dependDesc->rd_att, values, nulls); simple_heap_insert(dependDesc, tup); /* keep indexes current */ if (indstate == NULL) indstate = CatalogOpenIndexes(dependDesc); CatalogIndexInsert(indstate, tup); heap_freetuple(tup); } } if (indstate != NULL) CatalogCloseIndexes(indstate); heap_close(dependDesc, RowExclusiveLock); }
void recordSharedDependencyOn | ( | ObjectAddress * | depender, | |
ObjectAddress * | referenced, | |||
SharedDependencyType | deptype | |||
) |
Definition at line 106 of file pg_shdepend.c.
References Assert, ObjectAddress::classId, heap_close, heap_open(), IsBootstrapProcessingMode, isSharedObjectPinned(), ObjectAddress::objectId, ObjectAddress::objectSubId, RowExclusiveLock, SharedDependRelationId, and shdepAddDependency().
Referenced by recordDependencyOnOwner().
{ Relation sdepRel; /* * Objects in pg_shdepend can't have SubIds. */ Assert(depender->objectSubId == 0); Assert(referenced->objectSubId == 0); /* * During bootstrap, do nothing since pg_shdepend may not exist yet. * initdb will fill in appropriate pg_shdepend entries after bootstrap. */ if (IsBootstrapProcessingMode()) return; sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock); /* If the referenced object is pinned, do nothing. */ if (!isSharedObjectPinned(referenced->classId, referenced->objectId, sdepRel)) { shdepAddDependency(sdepRel, depender->classId, depender->objectId, depender->objectSubId, referenced->classId, referenced->objectId, deptype); } heap_close(sdepRel, RowExclusiveLock); }
Definition at line 503 of file pg_depend.c.
References AccessShareLock, Anum_pg_depend_classid, Anum_pg_depend_objid, BTEqualStrategyNumber, DependDependerIndexId, DEPENDENCY_AUTO, DependRelationId, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RelationRelationId, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by AlterTableNamespace(), and ATExecChangeOwner().
{ bool ret = false; Relation depRel; ScanKeyData key[2]; SysScanDesc scan; HeapTuple tup; depRel = heap_open(DependRelationId, AccessShareLock); ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationRelationId)); ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(seqId)); scan = systable_beginscan(depRel, DependDependerIndexId, true, SnapshotNow, 2, key); while (HeapTupleIsValid((tup = systable_getnext(scan)))) { Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup); if (depform->refclassid == RelationRelationId && depform->deptype == DEPENDENCY_AUTO) { *tableId = depform->refobjid; *colId = depform->refobjsubid; ret = true; break; /* no need to keep scanning */ } } systable_endscan(scan); heap_close(depRel, AccessShareLock); return ret; }
void shdepDropOwned | ( | List * | relids, | |
DropBehavior | behavior | |||
) |
Definition at line 1163 of file pg_shdepend.c.
References add_exact_object_address(), Anum_pg_shdepend_refclassid, Anum_pg_shdepend_refobjid, AuthIdRelationId, BTEqualStrategyNumber, ObjectAddress::classId, elog, ereport, errcode(), errmsg(), ERROR, free_object_addresses(), getObjectDescription(), GETSTRUCT, heap_close, heap_open(), InvalidOid, isSharedObjectPinned(), lfirst_oid, MyDatabaseId, new_object_addresses(), NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, performMultipleDeletions(), RemoveRoleFromObjectACL(), RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_ACL, SHARED_DEPENDENCY_INVALID, SHARED_DEPENDENCY_OWNER, SHARED_DEPENDENCY_PIN, SharedDependReferenceIndexId, SharedDependRelationId, SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by DropOwnedObjects().
{ Relation sdepRel; ListCell *cell; ObjectAddresses *deleteobjs; deleteobjs = new_object_addresses(); /* * We don't need this strong a lock here, but we'll call routines that * acquire RowExclusiveLock. Better get that right now to avoid potential * deadlock failures. */ sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock); /* * For each role, find the dependent objects and drop them using the * regular (non-shared) dependency management. */ foreach(cell, roleids) { Oid roleid = lfirst_oid(cell); ScanKeyData key[2]; SysScanDesc scan; HeapTuple tuple; /* Doesn't work for pinned objects */ if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel)) { ObjectAddress obj; obj.classId = AuthIdRelationId; obj.objectId = roleid; obj.objectSubId = 0; ereport(ERROR, (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), errmsg("cannot drop objects owned by %s because they are " "required by the database system", getObjectDescription(&obj)))); } ScanKeyInit(&key[0], Anum_pg_shdepend_refclassid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(AuthIdRelationId)); ScanKeyInit(&key[1], Anum_pg_shdepend_refobjid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(roleid)); scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true, SnapshotNow, 2, key); while ((tuple = systable_getnext(scan)) != NULL) { Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple); ObjectAddress obj; /* * We only operate on shared objects and objects in the current * database */ if (sdepForm->dbid != MyDatabaseId && sdepForm->dbid != InvalidOid) continue; switch (sdepForm->deptype) { /* Shouldn't happen */ case SHARED_DEPENDENCY_PIN: case SHARED_DEPENDENCY_INVALID: elog(ERROR, "unexpected dependency type"); break; case SHARED_DEPENDENCY_ACL: RemoveRoleFromObjectACL(roleid, sdepForm->classid, sdepForm->objid); break; case SHARED_DEPENDENCY_OWNER: /* If a local object, save it for deletion below */ if (sdepForm->dbid == MyDatabaseId) { obj.classId = sdepForm->classid; obj.objectId = sdepForm->objid; obj.objectSubId = sdepForm->objsubid; add_exact_object_address(&obj, deleteobjs); } break; } } systable_endscan(scan); } /* the dependency mechanism does the actual work */ performMultipleDeletions(deleteobjs, behavior, 0); heap_close(sdepRel, RowExclusiveLock); free_object_addresses(deleteobjs); }
Definition at line 990 of file pg_shdepend.c.
References AccessShareLock, AuthIdRelationId, AUTHOID, DatabaseRelationId, elog, ereport, errcode(), errmsg(), ERROR, get_database_name(), get_tablespace_name(), LockSharedObject(), NULL, ObjectIdGetDatum, pfree(), SearchSysCacheExists1, tablespace, and TableSpaceRelationId.
Referenced by AlterDatabaseSet(), AlterRoleSet(), shdepAddDependency(), and shdepChangeDep().
{ /* AccessShareLock should be OK, since we are not modifying the object */ LockSharedObject(classId, objectId, 0, AccessShareLock); switch (classId) { case AuthIdRelationId: if (!SearchSysCacheExists1(AUTHOID, ObjectIdGetDatum(objectId))) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("role %u was concurrently dropped", objectId))); break; /* * Currently, this routine need not support any other shared * object types besides roles. If we wanted to record explicit * dependencies on databases or tablespaces, we'd need code along * these lines: */ #ifdef NOT_USED case TableSpaceRelationId: { /* For lack of a syscache on pg_tablespace, do this: */ char *tablespace = get_tablespace_name(objectId); if (tablespace == NULL) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("tablespace %u was concurrently dropped", objectId))); pfree(tablespace); break; } #endif case DatabaseRelationId: { /* For lack of a syscache on pg_database, do this: */ char *database = get_database_name(objectId); if (database == NULL) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("database %u was concurrently dropped", objectId))); pfree(database); break; } default: elog(ERROR, "unrecognized shared classId: %u", classId); } }
Definition at line 1273 of file pg_shdepend.c.
References AccessExclusiveLock, AlterEventTriggerOwner_oid(), AlterForeignDataWrapperOwner_oid(), AlterForeignServerOwner_oid(), AlterObjectOwner_internal(), AlterSchemaOwner_oid(), AlterTypeOwnerInternal(), Anum_pg_shdepend_refclassid, Anum_pg_shdepend_refobjid, ATExecChangeOwner(), AuthIdRelationId, BTEqualStrategyNumber, ObjectAddress::classId, CollationRelationId, CommandCounterIncrement(), ConversionRelationId, DatabaseRelationId, DefaultAclRelationId, elog, ereport, errcode(), errmsg(), ERROR, EventTriggerRelationId, ExtensionRelationId, ForeignDataWrapperRelationId, ForeignServerRelationId, getObjectDescription(), GETSTRUCT, heap_close, heap_open(), InvalidOid, isSharedObjectPinned(), LanguageRelationId, LargeObjectRelationId, lfirst_oid, MyDatabaseId, NamespaceRelationId, NoLock, NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OperatorClassRelationId, OperatorFamilyRelationId, OperatorRelationId, ProcedureRelationId, RelationRelationId, RowExclusiveLock, ScanKeyInit(), SHARED_DEPENDENCY_OWNER, SHARED_DEPENDENCY_PIN, SharedDependReferenceIndexId, SharedDependRelationId, SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), TableSpaceRelationId, and TypeRelationId.
Referenced by ReassignOwnedObjects().
{ Relation sdepRel; ListCell *cell; /* * We don't need this strong a lock here, but we'll call routines that * acquire RowExclusiveLock. Better get that right now to avoid potential * deadlock problems. */ sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock); foreach(cell, roleids) { SysScanDesc scan; ScanKeyData key[2]; HeapTuple tuple; Oid roleid = lfirst_oid(cell); /* Refuse to work on pinned roles */ if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel)) { ObjectAddress obj; obj.classId = AuthIdRelationId; obj.objectId = roleid; obj.objectSubId = 0; ereport(ERROR, (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system", getObjectDescription(&obj)))); /* * There's no need to tell the whole truth, which is that we * didn't track these dependencies at all ... */ } ScanKeyInit(&key[0], Anum_pg_shdepend_refclassid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(AuthIdRelationId)); ScanKeyInit(&key[1], Anum_pg_shdepend_refobjid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(roleid)); scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true, SnapshotNow, 2, key); while ((tuple = systable_getnext(scan)) != NULL) { Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple); /* * We only operate on shared objects and objects in the current * database */ if (sdepForm->dbid != MyDatabaseId && sdepForm->dbid != InvalidOid) continue; /* Unexpected because we checked for pins above */ if (sdepForm->deptype == SHARED_DEPENDENCY_PIN) elog(ERROR, "unexpected shared pin"); /* We leave non-owner dependencies alone */ if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER) continue; /* Issue the appropriate ALTER OWNER call */ switch (sdepForm->classid) { case TypeRelationId: AlterTypeOwnerInternal(sdepForm->objid, newrole, true); break; case NamespaceRelationId: AlterSchemaOwner_oid(sdepForm->objid, newrole); break; case RelationRelationId: /* * Pass recursing = true so that we don't fail on indexes, * owned sequences, etc when we happen to visit them * before their parent table. */ ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock); break; case DefaultAclRelationId: /* * Ignore default ACLs; they should be handled by DROP * OWNED, not REASSIGN OWNED. */ break; case ForeignServerRelationId: AlterForeignServerOwner_oid(sdepForm->objid, newrole); break; case ForeignDataWrapperRelationId: AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole); break; case EventTriggerRelationId: AlterEventTriggerOwner_oid(sdepForm->objid, newrole); break; /* Generic alter owner cases */ case CollationRelationId: case ConversionRelationId: case OperatorRelationId: case ProcedureRelationId: case LanguageRelationId: case LargeObjectRelationId: case OperatorFamilyRelationId: case OperatorClassRelationId: case ExtensionRelationId: case TableSpaceRelationId: case DatabaseRelationId: { Oid classId = sdepForm->classid; Relation catalog; if (classId == LargeObjectRelationId) classId = LargeObjectMetadataRelationId; catalog = heap_open(classId, RowExclusiveLock); AlterObjectOwner_internal(catalog, sdepForm->objid, newrole); heap_close(catalog, NoLock); } break; default: elog(ERROR, "unexpected classid %u", sdepForm->classid); break; } /* Make sure the next iteration will see my changes */ CommandCounterIncrement(); } systable_endscan(scan); } heap_close(sdepRel, RowExclusiveLock); }
void updateAclDependencies | ( | Oid | classId, | |
Oid | objectId, | |||
int32 | objectSubId, | |||
Oid | ownerId, | |||
int | noldmembers, | |||
Oid * | oldmembers, | |||
int | nnewmembers, | |||
Oid * | newmembers | |||
) |
Definition at line 418 of file pg_shdepend.c.
References AuthIdRelationId, getOidListDiff(), heap_close, heap_open(), i, isSharedObjectPinned(), pfree(), RowExclusiveLock, SHARED_DEPENDENCY_ACL, SharedDependRelationId, shdepAddDependency(), and shdepDropDependency().
Referenced by ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), heap_create_with_catalog(), ProcedureCreate(), and SetDefaultACL().
{ Relation sdepRel; int i; /* * Remove entries that are common to both lists; those represent existing * dependencies we don't need to change. * * OK to overwrite the inputs since we'll pfree them anyway. */ getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers); if (noldmembers > 0 || nnewmembers > 0) { sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock); /* Add new dependencies that weren't already present */ for (i = 0; i < nnewmembers; i++) { Oid roleid = newmembers[i]; /* * Skip the owner: he has an OWNER shdep entry instead. (This is * not just a space optimization; it makes ALTER OWNER easier. See * notes in changeDependencyOnOwner.) */ if (roleid == ownerId) continue; /* Skip pinned roles; they don't need dependency entries */ if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel)) continue; shdepAddDependency(sdepRel, classId, objectId, objsubId, AuthIdRelationId, roleid, SHARED_DEPENDENCY_ACL); } /* Drop no-longer-used old dependencies */ for (i = 0; i < noldmembers; i++) { Oid roleid = oldmembers[i]; /* Skip the owner, same as above */ if (roleid == ownerId) continue; /* Skip pinned roles */ if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel)) continue; shdepDropDependency(sdepRel, classId, objectId, objsubId, false, /* exact match on objsubId */ AuthIdRelationId, roleid, SHARED_DEPENDENCY_ACL); } heap_close(sdepRel, RowExclusiveLock); } if (oldmembers) pfree(oldmembers); if (newmembers) pfree(newmembers); }