first_partial_plan_fix.patch
application/octet-stream
Filename: first_partial_plan_fix.patch
Type: application/octet-stream
Part: 2
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/executor/nodeAppend.c | 19 | 5 |
| src/include/nodes/execnodes.h | 2 | 0 |
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;