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

Commit3c71cb4

Browse files
committed
Reject modifying a temp table of another session with ALTER TABLE.
Normally this case isn't even reachable by non-superusers, sincepermissions checks prevent naming such a table. However, it ispossible to make it happen by altering a parent table whose childis another session's temp table.We definitely can't support any such ALTER that requires modifyingthe contents of such a table, since we lack access to the othersession's temporary-buffer pool. But there seems no good reasonto allow it even if it'd only require changing catalog contents.One reason not to allow it is that we'd rather not expose theimplementation-dependent behavior of whether a specific ALTERrequires touching the table contents. Another is that there maybe (in future, even if not today) optimizations that assume thata session's own temp tables won't be modified by other sessions.Hence, add a RELATION_IS_OTHER_TEMP() check to all the placeswhere ALTER TABLE currently does CheckTableNotInUse(). (I lookedthrough all other callers of CheckTableNotInUse(), and they seemOK already.)Per bug #18492 from Alexander Lakhin. Back-patch to all supportedbranches.Discussion:https://postgr.es/m/18492-c7a2634bf4968763@postgresql.org
1 parenta160e92 commit3c71cb4

File tree

1 file changed

+47
-13
lines changed

1 file changed

+47
-13
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
387387
static void validateForeignKeyConstraint(char *conname,
388388
Relation rel, Relation pkrel,
389389
Oid pkindOid, Oid constraintOid);
390+
static void CheckAlterTableIsSafe(Relation rel);
390391
static void ATController(AlterTableStmt *parsetree,
391392
Relation rel, List *cmds, bool recurse, LOCKMODE lockmode,
392393
AlterTableUtilityContext *context);
@@ -4014,6 +4015,37 @@ CheckTableNotInUse(Relation rel, const char *stmt)
40144015
stmt, RelationGetRelationName(rel))));
40154016
}
40164017

4018+
/*
4019+
* CheckAlterTableIsSafe
4020+
*Verify that it's safe to allow ALTER TABLE on this relation.
4021+
*
4022+
* This consists of CheckTableNotInUse() plus a check that the relation
4023+
* isn't another session's temp table. We must split out the temp-table
4024+
* check because there are callers of CheckTableNotInUse() that don't want
4025+
* that, notably DROP TABLE. (We must allow DROP or we couldn't clean out
4026+
* an orphaned temp schema.) Compare truncate_check_activity().
4027+
*/
4028+
static void
4029+
CheckAlterTableIsSafe(Relation rel)
4030+
{
4031+
/*
4032+
* Don't allow ALTER on temp tables of other backends. Their local buffer
4033+
* manager is not going to cope if we need to change the table's contents.
4034+
* Even if we don't, there may be optimizations that assume temp tables
4035+
* aren't subject to such interference.
4036+
*/
4037+
if (RELATION_IS_OTHER_TEMP(rel))
4038+
ereport(ERROR,
4039+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4040+
errmsg("cannot alter temporary tables of other sessions")));
4041+
4042+
/*
4043+
* Also check for active uses of the relation in the current transaction,
4044+
* including open scans and pending AFTER trigger events.
4045+
*/
4046+
CheckTableNotInUse(rel, "ALTER TABLE");
4047+
}
4048+
40174049
/*
40184050
* AlterTableLookupRelation
40194051
*Look up, and lock, the OID for the relation named by an alter table
@@ -4088,7 +4120,7 @@ AlterTable(AlterTableStmt *stmt, LOCKMODE lockmode,
40884120
/* Caller is required to provide an adequate lock. */
40894121
rel = relation_open(context->relid, NoLock);
40904122

4091-
CheckTableNotInUse(rel, "ALTER TABLE");
4123+
CheckAlterTableIsSafe(rel);
40924124

40934125
ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode, context);
40944126
}
@@ -5480,7 +5512,9 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode,
54805512

54815513
/*
54825514
* Don't allow rewrite on temp tables of other backends ... their
5483-
* local buffer manager is not going to cope.
5515+
* local buffer manager is not going to cope. (This is redundant
5516+
* with the check in CheckAlterTableIsSafe, but for safety we'll
5517+
* check here too.)
54845518
*/
54855519
if (RELATION_IS_OTHER_TEMP(OldHeap))
54865520
ereport(ERROR,
@@ -6348,7 +6382,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
63486382
continue;
63496383
/* find_all_inheritors already got lock */
63506384
childrel = relation_open(childrelid, NoLock);
6351-
CheckTableNotInUse(childrel, "ALTER TABLE");
6385+
CheckAlterTableIsSafe(childrel);
63526386
ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode, context);
63536387
relation_close(childrel, NoLock);
63546388
}
@@ -6357,7 +6391,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
63576391

