Skip to content

Commit 4b21acf

Browse files
committed
Introduce access/{table.h, relation.h}, for generic functions from heapam.h.
access/heapam contains functions that are very storage specific (say heap_insert() and a lot of lower level functions), and fairly generic infrastructure like relation_open(), heap_open() etc. In the upcoming pluggable storage work we're introducing a layer between table accesses in general and heapam, to allow for different storage methods. For a bit cleaner separation it thus seems advantageous to move generic functions like the aforementioned to their own headers. access/relation.h will contain relation_open() etc, and access/table.h will contain table_open() (formerly known as heap_open()). I've decided for table.h not to include relation.h, but we might change that at a later stage. relation.h already exists in another directory, but the other plausible name (rel.h) also conflicts. It'd be nice if there were a non-conflicting name, but nobody came up with a suggestion. It's possible that the appropriate way to address the naming conflict would be to rename nodes/relation.h, which isn't particularly well named. To avoid breaking a lot of extensions that just use heap_open() etc, table.h has macros mapping the old names to the new ones, and heapam.h includes relation, table.h. That also allows to keep the bulk renaming of existing callers in a separate commit. Author: Andres Freund Discussion: https://postgr.es/m/20190111000539.xbv7s6w7ilcvm7dp@alap3.anarazel.de
1 parent f1ad067 commit 4b21acf

File tree

9 files changed

+441
-305
lines changed

9 files changed

+441
-305
lines changed

src/backend/access/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ top_builddir = ../../..
99
include $(top_builddir)/src/Makefile.global
1010

1111
SUBDIRS = brin common gin gist hash heap index nbtree rmgrdesc spgist \
12-
tablesample transam
12+
table tablesample transam
1313

1414
include $(top_srcdir)/src/backend/common.mk

src/backend/access/common/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

1515
OBJS = bufmask.o heaptuple.o indextuple.o printsimple.o printtup.o \
16-
reloptions.o scankey.o session.o tupconvert.o tupdesc.o
16+
relation.o reloptions.o scankey.o session.o tupconvert.o tupdesc.o
1717

1818
include $(top_srcdir)/src/backend/common.mk

src/backend/access/common/relation.c

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* relation.c
4+
* Generic relation related routines.
5+
*
6+
* Portions Copyright (c) 1996-2019, 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+
*/
47+
Relation
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 ||
69+
IsBootstrapProcessingMode() ||
70+
CheckRelationLockedByMe(r, AccessShareLock, true));
71+
72+
/* Make note that we've accessed a temporary relation */
73+
if (RelationUsesLocalBuffers(r))
74+
MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL;
75+
76+
pgstat_initstats(r);
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+
*/
88+
Relation
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 ||
120+
CheckRelationLockedByMe(r, AccessShareLock, true));
121+
122+
/* Make note that we've accessed a temporary relation */
123+
if (RelationUsesLocalBuffers(r))
124+
MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL;
125+
126+
pgstat_initstats(r);
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)
154+
AcceptInvalidationMessages();
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)
183+
AcceptInvalidationMessages();
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+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy