@ -355,6 +355,7 @@ static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
static void validateForeignKeyConstraint ( char * conname ,
Relation rel , Relation pkrel ,
Oid pkindOid , Oid constraintOid ) ;
static void CheckAlterTableIsSafe ( Relation rel ) ;
static void ATController ( AlterTableStmt * parsetree ,
Relation rel , List * cmds , bool recurse , LOCKMODE lockmode ,
AlterTableUtilityContext * context ) ;
@ -3697,6 +3698,37 @@ CheckTableNotInUse(Relation rel, const char *stmt)
stmt , RelationGetRelationName ( rel ) ) ) ) ;
}
/*
* CheckAlterTableIsSafe
* Verify that it ' s safe to allow ALTER TABLE on this relation .
*
* This consists of CheckTableNotInUse ( ) plus a check that the relation
* isn ' t another session ' s temp table . We must split out the temp - table
* check because there are callers of CheckTableNotInUse ( ) that don ' t want
* that , notably DROP TABLE . ( We must allow DROP or we couldn ' t clean out
* an orphaned temp schema . ) Compare truncate_check_activity ( ) .
*/
static void
CheckAlterTableIsSafe ( Relation rel )
{
/*
* Don ' t allow ALTER on temp tables of other backends . Their local buffer
* manager is not going to cope if we need to change the table ' s contents .
* Even if we don ' t , there may be optimizations that assume temp tables
* aren ' t subject to such interference .
*/
if ( RELATION_IS_OTHER_TEMP ( rel ) )
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot alter temporary tables of other sessions " ) ) ) ;
/*
* Also check for active uses of the relation in the current transaction ,
* including open scans and pending AFTER trigger events .
*/
CheckTableNotInUse ( rel , " ALTER TABLE " ) ;
}
/*
* AlterTableLookupRelation
* Look up , and lock , the OID for the relation named by an alter table
@ -3771,7 +3803,7 @@ AlterTable(AlterTableStmt *stmt, LOCKMODE lockmode,
/* Caller is required to provide an adequate lock. */
rel = relation_open ( context - > relid , NoLock ) ;
CheckTableNot InU se ( rel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( rel ) ;
ATController ( stmt , rel , stmt - > cmds , stmt - > relation - > inh , lockmode , context ) ;
}
@ -5092,7 +5124,9 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode,
/*
* Don ' t allow rewrite on temp tables of other backends . . . their
* local buffer manager is not going to cope .
* local buffer manager is not going to cope . ( This is redundant
* with the check in CheckAlterTableIsSafe , but for safety we ' ll
* check here too . )
*/
if ( RELATION_IS_OTHER_TEMP ( OldHeap ) )
ereport ( ERROR ,
@ -5835,7 +5869,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
continue ;
/* find_all_inheritors already got lock */
childrel = relation_open ( childrelid , NoLock ) ;
CheckTableNot InU se ( childrel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( childrel ) ;
ATPrepCmd ( wqueue , childrel , cmd , false , true , lockmode , context ) ;
relation_close ( childrel , NoLock ) ;
}
@ -5844,7 +5878,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
/*
* Obtain list of partitions of the given table , locking them all at the given
* lockmode and ensuring that they all pass CheckTableNot InU se .
* lockmode and ensuring that they all pass CheckAlter TableIsSaf e .
*
* This function is a no - op if the given relation is not a partitioned table ;
* in particular , nothing is done if it ' s a legacy inheritance parent .
@ -5865,7 +5899,7 @@ ATCheckPartitionsNotInUse(Relation rel, LOCKMODE lockmode)
/* find_all_inheritors already got lock */
childrel = table_open ( lfirst_oid ( cell ) , NoLock ) ;
CheckTableNot InU se ( childrel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( childrel ) ;
table_close ( childrel , NoLock ) ;
}
list_free ( inh ) ;
@ -5898,7 +5932,7 @@ ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
Relation childrel ;
childrel = relation_open ( childrelid , lockmode ) ;
CheckTableNot InU se ( childrel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( childrel ) ;
ATPrepCmd ( wqueue , childrel , cmd , true , true , lockmode , context ) ;
relation_close ( childrel , NoLock ) ;
}
@ -6591,7 +6625,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* find_inheritance_children already got lock */
childrel = table_open ( childrelid , NoLock ) ;
CheckTableNot InU se ( childrel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( childrel ) ;
/* Find or create work queue entry for this table */
childtab = ATGetQueueEntry ( wqueue , childrel ) ;
@ -8050,7 +8084,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
/* find_inheritance_children already got lock */
childrel = table_open ( childrelid , NoLock ) ;
CheckTableNot InU se ( childrel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( childrel ) ;
tuple = SearchSysCacheCopyAttName ( childrelid , colName ) ;
if ( ! HeapTupleIsValid ( tuple ) ) /* shouldn't happen */
@ -8508,7 +8542,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* find_inheritance_children already got lock */
childrel = table_open ( childrelid , NoLock ) ;
CheckTableNot InU se ( childrel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( childrel ) ;
/* Find or create work queue entry for this table */
childtab = ATGetQueueEntry ( wqueue , childrel ) ;
@ -9258,7 +9292,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel,
referenced ;
ListCell * cell ;
CheckTableNot InU se ( partition , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( partition ) ;
attmap = build_attrmap_by_name ( RelationGetDescr ( partition ) ,
RelationGetDescr ( rel ) ) ;
@ -11131,7 +11165,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
/* Must match lock taken by RemoveTriggerById: */
frel = table_open ( con - > confrelid , AccessExclusiveLock ) ;
CheckTableNot InU se ( frel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( frel ) ;
table_close ( frel , NoLock ) ;
}
@ -11209,7 +11243,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
/* find_inheritance_children already got lock */
childrel = table_open ( childrelid , NoLock ) ;
CheckTableNot InU se ( childrel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( childrel ) ;
ScanKeyInit ( & skey [ 0 ] ,
Anum_pg_constraint_conrelid ,
@ -11512,7 +11546,7 @@ ATPrepAlterColumnType(List **wqueue,
/* find_all_inheritors already got lock */
childrel = relation_open ( childrelid , NoLock ) ;
CheckTableNot InU se ( childrel , " ALTER TABLE " ) ;
CheckAlter TableIsSaf e ( childrel ) ;
/*
* Verify that the child doesn ' t have any inherited definitions of