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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user