greenplumn relation 源码
greenplumn relation 代码
文件路径:/src/backend/access/common/relation.c
/*-------------------------------------------------------------------------
*
* 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);
/* GPDB_12_AFTER_MERGE_FIXME: We had added the errdetail in GPDB. Is it still valid? */
if (!RelationIsValid(r))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("could not open relation with OID %u", relationId),
errdetail("This can be validly caused by a concurrent delete operation on this object.")));
/*
* 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));
#if 0 /* Upstream code not applicable to GPDB */
/* Make note that we've accessed a temporary relation */
if (RelationUsesLocalBuffers(r))
MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
#endif
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, bool noWait)
{
Relation r;
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
/* Get the lock first */
if (lockmode != NoLock)
{
if (!noWait)
LockRelationOid(relationId, lockmode);
else
{
/*
* noWait is a Greenplum addition to the open_relation code
* basically to support INSERT ... FOR UPDATE NOWAIT. Our NoWait
* handling needs to be more tolerant of failed locks than standard
* postgres largely due to the fact that we have to promote certain
* update locks in order to handle distributed updates.
*/
if (!ConditionalLockRelationOid(relationId, lockmode))
return NULL;
}
}
/*
* 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))
{
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("could not open relation with OID %u", relationId),
errdetail("This can be validly caused by a concurrent delete operation on this object.")));
}
/* If we didn't get the lock ourselves, assert that caller holds one */
Assert(lockmode != NoLock ||
CheckRelationLockedByMe(r, AccessShareLock, true));
#if 0 /* Upstream code not applicable to GPDB */
/* Make note that we've accessed a temporary relation */
if (RelationUsesLocalBuffers(r))
MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
#endif
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 try_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);
else
{
LOCKTAG tag;
SET_LOCKTAG_RELATION(tag, relid.dbId, relid.relId);
/*
* Closing with NoLock is a sufficient condition for a relation lock
* to be transaction-level(means the lock can only be released after
* the holding transaction is over).
* This is because the difference betwwen the ref counts in the
* relation and the lock tag can not be removed.
* So this is a good time to set the holdTillEndXact flag for the lock.
*/
LockSetHoldTillEndXact(&tag);
}
}
相关信息
相关文章
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