Header And Logo

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

Functions

catalog.c File Reference

#include "postgres.h"
#include <fcntl.h>
#include <unistd.h>
#include "access/genam.h"
#include "access/sysattr.h"
#include "access/transam.h"
#include "catalog/catalog.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_pltemplate.h"
#include "catalog/pg_db_role_setting.h"
#include "catalog/pg_shdepend.h"
#include "catalog/pg_shdescription.h"
#include "catalog/pg_shseclabel.h"
#include "catalog/pg_tablespace.h"
#include "catalog/toasting.h"
#include "common/relpath.h"
#include "miscadmin.h"
#include "storage/fd.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
#include "utils/tqual.h"
Include dependency graph for catalog.c:

Go to the source code of this file.

Functions

ForkNumber forkname_to_number (char *forkName)
char * GetDatabasePath (Oid dbNode, Oid spcNode)
bool IsSystemRelation (Relation relation)
bool IsSystemClass (Form_pg_class reltuple)
bool IsToastRelation (Relation relation)
bool IsToastClass (Form_pg_class reltuple)
bool IsSystemNamespace (Oid namespaceId)
bool IsToastNamespace (Oid namespaceId)
bool IsReservedName (const char *name)
bool IsSharedRelation (Oid relationId)
Oid GetNewOid (Relation relation)
Oid GetNewOidWithIndex (Relation relation, Oid indexId, AttrNumber oidcolumn)
Oid GetNewRelFileNode (Oid reltablespace, Relation pg_class, char relpersistence)

Function Documentation

ForkNumber forkname_to_number ( char *  forkName  ) 

Definition at line 53 of file catalog.c.

References ereport, errcode(), errhint(), errmsg(), ERROR, and forkNames.

Referenced by get_raw_page_fork(), and pg_relation_size().

{
    ForkNumber  forkNum;

    for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
        if (strcmp(forkNames[forkNum], forkName) == 0)
            return forkNum;

    ereport(ERROR,
            (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
             errmsg("invalid fork name"),
             errhint("Valid fork names are \"main\", \"fsm\", and \"vm\".")));
    return InvalidForkNumber;   /* keep compiler quiet */
}

char* GetDatabasePath ( Oid  dbNode,
Oid  spcNode 
)

Definition at line 76 of file catalog.c.

References Assert, DEFAULTTABLESPACE_OID, GLOBALTABLESPACE_OID, OIDCHARS, palloc(), snprintf(), and TABLESPACE_VERSION_DIRECTORY.

Referenced by check_db_file_conflict(), createdb(), dbase_redo(), InitPostgres(), movedb(), movedb_failure_callback(), ProcessCommittedInvalidationMessages(), relmap_redo(), remove_dbtablespaces(), and TablespaceCreateDbspace().

{
    int         pathlen;
    char       *path;

    if (spcNode == GLOBALTABLESPACE_OID)
    {
        /* Shared system relations live in {datadir}/global */
        Assert(dbNode == 0);
        pathlen = 6 + 1;
        path = (char *) palloc(pathlen);
        snprintf(path, pathlen, "global");
    }
    else if (spcNode == DEFAULTTABLESPACE_OID)
    {
        /* The default tablespace is {datadir}/base */
        pathlen = 5 + OIDCHARS + 1;
        path = (char *) palloc(pathlen);
        snprintf(path, pathlen, "base/%u",
                 dbNode);
    }
    else
    {
        /* All other tablespaces are accessed via symlinks */
        pathlen = 9 + 1 + OIDCHARS + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) +
            1 + OIDCHARS + 1;
        path = (char *) palloc(pathlen);
        snprintf(path, pathlen, "pg_tblspc/%u/%s/%u",
                 spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode);
    }
    return path;
}

Oid GetNewOid ( Relation  relation  ) 

Definition at line 298 of file catalog.c.

References Assert, elog, GetNewObjectId(), GetNewOidWithIndex(), IsBootstrapProcessingMode, IsSystemRelation(), ObjectIdAttributeNumber, OidIsValid, RelationData::rd_rel, RelationGetOidIndex(), RelationGetRelationName, and WARNING.

Referenced by AddEnumLabel(), AssignTypeArrayOid(), createdb(), CreateTrigger(), EnumValuesCreate(), GetNewRelFileNode(), and heap_prepare_insert().

