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