@@ -355,6 +355,7 @@ static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
355355static void validateForeignKeyConstraint(char *conname,
356356 Relation rel, Relation pkrel,
357357 Oid pkindOid, Oid constraintOid);
358+ static void CheckAlterTableIsSafe(Relation rel);
358359static 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)
36973698stmt, 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. */
37723804rel = relation_open(context->relid, NoLock);
37733805
3774- CheckTableNotInUse (rel, "ALTER TABLE" );
3806+ CheckAlterTableIsSafe (rel);
37753807
37763808ATController(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 */
50975131if (RELATION_IS_OTHER_TEMP(OldHeap))
50985132ereport(ERROR,
@@ -5835,7 +5869,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
58355869continue;
58365870/* find_all_inheritors already got lock */
58375871childrel = relation_open(childrelid, NoLock);
5838- CheckTableNotInUse (childrel, "ALTER TABLE" );
5872+ CheckAlterTableIsSafe (childrel);
58395873ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode, context);
58405874relation_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 */
58675901childrel = table_open(lfirst_oid(cell), NoLock);
5868- CheckTableNotInUse (childrel, "ALTER TABLE" );
5902+ CheckAlterTableIsSafe (childrel);
58695903table_close(childrel, NoLock);
58705904}
58715905list_free(inh);
@@ -5898,7 +5932,7 @@ ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
58985932Relationchildrel;
58995933
59005934childrel = relation_open(childrelid, lockmode);
5901- CheckTableNotInUse (childrel, "ALTER TABLE" );
5935+ CheckAlterTableIsSafe (childrel);
59025936ATPrepCmd(wqueue, childrel, cmd, true, true, lockmode, context);
59035937relation_close(childrel, NoLock);
59045938}
@@ -6591,7 +6625,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
65916625
65926626/* find_inheritance_children already got lock */
65936627childrel = table_open(childrelid, NoLock);
6594- CheckTableNotInUse (childrel, "ALTER TABLE" );
6628+ CheckAlterTableIsSafe (childrel);
65956629
65966630/* Find or create work queue entry for this table */
65976631childtab = ATGetQueueEntry(wqueue, childrel);
@@ -8050,7 +8084,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
80508084
80518085/* find_inheritance_children already got lock */
80528086childrel = table_open(childrelid, NoLock);
8053- CheckTableNotInUse (childrel, "ALTER TABLE" );
8087+ CheckAlterTableIsSafe (childrel);
80548088
80558089tuple = SearchSysCacheCopyAttName(childrelid, colName);
80568090if (!HeapTupleIsValid(tuple))/* shouldn't happen */
@@ -8508,7 +8542,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
85088542
85098543/* find_inheritance_children already got lock */
85108544childrel = table_open(childrelid, NoLock);
8511- CheckTableNotInUse (childrel, "ALTER TABLE" );
8545+ CheckAlterTableIsSafe (childrel);
85128546
85138547/* Find or create work queue entry for this table */
85148548childtab = ATGetQueueEntry(wqueue, childrel);
@@ -9258,7 +9292,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
92589292referenced;
92599293ListCell *cell;
92609294
9261- CheckTableNotInUse (partition, "ALTER TABLE" );
9295+ CheckAlterTableIsSafe (partition);
92629296
92639297attmap = 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: */
1113311167frel = table_open(con->confrelid, AccessExclusiveLock);
11134- CheckTableNotInUse (frel, "ALTER TABLE" );
11168+ CheckAlterTableIsSafe (frel);
1113511169table_close(frel, NoLock);
1113611170}
1113711171
@@ -11209,7 +11243,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1120911243
1121011244/* find_inheritance_children already got lock */
1121111245childrel = table_open(childrelid, NoLock);
11212- CheckTableNotInUse (childrel, "ALTER TABLE" );
11246+ CheckAlterTableIsSafe (childrel);
1121311247
1121411248ScanKeyInit(&skey[0],
1121511249Anum_pg_constraint_conrelid,
@@ -11512,7 +11546,7 @@ ATPrepAlterColumnType(List **wqueue,
1151211546
1151311547/* find_all_inheritors already got lock */
1151411548childrel = 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