OSDN Git Service

Fix problem reported by Alex Korn: if a relation has been dropped and
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 2 Nov 2001 16:30:29 +0000 (16:30 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 2 Nov 2001 16:30:29 +0000 (16:30 +0000)
recreated since the start of our transaction, our first reference to it
errored out because we'd try to reuse our old relcache entry for it.
Do this by accepting SI inval messages just before relcache search in
heap_openr, so that dead relcache entries will be flushed before we
search.  Also, break heap_open/openr into two pairs of routines,
relation_open(r) and heap_open(r).  The relation_open routines make
no tests on relkind and so can be used to open anything that has a
pg_class entry.  The heap_open routines are wrappers that add a relkind
test to preserve their established behavior.  Use the relation_open
routines in several places that had various kluge solutions for opening
rels that might be either heap or index rels.

Also, remove the old 'heap stats' code that's been superseded by Jan's
stats collector, and clean up some inconsistencies in error reporting
between the different types of ALTER TABLE.

14 files changed:
src/backend/access/heap/Makefile
src/backend/access/heap/heapam.c
src/backend/access/heap/stats.c [deleted file]
src/backend/access/index/indexam.c
src/backend/catalog/index.c
src/backend/commands/command.c
src/backend/commands/comment.c
src/backend/commands/rename.c
src/backend/parser/parse_func.c
src/backend/utils/init/postinit.c
src/include/access/genam.h
src/include/access/heapam.h
src/test/regress/expected/errors.out
src/test/regress/expected/temp.out

index 95575f8..352ced3 100644 (file)
@@ -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
 
index f73ca50..bf7798a 100644 (file)
@@ -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 (file)
index 6f5dfbe..0000000
+++ /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();
-}
index 8e1d5b8..523349e 100644 (file)
@@ -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
  *                                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);
 
index 4e338b0..b5c2551 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.167 2001/10/25 20:37:30 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.168 2001/11/02 16:30:29 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1417,15 +1417,9 @@ UpdateStats(Oid relid, double reltuples)
         */
 
        /*
-        * Can't use heap_open here since we don't know if it's an index...
+        * Grabbing lock here is probably redundant ...
         */
-       whichRel = RelationIdGetRelation(relid);
-
-       if (!RelationIsValid(whichRel))
-               elog(ERROR, "UpdateStats: cannot open relation id %u", relid);
-
-       /* Grab lock to be held till end of xact (probably redundant...) */
-       LockRelation(whichRel, ShareLock);
+       whichRel = relation_open(relid, ShareLock);
 
        /*
         * Find the RELATION relation tuple for the given relation.
@@ -1553,8 +1547,7 @@ UpdateStats(Oid relid, double reltuples)
                heap_endscan(pg_class_scan);
 
        heap_close(pg_class, RowExclusiveLock);
-       /* Cheating a little bit since we didn't open it with heap_open... */
-       heap_close(whichRel, NoLock);
+       relation_close(whichRel, NoLock);
 }
 
 
index b9cfee9..93c52e1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.148 2001/10/31 04:49:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.149 2001/11/02 16:30:29 tgl Exp $
  *
  * NOTES
  *       The PerformAddAttribute() code, like most of the relation
@@ -55,7 +55,6 @@
 
 static void drop_default(Oid relid, int16 attnum);
 static bool needs_toast_table(Relation rel);
-static bool is_relation(char *name);
 
 
 /* --------------------------------
@@ -554,9 +553,11 @@ AlterTableAlterColumnDefault(const char *relationName,
 #endif
 
        rel = heap_openr(relationName, AccessExclusiveLock);
+
        if (rel->rd_rel->relkind != RELKIND_RELATION)
                elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
                         relationName);
+
        myrelid = RelationGetRelid(rel);
        heap_close(rel, NoLock);
 
@@ -721,9 +722,11 @@ AlterTableAlterColumnStatistics(const char *relationName,
 #endif
 
        rel = heap_openr(relationName, AccessExclusiveLock);
+
        if (rel->rd_rel->relkind != RELKIND_RELATION)
                elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
                         relationName);
+
        myrelid = RelationGetRelid(rel);
        heap_close(rel, NoLock);        /* close rel, but keep lock! */
 
