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