PostgreSQL Source Code git master
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-2025, 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 "utils/inval.h"
29#include "utils/syscache.h"
30
31
32/* ----------------
33 * relation_open - open any relation by relation OID
34 *
35 * If lockmode is not "NoLock", the specified kind of lock is
36 * obtained on the relation. (Generally, NoLock should only be
37 * used if the caller knows it has some appropriate lock on the
38 * relation already.)
39 *
40 * An error is raised if the relation does not exist.
41 *
42 * NB: a "relation" is anything with a pg_class entry. The caller is
43 * expected to check whether the relkind is something it can handle.
44 * ----------------
45 */
47relation_open(Oid relationId, LOCKMODE lockmode)
48{
49 Relation r;
50
51 Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
52
53 /* Get the lock before trying to open the relcache entry */
54 if (lockmode != NoLock)
55 LockRelationOid(relationId, lockmode);
56
57 /* The relcache does all the real work... */
58 r = RelationIdGetRelation(relationId);
59
60 if (!RelationIsValid(r))
61 elog(ERROR, "could not open relation with OID %u", relationId);
62
63 /*
64 * If we didn't get the lock ourselves, assert that caller holds one,
65 * except in bootstrap mode where no locks are used.
66 */
67 Assert(lockmode != NoLock ||
70
71 /* Make note that we've accessed a temporary relation */
74
76
77 return r;
78}
79
80/* ----------------
81 * try_relation_open - open any relation by relation OID
82 *
83 * Same as relation_open, except return NULL instead of failing
84 * if the relation does not exist.
85 * ----------------
86 */
88try_relation_open(Oid relationId, LOCKMODE lockmode)
89{
90 Relation r;
91
92 Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
93
94 /* Get the lock first */
95 if (lockmode != NoLock)
96 LockRelationOid(relationId, lockmode);
97
98 /*
99 * Now that we have the lock, probe to see if the relation really exists
100 * or not.
101 */
102 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId)))
103 {
104 /* Release useless lock */
105 if (lockmode != NoLock)
106 UnlockRelationOid(relationId, lockmode);
107
108 return NULL;
109 }
110
111 /* Should be safe to do a relcache load */
112 r = RelationIdGetRelation(relationId);
113
114 if (!RelationIsValid(r))
115 elog(ERROR, "could not open relation with OID %u", relationId);
116
117 /* If we didn't get the lock ourselves, assert that caller holds one */
118 Assert(lockmode != NoLock ||
120
121 /* Make note that we've accessed a temporary relation */
124
126
127 return r;
128}
129
130/* ----------------
131 * relation_openrv - open any relation specified by a RangeVar
132 *
133 * Same as relation_open, but the relation is specified by a RangeVar.
134 * ----------------
135 */
137relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
138{
139 Oid relOid;
140
141 /*
142 * Check for shared-cache-inval messages before trying to open the
143 * relation. This is needed even if we already hold a lock on the
144 * relation, because GRANT/REVOKE are executed without taking any lock on
145 * the target relation, and we want to be sure we see current ACL
146 * information. We can skip this if asked for NoLock, on the assumption
147 * that such a call is not the first one in the current command, and so we
148 * should be reasonably up-to-date already. (XXX this all could stand to
149 * be redesigned, but for the moment we'll keep doing this like it's been
150 * done historically.)
151 */
152 if (lockmode != NoLock)
154
155 /* Look up and lock the appropriate relation using namespace search */
156 relOid = RangeVarGetRelid(relation, lockmode, false);
157
158 /* Let relation_open do the rest */
159 return relation_open(relOid, NoLock);
160}
161
162/* ----------------
163 * relation_openrv_extended - open any relation specified by a RangeVar
164 *
165 * Same as relation_openrv, but with an additional missing_ok argument
166 * allowing a NULL return rather than an error if the relation is not
167 * found. (Note that some other causes, such as permissions problems,
168 * will still result in an ereport.)
169 * ----------------
170 */
173 bool missing_ok)
174{
175 Oid relOid;
176
177 /*
178 * Check for shared-cache-inval messages before trying to open the
179 * relation. See comments in relation_openrv().
180 */
181 if (lockmode != NoLock)
183
184 /* Look up and lock the appropriate relation using namespace search */
185 relOid = RangeVarGetRelid(relation, lockmode, missing_ok);
186
187 /* Return NULL on not-found */
188 if (!OidIsValid(relOid))
189 return NULL;
190
191 /* Let relation_open do the rest */
192 return relation_open(relOid, NoLock);
193}
194
195/* ----------------
196 * relation_close - close any relation
197 *
198 * If lockmode is not "NoLock", we then release the specified lock.
199 *
200 * Note that it is often sensible to hold a lock beyond relation_close;
201 * in that case, the lock is released automatically at xact end.
202 * ----------------
203 */
204void
206{
207 LockRelId relid = relation->rd_lockInfo.lockRelId;
208
209 Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
210
211 /* The relcache does the real work... */
212 RelationClose(relation);
213
214 if (lockmode != NoLock)
215 UnlockRelationId(&relid, lockmode);
216}
#define OidIsValid(objectId)
Definition: c.h:746
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
Assert(PointerIsAligned(start, uint64))
void AcceptInvalidationMessages(void)
Definition: inval.c:929
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:83
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:474
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:80
void pgstat_init_relation(Relation rel)
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
unsigned int Oid
Definition: postgres_ext.h:32
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:644
#define RelationIsValid(relation)
Definition: rel.h:485
Relation RelationIdGetRelation(Oid relationId)
Definition: relcache.c:2056
void RelationClose(Relation relation)
Definition: relcache.c:2178
Relation relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
Definition: relation.c:172
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:88
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: relation.c:137
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
LockRelId lockRelId
Definition: rel.h:46
Definition: rel.h:39
LockInfoData rd_lockInfo
Definition: rel.h:114
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:100
int MyXactFlags
Definition: xact.c:136
#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE
Definition: xact.h:102