@@ -1192,12 +1195,16 @@ AlterTableAddConstraint(char *relationName,
                elog(ERROR, "ALTER TABLE: permission denied");
 #endif
 
-       /* Disallow ADD CONSTRAINT on views, indexes, sequences, etc */
-       if (!is_relation(relationName))
-               elog(ERROR, "ALTER TABLE ADD CONSTRAINT: %s is not a table",
+       /*
+        * Grab an exclusive lock on the target table, which we will NOT
+        * release until end of transaction.
+        */
+       rel = heap_openr(relationName, AccessExclusiveLock);
+
+       if (rel->rd_rel->relkind != RELKIND_RELATION)
+               elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
                         relationName);
 
-       rel = heap_openr(relationName, AccessExclusiveLock);
        myrelid = RelationGetRelid(rel);
 
        if (inh)
@@ -1686,7 +1693,7 @@ AlterTableDropConstraint(const char *relationName,
 
        /* Disallow DROP CONSTRAINT on views, indexes, sequences, etc */
        if (rel->rd_rel->relkind != RELKIND_RELATION)
-               elog(ERROR, "ALTER TABLE / DROP CONSTRAINT: %s is not a table",
+               elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
                         relationName);
 
        /*
@@ -2053,7 +2060,6 @@ void
 LockTableCommand(LockStmt *lockstmt)
 {
        List       *p;
-       Relation        rel;
 
        /*
         * Iterate over the list and open, lock, and close the relations one
@@ -2064,12 +2070,7 @@ LockTableCommand(LockStmt *lockstmt)
        {
                char       *relname = strVal(lfirst(p));
                int                     aclresult;
-
-               rel = heap_openr(relname, NoLock);
-
-               if (rel->rd_rel->relkind != RELKIND_RELATION)
-                       elog(ERROR, "LOCK TABLE: %s is not a table",
-                                relname);
+               Relation        rel;
 
                if (lockstmt->mode == AccessShareLock)
                        aclresult = pg_aclcheck(relname, GetUserId(),
@@ -2081,21 +2082,13 @@ LockTableCommand(LockStmt *lockstmt)
                if (aclresult != ACLCHECK_OK)
                        elog(ERROR, "LOCK TABLE: permission denied");
 
-               LockRelation(rel, lockstmt->mode);
-
-               heap_close(rel, NoLock);        /* close rel, keep lock */
-       }
-}
-
-
-static bool
-is_relation(char *name)
-{
-       Relation        rel = heap_openr(name, NoLock);
+               rel = relation_openr(relname, lockstmt->mode);
 
-       bool            retval = (rel->rd_rel->relkind == RELKIND_RELATION);
-
-       heap_close(rel, NoLock);
+               /* Currently, we only allow plain tables to be locked */
+               if (rel->rd_rel->relkind != RELKIND_RELATION)
+                       elog(ERROR, "LOCK TABLE: %s is not a table",
+                                relname);
 
-       return retval;
+               relation_close(rel, NoLock);    /* close rel, keep lock */
+       }
 }
index 647cb55..baeff0c 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.34 2001/10/25 05:49:24 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.35 2001/11/02 16:30:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -336,16 +336,8 @@ CommentRelation(int reltype, char *relname, char *comment)
         * ensures no one else drops the relation before we commit.  (If they
         * did, they'd fail to remove the entry we are about to make in
         * pg_description.)
-        *
-        * heap_openr will complain if it's an index, so we must do this:
         */
-       if (reltype != INDEX)
-               relation = heap_openr(relname, AccessShareLock);
-       else
-       {
-               relation = index_openr(relname);
-               LockRelation(relation, AccessShareLock);
-       }
+       relation = relation_openr(relname, AccessShareLock);
 
        /* Next, verify that the relation type matches the intent */
 
@@ -374,11 +366,7 @@ CommentRelation(int reltype, char *relname, char *comment)
        CreateComments(RelationGetRelid(relation), RelOid_pg_class, 0, comment);
 
        /* Done, but hold lock until commit */
-
-       if (reltype != INDEX)
-               heap_close(relation, NoLock);
-       else
-               index_close(relation);
+       relation_close(relation, NoLock);
 }
 
 /*------------------------------------------------------------------
index c65cfcc..42abe24 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.59 2001/10/25 05:49:25 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.60 2001/11/02 16:30:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -258,19 +258,10 @@ renamerel(const char *oldrelname, const char *newrelname)
                return;                                 /* all done... */
 
        /*
-        * Instead of using heap_openr(), do it the hard way, so that we can
-        * rename indexes as well as regular relations.
-        */
-       targetrelation = RelationNameGetRelation(oldrelname);
-
-       if (!RelationIsValid(targetrelation))
-               elog(ERROR, "Relation \"%s\" does not exist", oldrelname);
-
-       /*
-        * Grab an exclusive lock on the target table, which we will NOT
+        * Grab an exclusive lock on the target table or index, which we will NOT
         * release until end of transaction.
         */
