PostgreSQL Source Code  git master
nodeAppend.h File Reference
#include "access/parallel.h"
#include "nodes/execnodes.h"
Include dependency graph for nodeAppend.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

AppendStateExecInitAppend (Append *node, EState *estate, int eflags)
 
void ExecEndAppend (AppendState *node)
 
void ExecReScanAppend (AppendState *node)
 
void ExecAppendEstimate (AppendState *node, ParallelContext *pcxt)
 
void ExecAppendInitializeDSM (AppendState *node, ParallelContext *pcxt)
 
void ExecAppendReInitializeDSM (AppendState *node, ParallelContext *pcxt)
 
void ExecAppendInitializeWorker (AppendState *node, ParallelWorkerContext *pwcxt)
 
void ExecAsyncAppendResponse (AsyncRequest *areq)
 

Function Documentation

◆ ExecAppendEstimate()

void ExecAppendEstimate ( AppendState node,
ParallelContext pcxt 
)

Definition at line 483 of file nodeAppend.c.

485 {
486  node->pstate_len =
487  add_size(offsetof(ParallelAppendState, pa_finished),
488  sizeof(bool) * node->as_nplans);
489 
491  shm_toc_estimate_keys(&pcxt->estimator, 1);
492 }
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
Size pstate_len
Definition: execnodes.h:1349
shm_toc_estimator estimator
Definition: parallel.h:42

References add_size(), AppendState::as_nplans, ParallelContext::estimator, AppendState::pstate_len, shm_toc_estimate_chunk, and shm_toc_estimate_keys.

Referenced by ExecParallelEstimate().

◆ ExecAppendInitializeDSM()

void ExecAppendInitializeDSM ( AppendState node,
ParallelContext pcxt 
)

Definition at line 502 of file nodeAppend.c.

504 {
505  ParallelAppendState *pstate;
506 
507  pstate = shm_toc_allocate(pcxt->toc, node->pstate_len);
508  memset(pstate, 0, node->pstate_len);
510  shm_toc_insert(pcxt->toc, node->ps.plan->plan_node_id, pstate);
511 
512  node->as_pstate = pstate;
514 }
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:729
@ LWTRANCHE_PARALLEL_APPEND
Definition: lwlock.h:199
static bool choose_next_subplan_for_leader(AppendState *node)
Definition: nodeAppend.c:616
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
bool(* choose_next_subplan)(AppendState *)
Definition: execnodes.h:1353
PlanState ps
Definition: execnodes.h:1330
ParallelAppendState * as_pstate
Definition: execnodes.h:1348
shm_toc * toc
Definition: parallel.h:45
Plan * plan
Definition: execnodes.h:1029
int plan_node_id
Definition: plannodes.h:152

References AppendState::as_pstate, AppendState::choose_next_subplan, choose_next_subplan_for_leader(), LWLockInitialize(), LWTRANCHE_PARALLEL_APPEND, ParallelAppendState::pa_lock, PlanState::plan, Plan::plan_node_id, AppendState::ps, AppendState::pstate_len, shm_toc_allocate(), shm_toc_insert(), and ParallelContext::toc.

Referenced by ExecParallelInitializeDSM().

◆ ExecAppendInitializeWorker()

void ExecAppendInitializeWorker ( AppendState node,
ParallelWorkerContext pwcxt 
)

Definition at line 539 of file nodeAppend.c.

540 {
541  node->as_pstate = shm_toc_lookup(pwcxt->toc, node->ps.plan->plan_node_id, false);
543 }
static bool choose_next_subplan_for_worker(AppendState *node)
Definition: nodeAppend.c:697
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232

References AppendState::as_pstate, AppendState::choose_next_subplan, choose_next_subplan_for_worker(), PlanState::plan, Plan::plan_node_id, AppendState::ps, shm_toc_lookup(), and ParallelWorkerContext::toc.

Referenced by ExecParallelInitializeWorker().

◆ ExecAppendReInitializeDSM()

void ExecAppendReInitializeDSM ( AppendState node,
ParallelContext pcxt 
)

Definition at line 523 of file nodeAppend.c.

