Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit842fe61

Browse files
committed
Ensure correct lock level is used in ALTER ... RENAME
Commit1b5d797 intended to relax the lock level used to renameindexes, but inadvertently allowed *any* relation to be renamed with alowered lock level, as long as the command is spelled ALTER INDEX.That's undesirable for other relation types, so retry the operation withthe higher lock if the relation turns out not to be an index.After this fix, ALTER INDEX <sometable> RENAME will require accessexclusive lock, which it didn't before.Author: Nathan Bossart <bossartn@amazon.com>Author: Álvaro Herrera <alvherre@alvh.no-ip.org>Reported-by: Onder Kalaci <onderk@microsoft.com>Discussion:https://postgr.es/m/PH0PR21MB1328189E2821CDEC646F8178D8AE9@PH0PR21MB1328.namprd21.prod.outlook.com
1 parent246a035 commit842fe61

File tree

3 files changed

+127
-14
lines changed

3 files changed

+127
-14
lines changed

‎src/backend/commands/tablecmds.c‎

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3448,7 +3448,7 @@ RenameConstraint(RenameStmt *stmt)
34483448
ObjectAddress
34493449
RenameRelation(RenameStmt *stmt)
34503450
{
3451-
boolis_index = stmt->renameType == OBJECT_INDEX;
3451+
boolis_index_stmt = stmt->renameType == OBJECT_INDEX;
34523452
Oidrelid;
34533453
ObjectAddress address;
34543454

@@ -3458,24 +3458,48 @@ RenameRelation(RenameStmt *stmt)
34583458
* end of transaction.
34593459
*
34603460
* Lock level used here should match RenameRelationInternal, to avoid lock
3461-
* escalation.
3461+
* escalation. However, because ALTER INDEX can be used with any relation
3462+
* type, we mustn't believe without verification.
34623463
*/
3463-
relid = RangeVarGetRelidExtended(stmt->relation,
3464-
is_index ? ShareUpdateExclusiveLock : AccessExclusiveLock,
3465-
stmt->missing_ok ? RVR_MISSING_OK : 0,
3466-
RangeVarCallbackForAlterRelation,
3467-
(void *) stmt);
3468-
3469-
if (!OidIsValid(relid))
3464+
for (;;)
34703465
{
3471-
ereport(NOTICE,
3472-
(errmsg("relation \"%s\" does not exist, skipping",
3473-
stmt->relation->relname)));
3474-
return InvalidObjectAddress;
3466+
LOCKMODElockmode;
3467+
charrelkind;
3468+
boolobj_is_index;
3469+
3470+
lockmode = is_index_stmt ? ShareUpdateExclusiveLock : AccessExclusiveLock;
3471+
3472+
relid = RangeVarGetRelidExtended(stmt->relation, lockmode,
3473+
stmt->missing_ok ? RVR_MISSING_OK : 0,
3474+
RangeVarCallbackForAlterRelation,
3475+
(void *) stmt);
3476+
3477+
if (!OidIsValid(relid))
3478+
{
3479+
ereport(NOTICE,
3480+
(errmsg("relation \"%s\" does not exist, skipping",
3481+
stmt->relation->relname)));
3482+
return InvalidObjectAddress;
3483+
}
3484+
3485+
/*
3486+
* We allow mismatched statement and object types (e.g., ALTER INDEX
3487+
* to rename a table), but we might've used the wrong lock level. If
3488+
* that happens, retry with the correct lock level. We don't bother
3489+
* if we already acquired AccessExclusiveLock with an index, however.
3490+
*/
3491+
relkind = get_rel_relkind(relid);
3492+
obj_is_index = (relkind == RELKIND_INDEX ||
3493+
relkind == RELKIND_PARTITIONED_INDEX);
3494+
if (obj_is_index || is_index_stmt == obj_is_index)
3495+
break;
3496+
3497+
UnlockRelationOid(relid, lockmode);
3498+
is_index_stmt = obj_is_index;
34753499
}
34763500

34773501
/* Do the work */
3478-
RenameRelationInternal(relid, stmt->newname, false,is_index);
3502+
RenameRelationInternal(relid, stmt->newname, false,is_index_stmt);
34793503

34803504
ObjectAddressSet(address, RelationRelationId, relid);
34813505

@@ -3523,6 +3547,16 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo
35233547
errmsg("relation \"%s\" already exists",
35243548
newrelname)));
35253549