-       LockRelation(targetrelation, AccessExclusiveLock);
+       targetrelation = relation_openr(oldrelname, AccessExclusiveLock);
 
        reloid = RelationGetRelid(targetrelation);
        relkind = targetrelation->rd_rel->relkind;
@@ -278,7 +269,7 @@ renamerel(const char *oldrelname, const char *newrelname)
        /*
         * Close rel, but keep exclusive lock!
         */
-       heap_close(targetrelation, NoLock);
+       relation_close(targetrelation, NoLock);
 
        /*
         * Flush the relcache entry (easier than trying to change it at
index f6d94e5..1f28870 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.112 2001/10/25 05:49:39 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.113 2001/11/02 16:30:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -131,7 +131,6 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
        List       *i = NIL;
        Node       *first_arg = NULL;
        char       *refname;
-       Relation        rd;
        int                     nargs = length(fargs);
        int                     argn;
        Func       *funcnode;
@@ -200,13 +199,10 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
                        if (attisset)
                        {
                                toid = exprType(first_arg);
-                               rd = heap_openr_nofail(typeidTypeName(toid));
-                               if (RelationIsValid(rd))
-                                       heap_close(rd, NoLock);
-                               else
+                               argrelid = typeidTypeRelid(toid);
+                               if (argrelid == InvalidOid)
                                        elog(ERROR, "Type '%s' is not a relation type",
                                                 typeidTypeName(toid));
-                               argrelid = typeidTypeRelid(toid);
 
                                /*
                                 * A projection must match an attribute name of the rel.
index 3dc6deb..3a48b13 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.96 2001/10/28 06:25:54 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.97 2001/11/02 16:30:29 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -293,12 +293,6 @@ InitPostgres(const char *dbname, const char *username)
        RelationCacheInitialize();
 
        /*
-        * Initialize the access methods. Does not touch files (?) - thomas
-        * 1997-11-01
-        */
-       initam();
-
-       /*
         * Initialize all the system catalog caches.
         *
         * Does not touch files since all routines are builtins (?) - thomas
index 88c1c06..dbef1a6 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: genam.h,v 1.29 2001/10/28 06:25:59 momjian Exp $
+ * $Id: genam.h,v 1.30 2001/11/02 16:30:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,7 +36,7 @@ typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state);
  * ----------------
  */
 extern Relation index_open(Oid relationId);
