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 499 of file nodeAppend.c.

501{
502 node->pstate_len =
503 add_size(offsetof(ParallelAppendState, pa_finished),
504 sizeof(bool) * node->as_nplans);
505
508}
#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:488
Size pstate_len
Definition: execnodes.h:1503
shm_toc_estimator estimator
Definition: parallel.h:41

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 518 of file nodeAppend.c.

520{
521 ParallelAppendState *pstate;
522
523 pstate = shm_toc_allocate(pcxt->toc, node->pstate_len);
524 memset(pstate, 0, node->pstate_len);
526 shm_toc_insert(pcxt->toc, node->ps.plan->plan_node_id, pstate);
527
528 node->as_pstate = pstate;
530}
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:718
@ LWTRANCHE_PARALLEL_APPEND
Definition: lwlock.h:204
static bool choose_next_subplan_for_leader(AppendState *node)
Definition: nodeAppend.c:635
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
bool(* choose_next_subplan)(AppendState *)
Definition: execnodes.h:1508
PlanState ps
Definition: execnodes.h:1484
ParallelAppendState * as_pstate
Definition: execnodes.h:1502
shm_toc * toc
Definition: parallel.h:44
Plan * plan
Definition: execnodes.h:1153
int plan_node_id
Definition: plannodes.h:197

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 555 of file nodeAppend.c.

556{
557 node->as_pstate = shm_toc_lookup(pwcxt->toc, node->ps.plan->plan_node_id, false);
559}
static bool choose_next_subplan_for_worker(AppendState *node)
Definition: nodeAppend.c:717
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 539 of file nodeAppend.c.

540{
541 ParallelAppendState *pstate = node->as_pstate;
542
543 pstate->pa_next_plan = 0;
544 memset(pstate->pa_finished, 0, sizeof(bool) * node->as_nplans);
545}
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 1142 of file nodeAppend.c.

1143{
1144 AppendState *node = (AppendState *) areq->requestor;
1145 TupleTableSlot *slot = areq->result;
1146
1147 /* The result should be a TupleTableSlot or NULL. */
1148 Assert(slot == NULL || IsA(slot, TupleTableSlot));
1149
1150 /* Nothing to do if the request is pending. */
1151 if (!areq->request_complete)
1152 {
1153 /* The request would have been pending for a callback. */
1154 Assert(areq->callback_pending);
1155 return;
1156 }
1157
1158 /* If the result is NULL or an empty slot, there's nothing more to do. */
1159 if (TupIsNull(slot))
1160 {
1161 /* The ending subplan wouldn't have been pending for a callback. */
1162 Assert(!areq->callback_pending);
1163 --node->as_nasyncremain;
1164 return;
1165 }
1166
1167 /* Save result so we can return it. */
1168 Assert(node->as_nasyncresults < node->as_nasyncplans);
1169 node->as_asyncresults[node->as_nasyncresults++] = slot;
1170
1171 /*
1172 * Mark the subplan that returned a result as ready for a new request. We
1173 * don't launch another one here immediately because it might complete.
1174 */
1176 areq->request_index);
1177}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
Assert(PointerIsAligned(start, uint64))
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
Bitmapset * as_needrequest
Definition: execnodes.h:1497
int as_nasyncresults
Definition: execnodes.h:1493
int as_nasyncremain
Definition: execnodes.h:1496
TupleTableSlot ** as_asyncresults
Definition: execnodes.h:1492
int as_nasyncplans
Definition: execnodes.h:1490
struct PlanState * requestor
Definition: execnodes.h:630
TupleTableSlot * result
Definition: execnodes.h:635
bool request_complete
Definition: execnodes.h:634
int request_index
Definition: execnodes.h:632
bool callback_pending
Definition: execnodes.h:633
#define TupIsNull(slot)
Definition: tuptable.h:306

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 401 of file nodeAppend.c.

