@@ -328,8 +328,9 @@ static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recu
328
328
bool is_view , AlterTableCmd * cmd , LOCKMODE lockmode );
329
329
static ObjectAddress ATExecAddColumn (List * * wqueue , AlteredTableInfo * tab ,
330
330
Relation rel , ColumnDef * colDef , bool isOid ,
331
- bool recurse , bool recursing , LOCKMODE lockmode );
332
- static void check_for_column_name_collision (Relation rel , const char * colname );
331
+ bool recurse , bool recursing , bool if_not_exists , LOCKMODE lockmode );
332
+ static bool check_for_column_name_collision (Relation rel , const char * colname ,
333
+ bool if_not_exists );
333
334
static void add_column_datatype_dependency (Oid relid , int32 attnum , Oid typid );
334
335
static void add_column_collation_dependency (Oid relid , int32 attnum , Oid collid );
335
336
static void ATPrepAddOids (List * * wqueue , Relation rel , bool recurse ,
@@ -2304,7 +2305,7 @@ renameatt_internal(Oid myrelid,
2304
2305
oldattname )));
2305
2306
2306
2307
/* new name should not already exist */
2307
- check_for_column_name_collision (targetrelation , newattname );
2308
+ ( void ) check_for_column_name_collision (targetrelation , newattname , false );
2308
2309
2309
2310
/* apply the update */
2310
2311
namestrcpy (& (attform -> attname ), newattname );
@@ -3455,11 +3456,11 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
3455
3456
case AT_AddColumnToView : /* add column via CREATE OR REPLACE
3456
3457
* VIEW */
3457
3458
address = ATExecAddColumn (wqueue , tab , rel , (ColumnDef * ) cmd -> def ,
3458
- false, false, false, lockmode );
3459
+ false, false, false, false, lockmode );
3459
3460
break ;
3460
3461
case AT_AddColumnRecurse :
3461
3462
address = ATExecAddColumn (wqueue , tab , rel , (ColumnDef * ) cmd -> def ,
3462
- false, true, false, lockmode );
3463
+ false, true, false, cmd -> missing_ok , lockmode );
3463
3464
break ;
3464
3465
case AT_ColumnDefault : /* ALTER COLUMN DEFAULT */
3465
3466
address = ATExecColumnDefault (rel , cmd -> name , cmd -> def , lockmode );
@@ -3572,14 +3573,14 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
3572
3573
if (cmd -> def != NULL )
3573
3574
address =
3574
3575
ATExecAddColumn (wqueue , tab , rel , (ColumnDef * ) cmd -> def ,
3575
- true, false, false, lockmode );
3576
+ true, false, false, cmd -> missing_ok , lockmode );
3576
3577
break ;
3577
3578
case AT_AddOidsRecurse : /* SET WITH OIDS */
3578
3579
/* Use the ADD COLUMN code, unless prep decided to do nothing */
3579
3580
if (cmd -> def != NULL )
3580
3581
address =
3581
3582
ATExecAddColumn (wqueue , tab , rel , (ColumnDef * ) cmd -> def ,
3582
- true, true, false, lockmode );
3583
+ true, true, false, cmd -> missing_ok , lockmode );
3583
3584
break ;
3584
3585
case AT_DropOids : /* SET WITHOUT OIDS */
3585
3586
@@ -4677,7 +4678,7 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
4677
4678
static ObjectAddress
4678
4679
ATExecAddColumn (List * * wqueue , AlteredTableInfo * tab , Relation rel ,
4679
4680
ColumnDef * colDef , bool isOid ,
4680
- bool recurse , bool recursing , LOCKMODE lockmode )
4681
+ bool recurse , bool recursing , bool if_not_exists , LOCKMODE lockmode )
4681
4682
{
4682
4683
Oid myrelid = RelationGetRelid (rel );
4683
4684
Relation pgclass ,
@@ -4771,8 +4772,14 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
4771
4772
elog (ERROR , "cache lookup failed for relation %u" , myrelid );
4772
4773
relkind = ((Form_pg_class ) GETSTRUCT (reltup ))-> relkind ;
4773
4774
4774
- /* new name should not already exist */
4775
- check_for_column_name_collision (rel , colDef -> colname );
4775
+ /* skip if the name already exists and if_not_exists is true */
4776
+ if (!check_for_column_name_collision (rel , colDef -> colname , if_not_exists ))
4777
+ {
4778
+ heap_close (attrdesc , RowExclusiveLock );
4779
+ heap_freetuple (reltup );
4780
+ heap_close (pgclass , RowExclusiveLock );
4781
+ return InvalidObjectAddress ;
4782
+ }
4776
4783
4777
4784
/* Determine the new attribute's number */
4778
4785
if (isOid )
@@ -5002,7 +5009,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
5002
5009
5003
5010
/* Recurse to child; return value is ignored */
5004
5011
ATExecAddColumn (wqueue , childtab , childrel ,
5005
- colDef , isOid , recurse , true, lockmode );
5012
+ colDef , isOid , recurse , true,
5013
+ if_not_exists , lockmode );
5006
5014
5007
5015
heap_close (childrel , NoLock );
5008
5016
}
@@ -5013,10 +5021,11 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
5013
5021
5014
5022
/*
5015
5023
* If a new or renamed column will collide with the name of an existing
5016
- * column, error out.
5024
+ * column and if_not_exists is false then error out, else do nothing .
5017
5025
*/
5018
- static void
5019
- check_for_column_name_collision (Relation rel , const char * colname )
5026
+ static bool
5027
+ check_for_column_name_collision (Relation rel , const char * colname ,
5028
+ bool if_not_exists )
5020
5029
{
5021
5030
HeapTuple attTuple ;
5022
5031
int attnum ;
@@ -5029,7 +5038,7 @@ check_for_column_name_collision(Relation rel, const char *colname)
5029
5038
ObjectIdGetDatum (RelationGetRelid (rel )),
5030
5039
PointerGetDatum (colname ));
5031
5040
if (!HeapTupleIsValid (attTuple ))
5032
- return ;
5041
+ return true ;
5033
5042
5034
5043
attnum = ((Form_pg_attribute ) GETSTRUCT (attTuple ))-> attnum ;
5035
5044
ReleaseSysCache (attTuple );
@@ -5045,10 +5054,23 @@ check_for_column_name_collision(Relation rel, const char *colname)
5045
5054
errmsg ("column name \"%s\" conflicts with a system column name" ,
5046
5055
colname )));
5047
5056
else
5057
+ {
5058
+ if (if_not_exists )
5059
+ {
5060
+ ereport (NOTICE ,
5061
+ (errcode (ERRCODE_DUPLICATE_COLUMN ),
5062
+ errmsg ("column \"%s\" of relation \"%s\" already exists, skipping" ,
5063
+ colname , RelationGetRelationName (rel ))));
5064
+ return false;
5065
+ }
5066
+
5048
5067
ereport (ERROR ,
5049
5068
(errcode (ERRCODE_DUPLICATE_COLUMN ),
5050
5069
errmsg ("column \"%s\" of relation \"%s\" already exists" ,
5051
5070
colname , RelationGetRelationName (rel ))));
5071
+ }
5072
+
5073
+ return true;
5052
5074
}
5053
5075
5054
5076
/*
0 commit comments