-extern Relation index_openr(char *relationName);
+extern Relation index_openr(const char *relationName);
 extern void index_close(Relation relation);
 extern InsertIndexResult index_insert(Relation relation,
                         Datum *datum, char *nulls,
index 61fa3af..b0124ed 100644 (file)
@@ -7,15 +7,13 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heapam.h,v 1.70 2001/10/28 06:25:59 momjian Exp $
+ * $Id: heapam.h,v 1.71 2001/11/02 16:30:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef HEAPAM_H
 #define HEAPAM_H
 
-#include <time.h>
-
 #include "access/htup.h"
 #include "access/relscan.h"
 #include "access/tupmacs.h"
 #include "utils/tqual.h"
 
 /* ----------------------------------------------------------------
- *                             heap access method statistics
+ *                             leftover cruft from old statistics code
  * ----------------------------------------------------------------
  */
 
-typedef struct HeapAccessStatisticsData
-{
-       time_t          init_global_timestamp;  /* time global statistics started */
-       time_t          local_reset_timestamp;  /* last time local reset was done */
-       time_t          last_request_timestamp; /* last time stats were requested */
-
-       int                     global_open;
-       int                     global_openr;
-       int                     global_close;
-       int                     global_beginscan;
-       int                     global_rescan;
-       int                     global_endscan;
-       int                     global_getnext;
-       int                     global_fetch;
-       int                     global_insert;
-       int                     global_delete;
-       int                     global_replace;
-       int                     global_mark4update;
-       int                     global_markpos;
-       int                     global_restrpos;
-       int                     global_BufferGetRelation;
-       int                     global_RelationIdGetRelation;
-       int                     global_RelationIdGetRelation_Buf;
-       int                     global_RelationNameGetRelation;
-       int                     global_getreldesc;
-       int                     global_heapgettup;
-       int                     global_RelationPutHeapTuple;
-       int                     global_RelationPutLongHeapTuple;
-
-       int                     local_open;
-       int                     local_openr;
-       int                     local_close;
-       int                     local_beginscan;
-       int                     local_rescan;
-       int                     local_endscan;
-       int                     local_getnext;
-       int                     local_fetch;
-       int                     local_insert;
-       int                     local_delete;
-       int                     local_replace;
-       int                     local_mark4update;
-       int                     local_markpos;
-       int                     local_restrpos;
-       int                     local_BufferGetRelation;
-       int                     local_RelationIdGetRelation;
-       int                     local_RelationIdGetRelation_Buf;
-       int                     local_RelationNameGetRelation;
-       int                     local_getreldesc;
-       int                     local_heapgettup;
-       int                     local_RelationPutHeapTuple;
-       int                     local_RelationPutLongHeapTuple;
-} HeapAccessStatisticsData;
-
-typedef HeapAccessStatisticsData *HeapAccessStatistics;
-
-#define IncrHeapAccessStat(x) \
-       (heap_access_stats == NULL ? 0 : (heap_access_stats->x)++)
+#define IncrHeapAccessStat(x)  ((void) 0)
 
 /* ----------------
  *             fastgetattr
@@ -180,7 +122,6 @@ extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
 
 extern Datum heap_getsysattr(HeapTuple tup, int attnum, bool *isnull);
 
-extern HeapAccessStatistics heap_access_stats; /* in stats.c */
 
 /* ----------------
  *             function prototypes for heap access method
@@ -192,11 +133,14 @@ extern HeapAccessStatistics heap_access_stats;    /* in stats.c */
 
 /* heapam.c */
 
+extern Relation relation_open(Oid relationId, LOCKMODE lockmode);
+extern Relation relation_openr(const char *relationName, LOCKMODE lockmode);
+extern void relation_close(Relation relation, LOCKMODE lockmode);
+
 extern Relation heap_open(Oid relationId, LOCKMODE lockmode);
 extern Relation heap_openr(const char *relationName, LOCKMODE lockmode);
-extern Relation heap_open_nofail(Oid relationId);
-extern Relation heap_openr_nofail(const char *relationName);
-extern void heap_close(Relation relation, LOCKMODE lockmode);
+#define heap_close(r,l)  relation_close(r,l)
+
 extern HeapScanDesc heap_beginscan(Relation relation, int atend,
                           Snapshot snapshot, unsigned nkeys, ScanKey key);
 extern void heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key);
@@ -242,8 +186,4 @@ extern HeapTuple heap_modifytuple(HeapTuple tuple,
 extern void heap_freetuple(HeapTuple tuple);
 extern HeapTuple heap_addheader(int natts, Size structlen, void *structure);
 
-/* in common/heap/stats.c */
-extern void PrintHeapAccessStatistics(HeapAccessStatistics stats);
-extern void initam(void);
-
 #endif  /* HEAPAM_H */
index f652fb1..8a4344f 100644 (file)
@@ -43,7 +43,7 @@ delete from;
 ERROR:  parser: parse error at or near ";"
 -- no such relation 
 delete from nonesuch;
-ERROR:  Relation 'nonesuch' does not exist
+ERROR:  Relation "nonesuch" does not exist
 --
 -- DESTROY
  
@@ -78,7 +78,7 @@ ERROR:  renamerel: relation "stud_emp" exists
 -- attribute renaming 
 -- no such relation 
 alter table nonesuchrel rename column nonesuchatt to newnonesuchatt;
-ERROR:  Relation 'nonesuchrel' does not exist
+ERROR:  Relation "nonesuchrel" does not exist
 -- no such attribute 
 alter table emp rename column nonesuchatt to newnonesuchatt;
 ERROR:  renameatt: attribute "nonesuchatt" does not exist
index 7d085de..a3a583e 100644 (file)
@@ -34,4 +34,4 @@ CREATE TEMP TABLE temptest(col int);
 -- test temp table deletion
 \c regression
 SELECT * FROM temptest;
-ERROR:  Relation 'temptest' does not exist
+ERROR:  Relation "temptest" does not exist