diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 359d478..50c93fe 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -335,13 +335,15 @@ static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel, IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode); static void ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, - Constraint *newConstraint, bool recurse, LOCKMODE lockmode); + Constraint *newConstraint, bool recurse, bool check_no_children, + LOCKMODE lockmode); static void ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, IndexStmt *stmt, LOCKMODE lockmode); static void ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Constraint *constr, - bool recurse, bool recursing, LOCKMODE lockmode); + bool recurse, bool recursing, bool check_no_children, + LOCKMODE lockmode); static void ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, Constraint *fkconstraint, LOCKMODE lockmode); static void ATExecDropConstraint(Relation rel, const char *constrName, @@ -3248,11 +3250,15 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, break; case AT_AddConstraint: /* ADD CONSTRAINT */ ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, - false, lockmode); + false, true, lockmode); + break; + case AT_ReAddConstraint: /* Re-add previously dropped CONSTRAINT */ + ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, + false, false, lockmode); break; case AT_AddConstraintRecurse: /* ADD CONSTRAINT with recursion */ ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, - true, lockmode); + true, true, lockmode); break; case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */ ATExecAddIndexConstraint(tab, rel, (IndexStmt *) cmd->def, lockmode); @@ -5499,7 +5505,8 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, */ static void ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, - Constraint *newConstraint, bool recurse, LOCKMODE lockmode) + Constraint *newConstraint, bool recurse, bool check_no_children, + LOCKMODE lockmode) { Assert(IsA(newConstraint, Constraint)); @@ -5512,7 +5519,8 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, { case CONSTR_CHECK: ATAddCheckConstraint(wqueue, tab, rel, - newConstraint, recurse, false, lockmode); + newConstraint, recurse, false, check_no_children, + lockmode); break; case CONSTR_FOREIGN: @@ -5568,7 +5576,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, static void ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Constraint *constr, bool recurse, bool recursing, - LOCKMODE lockmode) + bool check_no_children, LOCKMODE lockmode) { List *newcons; ListCell *lcon; @@ -5646,14 +5654,24 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, children = find_inheritance_children(RelationGetRelid(rel), lockmode); /* - * Check if ONLY was specified with ALTER TABLE. If so, allow the - * contraint creation only if there are no children currently. Error out - * otherwise. + * Check if either ONLY was specified with ALTER TABLE or if we are adding + * back a constraint in AT_PASS_OLD_CONSTR pass, that was previously + * dropped constraint. We don't recurse in both the cases. */ - if (!recurse && children != NIL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("constraint must be added to child tables too"))); + if (!recurse) + { + /* + * We have been told not to recurse. Unless we have been explicitly + * told not to check for exitsing children, error out if there are + * existing children + */ + if (check_no_children && children != NIL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("constraint must be added to child tables too"))); + else + return; + } foreach(child, children) { @@ -5670,7 +5688,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, /* Recurse to child */ ATAddCheckConstraint(wqueue, childtab, childrel, - constr, recurse, true, lockmode); + constr, recurse, true, true, lockmode); heap_close(childrel, NoLock); } @@ -7914,6 +7932,7 @@ ATPostAlterTypeParse(Oid oldId, char *cmd, case AT_AddConstraint: Assert(IsA(cmd->def, Constraint)); con = (Constraint *) cmd->def; + cmd->subtype = AT_ReAddConstraint; /* rewriting neither side of a FK */ if (con->contype == CONSTR_FOREIGN && !rewrite && !tab->rewrite) diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 09b15e7..b58fa82 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1196,6 +1196,7 @@ typedef enum AlterTableType AT_AddIndex, /* add index */ AT_ReAddIndex, /* internal to commands/tablecmds.c */ AT_AddConstraint, /* add constraint */ + AT_ReAddConstraint, /* re-add previously dropped constraint */ AT_AddConstraintRecurse, /* internal to commands/tablecmds.c */ AT_ValidateConstraint, /* validate constraint */ AT_ValidateConstraintRecurse, /* internal to commands/tablecmds.c */