1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-07 19:06:32 +03:00

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

@@ -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