Age Owner TLA 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-2023, 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 *
6249 tgl 142 CBC 712398 : 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 : */
9345 bruce 151 712398 : if (node == NULL)
7430 tgl 152 143915 : 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 : */
2092 andres 159 568483 : check_stack_depth();
160 :
9345 bruce 161 568483 : switch (nodeTag(node))
162 : {
163 : /*
164 : * control nodes
165 : */
9344 166 147688 : case T_Result:
6249 tgl 167 147688 : result = (PlanState *) ExecInitResult((Result *) node,
168 : estate, eflags);
9344 bruce 169 147653 : break;
170 :
2272 andres 171 3505 : case T_ProjectSet:
172 3505 : result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
173 : estate, eflags);
174 3503 : break;
175 :
4929 tgl 176 65639 : case T_ModifyTable:
177 65639 : result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
178 : estate, eflags);
179 65505 : break;
180 :
9344 bruce 181 6518 : case T_Append:
6249 tgl 182 6518 : result = (PlanState *) ExecInitAppend((Append *) node,
183 : estate, eflags);
9344 bruce 184 6518 : break;
185 :
4560 tgl 186 207 : case T_MergeAppend:
187 207 : result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
188 : estate, eflags);
189 207 : break;
190 :
5300 191 354 : case T_RecursiveUnion:
192 354 : result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
193 : estate, eflags);
194 354 : break;
195 :
6564 196 38 : case T_BitmapAnd:
6249 197 38 : result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
198 : estate, eflags);
6564 199 38 : break;
200 :
201 111 : case T_BitmapOr:
6249 202 111 : result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
203 : estate, eflags);
6564 204 111 : break;
205 :
206 : /*
207 : * scan nodes
208 : */
9344 bruce 209 93562 : case T_SeqScan:
6249 tgl 210 93562 : result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
211 : estate, eflags);
9344 bruce 212 93556 : break;
213 :
2886 simon 214 126 : case T_SampleScan:
215 126 : result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
216 : estate, eflags);
217 126 : break;
218 :
9344 bruce 219 60051 : case T_IndexScan:
6249 tgl 220 60051 : result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
221 : estate, eflags);
9344 bruce 222 60051 : break;
223 :
4198 tgl 224 6527 : case T_IndexOnlyScan:
225 6527 : result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
226 : estate, eflags);
227 6527 : break;
228 :
6564 229 10774 : case T_BitmapIndexScan:
6249 230 10774 : result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
231 : estate, eflags);
6564 232 10774 : break;
233 :
234 10598 : case T_BitmapHeapScan:
6249 235 10598 : result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
236 : estate, eflags);
6564 237 10598 : break;
238 :
8227 239 359 : case T_TidScan:
6249 240 359 : result = (PlanState *) ExecInitTidScan((TidScan *) node,
241 : estate, eflags);
8227 242 359 : break;
243 :
771 drowley 244 101 : case T_TidRangeScan:
245 101 : result = (PlanState *) ExecInitTidRangeScan((TidRangeScan *) node,
246 : estate, eflags);
247 101 : break;
248 :
8227 tgl 249 4701 : case T_SubqueryScan:
6249 250 4701 : result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
251 : estate, eflags);
8227 252 4701 : break;
253 :
7637 254 26789 : case T_FunctionScan:
6249 255 26789 : result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
256 : estate, eflags);
7637 257 26785 : break;
258 :
2223 alvherre 259 108 : case T_TableFuncScan:
260 108 : result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
261 : estate, eflags);
262 108 : break;
263 :
6094 mail 264 3958 : case T_ValuesScan:
265 3958 : result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
266 : estate, eflags);
267 3958 : break;
268 :
5300 tgl 269 1242 : case T_CteScan:
270 1242 : result = (PlanState *) ExecInitCteScan((CteScan *) node,
271 : estate, eflags);
272 1242 : break;
273 :
2200 kgrittn 274 330 : case T_NamedTuplestoreScan:
275 330 : result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node,
276 : estate, eflags);
277 330 : break;
278 :
5300 tgl 279 354 : case T_WorkTableScan:
280 354 : result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
281 : estate, eflags);
282 354 : break;
283 :
4431 284 951 : case T_ForeignScan:
285 951 : result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
286 : estate, eflags);
287 943 : break;
288 :
3075 rhaas 289 UBC 0 : case T_CustomScan:
290 0 : result = (PlanState *) ExecInitCustomScan((CustomScan *) node,
291 : estate, eflags);
292 0 : break;
293 :
294 : /*
295 : * join nodes
296 : */
9344 bruce 297 CBC 34215 : case T_NestLoop:
6249 tgl 298 34215 : result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
299 : estate, eflags);
9344 bruce 300 34215 : break;
301 :
302 2325 : case T_MergeJoin:
6249 tgl 303 2325 : result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
304 : estate, eflags);
8227 305 2325 : break;
306 :
307 14214 : case T_HashJoin:
6249 308 14214 : result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
309 : estate, eflags);
8227 310 14214 : break;
311 :
312 : /*
313 : * materialization nodes
314 : */
9344 bruce 315 1826 : case T_Material:
6249 tgl 316 1826 : result = (PlanState *) ExecInitMaterial((Material *) node,
317 : estate, eflags);
9344 bruce 318 1826 : break;
319 :
320 26053 : case T_Sort:
6249 tgl 321 26053 : result = (PlanState *) ExecInitSort((Sort *) node,
322 : estate, eflags);
9344 bruce 323 26050 : break;
324 :
1098 tomas.vondra 325 297 : case T_IncrementalSort:
326 297 : result = (PlanState *) ExecInitIncrementalSort((IncrementalSort *) node,
327 : estate, eflags);
328 297 : break;
329 :
634 drowley 330 508 : case T_Memoize:
331 508 : result = (PlanState *) ExecInitMemoize((Memoize *) node, estate,
332 : eflags);
737 333 508 : break;
334 :
7430 tgl 335 111 : case T_Group:
6249 336 111 : result = (PlanState *) ExecInitGroup((Group *) node,
337 : estate, eflags);
9344 bruce 338 111 : break;
339 :
7430 tgl 340 21244 : case T_Agg:
6249 341 21244 : result = (PlanState *) ExecInitAgg((Agg *) node,
342 : estate, eflags);
8221 343 21241 : break;
344 :
5215 345 1089 : case T_WindowAgg:
346 1089 : result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
347 : estate, eflags);
348 1089 : break;
349 :
7430 350 793 : case T_Unique:
6249 351 793 : result = (PlanState *) ExecInitUnique((Unique *) node,
352 : estate, eflags);
8200 353 793 : break;
354 :
2748 rhaas 355 479 : case T_Gather:
356 479 : result = (PlanState *) ExecInitGather((Gather *) node,
357 : estate, eflags);
358 479 : break;
359 :
2222 360 138 : case T_GatherMerge:
361 138 : result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
362 : estate, eflags);
363 138 : break;
364 :
7430 tgl 365 14214 : case T_Hash:
6249 366 14214 : result = (PlanState *) ExecInitHash((Hash *) node,
367 : estate, eflags);
9344 bruce 368 14214 : break;
369 :
7430 tgl 370 303 : case T_SetOp:
6249 371 303 : result = (PlanState *) ExecInitSetOp((SetOp *) node,
372 : estate, eflags);
7430 373 303 : break;
374 :
4927 375 3511 : case T_LockRows:
376 3511 : result = (PlanState *) ExecInitLockRows((LockRows *) node,
377 : estate, eflags);
378 3511 : break;
379 :
7430 380 2572 : case T_Limit:
6249 381 2572 : result = (PlanState *) ExecInitLimit((Limit *) node,
382 : estate, eflags);
9344 bruce 383 2572 : break;
384 :
9344 bruce 385 UBC 0 : default:
7202 tgl 386 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
387 : result = NULL; /* keep compiler quiet */
388 : break;
389 : }
390 :
1943 andres 391 CBC 568288 : 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 : */
7430 tgl 397 568288 : subps = NIL;
6892 neilc 398 577059 : foreach(l, node->initPlan)
399 : {
400 8771 : SubPlan *subplan = (SubPlan *) lfirst(l);
401 : SubPlanState *sstate;
402 :
7421 tgl 403 8771 : Assert(IsA(subplan, SubPlan));
5885 404 8771 : sstate = ExecInitSubPlan(subplan, result);
7422 405 8771 : subps = lappend(subps, sstate);
406 : }
7430 407 568288 : result->initPlan = subps;
408 :
409 : /* Set up instrumentation for this node if requested */
410 568288 : if (estate->es_instrument)
697 efujita 411 4934 : result->instrument = InstrAlloc(1, estate->es_instrument,
412 4934 : result->async_capable);
413 :
9345 bruce 414 568288 : return result;
415 : }
416 :
417 :
418 : /*
419 : * If a node wants to change its ExecProcNode function after ExecInitNode()
420 : * has finished, it should do so with this function. That way any wrapper
421 : * functions can be reinstalled, without the node having to know how that
422 : * works.
423 : */
424 : void
1943 andres 425 568492 : ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function)
426 : {
427 : /*
428 : * Add a wrapper around the ExecProcNode callback that checks stack depth
429 : * during the first execution and maybe adds an instrumentation wrapper.
430 : * When the callback is changed after execution has already begun that
431 : * means we'll superfluously execute ExecProcNodeFirst, but that seems ok.
432 : */
433 568492 : node->ExecProcNodeReal = function;
434 568492 : node->ExecProcNode = ExecProcNodeFirst;
435 568492 : }
436 :
437 :
438 : /*
439 : * ExecProcNode wrapper that performs some one-time checks, before calling
440 : * the relevant node method (possibly via an instrumentation wrapper).
441 : */
442 : static TupleTableSlot *
2092 443 490250 : ExecProcNodeFirst(PlanState *node)
444 : {
445 : /*
446 : * Perform stack depth check during the first execution of the node. We
447 : * only do so the first time round because it turns out to not be cheap on
448 : * some common architectures (eg. x86). This relies on the assumption
449 : * that ExecProcNode calls for a given plan node will always be made at
450 : * roughly the same stack depth.
451 : */
452 490250 : check_stack_depth();
453 :
454 : /*
455 : * If instrumentation is required, change the wrapper to one that just
456 : * does instrumentation. Otherwise we can dispense with all wrappers and
457 : * have ExecProcNode() directly call the relevant function from now on.
458 : */
7873 tgl 459 490250 : if (node->instrument)
2092 andres 460 3780 : node->ExecProcNode = ExecProcNodeInstr;
461 : else
462 486470 : node->ExecProcNode = node->ExecProcNodeReal;
463 :
464 490250 : return node->ExecProcNode(node);
465 : }
466 :
467 :
468 : /*
469 : * ExecProcNode wrapper that performs instrumentation calls. By keeping
470 : * this a separate function, we avoid overhead in the normal case where
471 : * no instrumentation is wanted.
472 : */
473 : static TupleTableSlot *
474 6599964 : ExecProcNodeInstr(PlanState *node)
475 : {
476 : TupleTableSlot *result;
477 :
478 6599964 : InstrStartNode(node->instrument);
479 :
480 6599964 : result = node->ExecProcNodeReal(node);
481 :
482 6599958 : InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
483 :
9345 bruce 484 6599958 : return result;
485 : }
486 :
487 :
488 : /* ----------------------------------------------------------------
489 : * MultiExecProcNode
490 : *
491 : * Execute a node that doesn't return individual tuples
492 : * (it might return a hashtable, bitmap, etc). Caller should
493 : * check it got back the expected kind of Node.
494 : *
495 : * This has essentially the same responsibilities as ExecProcNode,
496 : * but it does not do InstrStartNode/InstrStopNode (mainly because
497 : * it can't tell how many returned tuples to count). Each per-node
498 : * function must provide its own instrumentation support.
499 : * ----------------------------------------------------------------
500 : */
501 : Node *
6567 tgl 502 18685 : MultiExecProcNode(PlanState *node)
503 : {
504 : Node *result;
505 :
2092 andres 506 18685 : check_stack_depth();
507 :
6567 tgl 508 18685 : CHECK_FOR_INTERRUPTS();
509 :
510 18685 : if (node->chgParam != NULL) /* something changed */
4654 511 2157 : ExecReScan(node); /* let ReScan handle this */
512 :
6567 513 18685 : switch (nodeTag(node))
514 : {
515 : /*
516 : * Only node types that actually support multiexec will be listed
517 : */
518 :
519 9886 : case T_HashState:
520 9886 : result = MultiExecHash((HashState *) node);
521 9886 : break;
522 :
6564 523 8691 : case T_BitmapIndexScanState:
524 8691 : result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node);
525 8691 : break;
526 :
527 26 : case T_BitmapAndState:
528 26 : result = MultiExecBitmapAnd((BitmapAndState *) node);
529 26 : break;
530 :
531 82 : case T_BitmapOrState:
532 82 : result = MultiExecBitmapOr((BitmapOrState *) node);
533 82 : break;
534 :
6567 tgl 535 UBC 0 : default:
536 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
537 : result = NULL;
538 : break;
539 : }
540 :
6567 tgl 541 CBC 18685 : return result;
542 : }
543 :
544 :
545 : /* ----------------------------------------------------------------
546 : * ExecEndNode
547 : *
548 : * Recursively cleans up all the nodes in the plan rooted
549 : * at 'node'.
550 : *
551 : * After this operation, the query plan will not be able to be
552 : * processed any further. This should be called only after
553 : * the query plan has been fully executed.
554 : * ----------------------------------------------------------------
555 : */
556 : void
7184 bruce 557 689750 : ExecEndNode(PlanState *node)
558 : {
559 : /*
560 : * do nothing when we get to the end of a leaf on tree.
561 : */
9345 562 689750 : if (node == NULL)
563 136181 : return;
564 :
565 : /*
566 : * Make sure there's enough stack available. Need to check here, in
567 : * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
568 : * guaranteed that ExecProcNode() is reached for all nodes.
569 : */
2092 andres 570 553569 : check_stack_depth();
571 :
7364 tgl 572 553569 : if (node->chgParam != NULL)
573 : {
574 2916 : bms_free(node->chgParam);
575 2916 : node->chgParam = NULL;
576 : }
577 :
9345 bruce 578 553569 : switch (nodeTag(node))
579 : {
580 : /*
581 : * control nodes
582 : */
7430 tgl 583 139971 : case T_ResultState:
584 139971 : ExecEndResult((ResultState *) node);
9344 bruce 585 139971 : break;
586 :
2272 andres 587 3197 : case T_ProjectSetState:
588 3197 : ExecEndProjectSet((ProjectSetState *) node);
589 3197 : break;
590 :
4929 tgl 591 63676 : case T_ModifyTableState:
592 63676 : ExecEndModifyTable((ModifyTableState *) node);
593 63676 : break;
594 :
7430 595 6379 : case T_AppendState:
596 6379 : ExecEndAppend((AppendState *) node);
9344 bruce 597 6379 : break;
598 :
4560 tgl 599 207 : case T_MergeAppendState:
600 207 : ExecEndMergeAppend((MergeAppendState *) node);
601 207 : break;
602 :
5300 603 354 : case T_RecursiveUnionState:
604 354 : ExecEndRecursiveUnion((RecursiveUnionState *) node);
605 354 : break;
606 :
6564 607 38 : case T_BitmapAndState:
608 38 : ExecEndBitmapAnd((BitmapAndState *) node);
609 38 : break;
610 :
611 111 : case T_BitmapOrState:
612 111 : ExecEndBitmapOr((BitmapOrState *) node);
613 111 : break;
614 :
615 : /*
616 : * scan nodes
617 : */
7430 618 92457 : case T_SeqScanState:
619 92457 : ExecEndSeqScan((SeqScanState *) node);
9344 bruce 620 92457 : break;
621 :
2886 simon 622 106 : case T_SampleScanState:
623 106 : ExecEndSampleScan((SampleScanState *) node);
624 106 : break;
625 :
2748 rhaas 626 476 : case T_GatherState:
627 476 : ExecEndGather((GatherState *) node);
628 476 : break;
629 :
2222 630 138 : case T_GatherMergeState:
631 138 : ExecEndGatherMerge((GatherMergeState *) node);
632 138 : break;
633 :
7430 tgl 634 59728 : case T_IndexScanState:
635 59728 : ExecEndIndexScan((IndexScanState *) node);
9344 bruce 636 59728 : break;
637 :
4198 tgl 638 6458 : case T_IndexOnlyScanState:
639 6458 : ExecEndIndexOnlyScan((IndexOnlyScanState *) node);
640 6458 : break;
641 :
6564 642 10743 : case T_BitmapIndexScanState:
643 10743 : ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
644 10743 : break;
645 :
646 10567 : case T_BitmapHeapScanState:
647 10567 : ExecEndBitmapHeapScan((BitmapHeapScanState *) node);
648 10567 : break;
649 :
7430 650 299 : case T_TidScanState:
651 299 : ExecEndTidScan((TidScanState *) node);
8227 652 299 : break;
653 :
771 drowley 654 101 : case T_TidRangeScanState:
655 101 : ExecEndTidRangeScan((TidRangeScanState *) node);
656 101 : break;
657 :
7430 tgl 658 4701 : case T_SubqueryScanState:
659 4701 : ExecEndSubqueryScan((SubqueryScanState *) node);
8227 660 4701 : break;
661 :
7430 662 24172 : case T_FunctionScanState:
663 24172 : ExecEndFunctionScan((FunctionScanState *) node);
7637 664 24172 : break;
665 :
2223 alvherre 666 99 : case T_TableFuncScanState:
667 99 : ExecEndTableFuncScan((TableFuncScanState *) node);
668 99 : break;
669 :
6094 mail 670 3894 : case T_ValuesScanState:
671 3894 : ExecEndValuesScan((ValuesScanState *) node);
672 3894 : break;
673 :
5300 tgl 674 1229 : case T_CteScanState:
675 1229 : ExecEndCteScan((CteScanState *) node);
676 1229 : break;
677 :
2200 kgrittn 678 330 : case T_NamedTuplestoreScanState:
679 330 : ExecEndNamedTuplestoreScan((NamedTuplestoreScanState *) node);
680 330 : break;
681 :
5300 tgl 682 354 : case T_WorkTableScanState:
683 354 : ExecEndWorkTableScan((WorkTableScanState *) node);
684 354 : break;
685 :
4431 686 920 : case T_ForeignScanState:
687 920 : ExecEndForeignScan((ForeignScanState *) node);
688 920 : break;
689 :
3075 rhaas 690 UBC 0 : case T_CustomScanState:
691 0 : ExecEndCustomScan((CustomScanState *) node);
692 0 : break;
693 :
694 : /*
695 : * join nodes
696 : */
7430 tgl 697 CBC 34118 : case T_NestLoopState:
698 34118 : ExecEndNestLoop((NestLoopState *) node);
9344 bruce 699 34118 : break;
700 :
7430 tgl 701 2322 : case T_MergeJoinState:
702 2322 : ExecEndMergeJoin((MergeJoinState *) node);
8227 703 2322 : break;
704 :
7430 705 14172 : case T_HashJoinState:
706 14172 : ExecEndHashJoin((HashJoinState *) node);
8227 707 14172 : break;
708 :
709 : /*
710 : * materialization nodes
711 : */
7430 712 1795 : case T_MaterialState:
713 1795 : ExecEndMaterial((MaterialState *) node);
9344 bruce 714 1795 : break;
715 :
7430 tgl 716 26011 : case T_SortState:
717 26011 : ExecEndSort((SortState *) node);
9344 bruce 718 26011 : break;
719 :
1098 tomas.vondra 720 297 : case T_IncrementalSortState:
721 297 : ExecEndIncrementalSort((IncrementalSortState *) node);
722 297 : break;
723 :
634 drowley 724 508 : case T_MemoizeState:
725 508 : ExecEndMemoize((MemoizeState *) node);
737 726 508 : break;
727 :
7430 tgl 728 111 : case T_GroupState:
729 111 : ExecEndGroup((GroupState *) node);
9344 bruce 730 111 : break;
731 :
7430 tgl 732 21188 : case T_AggState:
733 21188 : ExecEndAgg((AggState *) node);
8221 734 21188 : break;
735 :
5215 736 1065 : case T_WindowAggState:
737 1065 : ExecEndWindowAgg((WindowAggState *) node);
738 1065 : break;
739 :
7430 740 793 : case T_UniqueState:
741 793 : ExecEndUnique((UniqueState *) node);
8200 742 793 : break;
743 :
7430 744 14172 : case T_HashState:
745 14172 : ExecEndHash((HashState *) node);
9344 bruce 746 14172 : break;
747 :
7430 tgl 748 303 : case T_SetOpState:
749 303 : ExecEndSetOp((SetOpState *) node);
750 303 : break;
751 :
4927 752 3468 : case T_LockRowsState:
753 3468 : ExecEndLockRows((LockRowsState *) node);
754 3468 : break;
755 :
7430 756 2541 : case T_LimitState:
757 2541 : ExecEndLimit((LimitState *) node);
9344 bruce 758 2541 : break;
759 :
9344 bruce 760 UBC 0 : default:
7202 tgl 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
2748 rhaas 773 CBC 249029 : ExecShutdownNode(PlanState *node)
774 : {
202 tgl 775 GNC 249029 : (void) ExecShutdownNode_walker(node, NULL);
202 tgl 776 CBC 249029 : }
777 :
778 : static bool
779 530185 : ExecShutdownNode_walker(PlanState *node, void *context)
780 : {
2748 rhaas 781 530185 : if (node == NULL)
2748 rhaas 782 UBC 0 : return false;
783 :
2092 andres 784 CBC 530185 : 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 : */
1710 akapila 796 530185 : if (node->instrument && node->instrument->running)
797 4187 : InstrStartNode(node->instrument);
798 :
202 tgl 799 530185 : planstate_tree_walker(node, ExecShutdownNode_walker, context);
800 :
2748 rhaas 801 530185 : switch (nodeTag(node))
802 : {
803 272 : case T_GatherState:
2726 804 272 : ExecShutdownGather((GatherState *) node);
2748 805 272 : break;
2233 806 542 : case T_ForeignScanState:
807 542 : ExecShutdownForeignScan((ForeignScanState *) node);
808 542 : break;
2233 rhaas 809 UBC 0 : case T_CustomScanState:
810 0 : ExecShutdownCustomScan((CustomScanState *) node);
811 0 : break;
2222 rhaas 812 CBC 60 : case T_GatherMergeState:
813 60 : ExecShutdownGatherMerge((GatherMergeState *) node);
814 60 : break;
1951 andres 815 12754 : case T_HashState:
816 12754 : ExecShutdownHash((HashState *) node);
817 12754 : break;
1936 818 12754 : case T_HashJoinState:
819 12754 : ExecShutdownHashJoin((HashJoinState *) node);
820 12754 : break;
2748 rhaas 821 503803 : default:
822 503803 : break;
823 : }
824 :
825 : /* Stop the node if we started it above, reporting 0 tuples. */
1710 akapila 826 530185 : if (node->instrument && node->instrument->running)
827 4187 : InstrStopNode(node->instrument, 0);
828 :
2237 rhaas 829 530185 : 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
2049 849 3971 : 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 3971 : 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 860 : SortState *sortState = (SortState *) child_node;
868 :
1098 tomas.vondra 869 860 : if (tuples_needed < 0)
870 : {
871 : /* make sure flag gets reset if needed upon rescan */
872 134 : sortState->bounded = false;
873 : }
874 : else
875 : {
876 726 : sortState->bounded = true;
877 726 : sortState->bound = tuples_needed;
878 : }
879 : }
880 3111 : 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 73 : IncrementalSortState *sortState = (IncrementalSortState *) child_node;
892 :
2049 rhaas 893 73 : if (tuples_needed < 0)
894 : {
895 : /* make sure flag gets reset if needed upon rescan */
2049 rhaas 896 UBC 0 : sortState->bounded = false;
897 : }
898 : else
899 : {
2049 rhaas 900 CBC 73 : sortState->bounded = true;
901 73 : sortState->bound = tuples_needed;
902 : }
903 : }
1465 tgl 904 3038 : 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 73 : AppendState *aState = (AppendState *) child_node;
912 : int i;
913 :
914 232 : for (i = 0; i < aState->as_nplans; i++)
915 159 : ExecSetTupleBound(tuples_needed, aState->appendplans[i]);
916 : }
2049 rhaas 917 2965 : 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 30 : MergeAppendState *maState = (MergeAppendState *) child_node;
925 : int i;
926 :
927 120 : for (i = 0; i < maState->ms_nplans; i++)
928 90 : ExecSetTupleBound(tuples_needed, maState->mergeplans[i]);
929 : }
930 2935 : 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 377 : if (outerPlanState(child_node))
942 51 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
943 : }
944 2558 : 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 47 : SubqueryScanState *subqueryState = (SubqueryScanState *) child_node;
951 :
952 47 : if (subqueryState->ss.ps.qual == NULL)
953 36 : ExecSetTupleBound(tuples_needed, subqueryState->subplan);
954 : }
955 2511 : 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 : */
2049 rhaas 965 UBC 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 : }
2049 rhaas 972 CBC 2511 : else if (IsA(child_node, GatherMergeState))
973 : {
974 : /* Same comments as for Gather */
975 15 : GatherMergeState *gstate = (GatherMergeState *) child_node;
976 :
977 15 : gstate->tuples_needed = tuples_needed;
978 :
979 15 : 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 3971 : }
|