@@ -323,13 +323,15 @@ static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
323
323
IndexStmt * stmt , bool is_rebuild , LOCKMODE lockmode );
324
324
static void ATExecAddConstraint (List * * wqueue ,
325
325
AlteredTableInfo * tab , Relation rel ,
326
- Constraint * newConstraint , bool recurse , LOCKMODE lockmode );
326
+ Constraint * newConstraint , bool recurse , bool is_readd ,
327
+ LOCKMODE lockmode );
327
328
static void ATExecAddIndexConstraint (AlteredTableInfo * tab , Relation rel ,
328
329
IndexStmt * stmt , LOCKMODE lockmode );
329
330
static void ATAddCheckConstraint (List * * wqueue ,
330
331
AlteredTableInfo * tab , Relation rel ,
331
332
Constraint * constr ,
332
- bool recurse , bool recursing , LOCKMODE lockmode );
333
+ bool recurse , bool recursing , bool is_readd ,
334
+ LOCKMODE lockmode );
333
335
static void ATAddForeignKeyConstraint (AlteredTableInfo * tab , Relation rel ,
334
336
Constraint * fkconstraint , LOCKMODE lockmode );
335
337
static void ATExecDropConstraint (Relation rel , const char * constrName ,
@@ -2560,6 +2562,7 @@ AlterTableGetLockLevel(List *cmds)
2560
2562
case AT_ColumnDefault :
2561
2563
case AT_ProcessedConstraint : /* becomes AT_AddConstraint */
2562
2564
case AT_AddConstraintRecurse : /* becomes AT_AddConstraint */
2565
+ case AT_ReAddConstraint : /* becomes AT_AddConstraint */
2563
2566
case AT_EnableTrig :
2564
2567
case AT_EnableAlwaysTrig :
2565
2568
case AT_EnableReplicaTrig :
@@ -3036,11 +3039,15 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
3036
3039
break ;
3037
3040
case AT_AddConstraint : /* ADD CONSTRAINT */
3038
3041
ATExecAddConstraint (wqueue , tab , rel , (Constraint * ) cmd -> def ,
3039
- false, lockmode );
3042
+ false, false, lockmode );
3040
3043
break ;
3041
3044
case AT_AddConstraintRecurse : /* ADD CONSTRAINT with recursion */
3042
3045
ATExecAddConstraint (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 );
3044
3051
break ;
3045
3052
case AT_AddIndexConstraint : /* ADD CONSTRAINT USING INDEX */
3046
3053
ATExecAddIndexConstraint (tab , rel , (IndexStmt * ) cmd -> def , lockmode );
@@ -5235,7 +5242,8 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
5235
5242
*/
5236
5243
static void
5237
5244
ATExecAddConstraint (List * * wqueue , AlteredTableInfo * tab , Relation rel ,
5238
- Constraint * newConstraint , bool recurse , LOCKMODE lockmode )
5245
+ Constraint * newConstraint , bool recurse , bool is_readd ,
5246
+ LOCKMODE lockmode )
5239
5247
{
5240
5248
Assert (IsA (newConstraint , Constraint ));
5241
5249
@@ -5248,7 +5256,8 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
5248
5256
{
5249
5257
case CONSTR_CHECK :
5250
5258
ATAddCheckConstraint (wqueue , tab , rel ,
5251
- newConstraint , recurse , false, lockmode );
5259
+ newConstraint , recurse , false, is_readd ,
5260
+ lockmode );
5252
5261
break ;
5253
5262
5254
5263
case CONSTR_FOREIGN :
@@ -5300,11 +5309,18 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
5300
5309
* AddRelationNewConstraints would normally assign different names to the
5301
5310
* child constraints. To fix that, we must capture the name assigned at
5302
5311
* 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.
5303
5319
*/
5304
5320
static void
5305
5321
ATAddCheckConstraint (List * * wqueue , AlteredTableInfo * tab , Relation rel ,
5306
5322
Constraint * constr , bool recurse , bool recursing ,
5307
- LOCKMODE lockmode )
5323
+ bool is_readd , LOCKMODE lockmode )
5308
5324
{
5309
5325
List * newcons ;
5310
5326
ListCell * lcon ;
@@ -5363,6 +5379,13 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
5363
5379
if (newcons == NIL )
5364
5380
return ;
5365
5381
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
+
5366
5389
/*
5367
5390
* Propagate to children as appropriate. Unlike most other ALTER
5368
5391
* 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,
5394
5417
5395
5418
/* Recurse to child */
5396
5419
ATAddCheckConstraint (wqueue , childtab , childrel ,
5397
- constr , recurse , true, lockmode );
5420
+ constr , recurse , true, is_readd , lockmode );
5398
5421
5399
5422
heap_close (childrel , NoLock );
5400
5423
}
@@ -7220,6 +7243,10 @@ ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode)
7220
7243
/*
7221
7244
* Attach each generated command to the proper place in the work queue.
7222
7245
* 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.
7223
7250
*/
7224
7251
foreach (list_item , querytree_list )
7225
7252
{
@@ -7263,6 +7290,7 @@ ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode)
7263
7290
lappend (tab -> subcmds [AT_PASS_OLD_INDEX ], cmd );
7264
7291
break ;
7265
7292
case AT_AddConstraint :
7293
+ cmd -> subtype = AT_ReAddConstraint ;
7266
7294
tab -> subcmds [AT_PASS_OLD_CONSTR ] =
7267
7295
lappend (tab -> subcmds [AT_PASS_OLD_CONSTR ], cmd );
7268
7296
break ;
0 commit comments