Fix problem reported by Alex Korn: if a relation has been dropped and

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.
This commit is contained in:
Tom Lane 2001-11-02 16:30:29 +00:00
parent 5d4b94085e
commit 7d05310828
14 changed files with 164 additions and 608 deletions

View 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

View 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,102 +499,44 @@ 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
*
* The caller must check for a NULL return value indicating
* that no such relation exists.
* No lock is obtained on the relation, either.
* ----------------
*/
Relation
heap_open_nofail(Oid relationId)
{
Relation r;
/*
* increment access statistics
*/
IncrHeapAccessStat(local_open);
IncrHeapAccessStat(global_open);
/* The relcache does all the real work... */
r = RelationIdGetRelation(relationId);
/* 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));
return r;
}
/* ----------------
* heap_openr_nofail - open a heap relation by name,
* do not raise error on failure
*
* The caller must check for a NULL return value indicating
* that no such relation exists.
* No lock is obtained on the relation, either.
* ----------------
*/
Relation
heap_openr_nofail(const char *relationName)
{
Relation r;
/*
* increment access statistics
*/
IncrHeapAccessStat(local_openr);
IncrHeapAccessStat(global_openr);
/* 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 (RelationIsValid(r))
pgstat_initstats(&r->pgstat_info, r);
return r;
}
/* ----------------
* heap_close - close a heap relation
* relation_close - close any relation
*
* If lockmode is not "NoLock", we first release the specified lock.
* Note that it is often sensible to hold a lock beyond heap_close;
*
* 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
heap_close(Relation relation, LOCKMODE lockmode)
relation_close(Relation relation, LOCKMODE lockmode)
{
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
@ -610,6 +554,59 @@ heap_close(Relation relation, LOCKMODE lockmode)
}
/* ----------------
* heap_open - open a heap relation by relation OID
*
* 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_open(Oid relationId, LOCKMODE lockmode)
{
Relation r;
r = relation_open(relationId, 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));
pgstat_initstats(&r->pgstat_info, r);
return r;
}
/* ----------------
* heap_openr - open a heap relation by name
*
* As above, but lookup by name instead of OID.
* ----------------
*/
Relation
heap_openr(const char *relationName, LOCKMODE lockmode)
{
Relation r;
r = relation_openr(relationName, 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));
pgstat_initstats(&r->pgstat_info, r);
return r;
}
/* ----------------
* heap_beginscan - begin relation scan
* ----------------
@ -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");

View File

@ -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();
}

View 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
@ -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);

View 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);
}

View 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);
rel = relation_openr(relname, lockstmt->mode);
heap_close(rel, NoLock); /* close rel, keep lock */
/* 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);
relation_close(rel, NoLock); /* close rel, keep lock */
}
}
static bool
is_relation(char *name)
{
Relation rel = heap_openr(name, NoLock);
bool retval = (rel->rd_rel->relkind == RELKIND_RELATION);
heap_close(rel, NoLock);
return retval;
}

View 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);
}
/*------------------------------------------------------------------

View 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

View 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.

View 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 $
*
*
*-------------------------------------------------------------------------
@ -292,12 +292,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.
*

View 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,

View 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"
@ -26,67 +24,11 @@
#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 */

View 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

View 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