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
This commit is contained in:
parent
f1ad067fc3
commit
4b21acf522
|
@ -9,6 +9,6 @@ top_builddir = ../../..
|
|||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
SUBDIRS = brin common gin gist hash heap index nbtree rmgrdesc spgist \
|
||||
tablesample transam
|
||||
table tablesample transam
|
||||
|
||||
include $(top_srcdir)/src/backend/common.mk
|
||||
|
|
|
@ -13,6 +13,6 @@ top_builddir = ../../../..
|
|||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = bufmask.o heaptuple.o indextuple.o printsimple.o printtup.o \
|
||||
reloptions.o scankey.o session.o tupconvert.o tupdesc.o
|
||||
relation.o reloptions.o scankey.o session.o tupconvert.o tupdesc.o
|
||||
|
||||
include $(top_srcdir)/src/backend/common.mk
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -12,12 +12,6 @@
|
|||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* relation_open - open any relation by relation OID
|
||||
* relation_openrv - open any relation specified by a RangeVar
|
||||
* relation_close - close any relation
|
||||
* heap_open - open a heap relation by relation OID
|
||||
* heap_openrv - open a heap relation specified by a RangeVar
|
||||
* heap_close - (now just a macro for relation_close)
|
||||
* heap_beginscan - begin relation scan
|
||||
* heap_rescan - restart a relation scan
|
||||
* heap_endscan - end relation scan
|
||||
|
@ -56,7 +50,6 @@
|
|||
#include "access/xloginsert.h"
|
||||
#include "access/xlogutils.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "miscadmin.h"
|
||||
#include "pgstat.h"
|
||||
#include "port/atomics.h"
|
||||
|
@ -73,7 +66,6 @@
|
|||
#include "utils/lsyscache.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
|
@ -1103,287 +1095,6 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
|
|||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------
|
||||
* heap_open - open a heap relation by relation OID
|
||||
*
|
||||
* This is essentially relation_open plus check that the relation
|
||||
* is not an index nor a composite type. (The caller should also
|
||||
* check that it's not a view or foreign table before assuming it has
|
||||
* storage.)
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
heap_open(Oid relationId, LOCKMODE lockmode)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
r = relation_open(relationId, lockmode);
|
||||
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX ||
|
||||
r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is an index",
|
||||
RelationGetRelationName(r))));
|
||||
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is a composite type",
|
||||
RelationGetRelationName(r))));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_openrv - open a heap relation specified
|
||||
* by a RangeVar node
|
||||
*
|
||||
* As above, but relation is specified by a RangeVar.
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
r = relation_openrv(relation, lockmode);
|
||||
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX ||
|
||||
r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is an index",
|
||||
RelationGetRelationName(r))));
|
||||
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is a composite type",
|
||||
RelationGetRelationName(r))));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_openrv_extended - open a heap relation specified
|
||||
* by a RangeVar node
|
||||
*
|
||||
* As above, but optionally return NULL instead of failing for
|
||||
* relation-not-found.
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
heap_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
|
||||
bool missing_ok)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
r = relation_openrv_extended(relation, lockmode, missing_ok);
|
||||
|
||||
if (r)
|
||||
{
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX ||
|
||||
r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is an index",
|
||||
RelationGetRelationName(r))));
|
||||
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is a composite type",
|
||||
RelationGetRelationName(r))));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------
|
||||
* heap_beginscan - begin relation scan
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile--
|
||||
# Makefile for access/table
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# src/backend/access/table/Makefile
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
subdir = src/backend/access/table
|
||||
top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = table.o
|
||||
|
||||
include $(top_srcdir)/src/backend/common.mk
|
|
@ -0,0 +1,136 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* table.c
|
||||
* Generic routines for table related code.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/backend/access/table/table.c
|
||||
*
|
||||
*
|
||||
* NOTES
|
||||
* This file contains table_ routines that implement access to tables (in
|
||||
* contrast to other relation types like indexes) that are independent of
|
||||
* individual table access methods.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/relation.h"
|
||||
#include "access/table.h"
|
||||
#include "storage/lmgr.h"
|
||||
|
||||
|
||||
/* ----------------
|
||||
* table_open - open a table relation by relation OID
|
||||
*
|
||||
* This is essentially relation_open plus check that the relation
|
||||
* is not an index nor a composite type. (The caller should also
|
||||
* check that it's not a view or foreign table before assuming it has
|
||||
* storage.)
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
table_open(Oid relationId, LOCKMODE lockmode)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
r = relation_open(relationId, lockmode);
|
||||
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX ||
|
||||
r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is an index",
|
||||
RelationGetRelationName(r))));
|
||||
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is a composite type",
|
||||
RelationGetRelationName(r))));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* table_openrv - open a table relation specified
|
||||
* by a RangeVar node
|
||||
*
|
||||
* As above, but relation is specified by a RangeVar.
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
table_openrv(const RangeVar *relation, LOCKMODE lockmode)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
r = relation_openrv(relation, lockmode);
|
||||
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX ||
|
||||
r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is an index",
|
||||
RelationGetRelationName(r))));
|
||||
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is a composite type",
|
||||
RelationGetRelationName(r))));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* table_openrv_extended - open a table relation specified
|
||||
* by a RangeVar node
|
||||
*
|
||||
* As above, but optionally return NULL instead of failing for
|
||||
* relation-not-found.
|
||||
* ----------------
|
||||
*/
|
||||
Relation
|
||||
table_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
|
||||
bool missing_ok)
|
||||
{
|
||||
Relation r;
|
||||
|
||||
r = relation_openrv_extended(relation, lockmode, missing_ok);
|
||||
|
||||
if (r)
|
||||
{
|
||||
if (r->rd_rel->relkind == RELKIND_INDEX ||
|
||||
r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is an index",
|
||||
RelationGetRelationName(r))));
|
||||
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is a composite type",
|
||||
RelationGetRelationName(r))));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* table_close - close a table
|
||||
*
|
||||
* 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
|
||||
table_close(Relation relation, LOCKMODE lockmode)
|
||||
{
|
||||
relation_close(relation, lockmode);
|
||||
}
|
|
@ -14,8 +14,10 @@
|
|||
#ifndef HEAPAM_H
|
||||
#define HEAPAM_H
|
||||
|
||||
#include "access/relation.h" /* for backward compatibility */
|
||||
#include "access/sdir.h"
|
||||
#include "access/skey.h"
|
||||
#include "access/table.h" /* for backward compatibility */
|
||||
#include "nodes/lockoptions.h"
|
||||
#include "nodes/primnodes.h"
|
||||
#include "storage/bufpage.h"
|
||||
|
@ -67,20 +69,6 @@ typedef struct HeapUpdateFailureData
|
|||
* ----------------
|
||||
*/
|
||||
|
||||
/* in heap/heapam.c */
|
||||
extern Relation relation_open(Oid relationId, LOCKMODE lockmode);
|
||||
extern Relation try_relation_open(Oid relationId, LOCKMODE lockmode);
|
||||
extern Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode);
|
||||
extern Relation relation_openrv_extended(const RangeVar *relation,
|
||||
LOCKMODE lockmode, bool missing_ok);
|
||||
extern void relation_close(Relation relation, LOCKMODE lockmode);
|
||||
|
||||
extern Relation heap_open(Oid relationId, LOCKMODE lockmode);
|
||||
extern Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode);
|
||||
extern Relation heap_openrv_extended(const RangeVar *relation,
|
||||
LOCKMODE lockmode, bool missing_ok);
|
||||
|
||||
#define heap_close(r,l) relation_close(r,l)
|
||||
|
||||
/* struct definitions appear in relscan.h */
|
||||
typedef struct HeapScanDescData *HeapScanDesc;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* relation.h
|
||||
* Generic relation related routines.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* src/include/access/relation.h
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef ACCESS_RELATION_H
|
||||
#define ACCESS_RELATION_H
|
||||
|
||||
#include "nodes/primnodes.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "storage/lockdefs.h"
|
||||
|
||||
|
||||
extern Relation relation_open(Oid relationId, LOCKMODE lockmode);
|
||||
extern Relation try_relation_open(Oid relationId, LOCKMODE lockmode);
|
||||
extern Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode);
|
||||
extern Relation relation_openrv_extended(const RangeVar *relation,
|
||||
LOCKMODE lockmode, bool missing_ok);
|
||||
extern void relation_close(Relation relation, LOCKMODE lockmode);
|
||||
|
||||
#endif /* ACCESS_RELATION_H */
|
|
@ -0,0 +1,38 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* table.h
|
||||
* Generic routines for table related code.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* src/include/access/table.h
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef TABLE_H
|
||||
#define TABLE_H
|
||||
|
||||
#include "nodes/primnodes.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "storage/lockdefs.h"
|
||||
|
||||
|
||||
extern Relation table_open(Oid relationId, LOCKMODE lockmode);
|
||||
extern Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode);
|
||||
extern Relation table_openrv_extended(const RangeVar *relation,
|
||||
LOCKMODE lockmode, bool missing_ok);
|
||||
extern void table_close(Relation relation, LOCKMODE lockmode);
|
||||
|
||||
/*
|
||||
* heap_ used to be the prefix for these routines, and a lot of code will just
|
||||
* continue to work without adaptions after the introduction of pluggable
|
||||
* storage, therefore just map these names.
|
||||
*/
|
||||
#define heap_open(r, l) table_open(r, l)
|
||||
#define heap_openrv(r, l) table_openrv(r, l)
|
||||
#define heap_openrv_extended(r, l, m) table_openrv_extended(r, l, m)
|
||||
#define heap_close(r, l) table_close(r, l)
|
||||
|
||||
#endif /* TABLE_H */
|
Loading…
Reference in New Issue