PostgreSQL Source Code git master
Loading...
Searching...
No Matches
relation.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * relation.c
4 * Generic relation related routines.
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/access/common/relation.c
12 *
13 * NOTES
14 * This file contains relation_ routines that implement access to relations
15 * (tables, indexes, etc). Support that's specific to subtypes of relations
16 * should go into their respective files, not here.
17 *
18 *-------------------------------------------------------------------------
19 */
20
21#include "postgres.h"
22
23#include "access/relation.h"
24#include "access/xact.h"
25#include "catalog/namespace.h"
26#include "pgstat.h"
27#include "storage/lmgr.h"
28#include "storage/lock.h"
29#include "utils/inval.h"
30#include "utils/syscache.h"
31
32
33/* ----------------
34 * relation_open - open any relation by relation OID
35 *
36 * If lockmode is not "NoLock", the specified kind of lock is
37 * obtained on the relation. (Generally, NoLock should only be
38 * used if the caller knows it has some appropriate lock on the
39 * relation already.)
40 *
41 * An error is raised if the relation does not exist.
42 *
43 * NB: a "relation" is anything with a pg_class entry. The caller is
44 * expected to check whether the relkind is something it can handle.
45 * ----------------
46 */
49{
50 Relation r;
51
52 Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
53
54 /* Get the lock before trying to open the relcache entry */
55 if (lockmode != NoLock)
56 LockRelationOid(relationId, lockmode);
57
58 /* The relcache does all the real work... */
60
61 if (!RelationIsValid(r))
62 elog(ERROR, "could not open relation with OID %u", relationId);
63
64 /*
65 * If we didn't get the lock ourselves, assert that caller holds one,
66 * except in bootstrap mode where no locks are used.
67 */
68 Assert(lockmode != NoLock ||
71
72 /* Make note that we've accessed a temporary relation */
75
77
78 return r;
79}
80
81/* ----------------
82 * try_relation_open - open any relation by relation OID
83 *
84 * Same as relation_open, except return NULL instead of failing
85 * if the relation does not exist.
86 * ----------------
87 */
90{
91 Relation r;
92
93 Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
94
95 /* Get the lock first */
96 if (lockmode != NoLock)
97 LockRelationOid(relationId, lockmode);
98
99 /*
100 * Now that we have the lock, probe to see if the relation really exists
101 * or not.
102 */
104 {
105 /* Release useless lock */
106 if (lockmode != NoLock)
107 UnlockRelationOid(relationId, lockmode);
108
109 return NULL;
110 }
111
112 /* Should be safe to do a relcache load */
114
115 if (!RelationIsValid(r))
116 elog(ERROR, "could not open relation with OID %u", relationId);
117
118 /* If we didn't get the lock ourselves, assert that caller holds one */
119 Assert(lockmode != NoLock ||
121
122 /* Make note that we've accessed a temporary relation */
125
127
128 return r;
129}
130
131/* ----------------
132 * relation_openrv - open any relation specified by a RangeVar
133 *
134 * Same as relation_open, but the relation is specified by a RangeVar.
135 * ----------------
136 */
138relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
139{
140 Oid relOid;
141
142 /*
143 * Check for shared-cache-inval messages before trying to open the
144 * relation. This is needed even if we already hold a lock on the
145 * relation, because GRANT/REVOKE are executed without taking any lock on
146 * the target relation, and we want to be sure we see current ACL
147 * information. We can skip this if asked for NoLock, on the assumption
148 * that such a call is not the first one in the current command, and so we
149 * should be reasonably up-to-date already. (XXX this all could stand to
150 * be redesigned, but for the moment we'll keep doing this like it's been
151 * done historically.)
152 */
153 if (lockmode != NoLock)
155
156 /* Look up and lock the appropriate relation using namespace search */
157 relOid = RangeVarGetRelid(relation, lockmode, false);
158
159 /* Let relation_open do the rest */
160 return relation_open(relOid, NoLock);
161}
162
163/* ----------------
164 * relation_openrv_extended - open any relation specified by a RangeVar
165 *
166 * Same as relation_openrv, but with an additional missing_ok argument
167 * allowing a NULL return rather than an error if the relation is not
168 * found. (Note that some other causes, such as permissions problems,
169 * will still result in an ereport.)
170 * ----------------
171 */
174 bool missing_ok)
175{
176 Oid relOid;
177
178 /*
179 * Check for shared-cache-inval messages before trying to open the
180 * relation. See comments in relation_openrv().
181 */
182 if (lockmode != NoLock)
184
185 /* Look up and lock the appropriate relation using namespace search */
186 relOid = RangeVarGetRelid(relation, lockmode, missing_ok);
187
188 /* Return NULL on not-found */
189 if (!OidIsValid(relOid))
190 return NULL;
191
192 /* Let relation_open do the rest */
193 return relation_open(relOid, NoLock);
194}
195
196/* ----------------
197 * relation_close - close any relation
198 *
199 * If lockmode is not "NoLock", we then release the specified lock.
200 *
201 * Note that it is often sensible to hold a lock beyond relation_close;
202 * in that case, the lock is released automatically at xact end.
203 * ----------------
204 */
205void
207{
208 LockRelId relid = relation->rd_lockInfo.lockRelId;
209
210 Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
211
212 /* The relcache does the real work... */
213 RelationClose(relation);
214
215 if (lockmode != NoLock)
216 UnlockRelationId(&relid, lockmode);
217}
#define Assert(condition)
Definition c.h:943
#define OidIsValid(objectId)
Definition c.h:858
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
void AcceptInvalidationMessages(void)
Definition inval.c:930
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:229
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode)
Definition lmgr.c:214
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition lmgr.c:334
#define MAX_LOCKMODES
Definition lock.h:85
int LOCKMODE
Definition lockdefs.h:26
#define NoLock
Definition lockdefs.h:34
#define AccessShareLock
Definition lockdefs.h:36
#define IsBootstrapProcessingMode()
Definition miscadmin.h:495
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition namespace.h:98
void pgstat_init_relation(Relation rel)
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
unsigned int Oid
static int fb(int x)
#define RelationUsesLocalBuffers(relation)
Definition rel.h:648
#define RelationIsValid(relation)
Definition rel.h:491
Relation RelationIdGetRelation(Oid relationId)
Definition relcache.c:2089
void RelationClose(Relation relation)
Definition relcache.c:2210
Relation relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
Definition relation.c:173
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:206
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:89
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition relation.c:138
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:48
LockRelId lockRelId
Definition rel.h:46
LockInfoData rd_lockInfo
Definition rel.h:114
#define SearchSysCacheExists1(cacheId, key1)
Definition syscache.h:100
int MyXactFlags
Definition xact.c:138
#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE
Definition xact.h:103