forked from apache/cloudberry
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce access/{table.h, relation.h}, for generic functions from he…
…apam.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
- Loading branch information
Showing
9 changed files
with
441 additions
and
305 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
/*------------------------------------------------------------------------- | ||
* | ||
* relation.c | ||
* Generic relation related routines. | ||
* | ||
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group | ||
* Portions Copyright (c) 1994, Regents of the University of California | ||
* | ||
* | ||
* IDENTIFICATION | ||
* src/backend/access/common/relation.c | ||
* | ||
* NOTES | ||
* This file contains relation_ routines that implement access to relations | ||
* (tables, indexes, etc). Support that's specific to subtypes of relations | ||
* should go into their respective files, not here. | ||
* | ||
*------------------------------------------------------------------------- | ||
*/ | ||
|
||
#include "postgres.h" | ||
|
||
#include "access/relation.h" | ||
#include "access/xact.h" | ||
#include "catalog/namespace.h" | ||
#include "miscadmin.h" | ||
#include "pgstat.h" | ||
#include "storage/lmgr.h" | ||
#include "utils/inval.h" | ||
#include "utils/syscache.h" | ||
|
||
|
||
/* ---------------- | ||
* relation_open - open any relation by relation OID | ||
* | ||
* If lockmode is not "NoLock", the specified kind of lock is | ||
* obtained on the relation. (Generally, NoLock should only be | ||
* used if the caller knows it has some appropriate lock on the | ||
* relation already.) | ||
* | ||
* An error is raised if the relation does not exist. | ||
* | ||
* NB: a "relation" is anything with a pg_class entry. The caller is | ||
* expected to check whether the relkind is something it can handle. | ||
* ---------------- | ||
*/ | ||
Relation | ||
relation_open(Oid relationId, LOCKMODE lockmode) | ||
{ | ||
Relation r; | ||
|
||
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); | ||
|
||
/* Get the lock before trying to open the relcache entry */ | ||
if (lockmode != NoLock) | ||
LockRelationOid(relationId, lockmode); | ||
|
||
/* The relcache does all the real work... */ | ||
r = RelationIdGetRelation(relationId); | ||
|
||
if (!RelationIsValid(r)) | ||
elog(ERROR, "could not open relation with OID %u", relationId); | ||
|
||
/* | ||
* If we didn't get the lock ourselves, assert that caller holds one, | ||
* except in bootstrap mode where no locks are used. | ||
*/ | ||
Assert(lockmode != NoLock || | ||
IsBootstrapProcessingMode() || | ||
CheckRelationLockedByMe(r, AccessShareLock, true)); | ||
|
||
/* Make note that we've accessed a temporary relation */ | ||
if (RelationUsesLocalBuffers(r)) | ||
MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL; | ||
|
||
pgstat_initstats(r); | ||
|
||
return r; | ||
} | ||
|
||
/* ---------------- | ||
* try_relation_open - open any relation by relation OID | ||
* | ||
* Same as relation_open, except return NULL instead of failing | ||
* if the relation does not exist. | ||
* ---------------- | ||
*/ | ||
Relation | ||
try_relation_open(Oid relationId, LOCKMODE lockmode) | ||
{ | ||
Relation r; | ||
|
||
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); | ||
|
||
/* Get the lock first */ | ||
if (lockmode != NoLock) | ||
LockRelationOid(relationId, lockmode); | ||
|
||
/* | ||
* Now that we have the lock, probe to see if the relation really exists | ||
* or not. | ||
*/ | ||
if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId))) | ||
{ | ||
/* Release useless lock */ | ||
if (lockmode != NoLock) | ||
UnlockRelationOid(relationId, lockmode); | ||
|
||
return NULL; | ||
} | ||
|
||
/* Should be safe to do a relcache load */ | ||
r = RelationIdGetRelation(relationId); | ||
|
||
if (!RelationIsValid(r)) | ||
elog(ERROR, "could not open relation with OID %u", relationId); | ||
|
||
/* If we didn't get the lock ourselves, assert that caller holds one */ | ||
Assert(lockmode != NoLock || | ||
CheckRelationLockedByMe(r, AccessShareLock, true)); | ||
|
||
/* Make note that we've accessed a temporary relation */ | ||
if (RelationUsesLocalBuffers(r)) | ||
MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL; | ||
|
||
pgstat_initstats(r); | ||
|
||
return r; | ||
} | ||
|
||
/* ---------------- | ||
* relation_openrv - open any relation specified by a RangeVar | ||
* | ||
* Same as relation_open, but the relation is specified by a RangeVar. | ||
* ---------------- | ||
*/ | ||
Relation | ||
relation_openrv(const RangeVar *relation, LOCKMODE lockmode) | ||
{ | ||
Oid relOid; | ||
|
||
/* | ||
* Check for shared-cache-inval messages before trying to open the | ||
* relation. This is needed even if we already hold a lock on the | ||
* relation, because GRANT/REVOKE are executed without taking any lock on | ||
* the target relation, and we want to be sure we see current ACL | ||
* information. We can skip this if asked for NoLock, on the assumption | ||
* that such a call is not the first one in the current command, and so we | ||
* should be reasonably up-to-date already. (XXX this all could stand to | ||
* be redesigned, but for the moment we'll keep doing this like it's been | ||
* done historically.) | ||
*/ | ||
if (lockmode != NoLock) | ||
AcceptInvalidationMessages(); | ||
|
||
/* Look up and lock the appropriate relation using namespace search */ | ||
relOid = RangeVarGetRelid(relation, lockmode, false); | ||
|
||
/* Let relation_open do the rest */ | ||
return relation_open(relOid, NoLock); | ||
} | ||
|
||
/* ---------------- | ||
* relation_openrv_extended - open any relation specified by a RangeVar | ||
* | ||
* Same as relation_openrv, but with an additional missing_ok argument | ||
* allowing a NULL return rather than an error if the relation is not | ||
* found. (Note that some other causes, such as permissions problems, | ||
* will still result in an ereport.) | ||
* ---------------- | ||
*/ | ||
Relation | ||
relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, | ||
bool missing_ok) | ||
{ | ||
Oid relOid; | ||
|
||
/* | ||
* Check for shared-cache-inval messages before trying to open the | ||
* relation. See comments in relation_openrv(). | ||
*/ | ||
if (lockmode != NoLock) | ||
AcceptInvalidationMessages(); | ||
|
||
/* Look up and lock the appropriate relation using namespace search */ | ||
relOid = RangeVarGetRelid(relation, lockmode, missing_ok); | ||
|
||
/* Return NULL on not-found */ | ||
if (!OidIsValid(relOid)) | ||
return NULL; | ||
|
||
/* Let relation_open do the rest */ | ||
return relation_open(relOid, NoLock); | ||
} | ||
|
||
/* ---------------- | ||
* relation_close - close any relation | ||
* | ||
* If lockmode is not "NoLock", we then release the specified lock. | ||
* | ||
* Note that it is often sensible to hold a lock beyond relation_close; | ||
* in that case, the lock is released automatically at xact end. | ||
* ---------------- | ||
*/ | ||
void | ||
relation_close(Relation relation, LOCKMODE lockmode) | ||
{ | ||
LockRelId relid = relation->rd_lockInfo.lockRelId; | ||
|
||
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); | ||
|
||
/* The relcache does the real work... */ | ||
RelationClose(relation); | ||
|
||
if (lockmode != NoLock) | ||
UnlockRelationId(&relid, lockmode); | ||
} |
Oops, something went wrong.