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

Commit7c4ac65

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 parent1d4ea13 commit7c4ac65

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
@@ -355,6 +355,7 @@ static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
355355
static void validateForeignKeyConstraint(char *conname,
356356
Relation rel, Relation pkrel,
357357
Oid pkindOid, Oid constraintOid);
358+
static void CheckAlterTableIsSafe(Relation rel);
358359
static void ATController(AlterTableStmt *parsetree,
359360
Relation rel, List *cmds, bool recurse, LOCKMODE lockmode,
360361
AlterTableUtilityContext *context);
@@ -3697,6 +3698,37 @@ CheckTableNotInUse(Relation rel, const char *stmt)
36973698
stmt, RelationGetRelationName(rel))));
36983699
}
36993700

3701+
/*
3702+
* CheckAlterTableIsSafe
3703+
*Verify that it's safe to allow ALTER TABLE on this relation.
3704+
*
3705+
* This consists of CheckTableNotInUse() plus a check that the relation
3706+
* isn't another session's temp table. We must split out the temp-table
3707+
* check because there are callers of CheckTableNotInUse() that don't want
3708+
* that, notably DROP TABLE. (We must allow DROP or we couldn't clean out
3709+
* an orphaned temp schema.) Compare truncate_check_activity().
3710+
*/
3711+
static void
3712+
CheckAlterTableIsSafe(Relation rel)
3713+
{
3714+
/*
3715+
* Don't allow ALTER on temp tables of other backends. Their local buffer
3716+
* manager is not going to cope if we need to change the table's contents.
3717+
* Even if we don't, there may be optimizations that assume temp tables
3718+
* aren't subject to such interference.
3719+
*/
3720+
if (RELATION_IS_OTHER_TEMP(rel))
3721+
ereport(ERROR,
3722+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3723+
errmsg("cannot alter temporary tables of other sessions")));
3724+
3725+
/*
3726+
* Also check for active uses of the relation in the current transaction,
3727+
* including open scans and pending AFTER trigger events.
3728+
*/
3729+
CheckTableNotInUse(rel, "ALTER TABLE");
3730+
}
3731+
37003732
/*
37013733
* AlterTableLookupRelation
37023734
*Look up, and lock, the OID for the relation named by an alter table
@@ -3771,7 +3803,7 @@ AlterTable(AlterTableStmt *stmt, LOCKMODE lockmode,
37713803
/* Caller is required to provide an adequate lock. */
37723804
rel = relation_open(context->relid, NoLock);
37733805

3774-
CheckTableNotInUse(rel, "ALTER TABLE");
3806+
CheckAlterTableIsSafe(rel);
37753807

37763808
ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode, context);
37773809
}
@@ -5092,7 +5124,9 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode,
50925124

50935125
/*
50945126
* Don't allow rewrite on temp tables of other backends ... their
5095-
* local buffer manager is not going to cope.
5127+
* local buffer manager is not going to cope. (This is redundant
5128+
* with the check in CheckAlterTableIsSafe, but for safety we'll
5129+
* check here too.)
50965130
*/
50975131
if (RELATION_IS_OTHER_TEMP(OldHeap))
50985132
ereport(ERROR,
@@ -5835,7 +5869,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
58355869
continue;
58365870
/* find_all_inheritors already got lock */
58375871
childrel = relation_open(childrelid, NoLock);
5838-
CheckTableNotInUse(childrel, "ALTER TABLE");
5872+
CheckAlterTableIsSafe(childrel);
58395873
ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode, context);
58405874
relation_close(childrel, NoLock);
58415875
}
@@ -5844,7 +5878,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
58445878