{
    Oid         oidIndex;

    /* If relation doesn't have OIDs at all, caller is confused */
    Assert(relation->rd_rel->relhasoids);

    /* In bootstrap mode, we don't have any indexes to use */
    if (IsBootstrapProcessingMode())
        return GetNewObjectId();

    /* The relcache will cache the identity of the OID index for us */
    oidIndex = RelationGetOidIndex(relation);

    /* If no OID index, just hand back the next OID counter value */
    if (!OidIsValid(oidIndex))
    {
        /*
         * System catalogs that have OIDs should *always* have a unique OID
         * index; we should only take this path for user tables. Give a
         * warning if it looks like somebody forgot an index.
         */
        if (IsSystemRelation(relation))
            elog(WARNING, "generating possibly-non-unique OID for \"%s\"",
                 RelationGetRelationName(relation));

        return GetNewObjectId();
    }

    /* Otherwise, use the index to find a nonconflicting OID */
    return GetNewOidWithIndex(relation, oidIndex, ObjectIdAttributeNumber);
}

Oid GetNewOidWithIndex ( Relation  relation,
Oid  indexId,
AttrNumber  oidcolumn 
)

Definition at line 345 of file catalog.c.

References BTEqualStrategyNumber, CHECK_FOR_INTERRUPTS, GetNewObjectId(), HeapTupleIsValid, InitDirtySnapshot, ObjectIdGetDatum, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by GetNewOid(), and toast_save_datum().

{
    Oid         newOid;
    SnapshotData SnapshotDirty;
    SysScanDesc scan;
    ScanKeyData key;
    bool        collides;

    InitDirtySnapshot(SnapshotDirty);

    /* Generate new OIDs until we find one not in the table */
    do
    {
        CHECK_FOR_INTERRUPTS();

        newOid = GetNewObjectId();

        ScanKeyInit(&key,
                    oidcolumn,
                    BTEqualStrategyNumber, F_OIDEQ,
                    ObjectIdGetDatum(newOid));

        /* see notes above about using SnapshotDirty */
        scan = systable_beginscan(relation, indexId, true,
                                  &SnapshotDirty, 1, &key);

        collides = HeapTupleIsValid(systable_getnext(scan));

        systable_endscan(scan);
    } while (collides);

    return newOid;
}

Oid GetNewRelFileNode ( Oid  reltablespace,
Relation  pg_class,
char  relpersistence 
)

Definition at line 396 of file catalog.c.

References RelFileNodeBackend::backend, BasicOpenFile(), CHECK_FOR_INTERRUPTS, close, RelFileNode::dbNode, elog, ERROR, GetNewObjectId(), GetNewOid(), InvalidOid, MAIN_FORKNUM, MyBackendId, MyDatabaseId, MyDatabaseTableSpace, RelFileNodeBackend::node, pfree(), PG_BINARY, RelFileNode::relNode, relpath, RELPERSISTENCE_PERMANENT, RELPERSISTENCE_TEMP, RELPERSISTENCE_UNLOGGED, and RelFileNode::spcNode.

Referenced by ATExecSetTableSpace(), heap_create_with_catalog(), index_create(), and RelationSetNewRelfilenode().

