summaryrefslogtreecommitdiff
path: root/src/backend/access/heap/heapam.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/heap/heapam.c')
-rw-r--r--src/backend/access/heap/heapam.c160
1 files changed, 78 insertions, 82 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index f73ca50285b..bf7798a07dc 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,14 +8,16 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.126 2001/10/25 05:49:21 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.127 2001/11/02 16:30:29 tgl Exp $
*
*
* INTERFACE ROUTINES
- * heap_open - open a heap relation by relationId
+ * relation_open - open any relation by relation OID
+ * relation_openr - open any relation by name
+ * relation_close - close any relation
+ * heap_open - open a heap relation by relation OID
* heap_openr - open a heap relation by name
- * heap_open[r]_nofail - same, but return NULL on failure instead of elog
- * heap_close - close a heap relation
+ * 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
@@ -440,15 +442,21 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
*/
/* ----------------
- * heap_open - open a heap relation by relationId
+ * relation_open - open any relation by relation OID
*
* If lockmode is not "NoLock", the specified kind of lock is
- * obtained on the relation.
+ * 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
-heap_open(Oid relationId, LOCKMODE lockmode)
+relation_open(Oid relationId, LOCKMODE lockmode)
{
Relation r;
@@ -466,10 +474,6 @@ heap_open(Oid relationId, LOCKMODE lockmode)
if (!RelationIsValid(r))
elog(ERROR, "Relation %u does not exist", relationId);
- /* Under no circumstances will we return an index as a relation. */
- if (r->rd_rel->relkind == RELKIND_INDEX)
- elog(ERROR, "%s is an index relation", RelationGetRelationName(r));
-
if (lockmode != NoLock)
LockRelation(r, lockmode);
@@ -477,15 +481,13 @@ heap_open(Oid relationId, LOCKMODE lockmode)
}
/* ----------------
- * heap_openr - open a heap relation by name
+ * relation_openr - open any relation by name
*
- * If lockmode is not "NoLock", the specified kind of lock is
- * obtained on the relation.
- * An error is raised if the relation does not exist.
+ * As above, but lookup by name instead of OID.
* ----------------
*/
Relation
-heap_openr(const char *relationName, LOCKMODE lockmode)
+relation_openr(const char *relationName, LOCKMODE lockmode)
{
Relation r;
@@ -497,116 +499,111 @@ heap_openr(const char *relationName, LOCKMODE lockmode)
IncrHeapAccessStat(local_openr);
IncrHeapAccessStat(global_openr);
+ /*
+ * Check for shared-cache-inval messages before trying to open the
+ * relation. This is needed to cover the case where the name identifies
+ * a rel that has been dropped and recreated since the start of our
+ * transaction: if we don't flush the old relcache entry then we'll
+ * latch onto that entry and suffer an error when we do LockRelation.
+ * Note that relation_open does not need to do this, since a relation's
+ * OID never changes.
+ *
+ * We skip this if asked for NoLock, on the assumption that the caller
+ * has already ensured some appropriate lock is held.
+ */
+ if (lockmode != NoLock)
+ AcceptInvalidationMessages();
+
/* The relcache does all the real work... */
r = RelationNameGetRelation(relationName);
if (!RelationIsValid(r))
- elog(ERROR, "Relation '%s' does not exist", relationName);
-
- /* Under no circumstances will we return an index as a relation. */
- if (r->rd_rel->relkind == RELKIND_INDEX)
- elog(ERROR, "%s is an index relation", RelationGetRelationName(r));
+ elog(ERROR, "Relation \"%s\" does not exist", relationName);
if (lockmode != NoLock)
LockRelation(r, lockmode);
- pgstat_initstats(&r->pgstat_info, r);
-
- pgstat_initstats(&r->pgstat_info, r);
-
return r;
}
/* ----------------
- * heap_open_nofail - open a heap relation by relationId,
- * do not raise error on failure
+ * relation_close - close any relation
+ *
+ * If lockmode is not "NoLock", we first release the specified lock.
*
- * The caller must check for a NULL return value indicating
- * that no such relation exists.
- * No lock is obtained on the relation, either.
+ * Note that it is often sensible to hold a lock beyond relation_close;
+ * in that case, the lock is released automatically at xact end.
* ----------------
*/
-Relation
-heap_open_nofail(Oid relationId)
+void
+relation_close(Relation relation, LOCKMODE lockmode)
{
- Relation r;
+ Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
/*
* increment access statistics
*/
- IncrHeapAccessStat(local_open);
- IncrHeapAccessStat(global_open);
-
- /* The relcache does all the real work... */
- r = RelationIdGetRelation(relationId);
+ IncrHeapAccessStat(local_close);
+ IncrHeapAccessStat(global_close);
- /* Under no circumstances will we return an index as a relation. */
- if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
- elog(ERROR, "%s is an index relation", RelationGetRelationName(r));
+ if (lockmode != NoLock)
+ UnlockRelation(relation, lockmode);
- return r;
+ /* The relcache does the real work... */
+ RelationClose(relation);
}
+
/* ----------------
- * heap_openr_nofail - open a heap relation by name,
- * do not raise error on failure
+ * heap_open - open a heap relation by relation OID
*
- * The caller must check for a NULL return value indicating
- * that no such relation exists.
- * No lock is obtained on the relation, either.
+ * This is essentially relation_open plus check that the relation
+ * is not an index or special relation. (The caller should also check
+ * that it's not a view before assuming it has storage.)
* ----------------
*/
Relation
-heap_openr_nofail(const char *relationName)
+heap_open(Oid relationId, LOCKMODE lockmode)
{
Relation r;
- /*
- * increment access statistics
- */
- IncrHeapAccessStat(local_openr);
- IncrHeapAccessStat(global_openr);
+ r = relation_open(relationId, lockmode);
- /* The relcache does all the real work... */
- r = RelationNameGetRelation(relationName);
-
- /* Under no circumstances will we return an index as a relation. */
- if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
- elog(ERROR, "%s is an index relation", RelationGetRelationName(r));
-
- if (RelationIsValid(r))
- pgstat_initstats(&r->pgstat_info, r);
+ if (r->rd_rel->relkind == RELKIND_INDEX)
+ elog(ERROR, "%s is an index relation",
+ RelationGetRelationName(r));
+ else if (r->rd_rel->relkind == RELKIND_SPECIAL)
+ elog(ERROR, "%s is a special relation",
+ RelationGetRelationName(r));
- if (RelationIsValid(r))
- pgstat_initstats(&r->pgstat_info, r);
+ pgstat_initstats(&r->pgstat_info, r);
return r;
}
/* ----------------
- * heap_close - close a heap relation
+ * heap_openr - open a heap relation by name
*
- * If lockmode is not "NoLock", we first release the specified lock.
- * Note that it is often sensible to hold a lock beyond heap_close;
- * in that case, the lock is released automatically at xact end.
+ * As above, but lookup by name instead of OID.
* ----------------
*/
-void
-heap_close(Relation relation, LOCKMODE lockmode)
+Relation
+heap_openr(const char *relationName, LOCKMODE lockmode)
{
- Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+ Relation r;
- /*
- * increment access statistics
- */
- IncrHeapAccessStat(local_close);
- IncrHeapAccessStat(global_close);
+ r = relation_openr(relationName, lockmode);
- if (lockmode != NoLock)
- UnlockRelation(relation, lockmode);
+ if (r->rd_rel->relkind == RELKIND_INDEX)
+ elog(ERROR, "%s is an index relation",
+ RelationGetRelationName(r));
+ else if (r->rd_rel->relkind == RELKIND_SPECIAL)
+ elog(ERROR, "%s is a special relation",
+ RelationGetRelationName(r));
- /* The relcache does the real work... */
- RelationClose(relation);
+ pgstat_initstats(&r->pgstat_info, r);
+
+ return r;
}
@@ -2332,8 +2329,7 @@ newsame:;
}
/* undo */
- if (XLByteLT(PageGetLSN(page), lsn)) /* changes are not applied
- * ?! */
+ if (XLByteLT(PageGetLSN(page), lsn)) /* changes not applied?! */
elog(STOP, "heap_update_undo: bad new tuple page LSN");
elog(STOP, "heap_update_undo: unimplemented");