524 {
525  ParallelAppendState *pstate = node->as_pstate;
526 
527  pstate->pa_next_plan = 0;
528  memset(pstate->pa_finished, 0, sizeof(bool) * node->as_nplans);
529 }
bool pa_finished[FLEXIBLE_ARRAY_MEMBER]
Definition: nodeAppend.c:80

References AppendState::as_nplans, AppendState::as_pstate, ParallelAppendState::pa_finished, and ParallelAppendState::pa_next_plan.

Referenced by ExecParallelReInitializeDSM().

◆ ExecAsyncAppendResponse()

void ExecAsyncAppendResponse ( AsyncRequest areq)

Definition at line 1096 of file nodeAppend.c.

1097 {
1098  AppendState *node = (AppendState *) areq->requestor;
1099  TupleTableSlot *slot = areq->result;
1100 
1101  /* The result should be a TupleTableSlot or NULL. */
1102  Assert(slot == NULL || IsA(slot, TupleTableSlot));
1103 
1104  /* Nothing to do if the request is pending. */
1105  if (!areq->request_complete)
1106  {
1107  /* The request would have been pending for a callback. */
1108  Assert(areq->callback_pending);
1109  return;
1110  }
1111 
1112  /* If the result is NULL or an empty slot, there's nothing more to do. */
1113  if (TupIsNull(slot))
1114  {
1115  /* The ending subplan wouldn't have been pending for a callback. */
1116  Assert(!areq->callback_pending);
1117  --node->as_nasyncremain;
1118  return;
1119  }
1120 
1121  /* Save result so we can return it. */
1122  Assert(node->as_nasyncresults < node->as_nasyncplans);
1123  node->as_asyncresults[node->as_nasyncresults++] = slot;
1124 
1125  /*
1126  * Mark the subplan that returned a result as ready for a new request. We
1127  * don't launch another one here immediately because it might complete.
1128  */
1130  areq->request_index);
1131 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:739
Assert(fmt[strlen(fmt) - 1] !='\n')
#define IsA(nodeptr, _type_)
Definition: nodes.h:168
Bitmapset * as_needrequest
Definition: execnodes.h:1343
int as_nasyncresults
Definition: execnodes.h:1339
int as_nasyncremain
Definition: execnodes.h:1342
TupleTableSlot ** as_asyncresults
Definition: execnodes.h:1338
int as_nasyncplans
Definition: execnodes.h:1336
struct PlanState * requestor
Definition: execnodes.h:591
TupleTableSlot * result
Definition: execnodes.h:596
bool request_complete
Definition: execnodes.h:595
int request_index
Definition: execnodes.h:593
bool callback_pending
Definition: execnodes.h:594
#define TupIsNull(slot)
Definition: tuptable.h:300

References AppendState::as_asyncresults, AppendState::as_nasyncplans, AppendState::as_nasyncremain, AppendState::as_nasyncresults, AppendState::as_needrequest, Assert(), bms_add_member(), AsyncRequest::callback_pending, IsA, AsyncRequest::request_complete, AsyncRequest::request_index, AsyncRequest::requestor, AsyncRequest::result, and TupIsNull.

Referenced by ExecAsyncResponse().

◆ ExecEndAppend()

void ExecEndAppend ( AppendState node)

Definition at line 383 of file nodeAppend.c.

