summaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/heap/Makefile4
-rw-r--r--src/backend/access/heap/heapam.c160
-rw-r--r--src/backend/access/heap/stats.c333
-rw-r--r--src/backend/access/index/indexam.c40
4 files changed, 99 insertions, 438 deletions
diff --git a/src/backend/access/heap/Makefile b/src/backend/access/heap/Makefile
index 95575f8e32..352ced3392 100644
--- a/src/backend/access/heap/Makefile
+++ b/src/backend/access/heap/Makefile
@@ -4,7 +4,7 @@
# Makefile for access/heap
#
# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/backend/access/heap/Makefile,v 1.11 2000/08/31 16:09:33 petere Exp $
+# $Header: /cvsroot/pgsql/src/backend/access/heap/Makefile,v 1.12 2001/11/02 16:30:29 tgl Exp $
#
#-------------------------------------------------------------------------
@@ -12,7 +12,7 @@ subdir = src/backend/access/heap
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
-OBJS = heapam.o hio.o stats.o tuptoaster.o
+OBJS = heapam.o hio.o tuptoaster.o
all: SUBSYS.o
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index f73ca50285..bf7798a07d 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");
diff --git a/src/backend/access/heap/stats.c b/src/backend/access/heap/stats.c
deleted file mode 100644
index 6f5dfbea14..0000000000
--- a/src/backend/access/heap/stats.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * stats.c
- * heap access method debugging statistic collection routines
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/heap/Attic/stats.c,v 1.25 2001/10/25 05:49:21 momjian Exp $
- *
- * NOTES
- * initam should be moved someplace else.
- *
- *-------------------------------------------------------------------------
- */
-
-#include <time.h>
-
-#include "postgres.h"
-
-#include "access/heapam.h"
-
-
-static void InitHeapAccessStatistics(void);
-
-/* ----------------
- * InitHeapAccessStatistics
- * ----------------
- */
-HeapAccessStatistics heap_access_stats = (HeapAccessStatistics) NULL;
-
-static void
-InitHeapAccessStatistics()
-{
- MemoryContext oldContext;
- HeapAccessStatistics stats;
-
- /*
- * make sure we don't initialize things twice
- */
- if (heap_access_stats != NULL)
- return;
-
- /*
- * allocate statistics structure from the top memory context
- */
- oldContext = MemoryContextSwitchTo(TopMemoryContext);
-
- stats = (HeapAccessStatistics)
- palloc(sizeof(HeapAccessStatisticsData));
-
- /*
- * initialize fields to default values
- */
- stats->global_open = 0;
- stats->global_openr = 0;
- stats->global_close = 0;
- stats->global_beginscan = 0;
- stats->global_rescan = 0;
- stats->global_endscan = 0;
- stats->global_getnext = 0;
- stats->global_fetch = 0;
- stats->global_insert = 0;
- stats->global_delete = 0;
- stats->global_replace = 0;
- stats->global_mark4update = 0;
- stats->global_markpos = 0;
- stats->global_restrpos = 0;
- stats->global_BufferGetRelation = 0;
- stats->global_RelationIdGetRelation = 0;
- stats->global_RelationIdGetRelation_Buf = 0;
- stats->global_getreldesc = 0;
- stats->global_heapgettup = 0;
- stats->global_RelationPutHeapTuple = 0;
- stats->global_RelationPutLongHeapTuple = 0;
-
- stats->local_open = 0;
- stats->local_openr = 0;
- stats->local_close = 0;
- stats->local_beginscan = 0;
- stats->local_rescan = 0;
- stats->local_endscan = 0;
- stats->local_getnext = 0;
- stats->local_fetch = 0;
- stats->local_insert = 0;
- stats->local_delete = 0;
- stats->local_replace = 0;
- stats->local_mark4update = 0;
- stats->local_markpos = 0;
- stats->local_restrpos = 0;
- stats->local_BufferGetRelation = 0;
- stats->local_RelationIdGetRelation = 0;
- stats->local_RelationIdGetRelation_Buf = 0;
- stats->local_getreldesc = 0;
- stats->local_heapgettup = 0;
- stats->local_RelationPutHeapTuple = 0;
- stats->local_RelationPutLongHeapTuple = 0;
- stats->local_RelationNameGetRelation = 0;
- stats->global_RelationNameGetRelation = 0;
-
- /*
- * record init times
- */
- time(&stats->init_global_timestamp);
- time(&stats->local_reset_timestamp);
- time(&stats->last_request_timestamp);
-
- /*
- * return to old memory context
- */
- MemoryContextSwitchTo(oldContext);
-
- heap_access_stats = stats;
-}
-
-#ifdef NOT_USED
-/* ----------------
- * ResetHeapAccessStatistics
- * ----------------
- */
-void
-ResetHeapAccessStatistics()
-{
- HeapAccessStatistics stats;
-
- /*
- * do nothing if stats aren't initialized
- */
- if (heap_access_stats == NULL)
- return;
-
- stats = heap_access_stats;
-
- /*
- * reset local counts
- */
- stats->local_open = 0;
- stats->local_openr = 0;
- stats->local_close = 0;
- stats->local_beginscan = 0;
- stats->local_rescan = 0;
- stats->local_endscan = 0;
- stats->local_getnext = 0;
- stats->local_fetch = 0;
- stats->local_insert = 0;
- stats->local_delete = 0;
- stats->local_replace = 0;
- stats->local_mark4update = 0;
- stats->local_markpos = 0;
- stats->local_restrpos = 0;
- stats->local_BufferGetRelation = 0;
- stats->local_RelationIdGetRelation = 0;
- stats->local_RelationIdGetRelation_Buf = 0;
- stats->local_getreldesc = 0;
- stats->local_heapgettup = 0;
- stats->local_RelationPutHeapTuple = 0;
- stats->local_RelationPutLongHeapTuple = 0;
-
- /*
- * reset local timestamps
- */
- time(&stats->local_reset_timestamp);
- time(&stats->last_request_timestamp);
-}
-#endif
-
-#ifdef NOT_USED
-/* ----------------
- * GetHeapAccessStatistics
- * ----------------
- */
-HeapAccessStatistics
-GetHeapAccessStatistics()
-{
- HeapAccessStatistics stats;
-
- /*
- * return nothing if stats aren't initialized
- */
- if (heap_access_stats == NULL)
- return NULL;
-
- /*
- * record the current request time
- */
- time(&heap_access_stats->last_request_timestamp);
-
- /*
- * allocate a copy of the stats and return it to the caller.
- */
- stats = (HeapAccessStatistics)
- palloc(sizeof(HeapAccessStatisticsData));
-
- memmove(stats,
- heap_access_stats,
- sizeof(HeapAccessStatisticsData));
-
- return stats;
-}
-#endif
-
-#ifdef NOT_USED
-/* ----------------
- * PrintHeapAccessStatistics
- * ----------------
- */
-void
-PrintHeapAccessStatistics(HeapAccessStatistics stats)
-{
- /*
- * return nothing if stats aren't valid
- */
- if (stats == NULL)
- return;
-
- printf("======== heap am statistics ========\n");
- printf("init_global_timestamp: %s",
- ctime(&(stats->init_global_timestamp)));
-
- printf("local_reset_timestamp: %s",
- ctime(&(stats->local_reset_timestamp)));
-
- printf("last_request_timestamp: %s",
- ctime(&(stats->last_request_timestamp)));
-
- printf("local/global_open: %6d/%6d\n",
- stats->local_open, stats->global_open);
-
- printf("local/global_openr: %6d/%6d\n",
- stats->local_openr, stats->global_openr);
-
- printf("local/global_close: %6d/%6d\n",
- stats->local_close, stats->global_close);
-
- printf("local/global_beginscan: %6d/%6d\n",
- stats->local_beginscan, stats->global_beginscan);
-
- printf("local/global_rescan: %6d/%6d\n",
- stats->local_rescan, stats->global_rescan);
-
- printf("local/global_endscan: %6d/%6d\n",
- stats->local_endscan, stats->global_endscan);
-
- printf("local/global_getnext: %6d/%6d\n",
- stats->local_getnext, stats->global_getnext);
-
- printf("local/global_fetch: %6d/%6d\n",
- stats->local_fetch, stats->global_fetch);
-
- printf("local/global_insert: %6d/%6d\n",
- stats->local_insert, stats->global_insert);
-
- printf("local/global_delete: %6d/%6d\n",
- stats->local_delete, stats->global_delete);
-
- printf("local/global_replace: %6d/%6d\n",
- stats->local_replace, stats->global_replace);
-
- printf("local/global_mark4update: %6d/%6d\n",
- stats->local_mark4update, stats->global_mark4update);
-
- printf("local/global_markpos: %6d/%6d\n",
- stats->local_markpos, stats->global_markpos);
-
- printf("local/global_restrpos: %6d/%6d\n",
- stats->local_restrpos, stats->global_restrpos);
-
- printf("================\n");
-
- printf("local/global_BufferGetRelation: %6d/%6d\n",
- stats->local_BufferGetRelation,
- stats->global_BufferGetRelation);
-
- printf("local/global_RelationIdGetRelation: %6d/%6d\n",
- stats->local_RelationIdGetRelation,
- stats->global_RelationIdGetRelation);
-
- printf("local/global_RelationIdGetRelation_Buf: %6d/%6d\n",
- stats->local_RelationIdGetRelation_Buf,
- stats->global_RelationIdGetRelation_Buf);
-
- printf("local/global_getreldesc: %6d/%6d\n",
- stats->local_getreldesc, stats->global_getreldesc);
-
- printf("local/global_heapgettup: %6d/%6d\n",
- stats->local_heapgettup, stats->global_heapgettup);
-
- printf("local/global_RelationPutHeapTuple: %6d/%6d\n",
- stats->local_RelationPutHeapTuple,
- stats->global_RelationPutHeapTuple);
-
- printf("local/global_RelationPutLongHeapTuple: %6d/%6d\n",
- stats->local_RelationPutLongHeapTuple,
- stats->global_RelationPutLongHeapTuple);
-
- printf("===================================\n");
-
- printf("\n");
-}
-#endif
-
-#ifdef NOT_USED
-/* ----------------
- * PrintAndFreeHeapAccessStatistics
- * ----------------
- */
-void
-PrintAndFreeHeapAccessStatistics(HeapAccessStatistics stats)
-{
- PrintHeapAccessStatistics(stats);
- if (stats != NULL)
- pfree(stats);
-}
-#endif
-
-/* ----------------------------------------------------------------
- * access method initialization
- * ----------------------------------------------------------------
- */
-/* ----------------
- * initam should someday be moved someplace else.
- * ----------------
- */
-void
-initam(void)
-{
- /*
- * initialize heap statistics.
- */
- InitHeapAccessStatistics();
-}
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 8e1d5b8733..523349ebdb 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -8,12 +8,12 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.54 2001/10/25 05:49:21 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.55 2001/11/02 16:30:29 tgl Exp $
*
* INTERFACE ROUTINES
- * index_open - open an index relation by relationId
- * index_openr - open a index relation by name
- * index_close - close a index relation
+ * index_open - open an index relation by relation OID
+ * index_openr - open an index relation by name
+ * index_close - close an index relation
* index_beginscan - start a scan of an index
* index_rescan - restart a scan of an index
* index_endscan - end a scan
@@ -106,15 +106,17 @@
* index_ interface functions
* ----------------------------------------------------------------
*/
+
/* ----------------
- * index_open - open an index relation by relationId
- *
- * presently the relcache routines do all the work we need
- * to open/close index relations. However, callers of index_open
- * expect it to succeed, so we need to check for a failure return.
+ * index_open - open an index relation by relation OID
*
* Note: we acquire no lock on the index. An AccessShareLock is
* acquired by index_beginscan (and released by index_endscan).
+ * Generally, the caller should already hold some type of lock on
+ * the parent relation to ensure that the index doesn't disappear.
+ *
+ * This is a convenience routine adapted for indexscan use.
+ * Some callers may prefer to use relation_open directly.
* ----------------
*/
Relation
@@ -122,13 +124,11 @@ index_open(Oid relationId)
{
Relation r;
- r = RelationIdGetRelation(relationId);
-
- if (!RelationIsValid(r))
- elog(ERROR, "Index %u does not exist", relationId);
+ r = relation_open(relationId, NoLock);
if (r->rd_rel->relkind != RELKIND_INDEX)
- elog(ERROR, "%s is not an index relation", RelationGetRelationName(r));
+ elog(ERROR, "%s is not an index relation",
+ RelationGetRelationName(r));
pgstat_initstats(&r->pgstat_info, r);
@@ -136,23 +136,21 @@ index_open(Oid relationId)
}
/* ----------------
- * index_openr - open a index relation by name
+ * index_openr - open an index relation by name
*
* As above, but lookup by name instead of OID.
* ----------------
*/
Relation
-index_openr(char *relationName)
+index_openr(const char *relationName)
{
Relation r;
- r = RelationNameGetRelation(relationName);
-
- if (!RelationIsValid(r))
- elog(ERROR, "Index '%s' does not exist", relationName);
+ r = relation_openr(relationName, NoLock);
if (r->rd_rel->relkind != RELKIND_INDEX)
- elog(ERROR, "%s is not an index relation", RelationGetRelationName(r));
+ elog(ERROR, "%s is not an index relation",
+ RelationGetRelationName(r));
pgstat_initstats(&r->pgstat_info, r);