diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index d062cfddac..188399cc12 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -204,6 +204,13 @@ ExecInitAppend(Append *node, EState *estate, int eflags) appendplanstates = (PlanState **) palloc(nplans * sizeof(PlanState *)); + /* + * We must determine the first valid partial plan. Default this to point + * beyond the final valid plan. We'll determine the actual first valid + * partial subplan in the loop below. + */ + appendstate->as_first_partial_plan = nplans; + /* * call ExecInitNode on each of the valid plans to be executed and save * the results into the appendplanstates array. @@ -215,6 +222,13 @@ ExecInitAppend(Append *node, EState *estate, int eflags) { Plan *initNode = (Plan *) lfirst(lc); + /* + * Record the lowest appendplanstates index which is a partial + * plan. + */ + if (i >= node->first_partial_plan && j < appendstate->as_first_partial_plan) + appendstate->as_first_partial_plan = j; + appendplanstates[j++] = ExecInitNode(initNode, estate, eflags); } i++; @@ -556,7 +570,7 @@ choose_next_subplan_for_leader(AppendState *node) } /* If non-partial, immediately mark as finished. */ - if (node->as_whichplan < append->first_partial_plan) + if (node->as_whichplan < node->as_first_partial_plan) node->as_pstate->pa_finished[node->as_whichplan] = true; LWLockRelease(&pstate->pa_lock); @@ -629,14 +643,14 @@ choose_next_subplan_for_worker(AppendState *node) /* Advance to the next valid plan. */ pstate->pa_next_plan = nextplan; } - else if (node->as_whichplan > append->first_partial_plan) + else if (node->as_whichplan > node->as_first_partial_plan) { /* * Try looping back to the first valid partial plan, if there is * one. If there isn't, arrange to bail out below. */ nextplan = bms_next_member(node->as_valid_subplans, - append->first_partial_plan - 1); + node->as_first_partial_plan - 1); pstate->pa_next_plan = nextplan < 0 ? node->as_whichplan : nextplan; } @@ -670,7 +684,7 @@ choose_next_subplan_for_worker(AppendState *node) if (pstate->pa_next_plan < 0) { int nextplan = bms_next_member(node->as_valid_subplans, - append->first_partial_plan - 1); + node->as_first_partial_plan - 1); if (nextplan >= 0) pstate->pa_next_plan = nextplan; @@ -686,7 +700,7 @@ choose_next_subplan_for_worker(AppendState *node) } /* If non-partial, immediately mark as finished. */ - if (node->as_whichplan < append->first_partial_plan) + if (node->as_whichplan < node->as_first_partial_plan) node->as_pstate->pa_finished[node->as_whichplan] = true; LWLockRelease(&pstate->pa_lock); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index deab875466..cff64337e2 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1150,6 +1150,8 @@ struct AppendState PlanState **appendplans; /* array of PlanStates for my inputs */ int as_nplans; int as_whichplan; + int as_first_partial_plan; /* Index of 'appendplans' containing + * the first partial plan */ ParallelAppendState *as_pstate; /* parallel coordination info */ Size pstate_len; /* size of parallel coordination info */ struct PartitionPruneState *as_prune_state;