aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/nodeAppend.c2
-rw-r--r--src/backend/executor/nodeMergeAppend.c137
2 files changed, 117 insertions, 22 deletions
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 5ce4fb43e1a..e7188b2d310 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -151,7 +151,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
/*
* The case where no subplans survive pruning must be handled
* specially. The problem here is that code in explain.c requires
- * an Append to have at least one subplan in order for it to
+ * a MergeAppend to have at least one subplan in order for it to
* properly determine the Vars in that subplan's targetlist. We
* sidestep this issue by just initializing the first subplan and
* setting as_whichplan to NO_MATCHING_SUBPLANS to indicate that
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index 118f4ef07df..ec8a49c3a84 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -39,6 +39,7 @@
#include "postgres.h"
#include "executor/execdebug.h"
+#include "executor/execPartition.h"
#include "executor/nodeMergeAppend.h"
#include "lib/binaryheap.h"
#include "miscadmin.h"
@@ -65,8 +66,10 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
{
MergeAppendState *mergestate = makeNode(MergeAppendState);
PlanState **mergeplanstates;
+ Bitmapset *validsubplans;
int nplans;
- int i;
+ int i,
+ j;
ListCell *lc;
/* check for unsupported flags */
@@ -79,18 +82,79 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
ExecLockNonLeafAppendTables(node->partitioned_rels, estate);
/*
- * Set up empty vector of subplan states
- */
- nplans = list_length(node->mergeplans);
-
- mergeplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
-
- /*
* create new MergeAppendState for our node
*/
mergestate->ps.plan = (Plan *) node;
mergestate->ps.state = estate;
mergestate->ps.ExecProcNode = ExecMergeAppend;
+ mergestate->ms_noopscan = false;
+
+ /* If run-time partition pruning is enabled, then set that up now */
+ if (node->part_prune_infos != NIL)
+ {
+ PartitionPruneState *prunestate;
+
+ /* We may need an expression context to evaluate partition exprs */
+ ExecAssignExprContext(estate, &mergestate->ps);
+
+ prunestate = ExecCreatePartitionPruneState(&mergestate->ps,
+ node->part_prune_infos);
+ mergestate->ms_prune_state = prunestate;
+
+ /* Perform an initial partition prune, if required. */
+ if (prunestate->do_initial_prune)
+ {
+ /* Determine which subplans survive initial pruning */
+ validsubplans = ExecFindInitialMatchingSubPlans(prunestate,
+ list_length(node->mergeplans));
+
+ /*
+ * The case where no subplans survive pruning must be handled
+ * specially. The problem here is that code in explain.c requires
+ * an Append to have at least one subplan in order for it to
+ * properly determine the Vars in that subplan's targetlist. We
+ * sidestep this issue by just initializing the first subplan and
+ * setting ms_noopscan to true to indicate that we don't really
+ * need to scan any subnodes.
+ */
+ if (bms_is_empty(validsubplans))
+ {
+ mergestate->ms_noopscan = true;
+
+ /* Mark the first as valid so that it's initialized below */
+ validsubplans = bms_make_singleton(0);
+ }
+
+ nplans = bms_num_members(validsubplans);
+ }
+ else
+ {
+ /* We'll need to initialize all subplans */
+ nplans = list_length(node->mergeplans);
+ validsubplans = bms_add_range(NULL, 0, nplans - 1);
+ }
+
+ /*
+ * If no runtime pruning is required, we can fill ms_valid_subplans
+ * immediately, preventing later calls to ExecFindMatchingSubPlans.
+ */
+ if (!prunestate->do_exec_prune)
+ mergestate->ms_valid_subplans = bms_add_range(NULL, 0, nplans - 1);
+ }
+ else
+ {
+ nplans = list_length(node->mergeplans);
+
+ /*
+ * When run-time partition pruning is not enabled we can just mark all
+ * subplans as valid; they must also all be initialized.
+ */
+ mergestate->ms_valid_subplans = validsubplans =
+ bms_add_range(NULL, 0, nplans - 1);
+ mergestate->ms_prune_state = NULL;
+ }
+
+ mergeplanstates = (PlanState **) palloc(nplans * sizeof(PlanState *));
mergestate->mergeplans = mergeplanstates;
mergestate->ms_nplans = nplans;
@@ -101,26 +165,24 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
/*
* Miscellaneous initialization
*
- * MergeAppend plans don't have expression contexts because they never
- * call ExecQual or ExecProject.
- */
-
- /*
* MergeAppend nodes do have Result slots, which hold pointers to tuples,
* so we have to initialize them.
*/
ExecInitResultTupleSlotTL(estate, &mergestate->ps);
/*
- * call ExecInitNode on each of the plans to be executed and save the
- * results into the array "mergeplans".
+ * call ExecInitNode on each of the valid plans to be executed and save
+ * the results into the mergeplanstates array.
*/
- i = 0;
+ j = i = 0;
foreach(lc, node->mergeplans)
{
- Plan *initNode = (Plan *) lfirst(lc);
+ if (bms_is_member(i, validsubplans))
+ {
+ Plan *initNode = (Plan *) lfirst(lc);
- mergeplanstates[i] = ExecInitNode(initNode, estate, eflags);
+ mergeplanstates[j++] = ExecInitNode(initNode, estate, eflags);
+ }
i++;
}
@@ -178,11 +240,25 @@ ExecMergeAppend(PlanState *pstate)
if (!node->ms_initialized)
{
+ /* Nothing to do if all subplans were pruned */
+ if (node->ms_noopscan)
+ return ExecClearTuple(node->ps.ps_ResultTupleSlot);
+
/*
- * First time through: pull the first tuple from each subplan, and set
- * up the heap.
+ * If we've yet to determine the valid subplans then do so now. If
+ * run-time pruning is disabled then the valid subplans will always be
+ * set to all subplans.
*/
- for (i = 0; i < node->ms_nplans; i++)
+ if (node->ms_valid_subplans == NULL)
+ node->ms_valid_subplans =
+ ExecFindMatchingSubPlans(node->ms_prune_state);
+
+ /*
+ * First time through: pull the first tuple from each valid subplan,
+ * and set up the heap.
+ */
+ i = -1;
+ while ((i = bms_next_member(node->ms_valid_subplans, i)) >= 0)
{
node->ms_slots[i] = ExecProcNode(node->mergeplans[i]);
if (!TupIsNull(node->ms_slots[i]))
@@ -288,6 +364,12 @@ ExecEndMergeAppend(MergeAppendState *node)
*/
for (i = 0; i < nplans; i++)
ExecEndNode(mergeplans[i]);
+
+ /*
+ * release any resources associated with run-time pruning
+ */
+ if (node->ms_prune_state)
+ ExecDestroyPartitionPruneState(node->ms_prune_state);
}
void
@@ -295,6 +377,19 @@ ExecReScanMergeAppend(MergeAppendState *node)
{
int i;
+ /*
+ * If any PARAM_EXEC Params used in pruning expressions have changed, then
+ * we'd better unset the valid subplans so that they are reselected for
+ * the new parameter values.
+ */
+ if (node->ms_prune_state &&
+ bms_overlap(node->ps.chgParam,
+ node->ms_prune_state->execparamids))
+ {
+ bms_free(node->ms_valid_subplans);
+ node->ms_valid_subplans = NULL;
+ }
+
for (i = 0; i < node->ms_nplans; i++)
{
PlanState *subnode = node->mergeplans[i];