1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * execProcnode.c |
4 | * contains dispatch functions which call the appropriate "initialize", |
5 | * "get a tuple", and "cleanup" routines for the given node type. |
6 | * If the node has children, then it will presumably call ExecInitNode, |
7 | * ExecProcNode, or ExecEndNode on its subnodes and do the appropriate |
8 | * processing. |
9 | * |
10 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
11 | * Portions Copyright (c) 1994, Regents of the University of California |
12 | * |
13 | * |
14 | * IDENTIFICATION |
15 | * src/backend/executor/execProcnode.c |
16 | * |
17 | *------------------------------------------------------------------------- |
18 | */ |
19 | /* |
20 | * NOTES |
21 | * This used to be three files. It is now all combined into |
22 | * one file so that it is easier to keep the dispatch routines |
23 | * in sync when new nodes are added. |
24 | * |
25 | * EXAMPLE |
26 | * Suppose we want the age of the manager of the shoe department and |
27 | * the number of employees in that department. So we have the query: |
28 | * |
29 | * select DEPT.no_emps, EMP.age |
30 | * from DEPT, EMP |
31 | * where EMP.name = DEPT.mgr and |
32 | * DEPT.name = "shoe" |
33 | * |
34 | * Suppose the planner gives us the following plan: |
35 | * |
36 | * Nest Loop (DEPT.mgr = EMP.name) |
37 | * / \ |
38 | * / \ |
39 | * Seq Scan Seq Scan |
40 | * DEPT EMP |
41 | * (name = "shoe") |
42 | * |
43 | * ExecutorStart() is called first. |
44 | * It calls InitPlan() which calls ExecInitNode() on |
45 | * the root of the plan -- the nest loop node. |
46 | * |
47 | * * ExecInitNode() notices that it is looking at a nest loop and |
48 | * as the code below demonstrates, it calls ExecInitNestLoop(). |
49 | * Eventually this calls ExecInitNode() on the right and left subplans |
50 | * and so forth until the entire plan is initialized. The result |
51 | * of ExecInitNode() is a plan state tree built with the same structure |
52 | * as the underlying plan tree. |
53 | * |
54 | * * Then when ExecutorRun() is called, it calls ExecutePlan() which calls |
55 | * ExecProcNode() repeatedly on the top node of the plan state tree. |
56 | * Each time this happens, ExecProcNode() will end up calling |
57 | * ExecNestLoop(), which calls ExecProcNode() on its subplans. |
58 | * Each of these subplans is a sequential scan so ExecSeqScan() is |
59 | * called. The slots returned by ExecSeqScan() may contain |
60 | * tuples which contain the attributes ExecNestLoop() uses to |
61 | * form the tuples it returns. |
62 | * |
63 | * * Eventually ExecSeqScan() stops returning tuples and the nest |
64 | * loop join ends. Lastly, ExecutorEnd() calls ExecEndNode() which |
65 | * calls ExecEndNestLoop() which in turn calls ExecEndNode() on |
66 | * its subplans which result in ExecEndSeqScan(). |
67 | * |
68 | * This should show how the executor works by having |
69 | * ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch |
70 | * their work to the appropriate node support routines which may |
71 | * in turn call these routines themselves on their subplans. |
72 | */ |
73 | #include "postgres.h" |
74 | |
75 | #include "executor/executor.h" |
76 | #include "executor/nodeAgg.h" |
77 | #include "executor/nodeAppend.h" |
78 | #include "executor/nodeBitmapAnd.h" |
79 | #include "executor/nodeBitmapHeapscan.h" |
80 | #include "executor/nodeBitmapIndexscan.h" |
81 | #include "executor/nodeBitmapOr.h" |
82 | #include "executor/nodeCtescan.h" |
83 | #include "executor/nodeCustom.h" |
84 | #include "executor/nodeForeignscan.h" |
85 | #include "executor/nodeFunctionscan.h" |
86 | #include "executor/nodeGather.h" |
87 | #include "executor/nodeGatherMerge.h" |
88 | #include "executor/nodeGroup.h" |
89 | #include "executor/nodeHash.h" |
90 | #include "executor/nodeHashjoin.h" |
91 | #include "executor/nodeIndexonlyscan.h" |
92 | #include "executor/nodeIndexscan.h" |
93 | #include "executor/nodeLimit.h" |
94 | #include "executor/nodeLockRows.h" |
95 | #include "executor/nodeMaterial.h" |
96 | #include "executor/nodeMergeAppend.h" |
97 | #include "executor/nodeMergejoin.h" |
98 | #include "executor/nodeModifyTable.h" |
99 | #include "executor/nodeNamedtuplestorescan.h" |
100 | #include "executor/nodeNestloop.h" |
101 | #include "executor/nodeProjectSet.h" |
102 | #include "executor/nodeRecursiveunion.h" |
103 | #include "executor/nodeResult.h" |
104 | #include "executor/nodeSamplescan.h" |
105 | #include "executor/nodeSeqscan.h" |
106 | #include "executor/nodeSetOp.h" |
107 | #include "executor/nodeSort.h" |
108 | #include "executor/nodeSubplan.h" |
109 | #include "executor/nodeSubqueryscan.h" |
110 | #include "executor/nodeTableFuncscan.h" |
111 | #include "executor/nodeTidscan.h" |
112 | #include "executor/nodeUnique.h" |
113 | #include "executor/nodeValuesscan.h" |
114 | #include "executor/nodeWindowAgg.h" |
115 | #include "executor/nodeWorktablescan.h" |
116 | #include "nodes/nodeFuncs.h" |
117 | #include "miscadmin.h" |
118 | |
119 | |
120 | static TupleTableSlot *ExecProcNodeFirst(PlanState *node); |
121 | static TupleTableSlot *ExecProcNodeInstr(PlanState *node); |
122 | |
123 | |
124 | /* ------------------------------------------------------------------------ |
125 | * ExecInitNode |
126 | * |
127 | * Recursively initializes all the nodes in the plan tree rooted |
128 | * at 'node'. |
129 | * |
130 | * Inputs: |
131 | * 'node' is the current node of the plan produced by the query planner |
132 | * 'estate' is the shared execution state for the plan tree |
133 | * 'eflags' is a bitwise OR of flag bits described in executor.h |
134 | * |
135 | * Returns a PlanState node corresponding to the given Plan node. |
136 | * ------------------------------------------------------------------------ |
137 | */ |
138 | PlanState * |
139 | ExecInitNode(Plan *node, EState *estate, int eflags) |
140 | { |
141 | PlanState *result; |
142 | List *subps; |
143 | ListCell *l; |
144 | |
145 | /* |
146 | * do nothing when we get to the end of a leaf on tree. |
147 | */ |
148 | if (node == NULL) |
149 | return NULL; |
150 | |
151 | /* |
152 | * Make sure there's enough stack available. Need to check here, in |
153 | * addition to ExecProcNode() (via ExecProcNodeFirst()), to ensure the |
154 | * stack isn't overrun while initializing the node tree. |
155 | */ |
156 | check_stack_depth(); |
157 | |
158 | switch (nodeTag(node)) |
159 | { |
160 | /* |
161 | * control nodes |
162 | */ |
163 | case T_Result: |
164 | result = (PlanState *) ExecInitResult((Result *) node, |
165 | estate, eflags); |
166 | break; |
167 | |
168 | case T_ProjectSet: |
169 | result = (PlanState *) ExecInitProjectSet((ProjectSet *) node, |
170 | estate, eflags); |
171 | break; |
172 | |
173 | case T_ModifyTable: |
174 | result = (PlanState *) ExecInitModifyTable((ModifyTable *) node, |
175 | estate, eflags); |
176 | break; |
177 | |
178 | case T_Append: |
179 | result = (PlanState *) ExecInitAppend((Append *) node, |
180 | estate, eflags); |
181 | break; |
182 | |
183 | case T_MergeAppend: |
184 | result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node, |
185 | estate, eflags); |
186 | break; |
187 | |
188 | case T_RecursiveUnion: |
189 | result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node, |
190 | estate, eflags); |
191 | break; |
192 | |
193 | case T_BitmapAnd: |
194 | result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node, |
195 | estate, eflags); |
196 | break; |
197 | |
198 | case T_BitmapOr: |
199 | result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node, |
200 | estate, eflags); |
201 | break; |
202 | |
203 | /* |
204 | * scan nodes |
205 | */ |
206 | case T_SeqScan: |
207 | result = (PlanState *) ExecInitSeqScan((SeqScan *) node, |
208 | estate, eflags); |
209 | break; |
210 | |
211 | case T_SampleScan: |
212 | result = (PlanState *) ExecInitSampleScan((SampleScan *) node, |
213 | estate, eflags); |
214 | break; |
215 | |
216 | case T_IndexScan: |
217 | result = (PlanState *) ExecInitIndexScan((IndexScan *) node, |
218 | estate, eflags); |
219 | break; |
220 | |
221 | case T_IndexOnlyScan: |
222 | result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node, |
223 | estate, eflags); |
224 | break; |
225 | |
226 | case T_BitmapIndexScan: |
227 | result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node, |
228 | estate, eflags); |
229 | break; |
230 | |
231 | case T_BitmapHeapScan: |
232 | result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node, |
233 | estate, eflags); |
234 | break; |
235 | |
236 | case T_TidScan: |
237 | result = (PlanState *) ExecInitTidScan((TidScan *) node, |
238 | estate, eflags); |
239 | break; |
240 | |
241 | case T_SubqueryScan: |
242 | result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node, |
243 | estate, eflags); |
244 | break; |
245 | |
246 | case T_FunctionScan: |
247 | result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node, |
248 | estate, eflags); |
249 | break; |
250 | |
251 | case T_TableFuncScan: |
252 | result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node, |
253 | estate, eflags); |
254 | break; |
255 | |
256 | case T_ValuesScan: |
257 | result = (PlanState *) ExecInitValuesScan((ValuesScan *) node, |
258 | estate, eflags); |
259 | break; |
260 | |
261 | case T_CteScan: |
262 | result = (PlanState *) ExecInitCteScan((CteScan *) node, |
263 | estate, eflags); |
264 | break; |
265 | |
266 | case T_NamedTuplestoreScan: |
267 | result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node, |
268 | estate, eflags); |
269 | break; |
270 | |
271 | case T_WorkTableScan: |
272 | result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node, |
273 | estate, eflags); |
274 | break; |
275 | |
276 | case T_ForeignScan: |
277 | result = (PlanState *) ExecInitForeignScan((ForeignScan *) node, |
278 | estate, eflags); |
279 | break; |
280 | |
281 | case T_CustomScan: |
282 | result = (PlanState *) ExecInitCustomScan((CustomScan *) node, |
283 | estate, eflags); |
284 | break; |
285 | |
286 | /* |
287 | * join nodes |
288 | */ |
289 | case T_NestLoop: |
290 | result = (PlanState *) ExecInitNestLoop((NestLoop *) node, |
291 | estate, eflags); |
292 | break; |
293 | |
294 | case T_MergeJoin: |
295 | result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node, |
296 | estate, eflags); |
297 | break; |
298 | |
299 | case T_HashJoin: |
300 | result = (PlanState *) ExecInitHashJoin((HashJoin *) node, |
301 | estate, eflags); |
302 | break; |
303 | |
304 | /* |
305 | * materialization nodes |
306 | */ |
307 | case T_Material: |
308 | result = (PlanState *) ExecInitMaterial((Material *) node, |
309 | estate, eflags); |
310 | break; |
311 | |
312 | case T_Sort: |
313 | result = (PlanState *) ExecInitSort((Sort *) node, |
314 | estate, eflags); |
315 | break; |
316 | |
317 | case T_Group: |
318 | result = (PlanState *) ExecInitGroup((Group *) node, |
319 | estate, eflags); |
320 | break; |
321 | |
322 | case T_Agg: |
323 | result = (PlanState *) ExecInitAgg((Agg *) node, |
324 | estate, eflags); |
325 | break; |
326 | |
327 | case T_WindowAgg: |
328 | result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node, |
329 | estate, eflags); |
330 | break; |
331 | |
332 | case T_Unique: |
333 | result = (PlanState *) ExecInitUnique((Unique *) node, |
334 | estate, eflags); |
335 | break; |
336 | |
337 | case T_Gather: |
338 | result = (PlanState *) ExecInitGather((Gather *) node, |
339 | estate, eflags); |
340 | break; |
341 | |
342 | case T_GatherMerge: |
343 | result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node, |
344 | estate, eflags); |
345 | break; |
346 | |
347 | case T_Hash: |
348 | result = (PlanState *) ExecInitHash((Hash *) node, |
349 | estate, eflags); |
350 | break; |
351 | |
352 | case T_SetOp: |
353 | result = (PlanState *) ExecInitSetOp((SetOp *) node, |
354 | estate, eflags); |
355 | break; |
356 | |
357 | case T_LockRows: |
358 | result = (PlanState *) ExecInitLockRows((LockRows *) node, |
359 | estate, eflags); |
360 | break; |
361 | |
362 | case T_Limit: |
363 | result = (PlanState *) ExecInitLimit((Limit *) node, |
364 | estate, eflags); |
365 | break; |
366 | |
367 | default: |
368 | elog(ERROR, "unrecognized node type: %d" , (int) nodeTag(node)); |
369 | result = NULL; /* keep compiler quiet */ |
370 | break; |
371 | } |
372 | |
373 | ExecSetExecProcNode(result, result->ExecProcNode); |
374 | |
375 | /* |
376 | * Initialize any initPlans present in this node. The planner put them in |
377 | * a separate list for us. |
378 | */ |
379 | subps = NIL; |
380 | foreach(l, node->initPlan) |
381 | { |
382 | SubPlan *subplan = (SubPlan *) lfirst(l); |
383 | SubPlanState *sstate; |
384 | |
385 | Assert(IsA(subplan, SubPlan)); |
386 | sstate = ExecInitSubPlan(subplan, result); |
387 | subps = lappend(subps, sstate); |
388 | } |
389 | result->initPlan = subps; |
390 | |
391 | /* Set up instrumentation for this node if requested */ |
392 | if (estate->es_instrument) |
393 | result->instrument = InstrAlloc(1, estate->es_instrument); |
394 | |
395 | return result; |
396 | } |
397 | |
398 | |
399 | /* |
400 | * If a node wants to change its ExecProcNode function after ExecInitNode() |
401 | * has finished, it should do so with this function. That way any wrapper |
402 | * functions can be reinstalled, without the node having to know how that |
403 | * works. |
404 | */ |
405 | void |
406 | ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function) |
407 | { |
408 | /* |
409 | * Add a wrapper around the ExecProcNode callback that checks stack depth |
410 | * during the first execution and maybe adds an instrumentation wrapper. |
411 | * When the callback is changed after execution has already begun that |
412 | * means we'll superfluously execute ExecProcNodeFirst, but that seems ok. |
413 | */ |
414 | node->ExecProcNodeReal = function; |
415 | node->ExecProcNode = ExecProcNodeFirst; |
416 | } |
417 | |
418 | |
419 | /* |
420 | * ExecProcNode wrapper that performs some one-time checks, before calling |
421 | * the relevant node method (possibly via an instrumentation wrapper). |
422 | */ |
423 | static TupleTableSlot * |
424 | ExecProcNodeFirst(PlanState *node) |
425 | { |
426 | /* |
427 | * Perform stack depth check during the first execution of the node. We |
428 | * only do so the first time round because it turns out to not be cheap on |
429 | * some common architectures (eg. x86). This relies on the assumption |
430 | * that ExecProcNode calls for a given plan node will always be made at |
431 | * roughly the same stack depth. |
432 | */ |
433 | check_stack_depth(); |
434 | |
435 | /* |
436 | * If instrumentation is required, change the wrapper to one that just |
437 | * does instrumentation. Otherwise we can dispense with all wrappers and |
438 | * have ExecProcNode() directly call the relevant function from now on. |
439 | */ |
440 | if (node->instrument) |
441 | node->ExecProcNode = ExecProcNodeInstr; |
442 | else |
443 | node->ExecProcNode = node->ExecProcNodeReal; |
444 | |
445 | return node->ExecProcNode(node); |
446 | } |
447 | |
448 | |
449 | /* |
450 | * ExecProcNode wrapper that performs instrumentation calls. By keeping |
451 | * this a separate function, we avoid overhead in the normal case where |
452 | * no instrumentation is wanted. |
453 | */ |
454 | static TupleTableSlot * |
455 | ExecProcNodeInstr(PlanState *node) |
456 | { |
457 | TupleTableSlot *result; |
458 | |
459 | InstrStartNode(node->instrument); |
460 | |
461 | result = node->ExecProcNodeReal(node); |
462 | |
463 | InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0); |
464 | |
465 | return result; |
466 | } |
467 | |
468 | |
469 | /* ---------------------------------------------------------------- |
470 | * MultiExecProcNode |
471 | * |
472 | * Execute a node that doesn't return individual tuples |
473 | * (it might return a hashtable, bitmap, etc). Caller should |
474 | * check it got back the expected kind of Node. |
475 | * |
476 | * This has essentially the same responsibilities as ExecProcNode, |
477 | * but it does not do InstrStartNode/InstrStopNode (mainly because |
478 | * it can't tell how many returned tuples to count). Each per-node |
479 | * function must provide its own instrumentation support. |
480 | * ---------------------------------------------------------------- |
481 | */ |
482 | Node * |
483 | MultiExecProcNode(PlanState *node) |
484 | { |
485 | Node *result; |
486 | |
487 | check_stack_depth(); |
488 | |
489 | CHECK_FOR_INTERRUPTS(); |
490 | |
491 | if (node->chgParam != NULL) /* something changed */ |
492 | ExecReScan(node); /* let ReScan handle this */ |
493 | |
494 | switch (nodeTag(node)) |
495 | { |
496 | /* |
497 | * Only node types that actually support multiexec will be listed |
498 | */ |
499 | |
500 | case T_HashState: |
501 | result = MultiExecHash((HashState *) node); |
502 | break; |
503 | |
504 | case T_BitmapIndexScanState: |
505 | result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node); |
506 | break; |
507 | |
508 | case T_BitmapAndState: |
509 | result = MultiExecBitmapAnd((BitmapAndState *) node); |
510 | break; |
511 | |
512 | case T_BitmapOrState: |
513 | result = MultiExecBitmapOr((BitmapOrState *) node); |
514 | break; |
515 | |
516 | default: |
517 | elog(ERROR, "unrecognized node type: %d" , (int) nodeTag(node)); |
518 | result = NULL; |
519 | break; |
520 | } |
521 | |
522 | return result; |
523 | } |
524 | |
525 | |
526 | /* ---------------------------------------------------------------- |
527 | * ExecEndNode |
528 | * |
529 | * Recursively cleans up all the nodes in the plan rooted |
530 | * at 'node'. |
531 | * |
532 | * After this operation, the query plan will not be able to be |
533 | * processed any further. This should be called only after |
534 | * the query plan has been fully executed. |
535 | * ---------------------------------------------------------------- |
536 | */ |
537 | void |
538 | ExecEndNode(PlanState *node) |
539 | { |
540 | /* |
541 | * do nothing when we get to the end of a leaf on tree. |
542 | */ |
543 | if (node == NULL) |
544 | return; |
545 | |
546 | /* |
547 | * Make sure there's enough stack available. Need to check here, in |
548 | * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not |
549 | * guaranteed that ExecProcNode() is reached for all nodes. |
550 | */ |
551 | check_stack_depth(); |
552 | |
553 | if (node->chgParam != NULL) |
554 | { |
555 | bms_free(node->chgParam); |
556 | node->chgParam = NULL; |
557 | } |
558 | |
559 | switch (nodeTag(node)) |
560 | { |
561 | /* |
562 | * control nodes |
563 | */ |
564 | case T_ResultState: |
565 | ExecEndResult((ResultState *) node); |
566 | break; |
567 | |
568 | case T_ProjectSetState: |
569 | ExecEndProjectSet((ProjectSetState *) node); |
570 | break; |
571 | |
572 | case T_ModifyTableState: |
573 | ExecEndModifyTable((ModifyTableState *) node); |
574 | break; |
575 | |
576 | case T_AppendState: |
577 | ExecEndAppend((AppendState *) node); |
578 | break; |
579 | |
580 | case T_MergeAppendState: |
581 | ExecEndMergeAppend((MergeAppendState *) node); |
582 | break; |
583 | |
584 | case T_RecursiveUnionState: |
585 | ExecEndRecursiveUnion((RecursiveUnionState *) node); |
586 | break; |
587 | |
588 | case T_BitmapAndState: |
589 | ExecEndBitmapAnd((BitmapAndState *) node); |
590 | break; |
591 | |
592 | case T_BitmapOrState: |
593 | ExecEndBitmapOr((BitmapOrState *) node); |
594 | break; |
595 | |
596 | /* |
597 | * scan nodes |
598 | */ |
599 | case T_SeqScanState: |
600 | ExecEndSeqScan((SeqScanState *) node); |
601 | break; |
602 | |
603 | case T_SampleScanState: |
604 | ExecEndSampleScan((SampleScanState *) node); |
605 | break; |
606 | |
607 | case T_GatherState: |
608 | ExecEndGather((GatherState *) node); |
609 | break; |
610 | |
611 | case T_GatherMergeState: |
612 | ExecEndGatherMerge((GatherMergeState *) node); |
613 | break; |
614 | |
615 | case T_IndexScanState: |
616 | ExecEndIndexScan((IndexScanState *) node); |
617 | break; |
618 | |
619 | case T_IndexOnlyScanState: |
620 | ExecEndIndexOnlyScan((IndexOnlyScanState *) node); |
621 | break; |
622 | |
623 | case T_BitmapIndexScanState: |
624 | ExecEndBitmapIndexScan((BitmapIndexScanState *) node); |
625 | break; |
626 | |
627 | case T_BitmapHeapScanState: |
628 | ExecEndBitmapHeapScan((BitmapHeapScanState *) node); |
629 | break; |
630 | |
631 | case T_TidScanState: |
632 | ExecEndTidScan((TidScanState *) node); |
633 | break; |
634 | |
635 | case T_SubqueryScanState: |
636 | ExecEndSubqueryScan((SubqueryScanState *) node); |
637 | break; |
638 | |
639 | case T_FunctionScanState: |
640 | ExecEndFunctionScan((FunctionScanState *) node); |
641 | break; |
642 | |
643 | case T_TableFuncScanState: |
644 | ExecEndTableFuncScan((TableFuncScanState *) node); |
645 | break; |
646 | |
647 | case T_ValuesScanState: |
648 | ExecEndValuesScan((ValuesScanState *) node); |
649 | break; |
650 | |
651 | case T_CteScanState: |
652 | ExecEndCteScan((CteScanState *) node); |
653 | break; |
654 | |
655 | case T_NamedTuplestoreScanState: |
656 | ExecEndNamedTuplestoreScan((NamedTuplestoreScanState *) node); |
657 | break; |
658 | |
659 | case T_WorkTableScanState: |
660 | ExecEndWorkTableScan((WorkTableScanState *) node); |
661 | break; |
662 | |
663 | case T_ForeignScanState: |
664 | ExecEndForeignScan((ForeignScanState *) node); |
665 | break; |
666 | |
667 | case T_CustomScanState: |
668 | ExecEndCustomScan((CustomScanState *) node); |
669 | break; |
670 | |
671 | /* |
672 | * join nodes |
673 | */ |
674 | case T_NestLoopState: |
675 | ExecEndNestLoop((NestLoopState *) node); |
676 | break; |
677 | |
678 | case T_MergeJoinState: |
679 | ExecEndMergeJoin((MergeJoinState *) node); |
680 | break; |
681 | |
682 | case T_HashJoinState: |
683 | ExecEndHashJoin((HashJoinState *) node); |
684 | break; |
685 | |
686 | /* |
687 | * materialization nodes |
688 | */ |
689 | case T_MaterialState: |
690 | ExecEndMaterial((MaterialState *) node); |
691 | break; |
692 | |
693 | case T_SortState: |
694 | ExecEndSort((SortState *) node); |
695 | break; |
696 | |
697 | case T_GroupState: |
698 | ExecEndGroup((GroupState *) node); |
699 | break; |
700 | |
701 | case T_AggState: |
702 | ExecEndAgg((AggState *) node); |
703 | break; |
704 | |
705 | case T_WindowAggState: |
706 | ExecEndWindowAgg((WindowAggState *) node); |
707 | break; |
708 | |
709 | case T_UniqueState: |
710 | ExecEndUnique((UniqueState *) node); |
711 | break; |
712 | |
713 | case T_HashState: |
714 | ExecEndHash((HashState *) node); |
715 | break; |
716 | |
717 | case T_SetOpState: |
718 | ExecEndSetOp((SetOpState *) node); |
719 | break; |
720 | |
721 | case T_LockRowsState: |
722 | ExecEndLockRows((LockRowsState *) node); |
723 | break; |
724 | |
725 | case T_LimitState: |
726 | ExecEndLimit((LimitState *) node); |
727 | break; |
728 | |
729 | default: |
730 | elog(ERROR, "unrecognized node type: %d" , (int) nodeTag(node)); |
731 | break; |
732 | } |
733 | } |
734 | |
735 | /* |
736 | * ExecShutdownNode |
737 | * |
738 | * Give execution nodes a chance to stop asynchronous resource consumption |
739 | * and release any resources still held. |
740 | */ |
741 | bool |
742 | ExecShutdownNode(PlanState *node) |
743 | { |
744 | if (node == NULL) |
745 | return false; |
746 | |
747 | check_stack_depth(); |
748 | |
749 | planstate_tree_walker(node, ExecShutdownNode, NULL); |
750 | |
751 | /* |
752 | * Treat the node as running while we shut it down, but only if it's run |
753 | * at least once already. We don't expect much CPU consumption during |
754 | * node shutdown, but in the case of Gather or Gather Merge, we may shut |
755 | * down workers at this stage. If so, their buffer usage will get |
756 | * propagated into pgBufferUsage at this point, and we want to make sure |
757 | * that it gets associated with the Gather node. We skip this if the node |
758 | * has never been executed, so as to avoid incorrectly making it appear |
759 | * that it has. |
760 | */ |
761 | if (node->instrument && node->instrument->running) |
762 | InstrStartNode(node->instrument); |
763 | |
764 | switch (nodeTag(node)) |
765 | { |
766 | case T_GatherState: |
767 | ExecShutdownGather((GatherState *) node); |
768 | break; |
769 | case T_ForeignScanState: |
770 | ExecShutdownForeignScan((ForeignScanState *) node); |
771 | break; |
772 | case T_CustomScanState: |
773 | ExecShutdownCustomScan((CustomScanState *) node); |
774 | break; |
775 | case T_GatherMergeState: |
776 | ExecShutdownGatherMerge((GatherMergeState *) node); |
777 | break; |
778 | case T_HashState: |
779 | ExecShutdownHash((HashState *) node); |
780 | break; |
781 | case T_HashJoinState: |
782 | ExecShutdownHashJoin((HashJoinState *) node); |
783 | break; |
784 | default: |
785 | break; |
786 | } |
787 | |
788 | /* Stop the node if we started it above, reporting 0 tuples. */ |
789 | if (node->instrument && node->instrument->running) |
790 | InstrStopNode(node->instrument, 0); |
791 | |
792 | return false; |
793 | } |
794 | |
795 | /* |
796 | * ExecSetTupleBound |
797 | * |
798 | * Set a tuple bound for a planstate node. This lets child plan nodes |
799 | * optimize based on the knowledge that the maximum number of tuples that |
800 | * their parent will demand is limited. The tuple bound for a node may |
801 | * only be changed between scans (i.e., after node initialization or just |
802 | * before an ExecReScan call). |
803 | * |
804 | * Any negative tuples_needed value means "no limit", which should be the |
805 | * default assumption when this is not called at all for a particular node. |
806 | * |
807 | * Note: if this is called repeatedly on a plan tree, the exact same set |
808 | * of nodes must be updated with the new limit each time; be careful that |
809 | * only unchanging conditions are tested here. |
810 | */ |
811 | void |
812 | ExecSetTupleBound(int64 tuples_needed, PlanState *child_node) |
813 | { |
814 | /* |
815 | * Since this function recurses, in principle we should check stack depth |
816 | * here. In practice, it's probably pointless since the earlier node |
817 | * initialization tree traversal would surely have consumed more stack. |
818 | */ |
819 | |
820 | if (IsA(child_node, SortState)) |
821 | { |
822 | /* |
823 | * If it is a Sort node, notify it that it can use bounded sort. |
824 | * |
825 | * Note: it is the responsibility of nodeSort.c to react properly to |
826 | * changes of these parameters. If we ever redesign this, it'd be a |
827 | * good idea to integrate this signaling with the parameter-change |
828 | * mechanism. |
829 | */ |
830 | SortState *sortState = (SortState *) child_node; |
831 | |
832 | if (tuples_needed < 0) |
833 | { |
834 | /* make sure flag gets reset if needed upon rescan */ |
835 | sortState->bounded = false; |
836 | } |
837 | else |
838 | { |
839 | sortState->bounded = true; |
840 | sortState->bound = tuples_needed; |
841 | } |
842 | } |
843 | else if (IsA(child_node, AppendState)) |
844 | { |
845 | /* |
846 | * If it is an Append, we can apply the bound to any nodes that are |
847 | * children of the Append, since the Append surely need read no more |
848 | * than that many tuples from any one input. |
849 | */ |
850 | AppendState *aState = (AppendState *) child_node; |
851 | int i; |
852 | |
853 | for (i = 0; i < aState->as_nplans; i++) |
854 | ExecSetTupleBound(tuples_needed, aState->appendplans[i]); |
855 | } |
856 | else if (IsA(child_node, MergeAppendState)) |
857 | { |
858 | /* |
859 | * If it is a MergeAppend, we can apply the bound to any nodes that |
860 | * are children of the MergeAppend, since the MergeAppend surely need |
861 | * read no more than that many tuples from any one input. |
862 | */ |
863 | MergeAppendState *maState = (MergeAppendState *) child_node; |
864 | int i; |
865 | |
866 | for (i = 0; i < maState->ms_nplans; i++) |
867 | ExecSetTupleBound(tuples_needed, maState->mergeplans[i]); |
868 | } |
869 | else if (IsA(child_node, ResultState)) |
870 | { |
871 | /* |
872 | * Similarly, for a projecting Result, we can apply the bound to its |
873 | * child node. |
874 | * |
875 | * If Result supported qual checking, we'd have to punt on seeing a |
876 | * qual. Note that having a resconstantqual is not a showstopper: if |
877 | * that condition succeeds it affects nothing, while if it fails, no |
878 | * rows will be demanded from the Result child anyway. |
879 | */ |
880 | if (outerPlanState(child_node)) |
881 | ExecSetTupleBound(tuples_needed, outerPlanState(child_node)); |
882 | } |
883 | else if (IsA(child_node, SubqueryScanState)) |
884 | { |
885 | /* |
886 | * We can also descend through SubqueryScan, but only if it has no |
887 | * qual (otherwise it might discard rows). |
888 | */ |
889 | SubqueryScanState *subqueryState = (SubqueryScanState *) child_node; |
890 | |
891 | if (subqueryState->ss.ps.qual == NULL) |
892 | ExecSetTupleBound(tuples_needed, subqueryState->subplan); |
893 | } |
894 | else if (IsA(child_node, GatherState)) |
895 | { |
896 | /* |
897 | * A Gather node can propagate the bound to its workers. As with |
898 | * MergeAppend, no one worker could possibly need to return more |
899 | * tuples than the Gather itself needs to. |
900 | * |
901 | * Note: As with Sort, the Gather node is responsible for reacting |
902 | * properly to changes to this parameter. |
903 | */ |
904 | GatherState *gstate = (GatherState *) child_node; |
905 | |
906 | gstate->tuples_needed = tuples_needed; |
907 | |
908 | /* Also pass down the bound to our own copy of the child plan */ |
909 | ExecSetTupleBound(tuples_needed, outerPlanState(child_node)); |
910 | } |
911 | else if (IsA(child_node, GatherMergeState)) |
912 | { |
913 | /* Same comments as for Gather */ |
914 | GatherMergeState *gstate = (GatherMergeState *) child_node; |
915 | |
916 | gstate->tuples_needed = tuples_needed; |
917 | |
918 | ExecSetTupleBound(tuples_needed, outerPlanState(child_node)); |
919 | } |
920 | |
921 | /* |
922 | * In principle we could descend through any plan node type that is |
923 | * certain not to discard or combine input rows; but on seeing a node that |
924 | * can do that, we can't propagate the bound any further. For the moment |
925 | * it's unclear that any other cases are worth checking here. |
926 | */ |
927 | } |
928 | |