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-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 : : */
46 : : Relation
1910 andres@anarazel.de 47 :CBC 17304531 : relation_open(Oid relationId, LOCKMODE lockmode)
48 : : {
49 : : Relation r;
50 : :
51 [ + - - + ]: 17304531 : Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
52 : :
53 : : /* Get the lock before trying to open the relcache entry */
54 [ + + ]: 17304531 : if (lockmode != NoLock)
55 : 15615121 : LockRelationOid(relationId, lockmode);
56 : :
57 : : /* The relcache does all the real work... */
58 : 17304530 : r = RelationIdGetRelation(relationId);
59 : :
60 [ + + ]: 17304520 : if (!RelationIsValid(r))
61 [ + - ]: 7 : 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 [ + + + + : 17304513 : Assert(lockmode != NoLock ||
- + ]
68 : : IsBootstrapProcessingMode() ||
69 : : CheckRelationLockedByMe(r, AccessShareLock, true));
70 : :
71 : : /* Make note that we've accessed a temporary relation */
72 [ + + ]: 17304513 : if (RelationUsesLocalBuffers(r))
1905 michael@paquier.xyz 73 : 125578 : MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
74 : :
739 andres@anarazel.de 75 : 17304513 : pgstat_init_relation(r);
76 : :
1910 77 : 17304513 : 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 : : */
87 : : Relation
88 : 249567 : try_relation_open(Oid relationId, LOCKMODE lockmode)
89 : : {
90 : : Relation r;
91 : :
92 [ + - - + ]: 249567 : Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
93 : :
94 : : /* Get the lock first */
95 [ + + ]: 249567 : if (lockmode != NoLock)
96 : 248924 : 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 [ + + ]: 249567 : if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId)))
103 : : {
104 : : /* Release useless lock */
105 [ + - ]: 7 : if (lockmode != NoLock)
106 : 7 : UnlockRelationOid(relationId, lockmode);
107 : :
108 : 7 : return NULL;
109 : : }
110 : :
111 : : /* Should be safe to do a relcache load */
112 : 249560 : r = RelationIdGetRelation(relationId);
113 : :
114 [ - + ]: 249560 : if (!RelationIsValid(r))
1910 andres@anarazel.de 115 [ # # ]:UBC 0 : 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 */
1910 andres@anarazel.de 118 [ + + - + ]:CBC 249560 : Assert(lockmode != NoLock ||
119 : : CheckRelationLockedByMe(r, AccessShareLock, true));
120 : :
121 : : /* Make note that we've accessed a temporary relation */
122 [ + + ]: 249560 : if (RelationUsesLocalBuffers(r))
1905 michael@paquier.xyz 123 : 270 : MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
124 : :
739 andres@anarazel.de 125 : 249560 : pgstat_init_relation(r);
126 : :
1910 127 : 249560 : 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 : 16385 : 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 [ + + ]: 16385 : if (lockmode != NoLock)
153 : 13663 : AcceptInvalidationMessages();
154 : :
155 : : /* Look up and lock the appropriate relation using namespace search */
156 : 16385 : relOid = RangeVarGetRelid(relation, lockmode, false);
157 : :
158 : : /* Let relation_open do the rest */
159 : 16335 : 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 : 210812 : 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 [ + - ]: 210812 : if (lockmode != NoLock)
182 : 210812 : AcceptInvalidationMessages();
183 : :
184 : : /* Look up and lock the appropriate relation using namespace search */
185 : 210812 : relOid = RangeVarGetRelid(relation, lockmode, missing_ok);
186 : :
187 : : /* Return NULL on not-found */
188 [ + + ]: 210615 : if (!OidIsValid(relOid))
189 : 112 : return NULL;
190 : :
191 : : /* Let relation_open do the rest */
192 : 210503 : 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 : 9183513 : relation_close(Relation relation, LOCKMODE lockmode)
206 : : {
207 : 9183513 : LockRelId relid = relation->rd_lockInfo.lockRelId;
208 : :
209 [ + - - + ]: 9183513 : Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
210 : :
211 : : /* The relcache does the real work... */
212 : 9183513 : RelationClose(relation);
213 : :
214 [ + + ]: 9183513 : if (lockmode != NoLock)
215 : 6993284 : UnlockRelationId(&relid, lockmode);
216 : 9183513 : }
|