@@ -323,13 +323,15 @@ static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
323323IndexStmt * stmt ,bool is_rebuild ,LOCKMODE lockmode );
324324static void ATExecAddConstraint (List * * wqueue ,
325325AlteredTableInfo * tab ,Relation rel ,
326- Constraint * newConstraint ,bool recurse ,LOCKMODE lockmode );
326+ Constraint * newConstraint ,bool recurse ,bool is_readd ,
327+ LOCKMODE lockmode );
327328static void ATExecAddIndexConstraint (AlteredTableInfo * tab ,Relation rel ,
328329IndexStmt * stmt ,LOCKMODE lockmode );
329330static void ATAddCheckConstraint (List * * wqueue ,
330331AlteredTableInfo * tab ,Relation rel ,
331332Constraint * constr ,
332- bool recurse ,bool recursing ,LOCKMODE lockmode );
333+ bool recurse ,bool recursing ,bool is_readd ,
334+ LOCKMODE lockmode );
333335static void ATAddForeignKeyConstraint (AlteredTableInfo * tab ,Relation rel ,
334336Constraint * fkconstraint ,LOCKMODE lockmode );
335337static void ATExecDropConstraint (Relation rel ,const char * constrName ,
@@ -2560,6 +2562,7 @@ AlterTableGetLockLevel(List *cmds)
25602562case AT_ColumnDefault :
25612563case AT_ProcessedConstraint :/* becomes AT_AddConstraint */
25622564case AT_AddConstraintRecurse :/* becomes AT_AddConstraint */
2565+ case AT_ReAddConstraint :/* becomes AT_AddConstraint */
25632566case AT_EnableTrig :
25642567case AT_EnableAlwaysTrig :
25652568case AT_EnableReplicaTrig :
@@ -3036,11 +3039,15 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
30363039break ;
30373040case AT_AddConstraint :/* ADD CONSTRAINT */
30383041ATExecAddConstraint (wqueue ,tab ,rel , (Constraint * )cmd -> def ,
3039- false,lockmode );
3042+ false,false, lockmode );
30403043break ;
30413044case AT_AddConstraintRecurse :/* ADD CONSTRAINT with recursion */
30423045ATExecAddConstraint (wqueue ,tab ,rel , (Constraint * )cmd -> def ,
3043- true,lockmode );
3046+ true, false,lockmode );
3047+ break ;
3048+ case AT_ReAddConstraint :/* Re-add pre-existing check constraint */
3049+ ATExecAddConstraint (wqueue ,tab ,rel , (Constraint * )cmd -> def ,
3050+ false, true,lockmode );
30443051break ;
30453052case AT_AddIndexConstraint :/* ADD CONSTRAINT USING INDEX */
30463053ATExecAddIndexConstraint (tab ,rel , (IndexStmt * )cmd -> def ,lockmode );
@@ -5235,7 +5242,8 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
52355242 */
52365243static void
52375244ATExecAddConstraint (List * * wqueue ,AlteredTableInfo * tab ,Relation rel ,
5238- Constraint * newConstraint ,bool recurse ,LOCKMODE lockmode )
5245+ Constraint * newConstraint ,bool recurse ,bool is_readd ,
5246+ LOCKMODE lockmode )
52395247{
52405248Assert (IsA (newConstraint ,Constraint ));
52415249
@@ -5248,7 +5256,8 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
52485256{
52495257case CONSTR_CHECK :
52505258ATAddCheckConstraint (wqueue ,tab ,rel ,
5251- newConstraint ,recurse , false,lockmode );
5259+ newConstraint ,recurse , false,is_readd ,
5260+ lockmode );
52525261break ;
52535262
52545263case CONSTR_FOREIGN :
@@ -5300,11 +5309,18 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
53005309 * AddRelationNewConstraints would normally assign different names to the
53015310 * child constraints. To fix that, we must capture the name assigned at
53025311 * the parent table and pass that down.
5312+ *
5313+ * When re-adding a previously existing constraint (during ALTER COLUMN TYPE),
5314+ * we don't need to recurse here, because recursion will be carried out at a
5315+ * higher level; the constraint name issue doesn't apply because the names
5316+ * have already been assigned and are just being re-used. We need a separate
5317+ * "is_readd" flag for that; just setting recurse=false would result in an
5318+ * error if there are child tables.
53035319 */
53045320static void
53055321ATAddCheckConstraint (List * * wqueue ,AlteredTableInfo * tab ,Relation rel ,
53065322Constraint * constr ,bool recurse ,bool recursing ,
5307- LOCKMODE lockmode )
5323+ bool is_readd , LOCKMODE lockmode )
53085324{
53095325List * newcons ;
53105326ListCell * lcon ;
@@ -5363,6 +5379,13 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
53635379if (newcons == NIL )
53645380return ;
53655381
5382+ /*
5383+ * Also, in a re-add operation, we don't need to recurse (that will be
5384+ * handled at higher levels).
5385+ */
5386+ if (is_readd )
5387+ return ;
5388+
53665389/*
53675390 * Propagate to children as appropriate. Unlike most other ALTER
53685391 * routines, we have to do this one level of recursion at a time; we can't
@@ -5394,7 +5417,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
53945417
53955418/* Recurse to child */
53965419ATAddCheckConstraint (wqueue ,childtab ,childrel ,
5397- constr ,recurse , true,lockmode );
5420+ constr ,recurse , true,is_readd , lockmode );
53985421
53995422heap_close (childrel ,NoLock );
54005423}
@@ -7220,6 +7243,10 @@ ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode)
72207243/*
72217244 * Attach each generated command to the proper place in the work queue.
72227245 * Note this could result in creation of entirely new work-queue entries.
7246+ *
7247+ * Also note that we have to tweak the command subtypes, because it turns
7248+ * out that re-creation of indexes and constraints has to act a bit
7249+ * differently from initial creation.
72237250 */
72247251foreach (list_item ,querytree_list )
72257252{
@@ -7263,6 +7290,7 @@ ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode)
72637290lappend (tab -> subcmds [AT_PASS_OLD_INDEX ],cmd );
72647291break ;
72657292case AT_AddConstraint :
7293+ cmd -> subtype = AT_ReAddConstraint ;
72667294tab -> subcmds [AT_PASS_OLD_CONSTR ]=
72677295lappend (tab -> subcmds [AT_PASS_OLD_CONSTR ],cmd );
72687296break ;