@@ -335,13 +335,15 @@ static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
335335 IndexStmt * stmt , bool is_rebuild , LOCKMODE lockmode );
336336static void ATExecAddConstraint (List * * wqueue ,
337337 AlteredTableInfo * tab , Relation rel ,
338- Constraint * newConstraint , bool recurse , LOCKMODE lockmode );
338+ Constraint * newConstraint , bool recurse , bool is_readd ,
339+ LOCKMODE lockmode );
339340static void ATExecAddIndexConstraint (AlteredTableInfo * tab , Relation rel ,
340341 IndexStmt * stmt , LOCKMODE lockmode );
341342static void ATAddCheckConstraint (List * * wqueue ,
342343 AlteredTableInfo * tab , Relation rel ,
343344 Constraint * constr ,
344- bool recurse , bool recursing , LOCKMODE lockmode );
345+ bool recurse , bool recursing , bool is_readd ,
346+ LOCKMODE lockmode );
345347static void ATAddForeignKeyConstraint (AlteredTableInfo * tab , Relation rel ,
346348 Constraint * fkconstraint , LOCKMODE lockmode );
347349static void ATExecDropConstraint (Relation rel , const char * constrName ,
@@ -2758,6 +2760,7 @@ AlterTableGetLockLevel(List *cmds)
27582760 case AT_ColumnDefault :
27592761 case AT_ProcessedConstraint : /* becomes AT_AddConstraint */
27602762 case AT_AddConstraintRecurse : /* becomes AT_AddConstraint */
2763+ case AT_ReAddConstraint : /* becomes AT_AddConstraint */
27612764 case AT_EnableTrig :
27622765 case AT_EnableAlwaysTrig :
27632766 case AT_EnableReplicaTrig :
@@ -3249,11 +3252,15 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
32493252 break ;
32503253 case AT_AddConstraint : /* ADD CONSTRAINT */
32513254 ATExecAddConstraint (wqueue , tab , rel , (Constraint * ) cmd -> def ,
3252- false, lockmode );
3255+ false, false, lockmode );
32533256 break ;
32543257 case AT_AddConstraintRecurse : /* ADD CONSTRAINT with recursion */
32553258 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 );
32573264 break ;
32583265 case AT_AddIndexConstraint : /* ADD CONSTRAINT USING INDEX */
32593266 ATExecAddIndexConstraint (tab , rel , (IndexStmt * ) cmd -> def , lockmode );
@@ -5500,7 +5507,8 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
55005507 */
55015508static void
55025509ATExecAddConstraint (List * * wqueue , AlteredTableInfo * tab , Relation rel ,
5503- Constraint * newConstraint , bool recurse , LOCKMODE lockmode )
5510+ Constraint * newConstraint , bool recurse , bool is_readd ,
5511+ LOCKMODE lockmode )
55045512{
55055513 Assert (IsA (newConstraint , Constraint ));
55065514
@@ -5513,7 +5521,8 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
55135521 {
55145522 case CONSTR_CHECK :
55155523 ATAddCheckConstraint (wqueue , tab , rel ,
5516- newConstraint , recurse , false, lockmode );
5524+ newConstraint , recurse , false, is_readd ,
5525+ lockmode );
55175526 break ;
55185527
55195528 case CONSTR_FOREIGN :
@@ -5565,11 +5574,18 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
55655574 * AddRelationNewConstraints would normally assign different names to the
55665575 * child constraints. To fix that, we must capture the name assigned at
55675576 * 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.
55685584 */
55695585static void
55705586ATAddCheckConstraint (List * * wqueue , AlteredTableInfo * tab , Relation rel ,
55715587 Constraint * constr , bool recurse , bool recursing ,
5572- LOCKMODE lockmode )
5588+ bool is_readd , LOCKMODE lockmode )
55735589{
55745590 List * newcons ;
55755591 ListCell * lcon ;
@@ -5634,9 +5650,11 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
56345650 return ;
56355651
56365652 /*
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).
56385656 */
5639- if (constr -> is_no_inherit )
5657+ if (constr -> is_no_inherit || is_readd )
56405658 return ;
56415659
56425660 /*
@@ -5671,7 +5689,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
56715689
56725690 /* Recurse to child */
56735691 ATAddCheckConstraint (wqueue , childtab , childrel ,
5674- constr , recurse , true, lockmode );
5692+ constr , recurse , true, is_readd , lockmode );
56755693
56765694 heap_close (childrel , NoLock );
56775695 }
@@ -7862,6 +7880,10 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
78627880 /*
78637881 * Attach each generated command to the proper place in the work queue.
78647882 * 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.
78657887 */
78667888 foreach (list_item , querytree_list )
78677889 {
@@ -7919,6 +7941,7 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
79197941 if (con -> contype == CONSTR_FOREIGN &&
79207942 !rewrite && !tab -> rewrite )
79217943 TryReuseForeignKey (oldId , con );
7944+ cmd -> subtype = AT_ReAddConstraint ;
79227945 tab -> subcmds [AT_PASS_OLD_CONSTR ] =
79237946 lappend (tab -> subcmds [AT_PASS_OLD_CONSTR ], cmd );
79247947 break ;
0 commit comments