@@ -335,13 +335,15 @@ static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
335
335
IndexStmt * stmt ,bool is_rebuild ,LOCKMODE lockmode );
336
336
static void ATExecAddConstraint (List * * wqueue ,
337
337
AlteredTableInfo * tab ,Relation rel ,
338
- Constraint * newConstraint ,bool recurse ,LOCKMODE lockmode );
338
+ Constraint * newConstraint ,bool recurse ,bool is_readd ,
339
+ LOCKMODE lockmode );
339
340
static void ATExecAddIndexConstraint (AlteredTableInfo * tab ,Relation rel ,
340
341
IndexStmt * stmt ,LOCKMODE lockmode );
341
342
static void ATAddCheckConstraint (List * * wqueue ,
342
343
AlteredTableInfo * tab ,Relation rel ,
343
344
Constraint * constr ,
344
- bool recurse ,bool recursing ,LOCKMODE lockmode );
345
+ bool recurse ,bool recursing ,bool is_readd ,
346
+ LOCKMODE lockmode );
345
347
static void ATAddForeignKeyConstraint (AlteredTableInfo * tab ,Relation rel ,
346
348
Constraint * fkconstraint ,LOCKMODE lockmode );
347
349
static void ATExecDropConstraint (Relation rel ,const char * constrName ,
@@ -2758,6 +2760,7 @@ AlterTableGetLockLevel(List *cmds)
2758
2760
case AT_ColumnDefault :
2759
2761
case AT_ProcessedConstraint :/* becomes AT_AddConstraint */
2760
2762
case AT_AddConstraintRecurse :/* becomes AT_AddConstraint */
2763
+ case AT_ReAddConstraint :/* becomes AT_AddConstraint */
2761
2764
case AT_EnableTrig :
2762
2765
case AT_EnableAlwaysTrig :
2763
2766
case AT_EnableReplicaTrig :
@@ -3249,11 +3252,15 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
3249
3252
break ;
3250
3253
case AT_AddConstraint :/* ADD CONSTRAINT */
3251
3254
ATExecAddConstraint (wqueue ,tab ,rel , (Constraint * )cmd -> def ,
3252
- false,lockmode );
3255
+ false,false, lockmode );
3253
3256
break ;
3254
3257
case AT_AddConstraintRecurse :/* ADD CONSTRAINT with recursion */
3255
3258
ATExecAddConstraint (wqueue ,tab ,rel , (Constraint * )cmd -> def ,
3256
- true,lockmode );
3259
+ true, false,lockmode );
3260
+ break ;
3261
+ case AT_ReAddConstraint :/* Re-add pre-existing check constraint */
3262
+ ATExecAddConstraint (wqueue ,tab ,rel , (Constraint * )cmd -> def ,
3263
+ false, true,lockmode );
3257
3264
break ;
3258
3265
case AT_AddIndexConstraint :/* ADD CONSTRAINT USING INDEX */
3259
3266
ATExecAddIndexConstraint (tab ,rel , (IndexStmt * )cmd -> def ,lockmode );
@@ -5500,7 +5507,8 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
5500
5507
*/
5501
5508
static void
5502
5509
ATExecAddConstraint (List * * wqueue ,AlteredTableInfo * tab ,Relation rel ,
5503
- Constraint * newConstraint ,bool recurse ,LOCKMODE lockmode )
5510
+ Constraint * newConstraint ,bool recurse ,bool is_readd ,
5511
+ LOCKMODE lockmode )
5504
5512
{
5505
5513
Assert (IsA (newConstraint ,Constraint ));
5506
5514
@@ -5513,7 +5521,8 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
5513
5521
{
5514
5522
case CONSTR_CHECK :
5515
5523
ATAddCheckConstraint (wqueue ,tab ,rel ,
5516
- newConstraint ,recurse , false,lockmode );
5524
+ newConstraint ,recurse , false,is_readd ,
5525
+ lockmode );
5517
5526
break ;
5518
5527
5519
5528
case CONSTR_FOREIGN :
@@ -5565,11 +5574,18 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
5565
5574
* AddRelationNewConstraints would normally assign different names to the
5566
5575
* child constraints. To fix that, we must capture the name assigned at
5567
5576
* the parent table and pass that down.
5577
+ *
5578
+ * When re-adding a previously existing constraint (during ALTER COLUMN TYPE),
5579
+ * we don't need to recurse here, because recursion will be carried out at a
5580
+ * higher level; the constraint name issue doesn't apply because the names
5581
+ * have already been assigned and are just being re-used. We need a separate
5582
+ * "is_readd" flag for that; just setting recurse=false would result in an
5583
+ * error if there are child tables.
5568
5584
*/
5569
5585
static void
5570
5586
ATAddCheckConstraint (List * * wqueue ,AlteredTableInfo * tab ,Relation rel ,
5571
5587
Constraint * constr ,bool recurse ,bool recursing ,
5572
- LOCKMODE lockmode )
5588
+ bool is_readd , LOCKMODE lockmode )
5573
5589
{
5574
5590
List * newcons ;
5575
5591
ListCell * lcon ;
@@ -5634,9 +5650,11 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
5634
5650
return ;
5635
5651
5636
5652
/*
5637
- * Adding a NO INHERIT constraint? No need to find our children
5653
+ * If adding a NO INHERIT constraint, no need to find our children.
5654
+ * Likewise, in a re-add operation, we don't need to recurse (that will be
5655
+ * handled at higher levels).
5638
5656
*/
5639
- if (constr -> is_no_inherit )
5657
+ if (constr -> is_no_inherit || is_readd )
5640
5658
return ;
5641
5659
5642
5660
/*
@@ -5671,7 +5689,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
5671
5689
5672
5690
/* Recurse to child */
5673
5691
ATAddCheckConstraint (wqueue ,childtab ,childrel ,
5674
- constr ,recurse , true,lockmode );
5692
+ constr ,recurse , true,is_readd , lockmode );
5675
5693
5676
5694
heap_close (childrel ,NoLock );
5677
5695
}
@@ -7862,6 +7880,10 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
7862
7880
/*
7863
7881
* Attach each generated command to the proper place in the work queue.
7864
7882
* Note this could result in creation of entirely new work-queue entries.
7883
+ *
7884
+ * Also note that we have to tweak the command subtypes, because it turns
7885
+ * out that re-creation of indexes and constraints has to act a bit
7886
+ * differently from initial creation.
7865
7887
*/
7866
7888
foreach (list_item ,querytree_list )
7867
7889
{
@@ -7919,6 +7941,7 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
7919
7941
if (con -> contype == CONSTR_FOREIGN &&
7920
7942
!rewrite && !tab -> rewrite )
7921
7943
TryReuseForeignKey (oldId ,con );
7944
+ cmd -> subtype = AT_ReAddConstraint ;
7922
7945
tab -> subcmds [AT_PASS_OLD_CONSTR ]=
7923
7946
lappend (tab -> subcmds [AT_PASS_OLD_CONSTR ],cmd );
7924
7947
break ;