3550+
/*
3551+
* RenameRelation is careful not to believe the caller's idea of the
3552+
* relation kind being handled. We don't have to worry about this, but
3553+
* let's not be totally oblivious to it. We can process an index as
3554+
* not-an-index, but not the other way around.
3555+
*/
3556+
Assert(!is_index ||
3557+
is_index == (targetrelation->rd_rel->relkind == RELKIND_INDEX ||
3558+
targetrelation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX));
3559+
35263560
/*
35273561
* Update pg_class tuple with new relname. (Scribbling on reltup is OK
35283562
* because it's a copy...)

‎src/test/regress/expected/alter_table.out‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,54 @@ SET ROLE regress_alter_table_user1;
237237
ALTER INDEX onek_unique1 RENAME TO fail; -- permission denied
238238
ERROR: must be owner of index onek_unique1
239239
RESET ROLE;
240+
-- rename statements with mismatching statement and object types
241+
CREATE TABLE alter_idx_rename_test (a INT);
242+
CREATE INDEX alter_idx_rename_test_idx ON alter_idx_rename_test (a);
243+
CREATE TABLE alter_idx_rename_test_parted (a INT) PARTITION BY LIST (a);
244+
CREATE INDEX alter_idx_rename_test_parted_idx ON alter_idx_rename_test_parted (a);
245+
BEGIN;
246+
ALTER INDEX alter_idx_rename_test RENAME TO alter_idx_rename_test_2;
247+
ALTER INDEX alter_idx_rename_test_parted RENAME TO alter_idx_rename_test_parted_2;
248+
SELECT relation::regclass, mode FROM pg_locks
249+
WHERE pid = pg_backend_pid() AND locktype = 'relation'
250+
AND relation::regclass::text LIKE 'alter\_idx%'
251+
ORDER BY relation::regclass::text;
252+
relation | mode
253+
--------------------------------+---------------------
254+
alter_idx_rename_test_2 | AccessExclusiveLock
255+
alter_idx_rename_test_parted_2 | AccessExclusiveLock
256+
(2 rows)
257+
258+
COMMIT;
259+
BEGIN;
260+
ALTER INDEX alter_idx_rename_test_idx RENAME TO alter_idx_rename_test_idx_2;
261+
ALTER INDEX alter_idx_rename_test_parted_idx RENAME TO alter_idx_rename_test_parted_idx_2;
262+
SELECT relation::regclass, mode FROM pg_locks
263+
WHERE pid = pg_backend_pid() AND locktype = 'relation'
264+
AND relation::regclass::text LIKE 'alter\_idx%'
265+
ORDER BY relation::regclass::text;
266+
relation | mode
267+
------------------------------------+--------------------------
268+
alter_idx_rename_test_idx_2 | ShareUpdateExclusiveLock
269+
alter_idx_rename_test_parted_idx_2 | ShareUpdateExclusiveLock
270+
(2 rows)
271+
272+
COMMIT;
273+
BEGIN;
274+
ALTER TABLE alter_idx_rename_test_idx_2 RENAME TO alter_idx_rename_test_idx_3;
275+
ALTER TABLE alter_idx_rename_test_parted_idx_2 RENAME TO alter_idx_rename_test_parted_idx_3;
276+
SELECT relation::regclass, mode FROM pg_locks
277+
WHERE pid = pg_backend_pid() AND locktype = 'relation'
278+
AND relation::regclass::text LIKE 'alter\_idx%'
279+
ORDER BY relation::regclass::text;
280+
relation | mode
281+
------------------------------------+---------------------
282+
alter_idx_rename_test_idx_3 | AccessExclusiveLock
283+
alter_idx_rename_test_parted_idx_3 | AccessExclusiveLock
284+
(2 rows)
285+
286+
COMMIT;
287+
DROP TABLE alter_idx_rename_test_2;
240288
-- renaming views
241289
CREATE VIEW attmp_view (unique1) AS SELECT unique1 FROM tenk1;
242290
ALTER TABLE attmp_view RENAME TO attmp_view_new;

‎src/test/regress/sql/alter_table.sql‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,37 @@ SET ROLE regress_alter_table_user1;
231231
ALTERINDEX onek_unique1 RENAME TO fail;-- permission denied
232232
RESET ROLE;
233233

234+
-- rename statements with mismatching statement and object types
235+
CREATETABLEalter_idx_rename_test (aINT);
236+
CREATEINDEXalter_idx_rename_test_idxON alter_idx_rename_test (a);
237+
CREATETABLEalter_idx_rename_test_parted (aINT) PARTITION BY LIST (a);
238+
CREATEINDEXalter_idx_rename_test_parted_idxON alter_idx_rename_test_parted (a);
239+
BEGIN;
240+
ALTERINDEX alter_idx_rename_test RENAME TO alter_idx_rename_test_2;
241+
ALTERINDEX alter_idx_rename_test_parted RENAME TO alter_idx_rename_test_parted_2;
242+
SELECT relation::regclass, modeFROM pg_locks
243+
WHERE pid= pg_backend_pid()AND locktype='relation'
244+
AND relation::regclass::textLIKE'alter\_idx%'
245+
ORDER BY relation::regclass::text;
246+
COMMIT;
247+
BEGIN;
248+
ALTERINDEX alter_idx_rename_test_idx RENAME TO alter_idx_rename_test_idx_2;
249+
ALTERINDEX alter_idx_rename_test_parted_idx RENAME TO alter_idx_rename_test_parted_idx_2;
250+
SELECT relation::regclass, modeFROM pg_locks
251+
WHERE pid= pg_backend_pid()AND locktype='relation'
252+
AND relation::regclass::textLIKE'alter\_idx%'
253+
ORDER BY relation::regclass::text;
254+
COMMIT;
255+
BEGIN;
256+
ALTERTABLE alter_idx_rename_test_idx_2 RENAME TO alter_idx_rename_test_idx_3;
257+
ALTERTABLE alter_idx_rename_test_parted_idx_2 RENAME TO alter_idx_rename_test_parted_idx_3;
258+
SELECT relation::regclass, modeFROM pg_locks
259+
WHERE pid= pg_backend_pid()AND locktype='relation'
260+
AND relation::regclass::textLIKE'alter\_idx%'
261+
ORDER BY relation::regclass::text;
262+
COMMIT;
263+
DROPTABLE alter_idx_rename_test_2;
264+
234265
-- renaming views
235266
CREATEVIEWattmp_view (unique1)ASSELECT unique1FROM tenk1;
236267
ALTERTABLE attmp_view RENAME TO attmp_view_new;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp