Header And Logo

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

Defines | Typedefs | Enumerations | Functions

dependency.h File Reference

#include "catalog/objectaddress.h"
Include dependency graph for dependency.h:

Go to the source code of this file.

Defines

#define PERFORM_DELETION_INTERNAL   0x0001
#define PERFORM_DELETION_CONCURRENTLY   0x0002

Typedefs

typedef enum DependencyType DependencyType
typedef enum SharedDependencyType SharedDependencyType
typedef struct ObjectAddresses ObjectAddresses
typedef enum ObjectClass ObjectClass

Enumerations

enum  DependencyType {
  DEPENDENCY_NORMAL = 'n', DEPENDENCY_AUTO = 'a', DEPENDENCY_INTERNAL = 'i', DEPENDENCY_EXTENSION = 'e',
  DEPENDENCY_PIN = 'p'
}
enum  SharedDependencyType { SHARED_DEPENDENCY_PIN = 'p', SHARED_DEPENDENCY_OWNER = 'o', SHARED_DEPENDENCY_ACL = 'a', SHARED_DEPENDENCY_INVALID = 0 }
enum  ObjectClass {
  OCLASS_CLASS, OCLASS_PROC, OCLASS_TYPE, OCLASS_CAST,
  OCLASS_COLLATION, OCLASS_CONSTRAINT, OCLASS_CONVERSION, OCLASS_DEFAULT,
  OCLASS_LANGUAGE, OCLASS_LARGEOBJECT, OCLASS_OPERATOR, OCLASS_OPCLASS,
  OCLASS_OPFAMILY, OCLASS_AMOP, OCLASS_AMPROC, OCLASS_REWRITE,
  OCLASS_TRIGGER, OCLASS_SCHEMA, OCLASS_TSPARSER, OCLASS_TSDICT,
  OCLASS_TSTEMPLATE, OCLASS_TSCONFIG, OCLASS_ROLE, OCLASS_DATABASE,
  OCLASS_TBLSPACE, OCLASS_FDW, OCLASS_FOREIGN_SERVER, OCLASS_USER_MAPPING,
  OCLASS_DEFACL, OCLASS_EXTENSION, OCLASS_EVENT_TRIGGER, MAX_OCLASS
}

Functions

void performDeletion (const ObjectAddress *object, DropBehavior behavior, int flags)
void performMultipleDeletions (const ObjectAddresses *objects, DropBehavior behavior, int flags)
void deleteWhatDependsOn (const ObjectAddress *object, bool showNotices)
void recordDependencyOnExpr (const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
void recordDependencyOnSingleRelExpr (const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior)
ObjectClass getObjectClass (const ObjectAddress *object)
ObjectAddressesnew_object_addresses (void)
void add_exact_object_address (const ObjectAddress *object, ObjectAddresses *addrs)
bool object_address_present (const ObjectAddress *object, const ObjectAddresses *addrs)
void record_object_address_dependencies (const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void free_object_addresses (ObjectAddresses *addrs)
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)
void recordSharedDependencyOn (ObjectAddress *depender, ObjectAddress *referenced, SharedDependencyType deptype)
void deleteSharedDependencyRecordsFor (Oid classId, Oid objectId, int32 objectSubId)
void recordDependencyOnOwner (Oid classId, Oid objectId, Oid owner)
void changeDependencyOnOwner (Oid classId, Oid objectId, Oid newOwnerId)
void updateAclDependencies (Oid classId, Oid objectId, int32 objectSubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
bool checkSharedDependencies (Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
void shdepLockAndCheckObject (Oid classId, Oid objectId)
void copyTemplateDependencies (Oid templateDbId, Oid newDbId)
void dropDatabaseDependencies (Oid databaseId)
void shdepDropOwned (List *relids, DropBehavior behavior)
void shdepReassignOwned (List *relids, Oid newrole)

Define Documentation

#define PERFORM_DELETION_CONCURRENTLY   0x0002

Definition at line 157 of file dependency.h.

Referenced by AcquireDeletionLock(), deleteOneObject(), and doDeletion().

#define PERFORM_DELETION_INTERNAL   0x0001

Typedef Documentation

Definition at line 111 of file dependency.h.

typedef enum ObjectClass ObjectClass

Enumeration Type Documentation

Enumerator:
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;

Enumerator:
OCLASS_CLASS 
OCLASS_PROC 
OCLASS_TYPE 
OCLASS_CAST 
OCLASS_COLLATION 
OCLASS_CONSTRAINT 
OCLASS_CONVERSION 
OCLASS_DEFAULT 
OCLASS_LANGUAGE 
OCLASS_LARGEOBJECT 
OCLASS_OPERATOR 
OCLASS_OPCLASS 
OCLASS_OPFAMILY 
OCLASS_AMOP 
OCLASS_AMPROC 
OCLASS_REWRITE 
OCLASS_TRIGGER 
OCLASS_SCHEMA 
OCLASS_TSPARSER 
OCLASS_TSDICT 
OCLASS_TSTEMPLATE 
OCLASS_TSCONFIG 
OCLASS_ROLE 
OCLASS_DATABASE 
OCLASS_TBLSPACE 
OCLASS_FDW 
OCLASS_FOREIGN_SERVER 
OCLASS_USER_MAPPING 
OCLASS_DEFACL 
OCLASS_EXTENSION 
OCLASS_EVENT_TRIGGER 
MAX_OCLASS 

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;

Enumerator:
SHARED_DEPENDENCY_PIN 
SHARED_DEPENDENCY_OWNER 
SHARED_DEPENDENCY_ACL 
SHARED_DEPENDENCY_INVALID 

Definition at line 102 of file dependency.h.


Function Documentation

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

void changeDependencyOnOwner ( Oid  classId,
Oid  objectId,
Oid  newOwnerId 
)

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

void copyTemplateDependencies ( Oid  templateDbId,
Oid  newDbId 
)

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

long deleteDependencyRecordsFor ( Oid  classId,
Oid  objectId,
bool  skipExtensionDeps 
)
long deleteDependencyRecordsForClass ( Oid  classId,
Oid  objectId,
Oid  refclassId,
char  deptype 
)
void deleteSharedDependencyRecordsFor ( Oid  classId,
Oid  objectId,
int32  objectSubId 
)
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  ) 
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 
)
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 */
}

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

void markSequenceUnowned ( Oid  seqId  ) 
ObjectAddresses* new_object_addresses ( void   ) 
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 
)
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 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);
}

void recordDependencyOnOwner ( Oid  classId,
Oid  objectId,
Oid  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);
}

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

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

void shdepLockAndCheckObject ( Oid  classId,
Oid  objectId 
)

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

void shdepReassignOwned ( List relids,
Oid  newrole 
)

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