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

Commit8397f16

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 parent0d18b8e commit8397f16

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
@@ -388,6 +388,7 @@ static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
388388
static void validateForeignKeyConstraint(char *conname,
389389
Relation rel, Relation pkrel,
390390
Oid pkindOid, Oid constraintOid);
391+
static void CheckAlterTableIsSafe(Relation rel);
391392
static void ATController(AlterTableStmt *parsetree,
392393
Relation rel, List *cmds, bool recurse, LOCKMODE lockmode,
393394
AlterTableUtilityContext *context);
@@ -4111,6 +4112,37 @@ CheckTableNotInUse(Relation rel, const char *stmt)
41114112
stmt, RelationGetRelationName(rel))));
41124113
}
41134114

4115+
/*
4116+
* CheckAlterTableIsSafe
4117+
*Verify that it's safe to allow ALTER TABLE on this relation.
4118+
*
4119+
* This consists of CheckTableNotInUse() plus a check that the relation
4120+
* isn't another session's temp table. We must split out the temp-table
4121+
* check because there are callers of CheckTableNotInUse() that don't want
4122+
* that, notably DROP TABLE. (We must allow DROP or we couldn't clean out
4123+
* an orphaned temp schema.) Compare truncate_check_activity().
4124+
*/
4125+
static void
4126+
CheckAlterTableIsSafe(Relation rel)
4127+
{
4128+
/*
4129+
* Don't allow ALTER on temp tables of other backends. Their local buffer
4130+
* manager is not going to cope if we need to change the table's contents.
4131+
* Even if we don't, there may be optimizations that assume temp tables
4132+
* aren't subject to such interference.
4133+
*/
4134+
if (RELATION_IS_OTHER_TEMP(rel))
4135+
ereport(ERROR,
4136+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4137+
errmsg("cannot alter temporary tables of other sessions")));
4138+
4139+
/*
4140+
* Also check for active uses of the relation in the current transaction,
4141+
* including open scans and pending AFTER trigger events.
4142+
*/
4143+
CheckTableNotInUse(rel, "ALTER TABLE");
4144+
}
4145+
41144146
/*
41154147
* AlterTableLookupRelation
41164148
*Look up, and lock, the OID for the relation named by an alter table
@@ -4184,7 +4216,7 @@ AlterTable(AlterTableStmt *stmt, LOCKMODE lockmode,
41844216
/* Caller is required to provide an adequate lock. */
41854217
rel = relation_open(context->relid, NoLock);
41864218

4187-
CheckTableNotInUse(rel, "ALTER TABLE");
4219+
CheckAlterTableIsSafe(rel);
41884220

41894221
ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode, context);
41904222
}
@@ -5541,7 +5573,9 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode,
55415573

55425574
/*
55435575
* Don't allow rewrite on temp tables of other backends ... their
5544-
* local buffer manager is not going to cope.
5576+
* local buffer manager is not going to cope. (This is redundant
5577+
* with the check in CheckAlterTableIsSafe, but for safety we'll
5578+
* check here too.)
55455579
*/
55465580
if (RELATION_IS_OTHER_TEMP(OldHeap))
55475581
ereport(ERROR,
@@ -6405,7 +6439,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
64056439
continue;
64066440
/* find_all_inheritors already got lock */
64076441
childrel = relation_open(childrelid, NoLock);
6408-
CheckTableNotInUse(childrel, "ALTER TABLE");
6442+
CheckAlterTableIsSafe(childrel);
64096443
ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode, context);
64106444
relation_close(childrel, NoLock);
64116445
}
@@ -6414,7 +6448,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
64146448