58455879
/*
58465880
* Obtain list of partitions of the given table, locking them all at the given
5847-
* lockmode and ensuring that they all passCheckTableNotInUse.
5881+
* lockmode and ensuring that they all passCheckAlterTableIsSafe.
58485882
*
58495883
* This function is a no-op if the given relation is not a partitioned table;
58505884
* in particular, nothing is done if it's a legacy inheritance parent.
@@ -5865,7 +5899,7 @@ ATCheckPartitionsNotInUse(Relation rel, LOCKMODE lockmode)
58655899

58665900
/* find_all_inheritors already got lock */
58675901
childrel = table_open(lfirst_oid(cell), NoLock);
5868-
CheckTableNotInUse(childrel, "ALTER TABLE");
5902+
CheckAlterTableIsSafe(childrel);
58695903
table_close(childrel, NoLock);
58705904
}
58715905
list_free(inh);
@@ -5898,7 +5932,7 @@ ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
58985932
Relationchildrel;
58995933

59005934
childrel = relation_open(childrelid, lockmode);
5901-
CheckTableNotInUse(childrel, "ALTER TABLE");
5935+
CheckAlterTableIsSafe(childrel);
59025936
ATPrepCmd(wqueue, childrel, cmd, true, true, lockmode, context);
59035937
relation_close(childrel, NoLock);
59045938
}
@@ -6591,7 +6625,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
65916625

65926626
/* find_inheritance_children already got lock */
65936627
childrel = table_open(childrelid, NoLock);
6594-
CheckTableNotInUse(childrel, "ALTER TABLE");
6628+
CheckAlterTableIsSafe(childrel);
65956629

65966630
/* Find or create work queue entry for this table */
65976631
childtab = ATGetQueueEntry(wqueue, childrel);
@@ -8050,7 +8084,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
80508084

80518085
/* find_inheritance_children already got lock */
80528086
childrel = table_open(childrelid, NoLock);
8053-
CheckTableNotInUse(childrel, "ALTER TABLE");
8087+
CheckAlterTableIsSafe(childrel);
80548088

80558089
tuple = SearchSysCacheCopyAttName(childrelid, colName);
80568090
if (!HeapTupleIsValid(tuple))/* shouldn't happen */
@@ -8508,7 +8542,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
85088542

85098543
/* find_inheritance_children already got lock */
85108544
childrel = table_open(childrelid, NoLock);
8511-
CheckTableNotInUse(childrel, "ALTER TABLE");
8545+
CheckAlterTableIsSafe(childrel);
85128546

85138547
/* Find or create work queue entry for this table */
85148548
childtab = ATGetQueueEntry(wqueue, childrel);
@@ -9258,7 +9292,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
92589292
referenced;
92599293
ListCell *cell;
92609294

9261-
CheckTableNotInUse(partition, "ALTER TABLE");
9295+
CheckAlterTableIsSafe(partition);
92629296

92639297
attmap = build_attrmap_by_name(RelationGetDescr(partition),
92649298
RelationGetDescr(rel));
@@ -11131,7 +11165,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1113111165

1113211166
/* Must match lock taken by RemoveTriggerById: */
1113311167
frel = table_open(con->confrelid, AccessExclusiveLock);
11134-
CheckTableNotInUse(frel, "ALTER TABLE");
11168+
CheckAlterTableIsSafe(frel);
1113511169
table_close(frel, NoLock);
1113611170
}
1113711171

@@ -11209,7 +11243,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1120911243

1121011244
/* find_inheritance_children already got lock */
1121111245
childrel = table_open(childrelid, NoLock);
11212-
CheckTableNotInUse(childrel, "ALTER TABLE");
11246+
CheckAlterTableIsSafe(childrel);
1121311247

1121411248
ScanKeyInit(&skey[0],
1121511249
Anum_pg_constraint_conrelid,
@@ -11512,7 +11546,7 @@ ATPrepAlterColumnType(List **wqueue,
1151211546

1151311547
/* find_all_inheritors already got lock */
1151411548
childrel = relation_open(childrelid, NoLock);
11515-
CheckTableNotInUse(childrel, "ALTER TABLE");
11549+
CheckAlterTableIsSafe(childrel);
1151611550

1151711551
/*
1151811552
* Verify that the child doesn't have any inherited definitions of

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp