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