63586392
/*
63596393
* Obtain list of partitions of the given table, locking them all at the given
6360-
* lockmode and ensuring that they all passCheckTableNotInUse.
6394+
* lockmode and ensuring that they all passCheckAlterTableIsSafe.
63616395
*
63626396
* This function is a no-op if the given relation is not a partitioned table;
63636397
* in particular, nothing is done if it's a legacy inheritance parent.
@@ -6378,7 +6412,7 @@ ATCheckPartitionsNotInUse(Relation rel, LOCKMODE lockmode)
63786412

63796413
/* find_all_inheritors already got lock */
63806414
childrel = table_open(lfirst_oid(cell), NoLock);
6381-
CheckTableNotInUse(childrel, "ALTER TABLE");
6415+
CheckAlterTableIsSafe(childrel);
63826416
table_close(childrel, NoLock);
63836417
}
63846418
list_free(inh);
@@ -6411,7 +6445,7 @@ ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
64116445
Relationchildrel;
64126446

64136447
childrel = relation_open(childrelid, lockmode);
6414-
CheckTableNotInUse(childrel, "ALTER TABLE");
6448+
CheckAlterTableIsSafe(childrel);
64156449
ATPrepCmd(wqueue, childrel, cmd, true, true, lockmode, context);
64166450
relation_close(childrel, NoLock);
64176451
}
@@ -7112,7 +7146,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
71127146

71137147
/* find_inheritance_children already got lock */
71147148
childrel = table_open(childrelid, NoLock);
7115-
CheckTableNotInUse(childrel, "ALTER TABLE");
7149+
CheckAlterTableIsSafe(childrel);
71167150

71177151
/* Find or create work queue entry for this table */
71187152
childtab = ATGetQueueEntry(wqueue, childrel);
@@ -8572,7 +8606,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
85728606

85738607
/* find_inheritance_children already got lock */
85748608
childrel = table_open(childrelid, NoLock);
8575-
CheckTableNotInUse(childrel, "ALTER TABLE");
8609+
CheckAlterTableIsSafe(childrel);
85768610

85778611
tuple = SearchSysCacheCopyAttName(childrelid, colName);
85788612
if (!HeapTupleIsValid(tuple))/* shouldn't happen */
@@ -9054,7 +9088,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
90549088

90559089
/* find_inheritance_children already got lock */
90569090
childrel = table_open(childrelid, NoLock);
9057-
CheckTableNotInUse(childrel, "ALTER TABLE");
9091+
CheckAlterTableIsSafe(childrel);
90589092

90599093
/* Find or create work queue entry for this table */
90609094
childtab = ATGetQueueEntry(wqueue, childrel);
@@ -9892,7 +9926,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
98929926
referenced;
98939927
ListCell *cell;
98949928

9895-
CheckTableNotInUse(partition, "ALTER TABLE");
9929+
CheckAlterTableIsSafe(partition);
98969930

98979931
attmap = build_attrmap_by_name(RelationGetDescr(partition),
98989932
RelationGetDescr(rel));
@@ -12019,7 +12053,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1201912053

1202012054
/* Must match lock taken by RemoveTriggerById: */
1202112055
frel = table_open(con->confrelid, AccessExclusiveLock);
12022-
CheckTableNotInUse(frel, "ALTER TABLE");
12056+
CheckAlterTableIsSafe(frel);
1202312057
table_close(frel, NoLock);
1202412058
}
1202512059

@@ -12097,7 +12131,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1209712131

1209812132
/* find_inheritance_children already got lock */
1209912133
childrel = table_open(childrelid, NoLock);
12100-
CheckTableNotInUse(childrel, "ALTER TABLE");
12134+
CheckAlterTableIsSafe(childrel);
1210112135

1210212136
ScanKeyInit(&skey[0],
1210312137
Anum_pg_constraint_conrelid,
@@ -12400,7 +12434,7 @@ ATPrepAlterColumnType(List **wqueue,
1240012434

1240112435
/* find_all_inheritors already got lock */
1240212436
childrel = relation_open(childrelid, NoLock);
12403-
CheckTableNotInUse(childrel, "ALTER TABLE");
12437+
CheckAlterTableIsSafe(childrel);
1240412438

1240512439
/*
1240612440
* Verify that the child doesn't have any inherited definitions of

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp