@@ -382,6 +382,7 @@ static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
382382static void validateForeignKeyConstraint(char *conname,
383383 Relation rel, Relation pkrel,
384384 Oid pkindOid, Oid constraintOid);
385+ static void CheckAlterTableIsSafe(Relation rel);
385386static void ATController(AlterTableStmt *parsetree,
386387 Relation rel, List *cmds, bool recurse, LOCKMODE lockmode,
387388 AlterTableUtilityContext *context);
@@ -3982,6 +3983,37 @@ CheckTableNotInUse(Relation rel, const char *stmt)
39823983stmt, RelationGetRelationName(rel))));
39833984}
39843985
3986+ /*
3987+ * CheckAlterTableIsSafe
3988+ *Verify that it's safe to allow ALTER TABLE on this relation.
3989+ *
3990+ * This consists of CheckTableNotInUse() plus a check that the relation
3991+ * isn't another session's temp table. We must split out the temp-table
3992+ * check because there are callers of CheckTableNotInUse() that don't want
3993+ * that, notably DROP TABLE. (We must allow DROP or we couldn't clean out
3994+ * an orphaned temp schema.) Compare truncate_check_activity().
3995+ */
3996+ static void
3997+ CheckAlterTableIsSafe(Relation rel)
3998+ {
3999+ /*
4000+ * Don't allow ALTER on temp tables of other backends. Their local buffer
4001+ * manager is not going to cope if we need to change the table's contents.
4002+ * Even if we don't, there may be optimizations that assume temp tables
4003+ * aren't subject to such interference.
4004+ */
4005+ if (RELATION_IS_OTHER_TEMP(rel))
4006+ ereport(ERROR,
4007+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4008+ errmsg("cannot alter temporary tables of other sessions")));
4009+
4010+ /*
4011+ * Also check for active uses of the relation in the current transaction,
4012+ * including open scans and pending AFTER trigger events.
4013+ */
4014+ CheckTableNotInUse(rel, "ALTER TABLE");
4015+ }
4016+
39854017/*
39864018 * AlterTableLookupRelation
39874019 *Look up, and lock, the OID for the relation named by an alter table
@@ -4056,7 +4088,7 @@ AlterTable(AlterTableStmt *stmt, LOCKMODE lockmode,
40564088/* Caller is required to provide an adequate lock. */
40574089rel = relation_open(context->relid, NoLock);
40584090
4059- CheckTableNotInUse (rel, "ALTER TABLE" );
4091+ CheckAlterTableIsSafe (rel);
40604092
40614093ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode, context);
40624094}
@@ -5425,7 +5457,9 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode,
54255457
54265458/*
54275459 * Don't allow rewrite on temp tables of other backends ... their
5428- * local buffer manager is not going to cope.
5460+ * local buffer manager is not going to cope. (This is redundant
5461+ * with the check in CheckAlterTableIsSafe, but for safety we'll
5462+ * check here too.)
54295463 */
54305464if (RELATION_IS_OTHER_TEMP(OldHeap))
54315465ereport(ERROR,
@@ -6169,7 +6203,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
61696203continue;
61706204/* find_all_inheritors already got lock */
61716205childrel = relation_open(childrelid, NoLock);
6172- CheckTableNotInUse (childrel, "ALTER TABLE" );
6206+ CheckAlterTableIsSafe (childrel);
61736207ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode, context);
61746208relation_close(childrel, NoLock);
61756209}
@@ -6178,7 +6212,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
61786212
61796213/*
61806214 * Obtain list of partitions of the given table, locking them all at the given
6181- * lockmode and ensuring that they all passCheckTableNotInUse .
6215+ * lockmode and ensuring that they all passCheckAlterTableIsSafe .
61826216 *
61836217 * This function is a no-op if the given relation is not a partitioned table;
61846218 * in particular, nothing is done if it's a legacy inheritance parent.
@@ -6199,7 +6233,7 @@ ATCheckPartitionsNotInUse(Relation rel, LOCKMODE lockmode)
61996233
62006234/* find_all_inheritors already got lock */
62016235childrel = table_open(lfirst_oid(cell), NoLock);
6202- CheckTableNotInUse (childrel, "ALTER TABLE" );
6236+ CheckAlterTableIsSafe (childrel);
62036237table_close(childrel, NoLock);
62046238}
62056239list_free(inh);
@@ -6232,7 +6266,7 @@ ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
62326266Relationchildrel;
62336267
62346268childrel = relation_open(childrelid, lockmode);
6235- CheckTableNotInUse (childrel, "ALTER TABLE" );
6269+ CheckAlterTableIsSafe (childrel);
62366270ATPrepCmd(wqueue, childrel, cmd, true, true, lockmode, context);
62376271relation_close(childrel, NoLock);
62386272}
@@ -6933,7 +6967,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
69336967
69346968/* find_inheritance_children already got lock */
69356969childrel = table_open(childrelid, NoLock);
6936- CheckTableNotInUse (childrel, "ALTER TABLE" );
6970+ CheckAlterTableIsSafe (childrel);
69376971
69386972/* Find or create work queue entry for this table */
69396973childtab = ATGetQueueEntry(wqueue, childrel);
@@ -8419,7 +8453,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
84198453
84208454/* find_inheritance_children already got lock */
84218455childrel = table_open(childrelid, NoLock);
8422- CheckTableNotInUse (childrel, "ALTER TABLE" );
8456+ CheckAlterTableIsSafe (childrel);
84238457
84248458tuple = SearchSysCacheCopyAttName(childrelid, colName);
84258459if (!HeapTupleIsValid(tuple))/* shouldn't happen */
@@ -8901,7 +8935,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
89018935
89028936/* find_inheritance_children already got lock */
89038937childrel = table_open(childrelid, NoLock);
8904- CheckTableNotInUse (childrel, "ALTER TABLE" );
8938+ CheckAlterTableIsSafe (childrel);
89058939
89068940/* Find or create work queue entry for this table */
89078941childtab = ATGetQueueEntry(wqueue, childrel);
@@ -9651,7 +9685,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
96519685referenced;
96529686ListCell *cell;
96539687
9654- CheckTableNotInUse (partition, "ALTER TABLE" );
9688+ CheckAlterTableIsSafe (partition);
96559689
96569690attmap = build_attrmap_by_name(RelationGetDescr(partition),
96579691 RelationGetDescr(rel));
@@ -11527,7 +11561,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1152711561
1152811562/* Must match lock taken by RemoveTriggerById: */
1152911563frel = table_open(con->confrelid, AccessExclusiveLock);
11530- CheckTableNotInUse (frel, "ALTER TABLE" );
11564+ CheckAlterTableIsSafe (frel);
1153111565table_close(frel, NoLock);
1153211566}
1153311567
@@ -11605,7 +11639,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1160511639
1160611640/* find_inheritance_children already got lock */
1160711641childrel = table_open(childrelid, NoLock);
11608- CheckTableNotInUse (childrel, "ALTER TABLE" );
11642+ CheckAlterTableIsSafe (childrel);
1160911643
1161011644ScanKeyInit(&skey[0],
1161111645Anum_pg_constraint_conrelid,
@@ -11908,7 +11942,7 @@ ATPrepAlterColumnType(List **wqueue,
1190811942
1190911943/* find_all_inheritors already got lock */
1191011944childrel = relation_open(childrelid, NoLock);
11911- CheckTableNotInUse (childrel, "ALTER TABLE" );
11945+ CheckAlterTableIsSafe (childrel);
1191211946
1191311947/*
1191411948 * Verify that the child doesn't have any inherited definitions of