@@ -388,6 +388,7 @@ static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
388388static void validateForeignKeyConstraint(char *conname,
389389 Relation rel, Relation pkrel,
390390 Oid pkindOid, Oid constraintOid);
391+ static void CheckAlterTableIsSafe(Relation rel);
391392static 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)
41114112stmt, 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. */
41854217rel = relation_open(context->relid, NoLock);
41864218
4187- CheckTableNotInUse (rel, "ALTER TABLE" );
4219+ CheckAlterTableIsSafe (rel);
41884220
41894221ATController(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 */
55465580if (RELATION_IS_OTHER_TEMP(OldHeap))
55475581ereport(ERROR,
@@ -6405,7 +6439,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
64056439continue;
64066440/* find_all_inheritors already got lock */
64076441childrel = relation_open(childrelid, NoLock);
6408- CheckTableNotInUse (childrel, "ALTER TABLE" );
6442+ CheckAlterTableIsSafe (childrel);
64096443ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode, context);
64106444relation_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 */
64376471childrel = table_open(lfirst_oid(cell), NoLock);
6438- CheckTableNotInUse (childrel, "ALTER TABLE" );
6472+ CheckAlterTableIsSafe (childrel);
64396473table_close(childrel, NoLock);
64406474}
64416475list_free(inh);
@@ -6468,7 +6502,7 @@ ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
64686502Relationchildrel;
64696503
64706504childrel = relation_open(childrelid, lockmode);
6471- CheckTableNotInUse (childrel, "ALTER TABLE" );
6505+ CheckAlterTableIsSafe (childrel);
64726506ATPrepCmd(wqueue, childrel, cmd, true, true, lockmode, context);
64736507relation_close(childrel, NoLock);
64746508}
@@ -7180,7 +7214,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
71807214
71817215/* find_inheritance_children already got lock */
71827216childrel = table_open(childrelid, NoLock);
7183- CheckTableNotInUse (childrel, "ALTER TABLE" );
7217+ CheckAlterTableIsSafe (childrel);
71847218
71857219/* Find or create work queue entry for this table */
71867220childtab = ATGetQueueEntry(wqueue, childrel);
@@ -8612,7 +8646,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
86128646
86138647/* find_inheritance_children already got lock */
86148648childrel = table_open(childrelid, NoLock);
8615- CheckTableNotInUse (childrel, "ALTER TABLE" );
8649+ CheckAlterTableIsSafe (childrel);
86168650
86178651tuple = SearchSysCacheCopyAttName(childrelid, colName);
86188652if (!HeapTupleIsValid(tuple))/* shouldn't happen */
@@ -9095,7 +9129,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
90959129
90969130/* find_inheritance_children already got lock */
90979131childrel = table_open(childrelid, NoLock);
9098- CheckTableNotInUse (childrel, "ALTER TABLE" );
9132+ CheckAlterTableIsSafe (childrel);
90999133
91009134/* Find or create work queue entry for this table */
91019135childtab = ATGetQueueEntry(wqueue, childrel);
@@ -9924,7 +9958,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
99249958referenced;
99259959ListCell *cell;
99269960
9927- CheckTableNotInUse (partition, "ALTER TABLE" );
9961+ CheckAlterTableIsSafe (partition);
99289962
99299963attmap = 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: */
1204712081frel = table_open(con->confrelid, AccessExclusiveLock);
12048- CheckTableNotInUse (frel, "ALTER TABLE" );
12082+ CheckAlterTableIsSafe (frel);
1204912083table_close(frel, NoLock);
1205012084}
1205112085
@@ -12123,7 +12157,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
1212312157
1212412158/* find_inheritance_children already got lock */
1212512159childrel = table_open(childrelid, NoLock);
12126- CheckTableNotInUse (childrel, "ALTER TABLE" );
12160+ CheckAlterTableIsSafe (childrel);
1212712161
1212812162ScanKeyInit(&skey[0],
1212912163Anum_pg_constraint_conrelid,
@@ -12426,7 +12460,7 @@ ATPrepAlterColumnType(List **wqueue,
1242612460
1242712461/* find_all_inheritors already got lock */
1242812462childrel = 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