64156449
/*
64166450
* Obtain list of partitions of the given table, locking them all at the given
6417-
* lockmode and ensuring that they all passCheckTableNotInUse.
6451+
* lockmode and ensuring that they all passCheckAlterTableIsSafe.
64186452
*
64196453
* This function is a no-op if the given relation is not a partitioned table;
64206454
* in particular, nothing is done if it's a legacy inheritance parent.
@@ -6435,7 +6469,7 @@ ATCheckPartitionsNotInUse(Relation rel, LOCKMODE lockmode)
64356469

64366470
/* find_all_inheritors already got lock */
64376471
childrel = table_open(lfirst_oid(cell), NoLock);
6438-
CheckTableNotInUse(childrel, "ALTER TABLE");
6472+
CheckAlterTableIsSafe(childrel);
64396473
table_close(childrel, NoLock);
64406474
}
64416475
list_free(inh);
@@ -6468,7 +6502,7 @@ ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
64686502
Relationchildrel;
64696503

64706504
childrel = relation_open(childrelid, lockmode);
6471-
CheckTableNotInUse(childrel, "ALTER TABLE");
6505+
CheckAlterTableIsSafe(childrel);
64726506
ATPrepCmd(wqueue, childrel, cmd, true, true, lockmode, context);
64736507
relation_close(childrel, NoLock);
64746508
}
@@ -7180,7 +7214,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
71807214

71817215
/* find_inheritance_children already got lock */
71827216
childrel = table_open(childrelid, NoLock);
7183-
CheckTableNotInUse(childrel, "ALTER TABLE");
7217+
CheckAlterTableIsSafe(childrel);
71847218

71857219
/* Find or create work queue entry for this table */
71867220
childtab = ATGetQueueEntry(wqueue, childrel);
@@ -8612,7 +8646,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
86128646

86138647
/* find_inheritance_children already got lock */
86148648
childrel = table_open(childrelid, NoLock);
8615-
CheckTableNotInUse(childrel, "ALTER TABLE");
8649+
CheckAlterTableIsSafe(childrel);
86168650

86178651
tuple = SearchSysCacheCopyAttName(childrelid, colName);
86188652
if (!HeapTupleIsValid(tuple))/* shouldn't happen */
@@ -9095,7 +9129,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
90959129

90969130
/* find_inheritance_children already got lock */
90979131
childrel = table_open(childrelid, NoLock);
9098-
CheckTableNotInUse(childrel, "ALTER TABLE");
9132+
CheckAlterTableIsSafe(childrel);
90999133

91009134
/* Find or create work queue entry for this table */
91019135
childtab = ATGetQueueEntry(wqueue, childrel);
@@ -9924,7 +9958,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
99249958
referenced;
99259959
ListCell *cell;
99269960

9927-
CheckTableNotInUse(partition, "ALTER TABLE");
9961+
CheckAlterTableIsSafe(partition);
99289962

99299963
attmap = build_attrmap_by_name(RelationGetDescr(partition),
99309964
RelationGetDescr(rel),
@@ -12045,7 +12079,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1204512079

1204612080
/* Must match lock taken by RemoveTriggerById: */
1204712081
frel = table_open(con->confrelid, AccessExclusiveLock);
12048-
CheckTableNotInUse(frel, "ALTER TABLE");
12082+
CheckAlterTableIsSafe(frel);
1204912083
table_close(frel, NoLock);
1205012084
}
1205112085

@@ -12123,7 +12157,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1212312157

1212412158
/* find_inheritance_children already got lock */
1212512159
childrel = table_open(childrelid, NoLock);
12126-
CheckTableNotInUse(childrel, "ALTER TABLE");
12160+
CheckAlterTableIsSafe(childrel);
1212712161

1212812162
ScanKeyInit(&skey[0],
1212912163
Anum_pg_constraint_conrelid,
@@ -12426,7 +12460,7 @@ ATPrepAlterColumnType(List **wqueue,
1242612460

1242712461
/* find_all_inheritors already got lock */
1242812462
childrel = relation_open(childrelid, NoLock);
12429-
CheckTableNotInUse(childrel, "ALTER TABLE");
12463+
CheckAlterTableIsSafe(childrel);
1243012464

1243112465
/*
1243212466
* Verify that the child doesn't have any inherited definitions of

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp