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-2023, 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 "miscadmin.h"
27 #include "pgstat.h"
28 #include "storage/lmgr.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  */
48 relation_open(Oid relationId, LOCKMODE lockmode)
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... */
59  r = RelationIdGetRelation(relationId);
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  */
89 try_relation_open(Oid relationId, LOCKMODE lockmode)
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  */
103  if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId)))
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 */
113  r = RelationIdGetRelation(relationId);
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  */
137 Relation
138 relation_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  */
172 Relation
173 relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
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  */
205 void
206 relation_close(Relation relation, LOCKMODE lockmode)
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 OidIsValid(objectId)
Definition: c.h:764
#define ERROR
Definition: elog.h:39
void AcceptInvalidationMessages(void)
Definition: inval.c:807
Assert(fmt[strlen(fmt) - 1] !='\n')
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:228
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:213
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition: lmgr.c:331
#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:417
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
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:638
#define RelationIsValid(relation)
Definition: rel.h:477
Relation RelationIdGetRelation(Oid relationId)
Definition: relcache.c:2056
void RelationClose(Relation relation)
Definition: relcache.c:2187
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
Definition: rel.h:39
LockInfoData rd_lockInfo
Definition: rel.h:114
@ RELOID
Definition: syscache.h:89
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:191
int MyXactFlags
Definition: xact.c:136
#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE
Definition: xact.h:102