#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"
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) |
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 */ }
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; }
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; }
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().
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 | ) |
Definition at line 137 of file catalog.c.
References IsSystemNamespace(), and IsToastNamespace().
Referenced by CheckRelationOwnership(), get_relation_info(), pg_class_aclmask(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), ReindexDatabase(), renameatt_check(), and swap_relation_files().
{ Oid relnamespace = reltuple->relnamespace; return IsSystemNamespace(relnamespace) || IsToastNamespace(relnamespace); }
Definition at line 177 of file catalog.c.
Referenced by check_relation_privileges(), IsSystemClass(), and IsSystemRelation().
{
return namespaceId == PG_CATALOG_NAMESPACE;
}
Definition at line 124 of file catalog.c.
References IsSystemNamespace(), IsToastNamespace(), and RelationGetNamespace.
Referenced by ATAddForeignKeyConstraint(), ATRewriteTables(), ATSimplePermissions(), CacheInvalidateHeapTuple(), copy_heap_data(), CreateTrigger(), DefineQueryRewrite(), ExecRefreshMatView(), GetNewOid(), heap_multi_insert(), index_constraint_create(), index_create(), IndexBuildHeapScan(), rebuild_relation(), RelationReloadIndexInfo(), RemoveTriggerById(), and truncate_check_rel().
{ return IsSystemNamespace(RelationGetNamespace(relation)) || IsToastNamespace(RelationGetNamespace(relation)); }
bool IsToastClass | ( | Form_pg_class | reltuple | ) |
Definition at line 162 of file catalog.c.
References IsToastNamespace().
{ Oid relnamespace = reltuple->relnamespace; return IsToastNamespace(relnamespace); }
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); }
Definition at line 150 of file catalog.c.
References IsToastNamespace(), and RelationGetNamespace.
Referenced by CacheInvalidateHeapTuple().
{ return IsToastNamespace(RelationGetNamespace(relation)); }