mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Improve behavior of concurrent rename statements.
Previously, renaming a table, sequence, view, index, foreign table, column, or trigger checked permissions before locking the object, which meant that if permissions were revoked during the lock wait, we would still allow the operation. Similarly, if the original object is dropped and a new one with the same name is created, the operation will be allowed if we had permissions on the old object; the permissions on the new object don't matter. All this is now fixed. Along the way, attempting to rename a trigger on a foreign table now gives the same error message as trying to create one there in the first place (i.e. that it's not a table or view) rather than simply stating that no trigger by that name exists. Patch by me; review by Noah Misch.
This commit is contained in:
@ -105,62 +105,18 @@ ExecRenameStmt(RenameStmt *stmt)
|
||||
case OBJECT_SEQUENCE:
|
||||
case OBJECT_VIEW:
|
||||
case OBJECT_INDEX:
|
||||
case OBJECT_FOREIGN_TABLE:
|
||||
RenameRelation(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_COLUMN:
|
||||
case OBJECT_ATTRIBUTE:
|
||||
renameatt(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_TRIGGER:
|
||||
case OBJECT_FOREIGN_TABLE:
|
||||
{
|
||||
Oid relid;
|
||||
|
||||
CheckRelationOwnership(stmt->relation, true);
|
||||
|
||||
/*
|
||||
* Lock level used here should match what will be taken later,
|
||||
* in RenameRelation, renameatt, or renametrig.
|
||||
*/
|
||||
relid = RangeVarGetRelid(stmt->relation, AccessExclusiveLock,
|
||||
false);
|
||||
|
||||
switch (stmt->renameType)
|
||||
{
|
||||
case OBJECT_TABLE:
|
||||
case OBJECT_SEQUENCE:
|
||||
case OBJECT_VIEW:
|
||||
case OBJECT_INDEX:
|
||||
case OBJECT_FOREIGN_TABLE:
|
||||
{
|
||||
/*
|
||||
* RENAME TABLE requires that we (still) hold
|
||||
* CREATE rights on the containing namespace, as
|
||||
* well as ownership of the table.
|
||||
*/
|
||||
Oid namespaceId = get_rel_namespace(relid);
|
||||
AclResult aclresult;
|
||||
|
||||
aclresult = pg_namespace_aclcheck(namespaceId,
|
||||
GetUserId(),
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||
get_namespace_name(namespaceId));
|
||||
|
||||
RenameRelation(relid, stmt->newname, stmt->renameType);
|
||||
break;
|
||||
}
|
||||
case OBJECT_COLUMN:
|
||||
case OBJECT_ATTRIBUTE:
|
||||
renameatt(relid, stmt);
|
||||
break;
|
||||
case OBJECT_TRIGGER:
|
||||
renametrig(relid,
|
||||
stmt->subname, /* old att name */
|
||||
stmt->newname); /* new att name */
|
||||
break;
|
||||
default:
|
||||
/* can't happen */ ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
renametrig(stmt);
|
||||
break;
|
||||
|
||||
case OBJECT_TSPARSER:
|
||||
RenameTSParser(stmt->object, stmt->newname);
|
||||
|
Reference in New Issue
Block a user