402{
403 PlanState **appendplans;
404 int nplans;
405 int i;
406
407 /*
408 * get information from the node
409 */
410 appendplans = node->appendplans;
411 nplans = node->as_nplans;
412
413 /*
414 * shut down each of the subscans
415 */
416 for (i = 0; i < nplans; i++)
417 ExecEndNode(appendplans[i]);
418}
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:562
int i
Definition: isn.c:74
PlanState ** appendplans
Definition: execnodes.h:1485

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 const TupleTableSlotOps *appendops;
114 Bitmapset *validsubplans;
115 Bitmapset *asyncplans;
116 int nplans;
117 int nasyncplans;
118 int firstvalid;
119 int i,
120 j;
121
122 /* check for unsupported flags */
123 Assert(!(eflags & EXEC_FLAG_MARK));
124
125 /*
126 * create new AppendState for our append node
127 */
128 appendstate->ps.plan = (Plan *) node;
129 appendstate->ps.state = estate;
130 appendstate->ps.ExecProcNode = ExecAppend;
131
132 /* Let choose_next_subplan_* function handle setting the first subplan */
133 appendstate->as_whichplan = INVALID_SUBPLAN_INDEX;
134 appendstate->as_syncdone = false;
135 appendstate->as_begun = false;
136
137 /* If run-time partition pruning is enabled, then set that up now */
138 if (node->part_prune_index >= 0)
139 {
140 PartitionPruneState *prunestate;
141
142 /*
143 * Set up pruning data structure. This also initializes the set of
144 * subplans to initialize (validsubplans) by taking into account the
145 * result of performing initial pruning if any.
146 */
147 prunestate = ExecInitPartitionExecPruning(&appendstate->ps,
149 node->part_prune_index,
150 node->apprelids,
151 &validsubplans);
152 appendstate->as_prune_state = prunestate;
153 nplans = bms_num_members(validsubplans);
154
155 /*
156 * When no run-time pruning is required and there's at least one
157 * subplan, we can fill as_valid_subplans immediately, preventing
158 * later calls to ExecFindMatchingSubPlans.
159 */
160 if (!prunestate->do_exec_prune && nplans > 0)
161 {
162 appendstate->as_valid_subplans = bms_add_range(NULL, 0, nplans - 1);
163 appendstate->as_valid_subplans_identified = true;
164 }
165 }
166 else
167 {
168 nplans = list_length(node->appendplans);
169
170 /*
171 * When run-time partition pruning is not enabled we can just mark all
172 * subplans as valid; they must also all be initialized.
173 */
174 Assert(nplans > 0);
175 appendstate->as_valid_subplans = validsubplans =
176 bms_add_range(NULL, 0, nplans - 1);
177 appendstate->as_valid_subplans_identified = true;
178 appendstate->as_prune_state = NULL;
179 }
180
181 appendplanstates = (PlanState **) palloc(nplans *
182 sizeof(PlanState *));
183
184 /*
185 * call ExecInitNode on each of the valid plans to be executed and save
186 * the results into the appendplanstates array.
187 *
188 * While at it, find out the first valid partial plan.
189 */
190 j = 0;
191 asyncplans = NULL;
192 nasyncplans = 0;
193 firstvalid = nplans;
194 i = -1;
195 while ((i = bms_next_member(validsubplans, i)) >= 0)
196 {
197 Plan *initNode = (Plan *) list_nth(node->appendplans, i);
198
199 /*
200 * Record async subplans. When executing EvalPlanQual, we treat them
201 * as sync ones; don't do this when initializing an EvalPlanQual plan
202 * tree.
203 */
204 if (initNode->async_capable && estate->es_epq_active == NULL)
205 {
206 asyncplans = bms_add_member(asyncplans, j);
207 nasyncplans++;
208 }
209
210 /*
211 * Record the lowest appendplans index which is a valid partial plan.
212 */
213 if (i >= node->first_partial_plan && j < firstvalid)
214 firstvalid = j;
215
216 appendplanstates[j++] = ExecInitNode(initNode, estate, eflags);
217 }
218
219 appendstate->as_first_partial_plan = firstvalid;
220 appendstate->appendplans = appendplanstates;
221 appendstate->as_nplans = nplans;
222
223 /*
224 * Initialize Append's result tuple type and slot. If the child plans all
225 * produce the same fixed slot type, we can use that slot type; otherwise
226 * make a virtual slot. (Note that the result slot itself is used only to
227 * return a null tuple at end of execution; real tuples are returned to
228 * the caller in the children's own result slots. What we are doing here
229 * is allowing the parent plan node to optimize if the Append will return
230 * only one kind of slot.)
231 */
232 appendops = ExecGetCommonSlotOps(appendplanstates, j);
233 if (appendops != NULL)
234 {
235 ExecInitResultTupleSlotTL(&appendstate->ps, appendops);
236 }
237 else
238 {
240 /* show that the output slot type is not fixed */
241 appendstate->ps.resultopsset = true;
242 appendstate->ps.resultopsfixed = false;
243 }
244
245 /* Initialize async state */
246 appendstate->as_asyncplans = asyncplans;
247 appendstate->as_nasyncplans = nasyncplans;
248 appendstate->as_asyncrequests = NULL;
249 appendstate->as_asyncresults = NULL;
250 appendstate->as_nasyncresults = 0;
251 appendstate->as_nasyncremain = 0;
252 appendstate->as_needrequest = NULL;
253 appendstate->as_eventset = NULL;
254 appendstate->as_valid_asyncplans = NULL;
255
256 if (nasyncplans > 0)
257 {
258 appendstate->as_asyncrequests = (AsyncRequest **)
259 palloc0(nplans * sizeof(AsyncRequest *));
260
261 i = -1;
262 while ((i = bms_next_member(asyncplans, i)) >= 0)
263 {
264 AsyncRequest *areq;
265
266 areq = palloc(sizeof(AsyncRequest));
267 areq->requestor = (PlanState *) appendstate;
268 areq->requestee = appendplanstates[i];
269 areq->request_index = i;
270 areq->callback_pending = false;
271 areq->request_complete = false;
272 areq->result = NULL;
273
274 appendstate->as_asyncrequests[i] = areq;
275 }
276
277 appendstate->as_asyncresults = (TupleTableSlot **)
278 palloc0(nasyncplans * sizeof(TupleTableSlot *));
279
280 if (appendstate->as_valid_subplans_identified)
281 classify_matching_subplans(appendstate);
282 }
283
284 /*
285 * Miscellaneous initialization
286 */
287
288 appendstate->ps.ps_ProjInfo = NULL;
289
290 /* For parallel query, this will be overridden later. */
292
293 return appendstate;
294}
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:1019
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:751
PartitionPruneState * ExecInitPartitionExecPruning(PlanState *planstate, int n_total_subplans, int part_prune_index, Bitmapset *relids, Bitmapset **initially_valid_subplans)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1986
const TupleTableSlotOps * ExecGetCommonSlotOps(PlanState **planstates, int nplans)
Definition: execUtils.c:538
#define EXEC_FLAG_MARK
Definition: executor.h:70
int j
Definition: isn.c:75
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
static void classify_matching_subplans(AppendState *node)
Definition: nodeAppend.c:1188
static TupleTableSlot * ExecAppend(PlanState *pstate)
Definition: nodeAppend.c:303
#define INVALID_SUBPLAN_INDEX
Definition: nodeAppend.c:83
static bool choose_next_subplan_locally(AppendState *node)
Definition: nodeAppend.c:569
#define makeNode(_type_)
Definition: nodes.h:155
static int list_length(const List *l)
Definition: pg_list.h:152
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
struct PartitionPruneState * as_prune_state
Definition: execnodes.h:1504
Bitmapset * as_valid_asyncplans
Definition: execnodes.h:1507
bool as_syncdone
Definition: execnodes.h:1494
AsyncRequest ** as_asyncrequests
Definition: execnodes.h:1491
bool as_begun
Definition: execnodes.h:1488
Bitmapset * as_asyncplans
Definition: execnodes.h:1489
int as_whichplan
Definition: execnodes.h:1487
struct WaitEventSet * as_eventset
Definition: execnodes.h:1498
int as_first_partial_plan
Definition: execnodes.h:1500
Bitmapset * as_valid_subplans
Definition: execnodes.h:1506
bool as_valid_subplans_identified
Definition: execnodes.h:1505
int first_partial_plan
Definition: plannodes.h:351
int part_prune_index
Definition: plannodes.h:358
Bitmapset * apprelids
Definition: plannodes.h:342
List * appendplans
Definition: plannodes.h:343
struct PlanState * requestee
Definition: execnodes.h:631
struct EPQState * es_epq_active
Definition: execnodes.h:735
bool resultopsset
Definition: execnodes.h:1238
EState * state
Definition: execnodes.h:1155
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1193
bool resultopsfixed
Definition: execnodes.h:1234
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1159
bool async_capable
Definition: plannodes.h:191

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_valid_subplans_identified, 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(), ExecGetCommonSlotOps(), ExecInitNode(), ExecInitPartitionExecPruning(), 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 421 of file nodeAppend.c.

