Age Owner Branch data TLA Line data Source code
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 : : */
47 : : Relation
2661 andres@anarazel.de 48 :CBC 26098939 : relation_open(Oid relationId, LOCKMODE lockmode)
49 : : {
50 : : Relation r;
51 : :
52 [ + - - + ]: 26098939 : Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
53 : :
54 : : /* Get the lock before trying to open the relcache entry */
55 [ + + ]: 26098939 : if (lockmode != NoLock)
56 : 23229109 : LockRelationOid(relationId, lockmode);
57 : :
58 : : /* The relcache does all the real work... */
59 : 26098938 : r = RelationIdGetRelation(relationId);
60 : :
61 [ + + ]: 26098929 : if (!RelationIsValid(r))
62 [ + - ]: 8 : 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 [ + + + + : 26098921 : Assert(lockmode != NoLock ||
- + ]
69 : : IsBootstrapProcessingMode() ||
70 : : CheckRelationLockedByMe(r, AccessShareLock, true));
71 : :
72 : : /* Make note that we've accessed a temporary relation */
73 [ + + ]: 26098921 : if (RelationUsesLocalBuffers(r))
2656 michael@paquier.xyz 74 : 208071 : MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
75 : :
1490 andres@anarazel.de 76 : 26098921 : pgstat_init_relation(r);
77 : :
2661 78 : 26098921 : 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 : : */
88 : : Relation
89 : 242006 : try_relation_open(Oid relationId, LOCKMODE lockmode)
90 : : {
91 : : Relation r;
92 : :
93 [ + - - + ]: 242006 : Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
94 : :
95 : : /* Get the lock first */
96 [ + + ]: 242006 : if (lockmode != NoLock)
97 : 240971 : 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 [ + + ]: 242006 : if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId)))
104 : : {
105 : : /* Release useless lock */
106 [ + - ]: 7 : if (lockmode != NoLock)
107 : 7 : UnlockRelationOid(relationId, lockmode);
108 : :
109 : 7 : return NULL;
110 : : }
111 : :
112 : : /* Should be safe to do a relcache load */
113 : 241999 : r = RelationIdGetRelation(relationId);
114 : :
115 [ - + ]: 241999 : if (!RelationIsValid(r))
2661 andres@anarazel.de 116 [ # # ]:UBC 0 : 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 */
2661 andres@anarazel.de 119 [ + + - + ]:CBC 241999 : Assert(lockmode != NoLock ||
120 : : CheckRelationLockedByMe(r, AccessShareLock, true));
121 : :
122 : : /* Make note that we've accessed a temporary relation */
123 [ + + ]: 241999 : if (RelationUsesLocalBuffers(r))
2656 michael@paquier.xyz 124 : 742 : MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
125 : :
1490 andres@anarazel.de 126 : 241999 : pgstat_init_relation(r);
127 : :
2661 128 : 241999 : 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 : 23518 : 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 [ + + ]: 23518 : if (lockmode != NoLock)
154 : 19547 : AcceptInvalidationMessages();
155 : :
156 : : /* Look up and lock the appropriate relation using namespace search */
157 : 23518 : relOid = RangeVarGetRelid(relation, lockmode, false);
158 : :
159 : : /* Let relation_open do the rest */
160 : 23440 : 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 : 318630 : 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 [ + + ]: 318630 : if (lockmode != NoLock)
183 : 318350 : AcceptInvalidationMessages();
184 : :
185 : : /* Look up and lock the appropriate relation using namespace search */
186 : 318630 : relOid = RangeVarGetRelid(relation, lockmode, missing_ok);
187 : :
188 : : /* Return NULL on not-found */
189 [ + + ]: 318340 : if (!OidIsValid(relOid))
190 : 137 : return NULL;
191 : :
192 : : /* Let relation_open do the rest */
193 : 318203 : 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 : 13787063 : relation_close(Relation relation, LOCKMODE lockmode)
207 : : {
208 : 13787063 : LockRelId relid = relation->rd_lockInfo.lockRelId;
209 : :
210 [ + - - + ]: 13787063 : Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
211 : :
212 : : /* The relcache does the real work... */
213 : 13787063 : RelationClose(relation);
214 : :
215 [ + + ]: 13787063 : if (lockmode != NoLock)
216 : 10271880 : UnlockRelationId(&relid, lockmode);
217 : 13787063 : }
|