{
    RelFileNodeBackend rnode;
    char       *rpath;
    int         fd;
    bool        collides;
    BackendId   backend;

    switch (relpersistence)
    {
        case RELPERSISTENCE_TEMP:
            backend = MyBackendId;
            break;
        case RELPERSISTENCE_UNLOGGED:
        case RELPERSISTENCE_PERMANENT:
            backend = InvalidBackendId;
            break;
        default:
            elog(ERROR, "invalid relpersistence: %c", relpersistence);
            return InvalidOid;  /* placate compiler */
    }

    /* This logic should match RelationInitPhysicalAddr */
    rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
    rnode.node.dbNode = (rnode.node.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : MyDatabaseId;

    /*
     * The relpath will vary based on the backend ID, so we must initialize
     * that properly here to make sure that any collisions based on filename
     * are properly detected.
     */
    rnode.backend = backend;

    do
    {
        CHECK_FOR_INTERRUPTS();

        /* Generate the OID */
        if (pg_class)
            rnode.node.relNode = GetNewOid(pg_class);
        else
            rnode.node.relNode = GetNewObjectId();

        /* Check for existing file of same name */
        rpath = relpath(rnode, MAIN_FORKNUM);
        fd = BasicOpenFile(rpath, O_RDONLY | PG_BINARY, 0);

        if (fd >= 0)
        {
            /* definite collision */
            close(fd);
            collides = true;
        }
        else
        {
            /*
             * Here we have a little bit of a dilemma: if errno is something
             * other than ENOENT, should we declare a collision and loop? In
             * particular one might think this advisable for, say, EPERM.
             * However there really shouldn't be any unreadable files in a
             * tablespace directory, and if the EPERM is actually complaining
             * that we can't read the directory itself, we'd be in an infinite
             * loop.  In practice it seems best to go ahead regardless of the
             * errno.  If there is a colliding file we will get an smgr
             * failure when we attempt to create the new relation file.
             */
            collides = false;
        }

        pfree(rpath);
    } while (collides);

    return rnode.node.relNode;
}

bool IsReservedName ( const char *  name  ) 

Definition at line 207 of file catalog.c.

Referenced by CreateSchemaCommand(), CreateTableSpace(), RenameSchema(), and RenameTableSpace().

{
    /* ugly coding for speed */
    return (name[0] == 'p' &&
            name[1] == 'g' &&
            name[2] == '_');
}

bool IsSharedRelation ( Oid  relationId  ) 

Definition at line 237 of file catalog.c.

References AuthIdOidIndexId, AuthIdRelationId, AuthIdRolnameIndexId, AuthMemMemRoleIndexId, AuthMemRelationId, AuthMemRoleMemIndexId, DatabaseNameIndexId, DatabaseOidIndexId, DatabaseRelationId, DbRoleSettingDatidRolidIndexId, DbRoleSettingRelationId, PgDbRoleSettingToastIndex, PgDbRoleSettingToastTable, PgShdescriptionToastIndex, PgShdescriptionToastTable, PLTemplateNameIndexId, PLTemplateRelationId, SharedDependDependerIndexId, SharedDependReferenceIndexId, SharedDependRelationId, SharedDescriptionObjIndexId, SharedDescriptionRelationId, SharedSecLabelObjectIndexId, SharedSecLabelRelationId, TablespaceNameIndexId, TablespaceOidIndexId, and TableSpaceRelationId.

Referenced by CacheInvalidateCatalog(), classIdGetDbId(), DeleteSecurityLabel(), get_object_address(), GetSecurityLabel(), RelationBuildLocalRelation(), SetLocktagRelationOid(), and SetSecurityLabel().

{
    /* These are the shared catalogs (look for BKI_SHARED_RELATION) */
    if (relationId == AuthIdRelationId ||
        relationId == AuthMemRelationId ||
        relationId == DatabaseRelationId ||
        relationId == PLTemplateRelationId ||
        relationId == SharedDescriptionRelationId ||
        relationId == SharedDependRelationId ||
        relationId == SharedSecLabelRelationId ||
        relationId == TableSpaceRelationId ||
        relationId == DbRoleSettingRelationId)
        return true;
    /* These are their indexes (see indexing.h) */
    if (relationId == AuthIdRolnameIndexId ||
        relationId == AuthIdOidIndexId ||
        relationId == AuthMemRoleMemIndexId ||
        relationId == AuthMemMemRoleIndexId ||
        relationId == DatabaseNameIndexId ||
        relationId == DatabaseOidIndexId ||
        relationId == PLTemplateNameIndexId ||
        relationId == SharedDescriptionObjIndexId ||
        relationId == SharedDependDependerIndexId ||
        relationId == SharedDependReferenceIndexId ||
        relationId == SharedSecLabelObjectIndexId ||
        relationId == TablespaceOidIndexId ||
        relationId == TablespaceNameIndexId ||
        relationId == DbRoleSettingDatidRolidIndexId)
        return true;
    /* These are their toast tables and toast indexes (see toasting.h) */
    if (relationId == PgShdescriptionToastTable ||
        relationId == PgShdescriptionToastIndex ||
        relationId == PgDbRoleSettingToastTable ||
        relationId == PgDbRoleSettingToastIndex)
        return true;
    return false;
}

bool IsSystemClass ( Form_pg_class  reltuple  ) 
bool IsSystemNamespace ( Oid  namespaceId  ) 

Definition at line 177 of file catalog.c.

Referenced by check_relation_privileges(), IsSystemClass(), and IsSystemRelation().

{
    return namespaceId == PG_CATALOG_NAMESPACE;
}

bool IsSystemRelation ( Relation  relation  ) 
bool IsToastClass ( Form_pg_class  reltuple  ) 

Definition at line 162 of file catalog.c.

References IsToastNamespace().

{
    Oid         relnamespace = reltuple->relnamespace;

    return IsToastNamespace(relnamespace);
}

bool IsToastNamespace ( Oid  namespaceId  ) 

Definition at line 191 of file catalog.c.

References isTempToastNamespace(), and PG_TOAST_NAMESPACE.

Referenced by IsSystemClass(), IsSystemRelation(), IsToastClass(), and IsToastRelation().

{
    return (namespaceId == PG_TOAST_NAMESPACE) ||
        isTempToastNamespace(namespaceId);
}

bool IsToastRelation ( Relation  relation  ) 

Definition at line 150 of file catalog.c.

References IsToastNamespace(), and RelationGetNamespace.

Referenced by CacheInvalidateHeapTuple().

{
    return IsToastNamespace(RelationGetNamespace(relation));
}