Age Owner Branch data 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-2024, 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 *
6620 tgl@sss.pgh.pa.us 142 :CBC 788635 : 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 : : */
9716 bruce@momjian.us 151 [ + + ]: 788635 : if (node == NULL)
7801 tgl@sss.pgh.pa.us 152 : 165708 : 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 : : */
2463 andres@anarazel.de 159 : 622927 : check_stack_depth();
160 : :
9716 bruce@momjian.us 161 [ + + + + : 622927 : switch (nodeTag(node))
+ + + + +
+ + + + +
+ + + + +
+ + + + +
- + + + +
+ + + + +
+ + + + +
+ + + - ]
162 : : {
163 : : /*
164 : : * control nodes
165 : : */
9715 166 : 170022 : case T_Result:
6620 tgl@sss.pgh.pa.us 167 : 170022 : result = (PlanState *) ExecInitResult((Result *) node,
168 : : estate, eflags);
9715 bruce@momjian.us 169 : 169991 : break;
170 : :
2643 andres@anarazel.de 171 : 4458 : case T_ProjectSet:
172 : 4458 : result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
173 : : estate, eflags);
174 : 4457 : break;
175 : :
5300 tgl@sss.pgh.pa.us 176 : 56703 : case T_ModifyTable:
177 : 56703 : result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
178 : : estate, eflags);
179 : 56566 : break;
180 : :
9715 bruce@momjian.us 181 : 6881 : case T_Append:
6620 tgl@sss.pgh.pa.us 182 : 6881 : result = (PlanState *) ExecInitAppend((Append *) node,
183 : : estate, eflags);
9715 bruce@momjian.us 184 : 6881 : break;
185 : :
4931 tgl@sss.pgh.pa.us 186 : 248 : case T_MergeAppend:
187 : 248 : result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
188 : : estate, eflags);
189 : 248 : break;
190 : :
5671 191 : 403 : case T_RecursiveUnion:
192 : 403 : result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
193 : : estate, eflags);
194 : 403 : break;
195 : :
6935 196 : 50 : case T_BitmapAnd:
6620 197 : 50 : result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
198 : : estate, eflags);
6935 199 : 50 : break;
200 : :
201 : 141 : case T_BitmapOr:
6620 202 : 141 : result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
203 : : estate, eflags);
6935 204 : 141 : break;
205 : :
206 : : /*
207 : : * scan nodes
208 : : */
9715 bruce@momjian.us 209 : 98160 : case T_SeqScan:
6620 tgl@sss.pgh.pa.us 210 : 98160 : result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
211 : : estate, eflags);
9715 bruce@momjian.us 212 : 98154 : break;
213 : :
3257 simon@2ndQuadrant.co 214 : 150 : case T_SampleScan:
215 : 150 : result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
216 : : estate, eflags);
217 : 150 : break;
218 : :
9715 bruce@momjian.us 219 : 73170 : case T_IndexScan:
6620 tgl@sss.pgh.pa.us 220 : 73170 : result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
221 : : estate, eflags);
9715 bruce@momjian.us 222 : 73170 : break;
223 : :
4569 tgl@sss.pgh.pa.us 224 : 6967 : case T_IndexOnlyScan:
225 : 6967 : result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
226 : : estate, eflags);
227 : 6967 : break;
228 : :
6935 229 : 9718 : case T_BitmapIndexScan:
6620 230 : 9718 : result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
231 : : estate, eflags);
6935 232 : 9718 : break;
233 : :
234 : 9500 : case T_BitmapHeapScan:
6620 235 : 9500 : result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
236 : : estate, eflags);
6935 237 : 9500 : break;
238 : :
8598 239 : 359 : case T_TidScan:
6620 240 : 359 : result = (PlanState *) ExecInitTidScan((TidScan *) node,
241 : : estate, eflags);
8598 242 : 359 : break;
243 : :
1142 drowley@postgresql.o 244 : 101 : case T_TidRangeScan:
245 : 101 : result = (PlanState *) ExecInitTidRangeScan((TidRangeScan *) node,
246 : : estate, eflags);
247 : 101 : break;
248 : :
8598 tgl@sss.pgh.pa.us 249 : 5229 : case T_SubqueryScan:
6620 250 : 5229 : result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
251 : : estate, eflags);
8598 252 : 5229 : break;
253 : :
8008 254 : 32197 : case T_FunctionScan:
6620 255 : 32197 : result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
256 : : estate, eflags);
8008 257 : 32193 : break;
258 : :
2594 alvherre@alvh.no-ip. 259 : 254 : case T_TableFuncScan:
260 : 254 : result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
261 : : estate, eflags);
262 : 254 : break;
263 : :
6465 mail@joeconway.com 264 : 4266 : case T_ValuesScan:
265 : 4266 : result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
266 : : estate, eflags);
267 : 4266 : break;
268 : :
5671 tgl@sss.pgh.pa.us 269 : 1605 : case T_CteScan:
270 : 1605 : result = (PlanState *) ExecInitCteScan((CteScan *) node,
271 : : estate, eflags);
272 : 1605 : break;
273 : :
2571 kgrittn@postgresql.o 274 : 330 : case T_NamedTuplestoreScan:
275 : 330 : result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node,
276 : : estate, eflags);
277 : 330 : break;
278 : :
5671 tgl@sss.pgh.pa.us 279 : 403 : case T_WorkTableScan:
280 : 403 : result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
281 : : estate, eflags);
282 : 403 : break;
283 : :
4802 284 : 978 : case T_ForeignScan:
285 : 978 : result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
286 : : estate, eflags);
287 : 967 : break;
288 : :
3446 rhaas@postgresql.org 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 : : */
9715 bruce@momjian.us 297 :CBC 41759 : case T_NestLoop:
6620 tgl@sss.pgh.pa.us 298 : 41759 : result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
299 : : estate, eflags);
9715 bruce@momjian.us 300 : 41759 : break;
301 : :
302 : 2840 : case T_MergeJoin:
6620 tgl@sss.pgh.pa.us 303 : 2840 : result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
304 : : estate, eflags);
8598 305 : 2840 : break;
306 : :
307 : 14898 : case T_HashJoin:
6620 308 : 14898 : result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
309 : : estate, eflags);
8598 310 : 14898 : break;
311 : :
312 : : /*
313 : : * materialization nodes
314 : : */
9715 bruce@momjian.us 315 : 1869 : case T_Material:
6620 tgl@sss.pgh.pa.us 316 : 1869 : result = (PlanState *) ExecInitMaterial((Material *) node,
317 : : estate, eflags);
9715 bruce@momjian.us 318 : 1869 : break;
319 : :
320 : 30899 : case T_Sort:
6620 tgl@sss.pgh.pa.us 321 : 30899 : result = (PlanState *) ExecInitSort((Sort *) node,
322 : : estate, eflags);
9715 bruce@momjian.us 323 : 30896 : break;
324 : :
1469 tomas.vondra@postgre 325 : 354 : case T_IncrementalSort:
326 : 354 : result = (PlanState *) ExecInitIncrementalSort((IncrementalSort *) node,
327 : : estate, eflags);
328 : 354 : break;
329 : :
1005 drowley@postgresql.o 330 : 676 : case T_Memoize:
331 : 676 : result = (PlanState *) ExecInitMemoize((Memoize *) node, estate,
332 : : eflags);
1108 333 : 676 : break;
334 : :
7801 tgl@sss.pgh.pa.us 335 : 111 : case T_Group:
6620 336 : 111 : result = (PlanState *) ExecInitGroup((Group *) node,
337 : : estate, eflags);
9715 bruce@momjian.us 338 : 111 : break;
339 : :
7801 tgl@sss.pgh.pa.us 340 : 21558 : case T_Agg:
6620 341 : 21558 : result = (PlanState *) ExecInitAgg((Agg *) node,
342 : : estate, eflags);
8592 343 : 21555 : break;
344 : :
5586 345 : 1222 : case T_WindowAgg:
346 : 1222 : result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
347 : : estate, eflags);
348 : 1222 : break;
349 : :
7801 350 : 2336 : case T_Unique:
6620 351 : 2336 : result = (PlanState *) ExecInitUnique((Unique *) node,
352 : : estate, eflags);
8571 353 : 2336 : break;
354 : :
3119 rhaas@postgresql.org 355 : 485 : case T_Gather:
356 : 485 : result = (PlanState *) ExecInitGather((Gather *) node,
357 : : estate, eflags);
358 : 485 : break;
359 : :
2593 360 : 159 : case T_GatherMerge:
361 : 159 : result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
362 : : estate, eflags);
363 : 159 : break;
364 : :
7801 tgl@sss.pgh.pa.us 365 : 14898 : case T_Hash:
6620 366 : 14898 : result = (PlanState *) ExecInitHash((Hash *) node,
367 : : estate, eflags);
9715 bruce@momjian.us 368 : 14898 : break;
369 : :
7801 tgl@sss.pgh.pa.us 370 : 304 : case T_SetOp:
6620 371 : 304 : result = (PlanState *) ExecInitSetOp((SetOp *) node,
372 : : estate, eflags);
7801 373 : 304 : break;
374 : :
5298 375 : 3957 : case T_LockRows:
376 : 3957 : result = (PlanState *) ExecInitLockRows((LockRows *) node,
377 : : estate, eflags);
378 : 3957 : break;
379 : :
7801 380 : 2309 : case T_Limit:
6620 381 : 2309 : result = (PlanState *) ExecInitLimit((Limit *) node,
382 : : estate, eflags);
9715 bruce@momjian.us 383 : 2309 : break;
384 : :
9715 bruce@momjian.us 385 :UBC 0 : default:
7573 tgl@sss.pgh.pa.us 386 [ # # ]: 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
387 : : result = NULL; /* keep compiler quiet */
388 : : break;
389 : : }
390 : :
2314 andres@anarazel.de 391 :CBC 622731 : 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 : : */
7801 tgl@sss.pgh.pa.us 397 : 622731 : subps = NIL;
7263 neilc@samurai.com 398 [ + + + + : 629429 : foreach(l, node->initPlan)
+ + ]
399 : : {
400 : 6698 : SubPlan *subplan = (SubPlan *) lfirst(l);
401 : : SubPlanState *sstate;
402 : :
7792 tgl@sss.pgh.pa.us 403 [ - + ]: 6698 : Assert(IsA(subplan, SubPlan));
6256 404 : 6698 : sstate = ExecInitSubPlan(subplan, result);
7793 405 : 6698 : subps = lappend(subps, sstate);
406 : : }
7801 407 : 622731 : result->initPlan = subps;
408 : :
409 : : /* Set up instrumentation for this node if requested */
410 [ + + ]: 622731 : if (estate->es_instrument)
1068 efujita@postgresql.o 411 : 5109 : result->instrument = InstrAlloc(1, estate->es_instrument,
412 : 5109 : result->async_capable);
413 : :
9716 bruce@momjian.us 414 : 622731 : 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
2314 andres@anarazel.de 425 : 622944 : 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 : 622944 : node->ExecProcNodeReal = function;
434 : 622944 : node->ExecProcNode = ExecProcNodeFirst;
435 : 622944 : }
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 *
2463 443 : 537460 : 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 : 537460 : 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 : : */
8244 tgl@sss.pgh.pa.us 459 [ + + ]: 537460 : if (node->instrument)
2463 andres@anarazel.de 460 : 3898 : node->ExecProcNode = ExecProcNodeInstr;
461 : : else
462 : 533562 : node->ExecProcNode = node->ExecProcNodeReal;
463 : :
464 : 537460 : 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 : 6623603 : ExecProcNodeInstr(PlanState *node)
475 : : {
476 : : TupleTableSlot *result;
477 : :
478 : 6623603 : InstrStartNode(node->instrument);
479 : :
480 : 6623603 : result = node->ExecProcNodeReal(node);
481 : :
482 [ + + + + ]: 6623597 : InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
483 : :
9716 bruce@momjian.us 484 : 6623597 : 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 *
6938 tgl@sss.pgh.pa.us 502 : 19905 : MultiExecProcNode(PlanState *node)
503 : : {
504 : : Node *result;
505 : :
2463 andres@anarazel.de 506 : 19905 : check_stack_depth();
507 : :
6938 tgl@sss.pgh.pa.us 508 [ - + ]: 19905 : CHECK_FOR_INTERRUPTS();
509 : :
510 [ + + ]: 19905 : if (node->chgParam != NULL) /* something changed */
5025 511 : 2784 : ExecReScan(node); /* let ReScan handle this */
512 : :
6938 513 [ + + + + : 19905 : switch (nodeTag(node))
- ]
514 : : {
515 : : /*
516 : : * Only node types that actually support multiexec will be listed
517 : : */
518 : :
519 : 10403 : case T_HashState:
520 : 10403 : result = MultiExecHash((HashState *) node);
521 : 10401 : break;
522 : :
6935 523 : 9352 : case T_BitmapIndexScanState:
524 : 9352 : result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node);
525 : 9352 : break;
526 : :
527 : 38 : case T_BitmapAndState:
528 : 38 : result = MultiExecBitmapAnd((BitmapAndState *) node);
529 : 38 : break;
530 : :
531 : 112 : case T_BitmapOrState:
532 : 112 : result = MultiExecBitmapOr((BitmapOrState *) node);
533 : 112 : break;
534 : :
6938 tgl@sss.pgh.pa.us 535 :UBC 0 : default:
536 [ # # ]: 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
537 : : result = NULL;
538 : : break;
539 : : }
540 : :
6938 tgl@sss.pgh.pa.us 541 :CBC 19903 : 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
7555 bruce@momjian.us 557 : 763400 : ExecEndNode(PlanState *node)
558 : : {
559 : : /*
560 : : * do nothing when we get to the end of a leaf on tree.
561 : : */
9716 562 [ + + ]: 763400 : if (node == NULL)
563 : 157212 : 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 : : */
2463 andres@anarazel.de 570 : 606188 : check_stack_depth();
571 : :
7735 tgl@sss.pgh.pa.us 572 [ + + ]: 606188 : if (node->chgParam != NULL)
573 : : {
574 : 3333 : bms_free(node->chgParam);
575 : 3333 : node->chgParam = NULL;
576 : : }
577 : :
9716 bruce@momjian.us 578 [ + + + + : 606188 : switch (nodeTag(node))
+ + + + +
+ + + + +
+ + + + +
+ + + + -
+ + + + +
+ + + + +
+ + + + +
+ - + - ]
579 : : {
580 : : /*
581 : : * control nodes
582 : : */
7801 tgl@sss.pgh.pa.us 583 : 161542 : case T_ResultState:
584 : 161542 : ExecEndResult((ResultState *) node);
9715 bruce@momjian.us 585 : 161542 : break;
586 : :
2643 andres@anarazel.de 587 : 3702 : case T_ProjectSetState:
588 : 3702 : ExecEndProjectSet((ProjectSetState *) node);
589 : 3702 : break;
590 : :
5300 tgl@sss.pgh.pa.us 591 : 54525 : case T_ModifyTableState:
592 : 54525 : ExecEndModifyTable((ModifyTableState *) node);
593 : 54525 : break;
594 : :
7801 595 : 6742 : case T_AppendState:
596 : 6742 : ExecEndAppend((AppendState *) node);
9715 bruce@momjian.us 597 : 6742 : break;
598 : :
4931 tgl@sss.pgh.pa.us 599 : 248 : case T_MergeAppendState:
600 : 248 : ExecEndMergeAppend((MergeAppendState *) node);
601 : 248 : break;
602 : :
5671 603 : 403 : case T_RecursiveUnionState:
604 : 403 : ExecEndRecursiveUnion((RecursiveUnionState *) node);
605 : 403 : break;
606 : :
6935 607 : 50 : case T_BitmapAndState:
608 : 50 : ExecEndBitmapAnd((BitmapAndState *) node);
609 : 50 : break;
610 : :
611 : 141 : case T_BitmapOrState:
612 : 141 : ExecEndBitmapOr((BitmapOrState *) node);
613 : 141 : break;
614 : :
615 : : /*
616 : : * scan nodes
617 : : */
7801 618 : 96962 : case T_SeqScanState:
619 : 96962 : ExecEndSeqScan((SeqScanState *) node);
9715 bruce@momjian.us 620 : 96962 : break;
621 : :
3257 simon@2ndQuadrant.co 622 : 130 : case T_SampleScanState:
623 : 130 : ExecEndSampleScan((SampleScanState *) node);
624 : 130 : break;
625 : :
3119 rhaas@postgresql.org 626 : 482 : case T_GatherState:
627 : 482 : ExecEndGather((GatherState *) node);
628 : 482 : break;
629 : :
2593 630 : 159 : case T_GatherMergeState:
631 : 159 : ExecEndGatherMerge((GatherMergeState *) node);
632 : 159 : break;
633 : :
7801 tgl@sss.pgh.pa.us 634 : 72767 : case T_IndexScanState:
635 : 72767 : ExecEndIndexScan((IndexScanState *) node);
9715 bruce@momjian.us 636 : 72767 : break;
637 : :
4569 tgl@sss.pgh.pa.us 638 : 6936 : case T_IndexOnlyScanState:
639 : 6936 : ExecEndIndexOnlyScan((IndexOnlyScanState *) node);
640 : 6936 : break;
641 : :
6935 642 : 9671 : case T_BitmapIndexScanState:
643 : 9671 : ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
644 : 9671 : break;
645 : :
646 : 9453 : case T_BitmapHeapScanState:
647 : 9453 : ExecEndBitmapHeapScan((BitmapHeapScanState *) node);
648 : 9453 : break;
649 : :
7801 650 : 299 : case T_TidScanState:
651 : 299 : ExecEndTidScan((TidScanState *) node);
8598 652 : 299 : break;
653 : :
1142 drowley@postgresql.o 654 : 101 : case T_TidRangeScanState:
655 : 101 : ExecEndTidRangeScan((TidRangeScanState *) node);
656 : 101 : break;
657 : :
7801 tgl@sss.pgh.pa.us 658 : 5229 : case T_SubqueryScanState:
659 : 5229 : ExecEndSubqueryScan((SubqueryScanState *) node);
8598 660 : 5229 : break;
661 : :
7801 662 : 29530 : case T_FunctionScanState:
663 : 29530 : ExecEndFunctionScan((FunctionScanState *) node);
8008 664 : 29530 : break;
665 : :
2594 alvherre@alvh.no-ip. 666 : 224 : case T_TableFuncScanState:
667 : 224 : ExecEndTableFuncScan((TableFuncScanState *) node);
668 : 224 : break;
669 : :
5671 tgl@sss.pgh.pa.us 670 : 1592 : case T_CteScanState:
671 : 1592 : ExecEndCteScan((CteScanState *) node);
672 : 1592 : break;
673 : :
4802 674 : 941 : case T_ForeignScanState:
675 : 941 : ExecEndForeignScan((ForeignScanState *) node);
676 : 941 : break;
677 : :
3446 rhaas@postgresql.org 678 :UBC 0 : case T_CustomScanState:
679 : 0 : ExecEndCustomScan((CustomScanState *) node);
680 : 0 : break;
681 : :
682 : : /*
683 : : * join nodes
684 : : */
7801 tgl@sss.pgh.pa.us 685 :CBC 41640 : case T_NestLoopState:
686 : 41640 : ExecEndNestLoop((NestLoopState *) node);
9715 bruce@momjian.us 687 : 41640 : break;
688 : :
7801 tgl@sss.pgh.pa.us 689 : 2837 : case T_MergeJoinState:
690 : 2837 : ExecEndMergeJoin((MergeJoinState *) node);
8598 691 : 2837 : break;
692 : :
7801 693 : 14843 : case T_HashJoinState:
694 : 14843 : ExecEndHashJoin((HashJoinState *) node);
8598 695 : 14843 : break;
696 : :
697 : : /*
698 : : * materialization nodes
699 : : */
7801 700 : 1838 : case T_MaterialState:
701 : 1838 : ExecEndMaterial((MaterialState *) node);
9715 bruce@momjian.us 702 : 1838 : break;
703 : :
7801 tgl@sss.pgh.pa.us 704 : 30824 : case T_SortState:
705 : 30824 : ExecEndSort((SortState *) node);
9715 bruce@momjian.us 706 : 30824 : break;
707 : :
1469 tomas.vondra@postgre 708 : 354 : case T_IncrementalSortState:
709 : 354 : ExecEndIncrementalSort((IncrementalSortState *) node);
710 : 354 : break;
711 : :
1005 drowley@postgresql.o 712 : 676 : case T_MemoizeState:
713 : 676 : ExecEndMemoize((MemoizeState *) node);
1108 714 : 676 : break;
715 : :
7801 tgl@sss.pgh.pa.us 716 : 111 : case T_GroupState:
717 : 111 : ExecEndGroup((GroupState *) node);
9715 bruce@momjian.us 718 : 111 : break;
719 : :
7801 tgl@sss.pgh.pa.us 720 : 21502 : case T_AggState:
721 : 21502 : ExecEndAgg((AggState *) node);
8592 722 : 21502 : break;
723 : :
5586 724 : 1156 : case T_WindowAggState:
725 : 1156 : ExecEndWindowAgg((WindowAggState *) node);
726 : 1156 : break;
727 : :
7801 728 : 2336 : case T_UniqueState:
729 : 2336 : ExecEndUnique((UniqueState *) node);
8571 730 : 2336 : break;
731 : :
7801 732 : 14843 : case T_HashState:
733 : 14843 : ExecEndHash((HashState *) node);
9715 bruce@momjian.us 734 : 14843 : break;
735 : :
7801 tgl@sss.pgh.pa.us 736 : 304 : case T_SetOpState:
737 : 304 : ExecEndSetOp((SetOpState *) node);
738 : 304 : break;
739 : :
5298 740 : 3914 : case T_LockRowsState:
741 : 3914 : ExecEndLockRows((LockRowsState *) node);
742 : 3914 : break;
743 : :
7801 744 : 2279 : case T_LimitState:
745 : 2279 : ExecEndLimit((LimitState *) node);
9715 bruce@momjian.us 746 : 2279 : break;
747 : :
748 : : /* No clean up actions for these nodes. */
199 amitlan@postgresql.o 749 :GNC 4902 : case T_ValuesScanState:
750 : : case T_NamedTuplestoreScanState:
751 : : case T_WorkTableScanState:
752 : 4902 : break;
753 : :
9715 bruce@momjian.us 754 :UBC 0 : default:
7573 tgl@sss.pgh.pa.us 755 [ # # ]: 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
756 : : break;
757 : : }
758 : : }
759 : :
760 : : /*
761 : : * ExecShutdownNode
762 : : *
763 : : * Give execution nodes a chance to stop asynchronous resource consumption
764 : : * and release any resources still held.
765 : : */
766 : : void
3119 rhaas@postgresql.org 767 :CBC 282825 : ExecShutdownNode(PlanState *node)
768 : : {
573 tgl@sss.pgh.pa.us 769 : 282825 : (void) ExecShutdownNode_walker(node, NULL);
770 : 282825 : }
771 : :
772 : : static bool
773 : 578674 : ExecShutdownNode_walker(PlanState *node, void *context)
774 : : {
3119 rhaas@postgresql.org 775 [ - + ]: 578674 : if (node == NULL)
3119 rhaas@postgresql.org 776 :UBC 0 : return false;
777 : :
2463 andres@anarazel.de 778 :CBC 578674 : check_stack_depth();
779 : :
780 : : /*
781 : : * Treat the node as running while we shut it down, but only if it's run
782 : : * at least once already. We don't expect much CPU consumption during
783 : : * node shutdown, but in the case of Gather or Gather Merge, we may shut
784 : : * down workers at this stage. If so, their buffer usage will get
785 : : * propagated into pgBufferUsage at this point, and we want to make sure
786 : : * that it gets associated with the Gather node. We skip this if the node
787 : : * has never been executed, so as to avoid incorrectly making it appear
788 : : * that it has.
789 : : */
2081 akapila@postgresql.o 790 [ + + + + ]: 578674 : if (node->instrument && node->instrument->running)
791 : 4333 : InstrStartNode(node->instrument);
792 : :
573 tgl@sss.pgh.pa.us 793 : 578674 : planstate_tree_walker(node, ExecShutdownNode_walker, context);
794 : :
3119 rhaas@postgresql.org 795 [ + + - + : 578674 : switch (nodeTag(node))
+ + + ]
796 : : {
797 : 275 : case T_GatherState:
3097 798 : 275 : ExecShutdownGather((GatherState *) node);
3119 799 : 275 : break;
2604 800 : 547 : case T_ForeignScanState:
801 : 547 : ExecShutdownForeignScan((ForeignScanState *) node);
802 : 547 : break;
2604 rhaas@postgresql.org 803 :UBC 0 : case T_CustomScanState:
804 : 0 : ExecShutdownCustomScan((CustomScanState *) node);
805 : 0 : break;
2593 rhaas@postgresql.org 806 :CBC 63 : case T_GatherMergeState:
807 : 63 : ExecShutdownGatherMerge((GatherMergeState *) node);
808 : 63 : break;
2322 andres@anarazel.de 809 : 13175 : case T_HashState:
810 : 13175 : ExecShutdownHash((HashState *) node);
811 : 13175 : break;
2307 812 : 13175 : case T_HashJoinState:
813 : 13175 : ExecShutdownHashJoin((HashJoinState *) node);
814 : 13175 : break;
3119 rhaas@postgresql.org 815 : 551439 : default:
816 : 551439 : break;
817 : : }
818 : :
819 : : /* Stop the node if we started it above, reporting 0 tuples. */
2081 akapila@postgresql.o 820 [ + + + + ]: 578674 : if (node->instrument && node->instrument->running)
821 : 4333 : InstrStopNode(node->instrument, 0);
822 : :
2608 rhaas@postgresql.org 823 : 578674 : return false;
824 : : }
825 : :
826 : : /*
827 : : * ExecSetTupleBound
828 : : *
829 : : * Set a tuple bound for a planstate node. This lets child plan nodes
830 : : * optimize based on the knowledge that the maximum number of tuples that
831 : : * their parent will demand is limited. The tuple bound for a node may
832 : : * only be changed between scans (i.e., after node initialization or just
833 : : * before an ExecReScan call).
834 : : *
835 : : * Any negative tuples_needed value means "no limit", which should be the
836 : : * default assumption when this is not called at all for a particular node.
837 : : *
838 : : * Note: if this is called repeatedly on a plan tree, the exact same set
839 : : * of nodes must be updated with the new limit each time; be careful that
840 : : * only unchanging conditions are tested here.
841 : : */
842 : : void
2420 843 : 3662 : ExecSetTupleBound(int64 tuples_needed, PlanState *child_node)
844 : : {
845 : : /*
846 : : * Since this function recurses, in principle we should check stack depth
847 : : * here. In practice, it's probably pointless since the earlier node
848 : : * initialization tree traversal would surely have consumed more stack.
849 : : */
850 : :
851 [ + + ]: 3662 : if (IsA(child_node, SortState))
852 : : {
853 : : /*
854 : : * If it is a Sort node, notify it that it can use bounded sort.
855 : : *
856 : : * Note: it is the responsibility of nodeSort.c to react properly to
857 : : * changes of these parameters. If we ever redesign this, it'd be a
858 : : * good idea to integrate this signaling with the parameter-change
859 : : * mechanism.
860 : : */
861 : 614 : SortState *sortState = (SortState *) child_node;
862 : :
1469 tomas.vondra@postgre 863 [ + + ]: 614 : if (tuples_needed < 0)
864 : : {
865 : : /* make sure flag gets reset if needed upon rescan */
866 : 146 : sortState->bounded = false;
867 : : }
868 : : else
869 : : {
870 : 468 : sortState->bounded = true;
871 : 468 : sortState->bound = tuples_needed;
872 : : }
873 : : }
874 [ + + ]: 3048 : else if (IsA(child_node, IncrementalSortState))
875 : : {
876 : : /*
877 : : * If it is an IncrementalSort node, notify it that it can use bounded
878 : : * sort.
879 : : *
880 : : * Note: it is the responsibility of nodeIncrementalSort.c to react
881 : : * properly to changes of these parameters. If we ever redesign this,
882 : : * it'd be a good idea to integrate this signaling with the
883 : : * parameter-change mechanism.
884 : : */
885 : 73 : IncrementalSortState *sortState = (IncrementalSortState *) child_node;
886 : :
2420 rhaas@postgresql.org 887 [ - + ]: 73 : if (tuples_needed < 0)
888 : : {
889 : : /* make sure flag gets reset if needed upon rescan */
2420 rhaas@postgresql.org 890 :UBC 0 : sortState->bounded = false;
891 : : }
892 : : else
893 : : {
2420 rhaas@postgresql.org 894 :CBC 73 : sortState->bounded = true;
895 : 73 : sortState->bound = tuples_needed;
896 : : }
897 : : }
1836 tgl@sss.pgh.pa.us 898 [ + + ]: 2975 : else if (IsA(child_node, AppendState))
899 : : {
900 : : /*
901 : : * If it is an Append, we can apply the bound to any nodes that are
902 : : * children of the Append, since the Append surely need read no more
903 : : * than that many tuples from any one input.
904 : : */
905 : 80 : AppendState *aState = (AppendState *) child_node;
906 : : int i;
907 : :
908 [ + + ]: 254 : for (i = 0; i < aState->as_nplans; i++)
909 : 174 : ExecSetTupleBound(tuples_needed, aState->appendplans[i]);
910 : : }
2420 rhaas@postgresql.org 911 [ + + ]: 2895 : else if (IsA(child_node, MergeAppendState))
912 : : {
913 : : /*
914 : : * If it is a MergeAppend, we can apply the bound to any nodes that
915 : : * are children of the MergeAppend, since the MergeAppend surely need
916 : : * read no more than that many tuples from any one input.
917 : : */
918 : 30 : MergeAppendState *maState = (MergeAppendState *) child_node;
919 : : int i;
920 : :
921 [ + + ]: 120 : for (i = 0; i < maState->ms_nplans; i++)
922 : 90 : ExecSetTupleBound(tuples_needed, maState->mergeplans[i]);
923 : : }
924 [ + + ]: 2865 : else if (IsA(child_node, ResultState))
925 : : {
926 : : /*
927 : : * Similarly, for a projecting Result, we can apply the bound to its
928 : : * child node.
929 : : *
930 : : * If Result supported qual checking, we'd have to punt on seeing a
931 : : * qual. Note that having a resconstantqual is not a showstopper: if
932 : : * that condition succeeds it affects nothing, while if it fails, no
933 : : * rows will be demanded from the Result child anyway.
934 : : */
935 [ + + ]: 288 : if (outerPlanState(child_node))
936 : 51 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
937 : : }
938 [ + + ]: 2577 : else if (IsA(child_node, SubqueryScanState))
939 : : {
940 : : /*
941 : : * We can also descend through SubqueryScan, but only if it has no
942 : : * qual (otherwise it might discard rows).
943 : : */
944 : 47 : SubqueryScanState *subqueryState = (SubqueryScanState *) child_node;
945 : :
946 [ + + ]: 47 : if (subqueryState->ss.ps.qual == NULL)
947 : 36 : ExecSetTupleBound(tuples_needed, subqueryState->subplan);
948 : : }
949 [ - + ]: 2530 : else if (IsA(child_node, GatherState))
950 : : {
951 : : /*
952 : : * A Gather node can propagate the bound to its workers. As with
953 : : * MergeAppend, no one worker could possibly need to return more
954 : : * tuples than the Gather itself needs to.
955 : : *
956 : : * Note: As with Sort, the Gather node is responsible for reacting
957 : : * properly to changes to this parameter.
958 : : */
2420 rhaas@postgresql.org 959 :UBC 0 : GatherState *gstate = (GatherState *) child_node;
960 : :
961 : 0 : gstate->tuples_needed = tuples_needed;
962 : :
963 : : /* Also pass down the bound to our own copy of the child plan */
964 : 0 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
965 : : }
2420 rhaas@postgresql.org 966 [ + + ]:CBC 2530 : else if (IsA(child_node, GatherMergeState))
967 : : {
968 : : /* Same comments as for Gather */
969 : 15 : GatherMergeState *gstate = (GatherMergeState *) child_node;
970 : :
971 : 15 : gstate->tuples_needed = tuples_needed;
972 : :
973 : 15 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
974 : : }
975 : :
976 : : /*
977 : : * In principle we could descend through any plan node type that is
978 : : * certain not to discard or combine input rows; but on seeing a node that
979 : : * can do that, we can't propagate the bound any further. For the moment
980 : : * it's unclear that any other cases are worth checking here.
981 : : */
982 : 3662 : }
|