1/*-------------------------------------------------------------------------
4 * relfilenumber to oid mapping cache.
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/backend/utils/cache/relfilenumbermap.c
12 *-------------------------------------------------------------------------
23#include "utils/fmgroids.h"
29/* Hash table for information about each relfilenumber <-> oid pair */
32/* built first time through in InitializeRelfilenumberMap */
48 * RelfilenumberMapInvalidateCallback
49 * Flush mapping entries when pg_class is updated in a relevant fashion.
57 /* callback only gets registered after creating the hash */
64 * If relid is InvalidOid, signaling a complete reset, we must remove
65 * all entries, otherwise just remove the specific relation's entry.
66 * Always remove negative cache entries.
68 if (relid ==
InvalidOid ||
/* complete reset */
70 entry->
relid == relid)
/* individual flushed relation */
82 * InitializeRelfilenumberMap
83 * Initialize cache, either on first use or after a reset.
91 /* Make sure we've initialized CacheMemoryContext. */
98 for (
i = 0;
i < 2;
i++)
112 * Only create the RelfilenumberMapHash now, so we don't end up partially
113 * initialized when fmgr_info_cxt() above ERRORs out with an out of memory
124 /* Watch for invalidation events. */
130 * Map a relation's (tablespace, relfilenumber) to a relation's oid and cache
133 * A temporary relation may share its relfilenumber with a permanent relation
134 * or temporary relations created in other backends. Being able to uniquely
135 * identify a temporary relation would require a backend's proc number, which
136 * we do not know about. Hence, this function ignores this case.
138 * Returns InvalidOid if no relation matching the criteria could be found.
154 /* pg_class will show 0 when the value is actually MyDatabaseTableSpace */
159 key.reltablespace = reltablespace;
160 key.relfilenumber = relfilenumber;
163 * Check cache and return entry if one is found. Even if no target
164 * relation can be found later on we store the negative match and return a
165 * InvalidOid from cache. That's not really necessary for performance
166 * since querying invalid values isn't supposed to be a frequent thing,
167 * but it's basically free.
174 /* ok, no previous cache entry, do it the hard way */
176 /* initialize empty/negative cache entry before doing the actual lookups */
179 if (reltablespace == GLOBALTABLESPACE_OID)
182 * Ok, shared table, check relmapper.
191 * Not a shared table, could either be a plain relation or a
192 * non-shared, nailed one, like e.g. pg_class.
195 /* check for plain relations by looking in pg_class */
198 /* copy scankey to local copy and set scan arguments */
204 ClassTblspcRelfilenodeIndexId,
216 if (classform->relpersistence == RELPERSISTENCE_TEMP)
221 "unexpected duplicate for tablespace %u, relfilenumber %u",
222 reltablespace, relfilenumber);
225 Assert(classform->reltablespace == reltablespace);
226 Assert(classform->relfilenode == relfilenumber);
227 relid = classform->oid;
233 /* check for tables that are mapped but not shared */
239 * Only enter entry into cache now, our opening of pg_class could have
240 * caused cache invalidations to be executed which would have deleted a
241 * new entry if we had entered it above.
246 entry->
relid = relid;
#define MemSet(start, val, len)
void CreateCacheMemoryContext(void)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
void * hash_seq_search(HASH_SEQ_STATUS *status)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
void systable_endscan(SysScanDesc sysscan)
HeapTuple systable_getnext(SysScanDesc sysscan)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
MemoryContext CacheMemoryContext
FormData_pg_class * Form_pg_class
static Datum ObjectIdGetDatum(Oid X)
static ScanKeyData relfilenumber_skey[2]
static void RelfilenumberMapInvalidateCallback(Datum arg, Oid relid)
static void InitializeRelfilenumberMap(void)
static HTAB * RelfilenumberMapHash
Oid RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber)
Oid RelationMapFilenumberToOid(RelFileNumber filenumber, bool shared)
#define BTEqualStrategyNumber
RelFileNumber relfilenumber
StrategyNumber sk_strategy
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)