@@ -335,13 +335,15 @@ static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
335335IndexStmt * stmt ,bool is_rebuild ,LOCKMODE lockmode );
336336static void ATExecAddConstraint (List * * wqueue ,
337337AlteredTableInfo * 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 ,
340341IndexStmt * stmt ,LOCKMODE lockmode );
341342static void ATAddCheckConstraint (List * * wqueue ,
342343AlteredTableInfo * tab ,Relation rel ,
343344Constraint * 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 ,
346348Constraint * fkconstraint ,LOCKMODE lockmode );
347349static void ATExecDropConstraint (Relation rel ,const char * constrName ,
@@ -2758,6 +2760,7 @@ AlterTableGetLockLevel(List *cmds)
27582760case AT_ColumnDefault :
27592761case AT_ProcessedConstraint :/* becomes AT_AddConstraint */
27602762case AT_AddConstraintRecurse :/* becomes AT_AddConstraint */
2763+ case AT_ReAddConstraint :/* becomes AT_AddConstraint */
27612764case AT_EnableTrig :
27622765case AT_EnableAlwaysTrig :
27632766case AT_EnableReplicaTrig :
@@ -3249,11 +3252,15 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
32493252break ;
32503253case AT_AddConstraint :/* ADD CONSTRAINT */
32513254ATExecAddConstraint (wqueue ,tab ,rel , (Constraint * )cmd -> def ,
3252- false,lockmode );
3255+ false,false, lockmode );
32533256break ;
32543257case AT_AddConstraintRecurse :/* ADD CONSTRAINT with recursion */
32553258ATExecAddConstraint (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 );
32573264break ;
32583265case AT_AddIndexConstraint :/* ADD CONSTRAINT USING INDEX */
32593266ATExecAddIndexConstraint (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{
55055513Assert (IsA (newConstraint ,Constraint ));
55065514
@@ -5513,7 +5521,8 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
55135521{
55145522case CONSTR_CHECK :
55155523ATAddCheckConstraint (wqueue ,tab ,rel ,
5516- newConstraint ,recurse , false,lockmode );
5524+ newConstraint ,recurse , false,is_readd ,
5525+ lockmode );
55175526break ;
55185527
55195528case 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 ,
55715587Constraint * constr ,bool recurse ,bool recursing ,
5572- LOCKMODE lockmode )
5588+ bool is_readd , LOCKMODE lockmode )
55735589{
55745590List * newcons ;
55755591ListCell * lcon ;
@@ -5634,9 +5650,11 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
56345650return ;
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 )
56405658return ;
56415659
56425660/*
@@ -5671,7 +5689,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
56715689
56725690/* Recurse to child */
56735691ATAddCheckConstraint (wqueue ,childtab ,childrel ,
5674- constr ,recurse , true,lockmode );
5692+ constr ,recurse , true,is_readd , lockmode );
56755693
56765694heap_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 */
78667888foreach (list_item ,querytree_list )
78677889{
@@ -7919,6 +7941,7 @@ ATPostAlterTypeParse(Oid oldId, char *cmd,
79197941if (con -> contype == CONSTR_FOREIGN &&
79207942!rewrite && !tab -> rewrite )
79217943TryReuseForeignKey (oldId ,con );
7944+ cmd -> subtype = AT_ReAddConstraint ;
79227945tab -> subcmds [AT_PASS_OLD_CONSTR ]=
79237946lappend (tab -> subcmds [AT_PASS_OLD_CONSTR ],cmd );
79247947break ;