@@ -4513,19 +4513,25 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
4513
4513
lockmode);
4514
4514
break;
4515
4515
case AT_AddConstraint: /* ADD CONSTRAINT */
4516
- cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, false, lockmode,
4517
- cur_pass, context);
4518
- /* Might not have gotten AddConstraint back from parse transform */
4516
+ /* Transform the command only during initial examination */
4517
+ if (cur_pass == AT_PASS_ADD_CONSTR)
4518
+ cmd = ATParseTransformCmd(wqueue, tab, rel, cmd,
4519
+ false, lockmode,
4520
+ cur_pass, context);
4521
+ /* Depending on constraint type, might be no more work to do now */
4519
4522
if (cmd != NULL)
4520
4523
address =
4521
4524
ATExecAddConstraint(wqueue, tab, rel,
4522
4525
(Constraint *) cmd->def,
4523
4526
false, false, lockmode);
4524
4527
break;
4525
4528
case AT_AddConstraintRecurse: /* ADD CONSTRAINT with recursion */
4526
- cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, true, lockmode,
4527
- cur_pass, context);
4528
- /* Might not have gotten AddConstraint back from parse transform */
4529
+ /* Transform the command only during initial examination */
4530
+ if (cur_pass == AT_PASS_ADD_CONSTR)
4531
+ cmd = ATParseTransformCmd(wqueue, tab, rel, cmd,
4532
+ true, lockmode,
4533
+ cur_pass, context);
4534
+ /* Depending on constraint type, might be no more work to do now */
4529
4535
if (cmd != NULL)
4530
4536
address =
4531
4537
ATExecAddConstraint(wqueue, tab, rel,
@@ -4787,75 +4793,88 @@ ATParseTransformCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
4787
4793
foreach(lc, atstmt->cmds)
4788
4794
{
4789
4795
AlterTableCmd *cmd2 = lfirst_node(AlterTableCmd, lc);
4796
+ int pass;
4797
+
4798
+ /*
4799
+ * This switch need only cover the subcommand types that can be added
4800
+ * by parse_utilcmd.c; otherwise, we'll use the default strategy of
4801
+ * executing the subcommand immediately, as a substitute for the
4802
+ * original subcommand. (Note, however, that this does cause
4803
+ * AT_AddConstraint subcommands to be rescheduled into later passes,
4804
+ * which is important for index and foreign key constraints.)
4805
+ *
4806
+ * We assume we needn't do any phase-1 checks for added subcommands.
4807
+ */
4808
+ switch (cmd2->subtype)
4809
+ {
4810
+ case AT_SetNotNull:
4811
+ /* Need command-specific recursion decision */
4812
+ ATPrepSetNotNull(wqueue, rel, cmd2,
4813
+ recurse, false,
4814
+ lockmode, context);
4815
+ pass = AT_PASS_COL_ATTRS;
4816
+ break;
4817
+ case AT_AddIndex:
4818
+ /* This command never recurses */
4819
+ /* No command-specific prep needed */
4820
+ pass = AT_PASS_ADD_INDEX;
4821
+ break;
4822
+ case AT_AddIndexConstraint:
4823
+ /* This command never recurses */
4824
+ /* No command-specific prep needed */
4825
+ pass = AT_PASS_ADD_INDEXCONSTR;
4826
+ break;
4827
+ case AT_AddConstraint:
4828
+ /* Recursion occurs during execution phase */
4829
+ if (recurse)
4830
+ cmd2->subtype = AT_AddConstraintRecurse;
4831
+ switch (castNode(Constraint, cmd2->def)->contype)
4832
+ {
4833
+ case CONSTR_PRIMARY:
4834
+ case CONSTR_UNIQUE:
4835
+ case CONSTR_EXCLUSION:
4836
+ pass = AT_PASS_ADD_INDEXCONSTR;
4837
+ break;
4838
+ default:
4839
+ pass = AT_PASS_ADD_OTHERCONSTR;
4840
+ break;
4841
+ }
4842
+ break;
4843
+ case AT_AlterColumnGenericOptions:
4844
+ /* This command never recurses */
4845
+ /* No command-specific prep needed */
4846
+ pass = AT_PASS_MISC;
4847
+ break;
4848
+ default:
4849
+ pass = cur_pass;
4850
+ break;
4851
+ }
4790
4852
4791
- if (newcmd == NULL &&
4792
- (cmd->subtype == cmd2->subtype ||
4793
- (cmd->subtype == AT_AddConstraintRecurse &&
4794
- cmd2->subtype == AT_AddConstraint)))
4853
+ if (pass < cur_pass)
4854
+ {
4855
+ /* Cannot schedule into a pass we already finished */
4856
+ elog(ERROR, "ALTER TABLE scheduling failure: too late for pass %d",
4857
+ pass);
4858
+ }
4859
+ else if (pass > cur_pass)
4795
4860
{
4796
- /* Found the transformed version of our subcommand */
4797
- cmd2->subtype = cmd->subtype; /* copy recursion flag */
4798
- newcmd = cmd2;
4861
+ /* OK, queue it up for later */
4862
+ tab->subcmds[pass] = lappend(tab->subcmds[pass], cmd2);
4799
4863
}
4800
4864
else
4801
4865
{
4802
- int pass;
4803
-
4804
4866
/*
4805
- * Schedule added subcommand appropriately. We assume we needn't
4806
- * do any phase-1 checks for it. This switch only has to cover
4807
- * the subcommand types that can be added by parse_utilcmd.c.
4867
+ * We should see at most one subcommand for the current pass,
4868
+ * which is the transformed version of the original subcommand.
4808
4869
*/
4809
- switch ( cmd2->subtype)
4870
+ if (newcmd == NULL && cmd->subtype == cmd2->subtype)
4810
4871
{
4811
- case AT_SetNotNull:
4812
- /* Need command-specific recursion decision */
4813
- ATPrepSetNotNull(wqueue, rel, cmd2,
4814
- recurse, false,
4815
- lockmode, context);
4816
- pass = AT_PASS_COL_ATTRS;
4817
- break;
4818
- case AT_AddIndex:
4819
- /* This command never recurses */
4820
- /* No command-specific prep needed */
4821
- pass = AT_PASS_ADD_INDEX;
4822
- break;
4823
- case AT_AddIndexConstraint:
4824
- /* This command never recurses */
4825
- /* No command-specific prep needed */
4826
- pass = AT_PASS_ADD_INDEXCONSTR;
4827
- break;
4828
- case AT_AddConstraint:
4829
- /* Recursion occurs during execution phase */
4830
- if (recurse)
4831
- cmd2->subtype = AT_AddConstraintRecurse;
4832
- switch (castNode(Constraint, cmd2->def)->contype)
4833
- {
4834
- case CONSTR_PRIMARY:
4835
- case CONSTR_UNIQUE:
4836
- case CONSTR_EXCLUSION:
4837
- pass = AT_PASS_ADD_INDEXCONSTR;
4838
- break;
4839
- default:
4840
- pass = AT_PASS_ADD_OTHERCONSTR;
4841
- break;
4842
- }
4843
- break;
4844
- case AT_AlterColumnGenericOptions:
4845
- /* This command never recurses */
4846
- /* No command-specific prep needed */
4847
- pass = AT_PASS_MISC;
4848
- break;
4849
- default:
4850
- elog(ERROR, "unexpected AlterTableType: %d",
4851
- (int) cmd2->subtype);
4852
- pass = AT_PASS_UNSET;
4853
- break;
4872
+ /* Found the transformed version of our subcommand */
4873
+ newcmd = cmd2;
4854
4874
}
4855
- /* Must be for a later pass than we're currently doing */
4856
- if (pass <= cur_pass)
4857
- elog(ERROR, "ALTER TABLE scheduling failure");
4858
- tab->subcmds[pass] = lappend(tab->subcmds[pass], cmd2);
4875
+ else
4876
+ elog(ERROR, "ALTER TABLE scheduling failure: bogus item for pass %d",
4877
+ pass);
4859
4878
}
4860
4879
}
4861
4880
0 commit comments