1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

Fix LOCK TABLE to eliminate the race condition that could make it give weird

errors when tables are concurrently dropped.  To do this we must take lock
on each relation before we check its privileges.  The old code was trying
to do that the other way around, which is a bit pointless when there are lots
of other commands that lock relations before checking privileges.  I did keep
it checking each relation's privilege before locking the next relation, which
is a detail that ALTER TABLE isn't too picky about.
This commit is contained in:
Tom Lane
2009-05-12 16:43:32 +00:00
parent d4a363cdf2
commit f23bdda324
3 changed files with 123 additions and 101 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.274 2009/01/20 18:59:36 heikki Exp $
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.275 2009/05/12 16:43:32 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -947,56 +947,6 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
return r;
}
/* ----------------
* relation_open_nowait - open but don't wait for lock
*
* Same as relation_open, except throw an error instead of waiting
* when the requested lock is not immediately obtainable.
* ----------------
*/
Relation
relation_open_nowait(Oid relationId, LOCKMODE lockmode)
{
Relation r;
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
/* Get the lock before trying to open the relcache entry */
if (lockmode != NoLock)
{
if (!ConditionalLockRelationOid(relationId, lockmode))
{
/* try to throw error by name; relation could be deleted... */
char *relname = get_rel_name(relationId);
if (relname)
ereport(ERROR,
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("could not obtain lock on relation \"%s\"",
relname)));
else
ereport(ERROR,
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("could not obtain lock on relation with OID %u",
relationId)));
}
}
/* The relcache does all the real work... */
r = RelationIdGetRelation(relationId);
if (!RelationIsValid(r))
elog(ERROR, "could not open relation with OID %u", relationId);
/* Make note that we've accessed a temporary relation */
if (r->rd_istemp)
MyXactAccessedTempRel = true;
pgstat_initstats(r);
return r;
}
/* ----------------
* relation_openrv - open any relation specified by a RangeVar
*