422{
423 int nasyncplans = node->as_nasyncplans;
424 int i;
425
426 /*
427 * If any PARAM_EXEC Params used in pruning expressions have changed, then
428 * we'd better unset the valid subplans so that they are reselected for
429 * the new parameter values.
430 */
431 if (node->as_prune_state &&
432 bms_overlap(node->ps.chgParam,
434 {
435 node->as_valid_subplans_identified = false;
437 node->as_valid_subplans = NULL;
439 node->as_valid_asyncplans = NULL;
440 }
441
442 for (i = 0; i < node->as_nplans; i++)
443 {
444 PlanState *subnode = node->appendplans[i];
445
446 /*
447 * ExecReScan doesn't know about my subplans, so I have to do
448 * changed-parameter signaling myself.
449 */
450 if (node->ps.chgParam != NULL)
451 UpdateChangedParamSet(subnode, node->ps.chgParam);
452
453 /*
454 * If chgParam of subnode is not null then plan will be re-scanned by
455 * first ExecProcNode or by first ExecAsyncRequest.
456 */
457 if (subnode->chgParam == NULL)
458 ExecReScan(subnode);
459 }
460
461 /* Reset async state */
462 if (nasyncplans > 0)
463 {
464 i = -1;
465 while ((i = bms_next_member(node->as_asyncplans, i)) >= 0)
466 {
467 AsyncRequest *areq = node->as_asyncrequests[i];
468
469 areq->callback_pending = false;
470 areq->request_complete = false;
471 areq->result = NULL;
472 }
473
474 node->as_nasyncresults = 0;
475 node->as_nasyncremain = 0;
477 node->as_needrequest = NULL;
478 }
479
480 /* Let choose_next_subplan_* function handle setting the first subplan */
482 node->as_syncdone = false;
483 node->as_begun = false;
484}
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition: execUtils.c:908
Bitmapset * execparamids
Bitmapset * chgParam
Definition: execnodes.h:1185

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_valid_subplans_identified, 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().