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-2024, 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  */
47 relation_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  */
88 try_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  */
136 Relation
137 relation_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  */
171 Relation
172 relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
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  */
204 void
205 relation_close(Relation relation, LOCKMODE lockmode)
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 Assert(condition)
Definition: c.h:812
#define OidIsValid(objectId)
Definition: c.h:729
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
void AcceptInvalidationMessages(void)
Definition: inval.c:863
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:226
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:211
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition: lmgr.c:329
#define MAX_LOCKMODES
Definition: lock.h:82
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:454
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:80
void pgstat_init_relation(Relation rel)
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationUsesLocalBuffers(relation)
Definition: rel.h:637
#define RelationIsValid(relation)
Definition: rel.h:478
Relation RelationIdGetRelation(Oid relationId)
Definition: relcache.c:2061
void RelationClose(Relation relation)
Definition: relcache.c:2183
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:135
#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE
Definition: xact.h:102