@ -328,8 +328,9 @@ static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recu
bool is_view , AlterTableCmd * cmd , LOCKMODE lockmode ) ;
static ObjectAddress ATExecAddColumn ( List * * wqueue , AlteredTableInfo * tab ,
Relation rel , ColumnDef * colDef , bool isOid ,
bool recurse , bool recursing , LOCKMODE lockmode ) ;
static void check_for_column_name_collision ( Relation rel , const char * colname ) ;
bool recurse , bool recursing , bool if_not_exists , LOCKMODE lockmode ) ;
static bool check_for_column_name_collision ( Relation rel , const char * colname ,
bool if_not_exists ) ;
static void add_column_datatype_dependency ( Oid relid , int32 attnum , Oid typid ) ;
static void add_column_collation_dependency ( Oid relid , int32 attnum , Oid collid ) ;
static void ATPrepAddOids ( List * * wqueue , Relation rel , bool recurse ,
@ -2304,7 +2305,7 @@ renameatt_internal(Oid myrelid,
oldattname ) ) ) ;
/* new name should not already exist */
check_for_column_name_collision ( targetrelation , newattname ) ;
( void ) check_for_column_name_collision ( targetrelation , newattname , fals e ) ;
/* apply the update */
namestrcpy ( & ( attform - > attname ) , newattname ) ;
@ -3455,11 +3456,11 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
case AT_AddColumnToView : /* add column via CREATE OR REPLACE
* VIEW */
address = ATExecAddColumn ( wqueue , tab , rel , ( ColumnDef * ) cmd - > def ,
false , false , false , lockmode ) ;
false , false , false , false , lockmode ) ;
break ;
case AT_AddColumnRecurse :
address = ATExecAddColumn ( wqueue , tab , rel , ( ColumnDef * ) cmd - > def ,
false , true , false , lockmode ) ;
false , true , false , cmd - > missing_ok , lockmode ) ;
break ;
case AT_ColumnDefault : /* ALTER COLUMN DEFAULT */
address = ATExecColumnDefault ( rel , cmd - > name , cmd - > def , lockmode ) ;
@ -3572,14 +3573,14 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
if ( cmd - > def ! = NULL )
address =
ATExecAddColumn ( wqueue , tab , rel , ( ColumnDef * ) cmd - > def ,
true , false , false , lockmode ) ;
true , false , false , cmd - > missing_ok , lockmode ) ;
break ;
case AT_AddOidsRecurse : /* SET WITH OIDS */
/* Use the ADD COLUMN code, unless prep decided to do nothing */
if ( cmd - > def ! = NULL )
address =
ATExecAddColumn ( wqueue , tab , rel , ( ColumnDef * ) cmd - > def ,
true , true , false , lockmode ) ;
true , true , false , cmd - > missing_ok , lockmode ) ;
break ;
case AT_DropOids : /* SET WITHOUT OIDS */
@ -4677,7 +4678,7 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
static ObjectAddress
ATExecAddColumn ( List * * wqueue , AlteredTableInfo * tab , Relation rel ,
ColumnDef * colDef , bool isOid ,
bool recurse , bool recursing , LOCKMODE lockmode )
bool recurse , bool recursing , bool if_not_exists , LOCKMODE lockmode )
{
Oid myrelid = RelationGetRelid ( rel ) ;
Relation pgclass ,
@ -4771,8 +4772,14 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
elog ( ERROR , " cache lookup failed for relation %u " , myrelid ) ;
relkind = ( ( Form_pg_class ) GETSTRUCT ( reltup ) ) - > relkind ;
/* new name should not already exist */
check_for_column_name_collision ( rel , colDef - > colname ) ;
/* skip if the name already exists and if_not_exists is true */
if ( ! check_for_column_name_collision ( rel , colDef - > colname , if_not_exists ) )
{
heap_close ( attrdesc , RowExclusiveLock ) ;
heap_freetuple ( reltup ) ;
heap_close ( pgclass , RowExclusiveLock ) ;
return InvalidObjectAddress ;
}
/* Determine the new attribute's number */
if ( isOid )
@ -5002,7 +5009,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* Recurse to child; return value is ignored */
ATExecAddColumn ( wqueue , childtab , childrel ,
colDef , isOid , recurse , true , lockmode ) ;
colDef , isOid , recurse , true ,
if_not_exists , lockmode ) ;
heap_close ( childrel , NoLock ) ;
}
@ -5013,10 +5021,11 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
/*
* If a new or renamed column will collide with the name of an existing
* column , error out .
* column and if_not_exists is false then error out , else do nothing .
*/
static void
check_for_column_name_collision ( Relation rel , const char * colname )
static bool
check_for_column_name_collision ( Relation rel , const char * colname ,
bool if_not_exists )
{
HeapTuple attTuple ;
int attnum ;
@ -5029,7 +5038,7 @@ check_for_column_name_collision(Relation rel, const char *colname)
ObjectIdGetDatum ( RelationGetRelid ( rel ) ) ,
PointerGetDatum ( colname ) ) ;
if ( ! HeapTupleIsValid ( attTuple ) )
return ;
return true ;
attnum = ( ( Form_pg_attribute ) GETSTRUCT ( attTuple ) ) - > attnum ;
ReleaseSysCache ( attTuple ) ;
@ -5045,10 +5054,23 @@ check_for_column_name_collision(Relation rel, const char *colname)
errmsg ( " column name \" %s \" conflicts with a system column name " ,
colname ) ) ) ;
else
{
if ( if_not_exists )
{
ereport ( NOTICE ,
( errcode ( ERRCODE_DUPLICATE_COLUMN ) ,
errmsg ( " column \" %s \" of relation \" %s \" already exists, skipping " ,
colname , RelationGetRelationName ( rel ) ) ) ) ;
return false ;
}
ereport ( ERROR ,
( errcode ( ERRCODE_DUPLICATE_COLUMN ) ,
errmsg ( " column \" %s \" of relation \" %s \" already exists " ,
colname , RelationGetRelationName ( rel ) ) ) ) ;
}
return true ;
}
/*