Header And Logo

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

Functions

pg_depend.c File Reference

#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_extension.h"
#include "commands/extension.h"
#include "miscadmin.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/tqual.h"
Include dependency graph for pg_depend.c:

Go to the source code of this file.

Functions

static bool isObjectPinned (const ObjectAddress *object, Relation rel)
void recordDependencyOn (const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
void recordMultipleDependencies (const ObjectAddress *depender, const ObjectAddress *referenced, int nreferenced, DependencyType behavior)
void recordDependencyOnCurrentExtension (const ObjectAddress *object, bool isReplace)
long deleteDependencyRecordsFor (Oid classId, Oid objectId, bool skipExtensionDeps)
long deleteDependencyRecordsForClass (Oid classId, Oid objectId, Oid refclassId, char deptype)
long changeDependencyFor (Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Oid getExtensionOfObject (Oid classId, Oid objectId)
bool sequenceIsOwned (Oid seqId, Oid *tableId, int32 *colId)
void markSequenceUnowned (Oid seqId)
ListgetOwnedSequences (Oid relid)
Oid get_constraint_index (Oid constraintId)
Oid get_index_constraint (Oid indexId)

Function Documentation

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;
}

long deleteDependencyRecordsFor ( Oid  classId,
Oid  objectId,
bool  skipExtensionDeps 
)
long deleteDependencyRecordsForClass ( Oid  classId,
Oid  objectId,
Oid  refclassId,
char  deptype 
)
Oid get_constraint_index ( Oid  constraintId  ) 

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;
}

Oid get_index_constraint ( Oid  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;
}

Oid getExtensionOfObject ( Oid  classId,
Oid  objectId 
)
List* getOwnedSequences ( Oid  relid  ) 

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;
}

static bool isObjectPinned ( const ObjectAddress object,
Relation  rel 
) [static]

Definition at line 392 of file pg_depend.c.

References Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, BTEqualStrategyNumber, ObjectAddress::classId, DEPENDENCY_PIN, DependReferenceIndexId, GETSTRUCT, HeapTupleIsValid, ObjectAddress::objectId, ObjectIdGetDatum, ScanKeyInit(), SnapshotNow, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by changeDependencyFor(), and recordMultipleDependencies().

{
    bool        ret = false;
    SysScanDesc scan;
    HeapTuple   tup;
    ScanKeyData key[2];

    ScanKeyInit(&key[0],
                Anum_pg_depend_refclassid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->classId));

    ScanKeyInit(&key[1],
                Anum_pg_depend_refobjid,
                BTEqualStrategyNumber, F_OIDEQ,
                ObjectIdGetDatum(object->objectId));

    scan = systable_beginscan(rel, DependReferenceIndexId, true,
                              SnapshotNow, 2, key);

    /*
     * Since we won't generate additional pg_depend entries for pinned
     * objects, there can be at most one entry referencing a pinned object.
     * Hence, it's sufficient to look at the first returned tuple; we don't
     * need to loop.
     */
    tup = systable_getnext(scan);
    if (HeapTupleIsValid(tup))
    {
        Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);

        if (foundDep->deptype == DEPENDENCY_PIN)
            ret = true;
    }

    systable_endscan(scan);

    return ret;
}

void markSequenceUnowned ( Oid  seqId  ) 
void recordDependencyOn ( const ObjectAddress depender,
const ObjectAddress referenced,
DependencyType  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 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);
}

bool sequenceIsOwned ( Oid  seqId,
Oid tableId,
int32 colId 
)

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;
}