Branch data 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 : 1043976 : 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 [ + + ]: 1043976 : if (node == NULL)
152 : 162508 : 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 : 881468 : check_stack_depth();
160 : :
161 [ + + + + : 881468 : switch (nodeTag(node))
+ + + + +
+ + + + +
+ + + + +
+ + + + +
- + + + +
+ + + + +
+ + + + +
+ + + - ]
162 : : {
163 : : /*
164 : : * control nodes
165 : : */
166 : 169472 : case T_Result:
167 : 169472 : result = (PlanState *) ExecInitResult((Result *) node,
168 : : estate, eflags);
169 : 169432 : break;
170 : :
171 : 9858 : case T_ProjectSet:
172 : 9858 : result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
173 : : estate, eflags);
174 : 9857 : break;
175 : :
176 : 73193 : case T_ModifyTable:
177 : 73193 : result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
178 : : estate, eflags);
179 : 72941 : break;
180 : :
181 : 12491 : case T_Append:
182 : 12491 : result = (PlanState *) ExecInitAppend((Append *) node,
183 : : estate, eflags);
184 : 12491 : break;
185 : :
186 : 390 : case T_MergeAppend:
187 : 390 : result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
188 : : estate, eflags);
189 : 390 : break;
190 : :
191 : 557 : case T_RecursiveUnion:
192 : 557 : result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
193 : : estate, eflags);
194 : 557 : 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 : 162385 : case T_SeqScan:
210 : 162385 : result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
211 : : estate, eflags);
212 : 162377 : break;
213 : :
214 : 200 : case T_SampleScan:
215 : 200 : result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
216 : : estate, eflags);
217 : 200 : break;
218 : :
219 : 101460 : case T_IndexScan:
220 : 101460 : result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
221 : : estate, eflags);
222 : 101460 : break;
223 : :
224 : 11996 : case T_IndexOnlyScan:
225 : 11996 : result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
226 : : estate, eflags);
227 : 11996 : break;
228 : :
229 : 16935 : case T_BitmapIndexScan:
230 : 16935 : result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
231 : : estate, eflags);
232 : 16935 : break;
233 : :
234 : 16531 : case T_BitmapHeapScan:
235 : 16531 : result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
236 : : estate, eflags);
237 : 16531 : break;
238 : :
239 : 533 : case T_TidScan:
240 : 533 : result = (PlanState *) ExecInitTidScan((TidScan *) node,
241 : : estate, eflags);
242 : 533 : break;
243 : :
244 : 1397 : case T_TidRangeScan:
245 : 1397 : result = (PlanState *) ExecInitTidRangeScan((TidRangeScan *) node,
246 : : estate, eflags);
247 : 1397 : break;
248 : :
249 : 13703 : case T_SubqueryScan:
250 : 13703 : result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
251 : : estate, eflags);
252 : 13703 : break;
253 : :
254 : 42075 : case T_FunctionScan:
255 : 42075 : result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
256 : : estate, eflags);
257 : 42071 : break;
258 : :
259 : 416 : case T_TableFuncScan:
260 : 416 : result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
261 : : estate, eflags);
262 : 416 : break;
263 : :
264 : 6344 : case T_ValuesScan:
265 : 6344 : result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
266 : : estate, eflags);
267 : 6344 : break;
268 : :
269 : 2619 : case T_CteScan:
270 : 2619 : result = (PlanState *) ExecInitCteScan((CteScan *) node,
271 : : estate, eflags);
272 : 2619 : break;
273 : :
274 : 530 : case T_NamedTuplestoreScan:
275 : 530 : result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node,
276 : : estate, eflags);
277 : 530 : break;
278 : :
279 : 557 : case T_WorkTableScan:
280 : 557 : result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
281 : : estate, eflags);
282 : 557 : break;
283 : :
284 : 1070 : case T_ForeignScan:
285 : 1070 : result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
286 : : estate, eflags);
287 : 1058 : 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 : 65286 : case T_NestLoop:
298 : 65286 : result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
299 : : estate, eflags);
300 : 65286 : break;
301 : :
302 : 4785 : case T_MergeJoin:
303 : 4785 : result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
304 : : estate, eflags);
305 : 4785 : break;
306 : :
307 : 27777 : case T_HashJoin:
308 : 27777 : result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
309 : : estate, eflags);
310 : 27777 : break;
311 : :
312 : : /*
313 : : * materialization nodes
314 : : */
315 : 2748 : case T_Material:
316 : 2748 : result = (PlanState *) ExecInitMaterial((Material *) node,
317 : : estate, eflags);
318 : 2748 : break;
319 : :
320 : 55066 : case T_Sort:
321 : 55066 : result = (PlanState *) ExecInitSort((Sort *) node,
322 : : estate, eflags);
323 : 55062 : break;
324 : :
325 : 648 : case T_IncrementalSort:
326 : 648 : result = (PlanState *) ExecInitIncrementalSort((IncrementalSort *) node,
327 : : estate, eflags);
328 : 648 : break;
329 : :
330 : 1312 : case T_Memoize:
331 : 1312 : result = (PlanState *) ExecInitMemoize((Memoize *) node, estate,
332 : : eflags);
333 : 1312 : break;
334 : :
335 : 182 : case T_Group:
336 : 182 : result = (PlanState *) ExecInitGroup((Group *) node,
337 : : estate, eflags);
338 : 182 : break;
339 : :
340 : 34509 : case T_Agg:
341 : 34509 : result = (PlanState *) ExecInitAgg((Agg *) node,
342 : : estate, eflags);
343 : 34505 : break;
344 : :
345 : 1918 : case T_WindowAgg:
346 : 1918 : result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
347 : : estate, eflags);
348 : 1918 : break;
349 : :
350 : 3478 : case T_Unique:
351 : 3478 : result = (PlanState *) ExecInitUnique((Unique *) node,
352 : : estate, eflags);
353 : 3478 : 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 : 27777 : case T_Hash:
366 : 27777 : result = (PlanState *) ExecInitHash((Hash *) node,
367 : : estate, eflags);
368 : 27777 : break;
369 : :
370 : 480 : case T_SetOp:
371 : 480 : result = (PlanState *) ExecInitSetOp((SetOp *) node,
372 : : estate, eflags);
373 : 480 : break;
374 : :
375 : 6164 : case T_LockRows:
376 : 6164 : result = (PlanState *) ExecInitLockRows((LockRows *) node,
377 : : estate, eflags);
378 : 6164 : break;
379 : :
380 : 3191 : case T_Limit:
381 : 3191 : result = (PlanState *) ExecInitLimit((Limit *) node,
382 : : estate, eflags);
383 : 3191 : 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 : 881143 : 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 : 881143 : subps = NIL;
402 [ + + + + : 890574 : foreach(l, node->initPlan)
+ + ]
403 : : {
404 : 9431 : SubPlan *subplan = (SubPlan *) lfirst(l);
405 : : SubPlanState *sstate;
406 : :
407 : : Assert(IsA(subplan, SubPlan));
408 : : Assert(subplan->args == NIL);
409 : 9431 : sstate = ExecInitSubPlan(subplan, result);
410 : 9431 : subps = lappend(subps, sstate);
411 : : }
412 : 881143 : result->initPlan = subps;
413 : :
414 : : /* Set up instrumentation for this node if requested */
415 [ + + ]: 881143 : if (estate->es_instrument)
416 : 6995 : result->instrument = InstrAllocNode(estate->es_instrument,
417 : 6995 : result->async_capable);
418 : :
419 : 881143 : 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 : 881439 : 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 : 881439 : node->ExecProcNodeReal = function;
439 : 881439 : node->ExecProcNode = ExecProcNodeFirst;
440 : 881439 : }
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 : 729245 : 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 : 729245 : 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 [ + + ]: 729245 : if (node->instrument)
465 : 5429 : node->ExecProcNode = ExecProcNodeInstr;
466 : : else
467 : 723816 : node->ExecProcNode = node->ExecProcNodeReal;
468 : :
469 : 729245 : 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 : 35112 : MultiExecProcNode(PlanState *node)
489 : : {
490 : : Node *result;
491 : :
492 : 35112 : check_stack_depth();
493 : :
494 [ - + ]: 35112 : CHECK_FOR_INTERRUPTS();
495 : :
496 [ + + ]: 35112 : if (node->chgParam != NULL) /* something changed */
497 : 3832 : ExecReScan(node); /* let ReScan handle this */
498 : :
499 [ + + + + : 35112 : switch (nodeTag(node))
- ]
500 : : {
501 : : /*
502 : : * Only node types that actually support multiexec will be listed
503 : : */
504 : :
505 : 19074 : case T_HashState:
506 : 19074 : result = MultiExecHash((HashState *) node);
507 : 19074 : break;
508 : :
509 : 15767 : case T_BitmapIndexScanState:
510 : 15767 : result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node);
511 : 15767 : break;
512 : :
513 : 114 : case T_BitmapAndState:
514 : 114 : result = MultiExecBitmapAnd((BitmapAndState *) node);
515 : 114 : break;
516 : :
517 : 157 : case T_BitmapOrState:
518 : 157 : result = MultiExecBitmapOr((BitmapOrState *) node);
519 : 157 : break;
520 : :
521 : 0 : default:
522 [ # # ]: 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
523 : : result = NULL;
524 : : break;
525 : : }
526 : :
527 : 35112 : 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 : 1007880 : ExecEndNode(PlanState *node)
544 : : {
545 : : /*
546 : : * do nothing when we get to the end of a leaf on tree.
547 : : */
548 [ + + ]: 1007880 : if (node == NULL)
549 : 150765 : 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 : 857115 : check_stack_depth();
557 : :
558 [ + + ]: 857115 : if (node->chgParam != NULL)
559 : : {
560 : 5300 : bms_free(node->chgParam);
561 : 5300 : node->chgParam = NULL;
562 : : }
563 : :
564 [ + + + + : 857115 : switch (nodeTag(node))
+ + + + +
+ + + + +
+ + + + +
+ + + + -
+ + + + +
+ + + + +
+ + + + +
+ - ]
565 : : {
566 : : /*
567 : : * control nodes
568 : : */
569 : 157751 : case T_ResultState:
570 : 157751 : ExecEndResult((ResultState *) node);
571 : 157751 : break;
572 : :
573 : 8710 : case T_ProjectSetState:
574 : 8710 : ExecEndProjectSet((ProjectSetState *) node);
575 : 8710 : break;
576 : :
577 : 69842 : case T_ModifyTableState:
578 : 69842 : ExecEndModifyTable((ModifyTableState *) node);
579 : 69842 : break;
580 : :
581 : 12290 : case T_AppendState:
582 : 12290 : ExecEndAppend((AppendState *) node);
583 : 12290 : break;
584 : :
585 : 390 : case T_MergeAppendState:
586 : 390 : ExecEndMergeAppend((MergeAppendState *) node);
587 : 390 : break;
588 : :
589 : 557 : case T_RecursiveUnionState:
590 : 557 : ExecEndRecursiveUnion((RecursiveUnionState *) node);
591 : 557 : 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 : 160517 : case T_SeqScanState:
605 : 160517 : ExecEndSeqScan((SeqScanState *) node);
606 : 160517 : 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 : 100907 : case T_IndexScanState:
621 : 100907 : ExecEndIndexScan((IndexScanState *) node);
622 : 100907 : break;
623 : :
624 : 11963 : case T_IndexOnlyScanState:
625 : 11963 : ExecEndIndexOnlyScan((IndexOnlyScanState *) node);
626 : 11963 : break;
627 : :
628 : 16855 : case T_BitmapIndexScanState:
629 : 16855 : ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
630 : 16855 : break;
631 : :
632 : 16451 : case T_BitmapHeapScanState:
633 : 16451 : ExecEndBitmapHeapScan((BitmapHeapScanState *) node);
634 : 16451 : break;
635 : :
636 : 442 : case T_TidScanState:
637 : 442 : ExecEndTidScan((TidScanState *) node);
638 : 442 : break;
639 : :
640 : 243 : case T_TidRangeScanState:
641 : 243 : ExecEndTidRangeScan((TidRangeScanState *) node);
642 : 243 : break;
643 : :
644 : 13697 : case T_SubqueryScanState:
645 : 13697 : ExecEndSubqueryScan((SubqueryScanState *) node);
646 : 13697 : break;
647 : :
648 : 39160 : case T_FunctionScanState:
649 : 39160 : ExecEndFunctionScan((FunctionScanState *) node);
650 : 39160 : break;
651 : :
652 : 340 : case T_TableFuncScanState:
653 : 340 : ExecEndTableFuncScan((TableFuncScanState *) node);
654 : 340 : break;
655 : :
656 : 2603 : case T_CteScanState:
657 : 2603 : ExecEndCteScan((CteScanState *) node);
658 : 2603 : break;
659 : :
660 : 1017 : case T_ForeignScanState:
661 : 1017 : ExecEndForeignScan((ForeignScanState *) node);
662 : 1016 : break;
663 : :
664 : 0 : case T_CustomScanState:
665 : 0 : ExecEndCustomScan((CustomScanState *) node);
666 : 0 : break;
667 : :
668 : : /*
669 : : * join nodes
670 : : */
671 : 65140 : case T_NestLoopState:
672 : 65140 : ExecEndNestLoop((NestLoopState *) node);
673 : 65140 : break;
674 : :
675 : 4781 : case T_MergeJoinState:
676 : 4781 : ExecEndMergeJoin((MergeJoinState *) node);
677 : 4781 : break;
678 : :
679 : 27705 : case T_HashJoinState:
680 : 27705 : ExecEndHashJoin((HashJoinState *) node);
681 : 27705 : break;
682 : :
683 : : /*
684 : : * materialization nodes
685 : : */
686 : 2706 : case T_MaterialState:
687 : 2706 : ExecEndMaterial((MaterialState *) node);
688 : 2706 : break;
689 : :
690 : 54955 : case T_SortState:
691 : 54955 : ExecEndSort((SortState *) node);
692 : 54955 : break;
693 : :
694 : 648 : case T_IncrementalSortState:
695 : 648 : ExecEndIncrementalSort((IncrementalSortState *) node);
696 : 648 : break;
697 : :
698 : 1312 : case T_MemoizeState:
699 : 1312 : ExecEndMemoize((MemoizeState *) node);
700 : 1312 : break;
701 : :
702 : 182 : case T_GroupState:
703 : 182 : ExecEndGroup((GroupState *) node);
704 : 182 : break;
705 : :
706 : 34385 : case T_AggState:
707 : 34385 : ExecEndAgg((AggState *) node);
708 : 34385 : break;
709 : :
710 : 1782 : case T_WindowAggState:
711 : 1782 : ExecEndWindowAgg((WindowAggState *) node);
712 : 1782 : break;
713 : :
714 : 3478 : case T_UniqueState:
715 : 3478 : ExecEndUnique((UniqueState *) node);
716 : 3478 : break;
717 : :
718 : 27705 : case T_HashState:
719 : 27705 : ExecEndHash((HashState *) node);
720 : 27705 : break;
721 : :
722 : 480 : case T_SetOpState:
723 : 480 : ExecEndSetOp((SetOpState *) node);
724 : 480 : break;
725 : :
726 : 6106 : case T_LockRowsState:
727 : 6106 : ExecEndLockRows((LockRowsState *) node);
728 : 6106 : break;
729 : :
730 : 3149 : case T_LimitState:
731 : 3149 : ExecEndLimit((LimitState *) node);
732 : 3149 : break;
733 : :
734 : : /* No clean up actions for these nodes. */
735 : 7265 : case T_ValuesScanState:
736 : : case T_NamedTuplestoreScanState:
737 : : case T_WorkTableScanState:
738 : 7265 : 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 : 329025 : ExecShutdownNode(PlanState *node)
754 : : {
755 : 329025 : (void) ExecShutdownNode_walker(node, NULL);
756 : 329025 : }
757 : :
758 : : static bool
759 : 813197 : ExecShutdownNode_walker(PlanState *node, void *context)
760 : : {
761 [ - + ]: 813197 : if (node == NULL)
762 : 0 : return false;
763 : :
764 : 813197 : 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 [ + + + + ]: 813197 : if (node->instrument && node->instrument->running)
777 : 5943 : InstrStartNode(node->instrument);
778 : :
779 : 813197 : planstate_tree_walker(node, ExecShutdownNode_walker, context);
780 : :
781 [ + + - + : 813197 : switch (nodeTag(node))
+ + + ]
782 : : {
783 : 443 : case T_GatherState:
784 : 443 : ExecShutdownGather((GatherState *) node);
785 : 443 : break;
786 : 589 : case T_ForeignScanState:
787 : 589 : ExecShutdownForeignScan((ForeignScanState *) node);
788 : 589 : 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 : 24874 : case T_HashState:
796 : 24874 : ExecShutdownHash((HashState *) node);
797 : 24874 : break;
798 : 24874 : case T_HashJoinState:
799 : 24874 : ExecShutdownHashJoin((HashJoinState *) node);
800 : 24874 : break;
801 : 762309 : default:
802 : 762309 : break;
803 : : }
804 : :
805 : : /* Stop the node if we started it above, reporting 0 tuples. */
806 [ + + + + ]: 813197 : if (node->instrument && node->instrument->running)
807 : 5943 : InstrStopNode(node->instrument, 0);
808 : :
809 : 813197 : 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 : 45068 : 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 [ + + ]: 45068 : 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 : 855 : SortState *sortState = (SortState *) child_node;
848 : :
849 [ + + ]: 855 : if (tuples_needed < 0)
850 : : {
851 : : /* make sure flag gets reset if needed upon rescan */
852 : 240 : sortState->bounded = false;
853 : : }
854 : : else
855 : : {
856 : 615 : sortState->bounded = true;
857 : 615 : sortState->bound = tuples_needed;
858 : : }
859 : : }
860 [ + + ]: 44213 : 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 [ + + ]: 44116 : 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 [ + + ]: 44011 : 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 [ + + ]: 43967 : 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 [ + + ]: 43532 : 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 [ - + ]: 43480 : 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 [ + + ]: 43480 : 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 : 45068 : }
|