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-2025, 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/nodeIncrementalSort.h"
92 : #include "executor/nodeIndexonlyscan.h"
93 : #include "executor/nodeIndexscan.h"
94 : #include "executor/nodeLimit.h"
95 : #include "executor/nodeLockRows.h"
96 : #include "executor/nodeMaterial.h"
97 : #include "executor/nodeMemoize.h"
98 : #include "executor/nodeMergeAppend.h"
99 : #include "executor/nodeMergejoin.h"
100 : #include "executor/nodeModifyTable.h"
101 : #include "executor/nodeNamedtuplestorescan.h"
102 : #include "executor/nodeNestloop.h"
103 : #include "executor/nodeProjectSet.h"
104 : #include "executor/nodeRecursiveunion.h"
105 : #include "executor/nodeResult.h"
106 : #include "executor/nodeSamplescan.h"
107 : #include "executor/nodeSeqscan.h"
108 : #include "executor/nodeSetOp.h"
109 : #include "executor/nodeSort.h"
110 : #include "executor/nodeSubplan.h"
111 : #include "executor/nodeSubqueryscan.h"
112 : #include "executor/nodeTableFuncscan.h"
113 : #include "executor/nodeTidrangescan.h"
114 : #include "executor/nodeTidscan.h"
115 : #include "executor/nodeUnique.h"
116 : #include "executor/nodeValuesscan.h"
117 : #include "executor/nodeWindowAgg.h"
118 : #include "executor/nodeWorktablescan.h"
119 : #include "miscadmin.h"
120 : #include "nodes/nodeFuncs.h"
121 :
122 : static TupleTableSlot *ExecProcNodeFirst(PlanState *node);
123 : static TupleTableSlot *ExecProcNodeInstr(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 1853734 : 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 1853734 : if (node == NULL)
152 344212 : 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 1509522 : check_stack_depth();
160 :
161 1509522 : switch (nodeTag(node))
162 : {
163 : /*
164 : * control nodes
165 : */
166 353958 : case T_Result:
167 353958 : result = (PlanState *) ExecInitResult((Result *) node,
168 : estate, eflags);
169 353896 : break;
170 :
171 9296 : case T_ProjectSet:
172 9296 : result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
173 : estate, eflags);
174 9294 : break;
175 :
176 120820 : case T_ModifyTable:
177 120820 : result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
178 : estate, eflags);
179 120502 : break;
180 :
181 14080 : case T_Append:
182 14080 : result = (PlanState *) ExecInitAppend((Append *) node,
183 : estate, eflags);
184 14080 : break;
185 :
186 538 : case T_MergeAppend:
187 538 : result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
188 : estate, eflags);
189 538 : break;
190 :
191 828 : case T_RecursiveUnion:
192 828 : result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
193 : estate, eflags);
194 828 : break;
195 :
196 160 : case T_BitmapAnd:
197 160 : result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
198 : estate, eflags);
199 160 : break;
200 :
201 306 : case T_BitmapOr:
202 306 : result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
203 : estate, eflags);
204 306 : break;
205 :
206 : /*
207 : * scan nodes
208 : */
209 246870 : case T_SeqScan:
210 246870 : result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
211 : estate, eflags);
212 246852 : break;
213 :
214 306 : case T_SampleScan:
215 306 : result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
216 : estate, eflags);
217 306 : break;
218 :
219 210936 : case T_IndexScan:
220 210936 : result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
221 : estate, eflags);
222 210936 : break;
223 :
224 16426 : case T_IndexOnlyScan:
225 16426 : result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
226 : estate, eflags);
227 16426 : break;
228 :
229 26944 : case T_BitmapIndexScan:
230 26944 : result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
231 : estate, eflags);
232 26944 : break;
233 :
234 26472 : case T_BitmapHeapScan:
235 26472 : result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
236 : estate, eflags);
237 26472 : break;
238 :
239 802 : case T_TidScan:
240 802 : result = (PlanState *) ExecInitTidScan((TidScan *) node,
241 : estate, eflags);
242 802 : break;
243 :
244 202 : case T_TidRangeScan:
245 202 : result = (PlanState *) ExecInitTidRangeScan((TidRangeScan *) node,
246 : estate, eflags);
247 202 : break;
248 :
249 10526 : case T_SubqueryScan:
250 10526 : result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
251 : estate, eflags);
252 10526 : break;
253 :
254 67724 : case T_FunctionScan:
255 67724 : result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
256 : estate, eflags);
257 67716 : break;
258 :
259 626 : case T_TableFuncScan:
260 626 : result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
261 : estate, eflags);
262 626 : break;
263 :
264 8970 : case T_ValuesScan:
265 8970 : result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
266 : estate, eflags);
267 8970 : break;
268 :
269 3290 : case T_CteScan:
270 3290 : result = (PlanState *) ExecInitCteScan((CteScan *) node,
271 : estate, eflags);
272 3290 : break;
273 :
274 684 : case T_NamedTuplestoreScan:
275 684 : result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node,
276 : estate, eflags);
277 684 : break;
278 :
279 828 : case T_WorkTableScan:
280 828 : result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
281 : estate, eflags);
282 828 : break;
283 :
284 1996 : case T_ForeignScan:
285 1996 : result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
286 : estate, eflags);
287 1980 : 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 160492 : case T_NestLoop:
298 160492 : result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
299 : estate, eflags);
300 160492 : break;
301 :
302 7090 : case T_MergeJoin:
303 7090 : result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
304 : estate, eflags);
305 7090 : break;
306 :
307 30248 : case T_HashJoin:
308 30248 : result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
309 : estate, eflags);
310 30248 : break;
311 :
312 : /*
313 : * materialization nodes
314 : */
315 4056 : case T_Material:
316 4056 : result = (PlanState *) ExecInitMaterial((Material *) node,
317 : estate, eflags);
318 4056 : break;
319 :
320 83264 : case T_Sort:
321 83264 : result = (PlanState *) ExecInitSort((Sort *) node,
322 : estate, eflags);
323 83258 : break;
324 :
325 780 : case T_IncrementalSort:
326 780 : result = (PlanState *) ExecInitIncrementalSort((IncrementalSort *) node,
327 : estate, eflags);
328 780 : break;
329 :
330 1464 : case T_Memoize:
331 1464 : result = (PlanState *) ExecInitMemoize((Memoize *) node, estate,
332 : eflags);
333 1464 : break;
334 :
335 246 : case T_Group:
336 246 : result = (PlanState *) ExecInitGroup((Group *) node,
337 : estate, eflags);
338 246 : break;
339 :
340 45100 : case T_Agg:
341 45100 : result = (PlanState *) ExecInitAgg((Agg *) node,
342 : estate, eflags);
343 45094 : break;
344 :
345 2486 : case T_WindowAgg:
346 2486 : result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
347 : estate, eflags);
348 2486 : break;
349 :
350 5218 : case T_Unique:
351 5218 : result = (PlanState *) ExecInitUnique((Unique *) node,
352 : estate, eflags);
353 5218 : break;
354 :
355 1066 : case T_Gather:
356 1066 : result = (PlanState *) ExecInitGather((Gather *) node,
357 : estate, eflags);
358 1066 : break;
359 :
360 330 : case T_GatherMerge:
361 330 : result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
362 : estate, eflags);
363 330 : break;
364 :
365 30248 : case T_Hash:
366 30248 : result = (PlanState *) ExecInitHash((Hash *) node,
367 : estate, eflags);
368 30248 : break;
369 :
370 686 : case T_SetOp:
371 686 : result = (PlanState *) ExecInitSetOp((SetOp *) node,
372 : estate, eflags);
373 686 : break;
374 :
375 8400 : case T_LockRows:
376 8400 : result = (PlanState *) ExecInitLockRows((LockRows *) node,
377 : estate, eflags);
378 8400 : break;
379 :
380 4760 : case T_Limit:
381 4760 : result = (PlanState *) ExecInitLimit((Limit *) node,
382 : estate, eflags);
383 4760 : 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 1509086 : 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 1509086 : subps = NIL;
402 1522248 : foreach(l, node->initPlan)
403 : {
404 13162 : SubPlan *subplan = (SubPlan *) lfirst(l);
405 : SubPlanState *sstate;
406 :
407 : Assert(IsA(subplan, SubPlan));
408 : Assert(subplan->args == NIL);
409 13162 : sstate = ExecInitSubPlan(subplan, result);
410 13162 : subps = lappend(subps, sstate);
411 : }
412 1509086 : result->initPlan = subps;
413 :
414 : /* Set up instrumentation for this node if requested */
415 1509086 : if (estate->es_instrument)
416 10316 : result->instrument = InstrAlloc(1, estate->es_instrument,
417 10316 : result->async_capable);
418 :
419 1509086 : 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 1509514 : 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 1509514 : node->ExecProcNodeReal = function;
439 1509514 : node->ExecProcNode = ExecProcNodeFirst;
440 1509514 : }
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 1281712 : 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 1281712 : 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 1281712 : if (node->instrument)
465 7894 : node->ExecProcNode = ExecProcNodeInstr;
466 : else
467 1273818 : node->ExecProcNode = node->ExecProcNodeReal;
468 :
469 1281712 : return node->ExecProcNode(node);
470 : }
471 :
472 :
473 : /*
474 : * ExecProcNode wrapper that performs instrumentation calls. By keeping
475 : * this a separate function, we avoid overhead in the normal case where
476 : * no instrumentation is wanted.
477 : */
478 : static TupleTableSlot *
479 12894796 : ExecProcNodeInstr(PlanState *node)
480 : {
481 : TupleTableSlot *result;
482 :
483 12894796 : InstrStartNode(node->instrument);
484 :
485 12894796 : result = node->ExecProcNodeReal(node);
486 :
487 12894784 : InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
488 :
489 12894784 : return result;
490 : }
491 :
492 :
493 : /* ----------------------------------------------------------------
494 : * MultiExecProcNode
495 : *
496 : * Execute a node that doesn't return individual tuples
497 : * (it might return a hashtable, bitmap, etc). Caller should
498 : * check it got back the expected kind of Node.
499 : *
500 : * This has essentially the same responsibilities as ExecProcNode,
501 : * but it does not do InstrStartNode/InstrStopNode (mainly because
502 : * it can't tell how many returned tuples to count). Each per-node
503 : * function must provide its own instrumentation support.
504 : * ----------------------------------------------------------------
505 : */
506 : Node *
507 45206 : MultiExecProcNode(PlanState *node)
508 : {
509 : Node *result;
510 :
511 45206 : check_stack_depth();
512 :
513 45206 : CHECK_FOR_INTERRUPTS();
514 :
515 45206 : if (node->chgParam != NULL) /* something changed */
516 11508 : ExecReScan(node); /* let ReScan handle this */
517 :
518 45206 : switch (nodeTag(node))
519 : {
520 : /*
521 : * Only node types that actually support multiexec will be listed
522 : */
523 :
524 19280 : case T_HashState:
525 19280 : result = MultiExecHash((HashState *) node);
526 19280 : break;
527 :
528 25616 : case T_BitmapIndexScanState:
529 25616 : result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node);
530 25616 : break;
531 :
532 112 : case T_BitmapAndState:
533 112 : result = MultiExecBitmapAnd((BitmapAndState *) node);
534 112 : break;
535 :
536 198 : case T_BitmapOrState:
537 198 : result = MultiExecBitmapOr((BitmapOrState *) node);
538 198 : break;
539 :
540 0 : default:
541 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
542 : result = NULL;
543 : break;
544 : }
545 :
546 45206 : return result;
547 : }
548 :
549 :
550 : /* ----------------------------------------------------------------
551 : * ExecEndNode
552 : *
553 : * Recursively cleans up all the nodes in the plan rooted
554 : * at 'node'.
555 : *
556 : * After this operation, the query plan will not be able to be
557 : * processed any further. This should be called only after
558 : * the query plan has been fully executed.
559 : * ----------------------------------------------------------------
560 : */
561 : void
562 1802262 : ExecEndNode(PlanState *node)
563 : {
564 : /*
565 : * do nothing when we get to the end of a leaf on tree.
566 : */
567 1802262 : if (node == NULL)
568 327098 : return;
569 :
570 : /*
571 : * Make sure there's enough stack available. Need to check here, in
572 : * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
573 : * guaranteed that ExecProcNode() is reached for all nodes.
574 : */
575 1475164 : check_stack_depth();
576 :
577 1475164 : if (node->chgParam != NULL)
578 : {
579 7272 : bms_free(node->chgParam);
580 7272 : node->chgParam = NULL;
581 : }
582 :
583 1475164 : switch (nodeTag(node))
584 : {
585 : /*
586 : * control nodes
587 : */
588 336878 : case T_ResultState:
589 336878 : ExecEndResult((ResultState *) node);
590 336878 : break;
591 :
592 7778 : case T_ProjectSetState:
593 7778 : ExecEndProjectSet((ProjectSetState *) node);
594 7778 : break;
595 :
596 116146 : case T_ModifyTableState:
597 116146 : ExecEndModifyTable((ModifyTableState *) node);
598 116146 : break;
599 :
600 13784 : case T_AppendState:
601 13784 : ExecEndAppend((AppendState *) node);
602 13784 : break;
603 :
604 538 : case T_MergeAppendState:
605 538 : ExecEndMergeAppend((MergeAppendState *) node);
606 538 : break;
607 :
608 828 : case T_RecursiveUnionState:
609 828 : ExecEndRecursiveUnion((RecursiveUnionState *) node);
610 828 : break;
611 :
612 160 : case T_BitmapAndState:
613 160 : ExecEndBitmapAnd((BitmapAndState *) node);
614 160 : break;
615 :
616 306 : case T_BitmapOrState:
617 306 : ExecEndBitmapOr((BitmapOrState *) node);
618 306 : break;
619 :
620 : /*
621 : * scan nodes
622 : */
623 244290 : case T_SeqScanState:
624 244290 : ExecEndSeqScan((SeqScanState *) node);
625 244290 : break;
626 :
627 266 : case T_SampleScanState:
628 266 : ExecEndSampleScan((SampleScanState *) node);
629 266 : break;
630 :
631 1054 : case T_GatherState:
632 1054 : ExecEndGather((GatherState *) node);
633 1054 : break;
634 :
635 330 : case T_GatherMergeState:
636 330 : ExecEndGatherMerge((GatherMergeState *) node);
637 330 : break;
638 :
639 210074 : case T_IndexScanState:
640 210074 : ExecEndIndexScan((IndexScanState *) node);
641 210074 : break;
642 :
643 16376 : case T_IndexOnlyScanState:
644 16376 : ExecEndIndexOnlyScan((IndexOnlyScanState *) node);
645 16376 : break;
646 :
647 26830 : case T_BitmapIndexScanState:
648 26830 : ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
649 26830 : break;
650 :
651 26358 : case T_BitmapHeapScanState:
652 26358 : ExecEndBitmapHeapScan((BitmapHeapScanState *) node);
653 26358 : break;
654 :
655 676 : case T_TidScanState:
656 676 : ExecEndTidScan((TidScanState *) node);
657 676 : break;
658 :
659 202 : case T_TidRangeScanState:
660 202 : ExecEndTidRangeScan((TidRangeScanState *) node);
661 202 : break;
662 :
663 10526 : case T_SubqueryScanState:
664 10526 : ExecEndSubqueryScan((SubqueryScanState *) node);
665 10526 : break;
666 :
667 62362 : case T_FunctionScanState:
668 62362 : ExecEndFunctionScan((FunctionScanState *) node);
669 62362 : break;
670 :
671 512 : case T_TableFuncScanState:
672 512 : ExecEndTableFuncScan((TableFuncScanState *) node);
673 512 : break;
674 :
675 3264 : case T_CteScanState:
676 3264 : ExecEndCteScan((CteScanState *) node);
677 3264 : break;
678 :
679 1924 : case T_ForeignScanState:
680 1924 : ExecEndForeignScan((ForeignScanState *) node);
681 1924 : break;
682 :
683 0 : case T_CustomScanState:
684 0 : ExecEndCustomScan((CustomScanState *) node);
685 0 : break;
686 :
687 : /*
688 : * join nodes
689 : */
690 160246 : case T_NestLoopState:
691 160246 : ExecEndNestLoop((NestLoopState *) node);
692 160246 : break;
693 :
694 7084 : case T_MergeJoinState:
695 7084 : ExecEndMergeJoin((MergeJoinState *) node);
696 7084 : break;
697 :
698 30136 : case T_HashJoinState:
699 30136 : ExecEndHashJoin((HashJoinState *) node);
700 30136 : break;
701 :
702 : /*
703 : * materialization nodes
704 : */
705 3990 : case T_MaterialState:
706 3990 : ExecEndMaterial((MaterialState *) node);
707 3990 : break;
708 :
709 83110 : case T_SortState:
710 83110 : ExecEndSort((SortState *) node);
711 83110 : break;
712 :
713 780 : case T_IncrementalSortState:
714 780 : ExecEndIncrementalSort((IncrementalSortState *) node);
715 780 : break;
716 :
717 1464 : case T_MemoizeState:
718 1464 : ExecEndMemoize((MemoizeState *) node);
719 1464 : break;
720 :
721 246 : case T_GroupState:
722 246 : ExecEndGroup((GroupState *) node);
723 246 : break;
724 :
725 44962 : case T_AggState:
726 44962 : ExecEndAgg((AggState *) node);
727 44962 : break;
728 :
729 2354 : case T_WindowAggState:
730 2354 : ExecEndWindowAgg((WindowAggState *) node);
731 2354 : break;
732 :
733 5218 : case T_UniqueState:
734 5218 : ExecEndUnique((UniqueState *) node);
735 5218 : break;
736 :
737 30136 : case T_HashState:
738 30136 : ExecEndHash((HashState *) node);
739 30136 : break;
740 :
741 686 : case T_SetOpState:
742 686 : ExecEndSetOp((SetOpState *) node);
743 686 : break;
744 :
745 8314 : case T_LockRowsState:
746 8314 : ExecEndLockRows((LockRowsState *) node);
747 8314 : break;
748 :
749 4700 : case T_LimitState:
750 4700 : ExecEndLimit((LimitState *) node);
751 4700 : break;
752 :
753 : /* No clean up actions for these nodes. */
754 10276 : case T_ValuesScanState:
755 : case T_NamedTuplestoreScanState:
756 : case T_WorkTableScanState:
757 10276 : break;
758 :
759 0 : default:
760 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
761 : break;
762 : }
763 : }
764 :
765 : /*
766 : * ExecShutdownNode
767 : *
768 : * Give execution nodes a chance to stop asynchronous resource consumption
769 : * and release any resources still held.
770 : */
771 : void
772 622672 : ExecShutdownNode(PlanState *node)
773 : {
774 622672 : (void) ExecShutdownNode_walker(node, NULL);
775 622672 : }
776 :
777 : static bool
778 1416086 : ExecShutdownNode_walker(PlanState *node, void *context)
779 : {
780 1416086 : if (node == NULL)
781 0 : return false;
782 :
783 1416086 : check_stack_depth();
784 :
785 : /*
786 : * Treat the node as running while we shut it down, but only if it's run
787 : * at least once already. We don't expect much CPU consumption during
788 : * node shutdown, but in the case of Gather or Gather Merge, we may shut
789 : * down workers at this stage. If so, their buffer usage will get
790 : * propagated into pgBufferUsage at this point, and we want to make sure
791 : * that it gets associated with the Gather node. We skip this if the node
792 : * has never been executed, so as to avoid incorrectly making it appear
793 : * that it has.
794 : */
795 1416086 : if (node->instrument && node->instrument->running)
796 8644 : InstrStartNode(node->instrument);
797 :
798 1416086 : planstate_tree_walker(node, ExecShutdownNode_walker, context);
799 :
800 1416086 : switch (nodeTag(node))
801 : {
802 622 : case T_GatherState:
803 622 : ExecShutdownGather((GatherState *) node);
804 622 : break;
805 1120 : case T_ForeignScanState:
806 1120 : ExecShutdownForeignScan((ForeignScanState *) node);
807 1120 : break;
808 0 : case T_CustomScanState:
809 0 : ExecShutdownCustomScan((CustomScanState *) node);
810 0 : break;
811 132 : case T_GatherMergeState:
812 132 : ExecShutdownGatherMerge((GatherMergeState *) node);
813 132 : break;
814 26472 : case T_HashState:
815 26472 : ExecShutdownHash((HashState *) node);
816 26472 : break;
817 26472 : case T_HashJoinState:
818 26472 : ExecShutdownHashJoin((HashJoinState *) node);
819 26472 : break;
820 1361268 : default:
821 1361268 : break;
822 : }
823 :
824 : /* Stop the node if we started it above, reporting 0 tuples. */
825 1416086 : if (node->instrument && node->instrument->running)
826 8644 : InstrStopNode(node->instrument, 0);
827 :
828 1416086 : return false;
829 : }
830 :
831 : /*
832 : * ExecSetTupleBound
833 : *
834 : * Set a tuple bound for a planstate node. This lets child plan nodes
835 : * optimize based on the knowledge that the maximum number of tuples that
836 : * their parent will demand is limited. The tuple bound for a node may
837 : * only be changed between scans (i.e., after node initialization or just
838 : * before an ExecReScan call).
839 : *
840 : * Any negative tuples_needed value means "no limit", which should be the
841 : * default assumption when this is not called at all for a particular node.
842 : *
843 : * Note: if this is called repeatedly on a plan tree, the exact same set
844 : * of nodes must be updated with the new limit each time; be careful that
845 : * only unchanging conditions are tested here.
846 : */
847 : void
848 67540 : ExecSetTupleBound(int64 tuples_needed, PlanState *child_node)
849 : {
850 : /*
851 : * Since this function recurses, in principle we should check stack depth
852 : * here. In practice, it's probably pointless since the earlier node
853 : * initialization tree traversal would surely have consumed more stack.
854 : */
855 :
856 67540 : if (IsA(child_node, SortState))
857 : {
858 : /*
859 : * If it is a Sort node, notify it that it can use bounded sort.
860 : *
861 : * Note: it is the responsibility of nodeSort.c to react properly to
862 : * changes of these parameters. If we ever redesign this, it'd be a
863 : * good idea to integrate this signaling with the parameter-change
864 : * mechanism.
865 : */
866 1230 : SortState *sortState = (SortState *) child_node;
867 :
868 1230 : if (tuples_needed < 0)
869 : {
870 : /* make sure flag gets reset if needed upon rescan */
871 292 : sortState->bounded = false;
872 : }
873 : else
874 : {
875 938 : sortState->bounded = true;
876 938 : sortState->bound = tuples_needed;
877 : }
878 : }
879 66310 : else if (IsA(child_node, IncrementalSortState))
880 : {
881 : /*
882 : * If it is an IncrementalSort node, notify it that it can use bounded
883 : * sort.
884 : *
885 : * Note: it is the responsibility of nodeIncrementalSort.c to react
886 : * properly to changes of these parameters. If we ever redesign this,
887 : * it'd be a good idea to integrate this signaling with the
888 : * parameter-change mechanism.
889 : */
890 146 : IncrementalSortState *sortState = (IncrementalSortState *) child_node;
891 :
892 146 : if (tuples_needed < 0)
893 : {
894 : /* make sure flag gets reset if needed upon rescan */
895 0 : sortState->bounded = false;
896 : }
897 : else
898 : {
899 146 : sortState->bounded = true;
900 146 : sortState->bound = tuples_needed;
901 : }
902 : }
903 66164 : else if (IsA(child_node, AppendState))
904 : {
905 : /*
906 : * If it is an Append, we can apply the bound to any nodes that are
907 : * children of the Append, since the Append surely need read no more
908 : * than that many tuples from any one input.
909 : */
910 160 : AppendState *aState = (AppendState *) child_node;
911 : int i;
912 :
913 508 : for (i = 0; i < aState->as_nplans; i++)
914 348 : ExecSetTupleBound(tuples_needed, aState->appendplans[i]);
915 : }
916 66004 : else if (IsA(child_node, MergeAppendState))
917 : {
918 : /*
919 : * If it is a MergeAppend, we can apply the bound to any nodes that
920 : * are children of the MergeAppend, since the MergeAppend surely need
921 : * read no more than that many tuples from any one input.
922 : */
923 60 : MergeAppendState *maState = (MergeAppendState *) child_node;
924 : int i;
925 :
926 240 : for (i = 0; i < maState->ms_nplans; i++)
927 180 : ExecSetTupleBound(tuples_needed, maState->mergeplans[i]);
928 : }
929 65944 : else if (IsA(child_node, ResultState))
930 : {
931 : /*
932 : * Similarly, for a projecting Result, we can apply the bound to its
933 : * child node.
934 : *
935 : * If Result supported qual checking, we'd have to punt on seeing a
936 : * qual. Note that having a resconstantqual is not a showstopper: if
937 : * that condition succeeds it affects nothing, while if it fails, no
938 : * rows will be demanded from the Result child anyway.
939 : */
940 620 : if (outerPlanState(child_node))
941 104 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
942 : }
943 65324 : else if (IsA(child_node, SubqueryScanState))
944 : {
945 : /*
946 : * We can also descend through SubqueryScan, but only if it has no
947 : * qual (otherwise it might discard rows).
948 : */
949 94 : SubqueryScanState *subqueryState = (SubqueryScanState *) child_node;
950 :
951 94 : if (subqueryState->ss.ps.qual == NULL)
952 72 : ExecSetTupleBound(tuples_needed, subqueryState->subplan);
953 : }
954 65230 : else if (IsA(child_node, GatherState))
955 : {
956 : /*
957 : * A Gather node can propagate the bound to its workers. As with
958 : * MergeAppend, no one worker could possibly need to return more
959 : * tuples than the Gather itself needs to.
960 : *
961 : * Note: As with Sort, the Gather node is responsible for reacting
962 : * properly to changes to this parameter.
963 : */
964 0 : GatherState *gstate = (GatherState *) child_node;
965 :
966 0 : gstate->tuples_needed = tuples_needed;
967 :
968 : /* Also pass down the bound to our own copy of the child plan */
969 0 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
970 : }
971 65230 : else if (IsA(child_node, GatherMergeState))
972 : {
973 : /* Same comments as for Gather */
974 30 : GatherMergeState *gstate = (GatherMergeState *) child_node;
975 :
976 30 : gstate->tuples_needed = tuples_needed;
977 :
978 30 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
979 : }
980 :
981 : /*
982 : * In principle we could descend through any plan node type that is
983 : * certain not to discard or combine input rows; but on seeing a node that
984 : * can do that, we can't propagate the bound any further. For the moment
985 : * it's unclear that any other cases are worth checking here.
986 : */
987 67540 : }
|