384 {
385  PlanState **appendplans;
386  int nplans;
387  int i;
388 
389  /*
390  * get information from the node
391  */
392  appendplans = node->appendplans;
393  nplans = node->as_nplans;
394 
395  /*
396  * shut down each of the subscans
397  */
398  for (i = 0; i < nplans; i++)
399  ExecEndNode(appendplans[i]);
400 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
int i
Definition: isn.c:73
PlanState ** appendplans
Definition: execnodes.h:1331

References AppendState::appendplans, AppendState::as_nplans, ExecEndNode(), and i.

Referenced by ExecEndNode().

◆ ExecInitAppend()

AppendState* ExecInitAppend ( Append node,
EState estate,
int  eflags 
)

Definition at line 109 of file nodeAppend.c.

110 {
111  AppendState *appendstate = makeNode(AppendState);
112  PlanState **appendplanstates;
113  Bitmapset *validsubplans;
114  Bitmapset *asyncplans;
115  int nplans;
116  int nasyncplans;
117  int firstvalid;
118  int i,
119  j;
120 
121  /* check for unsupported flags */
122  Assert(!(eflags & EXEC_FLAG_MARK));
123 
124  /*
125  * create new AppendState for our append node
126  */
127  appendstate->ps.plan = (Plan *) node;
128  appendstate->ps.state = estate;
129  appendstate->ps.ExecProcNode = ExecAppend;
130 
131  /* Let choose_next_subplan_* function handle setting the first subplan */
132  appendstate->as_whichplan = INVALID_SUBPLAN_INDEX;
133  appendstate->as_syncdone = false;
134  appendstate->as_begun = false;
135 
136  /* If run-time partition pruning is enabled, then set that up now */
137  if (node->part_prune_index >= 0)
138  {
139  PartitionPruneState *prunestate;
140 
141  /*
142  * Set up pruning data structure. This also initializes the set of
143  * subplans to initialize (validsubplans) by taking into account the
144  * result of performing initial pruning if any.
145  */
146  prunestate = ExecInitPartitionPruning(&appendstate->ps,
147  list_length(node->appendplans),
148  node->part_prune_index,
149  node->apprelids,
150  &validsubplans);
151  appendstate->as_prune_state = prunestate;
152  nplans = bms_num_members(validsubplans);
153 
154  /*
155  * When no run-time pruning is required and there's at least one
156  * subplan, we can fill as_valid_subplans immediately, preventing
157  * later calls to ExecFindMatchingSubPlans.
158  */
159  if (!prunestate->do_exec_prune && nplans > 0)
160  appendstate->as_valid_subplans = bms_add_range(NULL, 0, nplans - 1);
161  }
162  else
163  {
164  nplans = list_length(node->appendplans);
165 
166  /*
167  * When run-time partition pruning is not enabled we can just mark all
168  * subplans as valid; they must also all be initialized.
169  */
170  Assert(nplans > 0);
171  appendstate->as_valid_subplans = validsubplans =
172  bms_add_range(NULL, 0, nplans - 1);
173  appendstate->as_prune_state = NULL;
174  }
175 
176  /*
177  * Initialize result tuple type and slot.
178  */
179  ExecInitResultTupleSlotTL(&appendstate->ps, &TTSOpsVirtual);
180 
181  /* node returns slots from each of its subnodes, therefore not fixed */
182  appendstate->ps.resultopsset = true;
183  appendstate->ps.resultopsfixed = false;
184 
185  appendplanstates = (PlanState **) palloc(nplans *
186  sizeof(PlanState *));
187 
188  /*
189  * call ExecInitNode on each of the valid plans to be executed and save
190  * the results into the appendplanstates array.
191  *
192  * While at it, find out the first valid partial plan.
193  */
194  j = 0;
195  asyncplans = NULL;
196  nasyncplans = 0;
197  firstvalid = nplans;
198  i = -1;
199  while ((i = bms_next_member(validsubplans, i)) >= 0)
200  {
201  Plan *initNode = (Plan *) list_nth(node->appendplans, i);
202 
203  /*
204  * Record async subplans. When executing EvalPlanQual, we treat them
205  * as sync ones; don't do this when initializing an EvalPlanQual plan
206  * tree.
207  */
208  if (initNode->async_capable && estate->es_epq_active == NULL)
209  {
210  asyncplans = bms_add_member(asyncplans, j);
211  nasyncplans++;
212  }
213 
214  /*
215  * Record the lowest appendplans index which is a valid partial plan.
216  */
217  if (i >= node->first_partial_plan && j < firstvalid)
218  firstvalid = j;
219 
220  appendplanstates[j++] = ExecInitNode(initNode, estate, eflags);
221  }
222 
223  appendstate->as_first_partial_plan = firstvalid;
224  appendstate->appendplans = appendplanstates;
225  appendstate->as_nplans = nplans;
226 
227  /* Initialize async state */
228  appendstate->as_asyncplans = asyncplans;
229  appendstate->as_nasyncplans = nasyncplans;
230  appendstate->as_asyncrequests = NULL;
231  appendstate->as_asyncresults = NULL;
232  appendstate->as_nasyncresults = 0;
233  appendstate->as_nasyncremain = 0;
234  appendstate->as_needrequest = NULL;
235  appendstate->as_eventset = NULL;
236  appendstate->as_valid_asyncplans = NULL;
237 
238  if (nasyncplans > 0)
239  {
240  appendstate->as_asyncrequests = (AsyncRequest **)
241  palloc0(nplans * sizeof(AsyncRequest *));
242 
243  i = -1;
244  while ((i = bms_next_member(asyncplans, i)) >= 0)
245  {
246  AsyncRequest *areq;
247 
248  areq = palloc(sizeof(AsyncRequest));
249  areq->requestor = (PlanState *) appendstate;
250  areq->requestee = appendplanstates[i];
251  areq->request_index = i;
252  areq->callback_pending = false;
253  areq->request_complete = false;
254  areq->result = NULL;
255 
256  appendstate->as_asyncrequests[i] = areq;
257  }
258 
259  appendstate->as_asyncresults = (TupleTableSlot **)
260  palloc0(nasyncplans * sizeof(TupleTableSlot *));
261 
262  if (appendstate->as_valid_subplans != NULL)
263  classify_matching_subplans(appendstate);
264  }
265 
266  /*
267  * Miscellaneous initialization
268  */
269 
270  appendstate->ps.ps_ProjInfo = NULL;
271 
272  /* For parallel query, this will be overridden later. */
274 
275  return appendstate;
276 }
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1047
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:649
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:837
PartitionPruneState * ExecInitPartitionPruning(PlanState *planstate, int n_total_subplans, int part_prune_index, Bitmapset *root_parent_relids, Bitmapset **initially_valid_subplans)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1799
#define EXEC_FLAG_MARK
Definition: executor.h:59
int j
Definition: isn.c:74
void * palloc0(Size size)
Definition: mcxt.c:1230
void * palloc(Size size)
Definition: mcxt.c:1199
static void classify_matching_subplans(AppendState *node)
Definition: nodeAppend.c:1142
static TupleTableSlot * ExecAppend(PlanState *pstate)
Definition: nodeAppend.c:285
#define INVALID_SUBPLAN_INDEX
Definition: nodeAppend.c:83
static bool choose_next_subplan_locally(AppendState *node)
Definition: nodeAppend.c:553
#define makeNode(_type_)
Definition: nodes.h:165
static int list_length(const List *l)
Definition: pg_list.h:150
static void * list_nth(const List *list, int n)
Definition: pg_list.h:297
struct PartitionPruneState * as_prune_state
Definition: execnodes.h:1350
Bitmapset * as_valid_asyncplans
Definition: execnodes.h:1352
bool as_syncdone
Definition: execnodes.h:1340
AsyncRequest ** as_asyncrequests
Definition: execnodes.h:1337
bool as_begun
Definition: execnodes.h:1334
Bitmapset * as_asyncplans
Definition: execnodes.h:1335
int as_whichplan
Definition: execnodes.h:1333
struct WaitEventSet * as_eventset
Definition: execnodes.h:1344
int as_first_partial_plan
Definition: execnodes.h:1346
Bitmapset * as_valid_subplans
Definition: execnodes.h:1351
int first_partial_plan
Definition: plannodes.h:274
int part_prune_index
Definition: plannodes.h:277
Bitmapset * apprelids
Definition: plannodes.h:266
List * appendplans
Definition: plannodes.h:267
struct PlanState * requestee
Definition: execnodes.h:592
struct EPQState * es_epq_active
Definition: execnodes.h:684
bool resultopsset
Definition: execnodes.h:1114
EState * state
Definition: execnodes.h:1031
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1069
bool resultopsfixed
Definition: execnodes.h:1110
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1035
bool async_capable
Definition: plannodes.h:147

References AppendState::appendplans, Append::appendplans, Append::apprelids, AppendState::as_asyncplans, AppendState::as_asyncrequests, AppendState::as_asyncresults, AppendState::as_begun, AppendState::as_eventset, AppendState::as_first_partial_plan, AppendState::as_nasyncplans, AppendState::as_nasyncremain, AppendState::as_nasyncresults, AppendState::as_needrequest, AppendState::as_nplans, AppendState::as_prune_state, AppendState::as_syncdone, AppendState::as_valid_asyncplans, AppendState::as_valid_subplans, AppendState::as_whichplan, Assert(), Plan::async_capable, bms_add_member(), bms_add_range(), bms_next_member(), bms_num_members(), AsyncRequest::callback_pending, AppendState::choose_next_subplan, choose_next_subplan_locally(), classify_matching_subplans(), PartitionPruneState::do_exec_prune, EState::es_epq_active, EXEC_FLAG_MARK, ExecAppend(), ExecInitNode(), ExecInitPartitionPruning(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, Append::first_partial_plan, i, INVALID_SUBPLAN_INDEX, j, list_length(), list_nth(), makeNode, palloc(), palloc0(), Append::part_prune_index, PlanState::plan, AppendState::ps, PlanState::ps_ProjInfo, AsyncRequest::request_complete, AsyncRequest::request_index, AsyncRequest::requestee, AsyncRequest::requestor, AsyncRequest::result, PlanState::resultopsfixed, PlanState::resultopsset, PlanState::state, and TTSOpsVirtual.

Referenced by ExecInitNode().

◆ ExecReScanAppend()

void ExecReScanAppend ( AppendState node)

Definition at line 403 of file nodeAppend.c.

404 {
405  int nasyncplans = node->as_nasyncplans;
406  int i;
407 
408  /*
409  * If any PARAM_EXEC Params used in pruning expressions have changed, then
410  * we'd better unset the valid subplans so that they are reselected for
411  * the new parameter values.
412  */
413  if (node->as_prune_state &&
414  bms_overlap(node->ps.chgParam,
416  {
418  node->as_valid_subplans = NULL;
419  if (nasyncplans > 0)
420  {
422  node->as_valid_asyncplans = NULL;
423  }
424  }
425 
426  for (i = 0; i < node->as_nplans; i++)
427  {
428  PlanState *subnode = node->appendplans[i];
429 
430  /*
431  * ExecReScan doesn't know about my subplans, so I have to do
432  * changed-parameter signaling myself.
433  */
434  if (node->ps.chgParam != NULL)
435  UpdateChangedParamSet(subnode, node->ps.chgParam);
436 
437  /*
438  * If chgParam of subnode is not null then plan will be re-scanned by
439  * first ExecProcNode or by first ExecAsyncRequest.
440  */
441  if (subnode->chgParam == NULL)
442  ExecReScan(subnode);
443  }
444 
445  /* Reset async state */
446  if (nasyncplans > 0)
447  {
448  i = -1;
449  while ((i = bms_next_member(node->as_asyncplans, i)) >= 0)
450  {
451  AsyncRequest *areq = node->as_asyncrequests[i];
452 
453  areq->callback_pending = false;
454  areq->request_complete = false;
455  areq->result = NULL;
456  }
457 
458  node->as_nasyncresults = 0;
459  node->as_nasyncremain = 0;
460  bms_free(node->as_needrequest);
461  node->as_needrequest = NULL;
462  }
463 
464  /* Let choose_next_subplan_* function handle setting the first subplan */
466  node->as_syncdone = false;
467  node->as_begun = false;
468 }
void bms_free(Bitmapset *a)
Definition: bitmapset.c:209
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:495
void ExecReScan(PlanState *node)
Definition: execAmi.c:78
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition: execUtils.c:866
Bitmapset * execparamids
Bitmapset * chgParam
Definition: execnodes.h:1061

References AppendState::appendplans, AppendState::as_asyncplans, AppendState::as_asyncrequests, AppendState::as_begun, AppendState::as_nasyncplans, AppendState::as_nasyncremain, AppendState::as_nasyncresults, AppendState::as_needrequest, AppendState::as_nplans, AppendState::as_prune_state, AppendState::as_syncdone, AppendState::as_valid_asyncplans, AppendState::as_valid_subplans, AppendState::as_whichplan, bms_free(), bms_next_member(), bms_overlap(), AsyncRequest::callback_pending, PlanState::chgParam, PartitionPruneState::execparamids, ExecReScan(), i, INVALID_SUBPLAN_INDEX, AppendState::ps, AsyncRequest::request_complete, AsyncRequest::result, and UpdateChangedParamSet().

Referenced by ExecReScan().