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-2025, PostgreSQL Global Development Group
11 : : * Portions Copyright (c) 1994, Regents of the University of California
12 : : *
13 : : *
14 : : * IDENTIFICATION
15 : : * src/backend/executor/execProcnode.c
16 : : *
17 : : *-------------------------------------------------------------------------
18 : : */
19 : : /*
20 : : * NOTES
21 : : * This used to be three files. It is now all combined into
22 : : * one file so that it is easier to keep the dispatch routines
23 : : * in sync when new nodes are added.
24 : : *
25 : : * EXAMPLE
26 : : * Suppose we want the age of the manager of the shoe department and
27 : : * the number of employees in that department. So we have the query:
28 : : *
29 : : * select DEPT.no_emps, EMP.age
30 : : * from DEPT, EMP
31 : : * where EMP.name = DEPT.mgr and
32 : : * DEPT.name = "shoe"
33 : : *
34 : : * Suppose the planner gives us the following plan:
35 : : *
36 : : * Nest Loop (DEPT.mgr = EMP.name)
37 : : * / \
38 : : * / \
39 : : * Seq Scan Seq Scan
40 : : * DEPT EMP
41 : : * (name = "shoe")
42 : : *
43 : : * ExecutorStart() is called first.
44 : : * It calls InitPlan() which calls ExecInitNode() on
45 : : * the root of the plan -- the nest loop node.
46 : : *
47 : : * * ExecInitNode() notices that it is looking at a nest loop and
48 : : * as the code below demonstrates, it calls ExecInitNestLoop().
49 : : * Eventually this calls ExecInitNode() on the right and left subplans
50 : : * and so forth until the entire plan is initialized. The result
51 : : * of ExecInitNode() is a plan state tree built with the same structure
52 : : * as the underlying plan tree.
53 : : *
54 : : * * Then when ExecutorRun() is called, it calls ExecutePlan() which calls
55 : : * ExecProcNode() repeatedly on the top node of the plan state tree.
56 : : * Each time this happens, ExecProcNode() will end up calling
57 : : * ExecNestLoop(), which calls ExecProcNode() on its subplans.
58 : : * Each of these subplans is a sequential scan so ExecSeqScan() is
59 : : * called. The slots returned by ExecSeqScan() may contain
60 : : * tuples which contain the attributes ExecNestLoop() uses to
61 : : * form the tuples it returns.
62 : : *
63 : : * * Eventually ExecSeqScan() stops returning tuples and the nest
64 : : * loop join ends. Lastly, ExecutorEnd() calls ExecEndNode() which
65 : : * calls ExecEndNestLoop() which in turn calls ExecEndNode() on
66 : : * its subplans which result in ExecEndSeqScan().
67 : : *
68 : : * This should show how the executor works by having
69 : : * ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch
70 : : * their work to the appropriate node support routines which may
71 : : * in turn call these routines themselves on their subplans.
72 : : */
73 : : #include "postgres.h"
74 : :
75 : : #include "executor/executor.h"
76 : : #include "executor/nodeAgg.h"
77 : : #include "executor/nodeAppend.h"
78 : : #include "executor/nodeBitmapAnd.h"
79 : : #include "executor/nodeBitmapHeapscan.h"
80 : : #include "executor/nodeBitmapIndexscan.h"
81 : : #include "executor/nodeBitmapOr.h"
82 : : #include "executor/nodeCtescan.h"
83 : : #include "executor/nodeCustom.h"
84 : : #include "executor/nodeForeignscan.h"
85 : : #include "executor/nodeFunctionscan.h"
86 : : #include "executor/nodeGather.h"
87 : : #include "executor/nodeGatherMerge.h"
88 : : #include "executor/nodeGroup.h"
89 : : #include "executor/nodeHash.h"
90 : : #include "executor/nodeHashjoin.h"
91 : : #include "executor/nodeIncrementalSort.h"
92 : : #include "executor/nodeIndexonlyscan.h"
93 : : #include "executor/nodeIndexscan.h"
94 : : #include "executor/nodeLimit.h"
95 : : #include "executor/nodeLockRows.h"
96 : : #include "executor/nodeMaterial.h"
97 : : #include "executor/nodeMemoize.h"
98 : : #include "executor/nodeMergeAppend.h"
99 : : #include "executor/nodeMergejoin.h"
100 : : #include "executor/nodeModifyTable.h"
101 : : #include "executor/nodeNamedtuplestorescan.h"
102 : : #include "executor/nodeNestloop.h"
103 : : #include "executor/nodeProjectSet.h"
104 : : #include "executor/nodeRecursiveunion.h"
105 : : #include "executor/nodeResult.h"
106 : : #include "executor/nodeSamplescan.h"
107 : : #include "executor/nodeSeqscan.h"
108 : : #include "executor/nodeSetOp.h"
109 : : #include "executor/nodeSort.h"
110 : : #include "executor/nodeSubplan.h"
111 : : #include "executor/nodeSubqueryscan.h"
112 : : #include "executor/nodeTableFuncscan.h"
113 : : #include "executor/nodeTidrangescan.h"
114 : : #include "executor/nodeTidscan.h"
115 : : #include "executor/nodeUnique.h"
116 : : #include "executor/nodeValuesscan.h"
117 : : #include "executor/nodeWindowAgg.h"
118 : : #include "executor/nodeWorktablescan.h"
119 : : #include "miscadmin.h"
120 : : #include "nodes/nodeFuncs.h"
121 : :
122 : : static TupleTableSlot *ExecProcNodeFirst(PlanState *node);
123 : : static TupleTableSlot *ExecProcNodeInstr(PlanState *node);
124 : : static bool ExecShutdownNode_walker(PlanState *node, void *context);
125 : :
126 : :
127 : : /* ------------------------------------------------------------------------
128 : : * ExecInitNode
129 : : *
130 : : * Recursively initializes all the nodes in the plan tree rooted
131 : : * at 'node'.
132 : : *
133 : : * Inputs:
134 : : * 'node' is the current node of the plan produced by the query planner
135 : : * 'estate' is the shared execution state for the plan tree
136 : : * 'eflags' is a bitwise OR of flag bits described in executor.h
137 : : *
138 : : * Returns a PlanState node corresponding to the given Plan node.
139 : : * ------------------------------------------------------------------------
140 : : */
141 : : PlanState *
7130 tgl@sss.pgh.pa.us 142 :CBC 776344 : 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 : : */
10226 bruce@momjian.us 151 [ + + ]: 776344 : if (node == NULL)
8311 tgl@sss.pgh.pa.us 152 : 131857 : 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 : : */
2973 andres@anarazel.de 159 : 644487 : check_stack_depth();
160 : :
10226 bruce@momjian.us 161 [ + + + + : 644487 : switch (nodeTag(node))
+ + + + +
+ + + + +
+ + + + +
+ + + + +
- + + + +
+ + + + +
+ + + + +
+ + + - ]
162 : : {
163 : : /*
164 : : * control nodes
165 : : */
10225 166 : 136778 : case T_Result:
7130 tgl@sss.pgh.pa.us 167 : 136778 : result = (PlanState *) ExecInitResult((Result *) node,
168 : : estate, eflags);
10225 bruce@momjian.us 169 : 136744 : break;
170 : :
3153 andres@anarazel.de 171 : 6926 : case T_ProjectSet:
172 : 6926 : result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
173 : : estate, eflags);
174 : 6925 : break;
175 : :
5810 tgl@sss.pgh.pa.us 176 : 55560 : case T_ModifyTable:
177 : 55560 : result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
178 : : estate, eflags);
179 : 55392 : break;
180 : :
10225 bruce@momjian.us 181 : 8664 : case T_Append:
7130 tgl@sss.pgh.pa.us 182 : 8664 : result = (PlanState *) ExecInitAppend((Append *) node,
183 : : estate, eflags);
10225 bruce@momjian.us 184 : 8664 : break;
185 : :
5441 tgl@sss.pgh.pa.us 186 : 296 : case T_MergeAppend:
187 : 296 : result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
188 : : estate, eflags);
189 : 296 : break;
190 : :
6181 191 : 463 : case T_RecursiveUnion:
192 : 463 : result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
193 : : estate, eflags);
194 : 463 : break;
195 : :
7445 196 : 121 : case T_BitmapAnd:
7130 197 : 121 : result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
198 : : estate, eflags);
7445 199 : 121 : break;
200 : :
201 : 209 : case T_BitmapOr:
7130 202 : 209 : result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
203 : : estate, eflags);
7445 204 : 209 : break;
205 : :
206 : : /*
207 : : * scan nodes
208 : : */
10225 bruce@momjian.us 209 : 112351 : case T_SeqScan:
7130 tgl@sss.pgh.pa.us 210 : 112351 : result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
211 : : estate, eflags);
10225 bruce@momjian.us 212 : 112345 : break;
213 : :
3767 simon@2ndQuadrant.co 214 : 153 : case T_SampleScan:
215 : 153 : result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
216 : : estate, eflags);
217 : 153 : break;
218 : :
10225 bruce@momjian.us 219 : 82387 : case T_IndexScan:
7130 tgl@sss.pgh.pa.us 220 : 82387 : result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
221 : : estate, eflags);
10225 bruce@momjian.us 222 : 82387 : break;
223 : :
5079 tgl@sss.pgh.pa.us 224 : 7807 : case T_IndexOnlyScan:
225 : 7807 : result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
226 : : estate, eflags);
227 : 7807 : break;
228 : :
7445 229 : 10642 : case T_BitmapIndexScan:
7130 230 : 10642 : result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
231 : : estate, eflags);
7445 232 : 10642 : break;
233 : :
234 : 10309 : case T_BitmapHeapScan:
7130 235 : 10309 : result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
236 : : estate, eflags);
7445 237 : 10309 : break;
238 : :
9108 239 : 423 : case T_TidScan:
7130 240 : 423 : result = (PlanState *) ExecInitTidScan((TidScan *) node,
241 : : estate, eflags);
9108 242 : 423 : break;
243 : :
1652 drowley@postgresql.o 244 : 968 : case T_TidRangeScan:
245 : 968 : result = (PlanState *) ExecInitTidRangeScan((TidRangeScan *) node,
246 : : estate, eflags);
247 : 968 : break;
248 : :
9108 tgl@sss.pgh.pa.us 249 : 5419 : case T_SubqueryScan:
7130 250 : 5419 : result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
251 : : estate, eflags);
9108 252 : 5419 : break;
253 : :
8518 254 : 34095 : case T_FunctionScan:
7130 255 : 34095 : result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
256 : : estate, eflags);
8518 257 : 34091 : break;
258 : :
3104 alvherre@alvh.no-ip. 259 : 311 : case T_TableFuncScan:
260 : 311 : result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
261 : : estate, eflags);
262 : 311 : break;
263 : :
6975 mail@joeconway.com 264 : 4538 : case T_ValuesScan:
265 : 4538 : result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
266 : : estate, eflags);
267 : 4538 : break;
268 : :
6181 tgl@sss.pgh.pa.us 269 : 2122 : case T_CteScan:
270 : 2122 : result = (PlanState *) ExecInitCteScan((CteScan *) node,
271 : : estate, eflags);
272 : 2122 : break;
273 : :
3081 kgrittn@postgresql.o 274 : 342 : case T_NamedTuplestoreScan:
275 : 342 : result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node,
276 : : estate, eflags);
277 : 342 : break;
278 : :
6181 tgl@sss.pgh.pa.us 279 : 463 : case T_WorkTableScan:
280 : 463 : result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
281 : : estate, eflags);
282 : 463 : break;
283 : :
5312 284 : 1024 : case T_ForeignScan:
285 : 1024 : result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
286 : : estate, eflags);
287 : 1012 : break;
288 : :
3956 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 : : */
10225 bruce@momjian.us 297 :CBC 47919 : case T_NestLoop:
7130 tgl@sss.pgh.pa.us 298 : 47919 : result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
299 : : estate, eflags);
10225 bruce@momjian.us 300 : 47919 : break;
301 : :
302 : 3757 : case T_MergeJoin:
7130 tgl@sss.pgh.pa.us 303 : 3757 : result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
304 : : estate, eflags);
9108 305 : 3757 : break;
306 : :
307 : 16602 : case T_HashJoin:
7130 308 : 16602 : result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
309 : : estate, eflags);
9108 310 : 16602 : break;
311 : :
312 : : /*
313 : : * materialization nodes
314 : : */
10225 bruce@momjian.us 315 : 2357 : case T_Material:
7130 tgl@sss.pgh.pa.us 316 : 2357 : result = (PlanState *) ExecInitMaterial((Material *) node,
317 : : estate, eflags);
10225 bruce@momjian.us 318 : 2357 : break;
319 : :
320 : 39457 : case T_Sort:
7130 tgl@sss.pgh.pa.us 321 : 39457 : result = (PlanState *) ExecInitSort((Sort *) node,
322 : : estate, eflags);
10225 bruce@momjian.us 323 : 39454 : break;
324 : :
1979 tomas.vondra@postgre 325 : 535 : case T_IncrementalSort:
326 : 535 : result = (PlanState *) ExecInitIncrementalSort((IncrementalSort *) node,
327 : : estate, eflags);
328 : 535 : break;
329 : :
1515 drowley@postgresql.o 330 : 1020 : case T_Memoize:
331 : 1020 : result = (PlanState *) ExecInitMemoize((Memoize *) node, estate,
332 : : eflags);
1618 333 : 1020 : break;
334 : :
8311 tgl@sss.pgh.pa.us 335 : 123 : case T_Group:
7130 336 : 123 : result = (PlanState *) ExecInitGroup((Group *) node,
337 : : estate, eflags);
10225 bruce@momjian.us 338 : 123 : break;
339 : :
8311 tgl@sss.pgh.pa.us 340 : 22045 : case T_Agg:
7130 341 : 22045 : result = (PlanState *) ExecInitAgg((Agg *) node,
342 : : estate, eflags);
9102 343 : 22042 : break;
344 : :
6096 345 : 1273 : case T_WindowAgg:
346 : 1273 : result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
347 : : estate, eflags);
348 : 1273 : break;
349 : :
8311 350 : 2819 : case T_Unique:
7130 351 : 2819 : result = (PlanState *) ExecInitUnique((Unique *) node,
352 : : estate, eflags);
9081 353 : 2819 : break;
354 : :
3629 rhaas@postgresql.org 355 : 544 : case T_Gather:
356 : 544 : result = (PlanState *) ExecInitGather((Gather *) node,
357 : : estate, eflags);
358 : 544 : break;
359 : :
3103 360 : 171 : case T_GatherMerge:
361 : 171 : result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
362 : : estate, eflags);
363 : 171 : break;
364 : :
8311 tgl@sss.pgh.pa.us 365 : 16602 : case T_Hash:
7130 366 : 16602 : result = (PlanState *) ExecInitHash((Hash *) node,
367 : : estate, eflags);
10225 bruce@momjian.us 368 : 16602 : break;
369 : :
8311 tgl@sss.pgh.pa.us 370 : 331 : case T_SetOp:
7130 371 : 331 : result = (PlanState *) ExecInitSetOp((SetOp *) node,
372 : : estate, eflags);
8311 373 : 331 : break;
374 : :
5808 375 : 4093 : case T_LockRows:
376 : 4093 : result = (PlanState *) ExecInitLockRows((LockRows *) node,
377 : : estate, eflags);
378 : 4093 : break;
379 : :
8311 380 : 2468 : case T_Limit:
7130 381 : 2468 : result = (PlanState *) ExecInitLimit((Limit *) node,
382 : : estate, eflags);
10225 bruce@momjian.us 383 : 2468 : break;
384 : :
10225 bruce@momjian.us 385 :UBC 0 : default:
8083 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 : :
2824 andres@anarazel.de 391 :CBC 644256 : 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 : : */
8311 tgl@sss.pgh.pa.us 401 : 644256 : subps = NIL;
7773 neilc@samurai.com 402 [ + + + + : 651531 : foreach(l, node->initPlan)
+ + ]
403 : : {
404 : 7275 : SubPlan *subplan = (SubPlan *) lfirst(l);
405 : : SubPlanState *sstate;
406 : :
8302 tgl@sss.pgh.pa.us 407 [ - + ]: 7275 : Assert(IsA(subplan, SubPlan));
402 andres@anarazel.de 408 [ - + ]: 7275 : Assert(subplan->args == NIL);
6766 tgl@sss.pgh.pa.us 409 : 7275 : sstate = ExecInitSubPlan(subplan, result);
8303 410 : 7275 : subps = lappend(subps, sstate);
411 : : }
8311 412 : 644256 : result->initPlan = subps;
413 : :
414 : : /* Set up instrumentation for this node if requested */
415 [ + + ]: 644256 : if (estate->es_instrument)
1578 efujita@postgresql.o 416 : 5213 : result->instrument = InstrAlloc(1, estate->es_instrument,
417 : 5213 : result->async_capable);
418 : :
10226 bruce@momjian.us 419 : 644256 : 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
2824 andres@anarazel.de 430 : 644469 : 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 : 644469 : node->ExecProcNodeReal = function;
439 : 644469 : node->ExecProcNode = ExecProcNodeFirst;
440 : 644469 : }
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 *
2973 448 : 545174 : 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 : 545174 : 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 : : */
8754 tgl@sss.pgh.pa.us 464 [ + + ]: 545174 : if (node->instrument)
2973 andres@anarazel.de 465 : 4045 : node->ExecProcNode = ExecProcNodeInstr;
466 : : else
467 : 541129 : node->ExecProcNode = node->ExecProcNodeReal;
468 : :
469 : 545174 : return node->ExecProcNode(node);
470 : : }
471 : :
472 : :
473 : : /*
474 : : * ExecProcNode wrapper that performs instrumentation calls. By keeping
475 : : * this a separate function, we avoid overhead in the normal case where
476 : : * no instrumentation is wanted.
477 : : */
478 : : static TupleTableSlot *
479 : 6757314 : ExecProcNodeInstr(PlanState *node)
480 : : {
481 : : TupleTableSlot *result;
482 : :
483 : 6757314 : InstrStartNode(node->instrument);
484 : :
485 : 6757314 : result = node->ExecProcNodeReal(node);
486 : :
487 [ + + + + ]: 6757308 : InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
488 : :
10226 bruce@momjian.us 489 : 6757308 : return result;
490 : : }
491 : :
492 : :
493 : : /* ----------------------------------------------------------------
494 : : * MultiExecProcNode
495 : : *
496 : : * Execute a node that doesn't return individual tuples
497 : : * (it might return a hashtable, bitmap, etc). Caller should
498 : : * check it got back the expected kind of Node.
499 : : *
500 : : * This has essentially the same responsibilities as ExecProcNode,
501 : : * but it does not do InstrStartNode/InstrStopNode (mainly because
502 : : * it can't tell how many returned tuples to count). Each per-node
503 : : * function must provide its own instrumentation support.
504 : : * ----------------------------------------------------------------
505 : : */
506 : : Node *
7448 tgl@sss.pgh.pa.us 507 : 22623 : MultiExecProcNode(PlanState *node)
508 : : {
509 : : Node *result;
510 : :
2973 andres@anarazel.de 511 : 22623 : check_stack_depth();
512 : :
7448 tgl@sss.pgh.pa.us 513 [ - + ]: 22623 : CHECK_FOR_INTERRUPTS();
514 : :
515 [ + + ]: 22623 : if (node->chgParam != NULL) /* something changed */
5535 516 : 3333 : ExecReScan(node); /* let ReScan handle this */
517 : :
7448 518 [ + + + + : 22623 : switch (nodeTag(node))
- ]
519 : : {
520 : : /*
521 : : * Only node types that actually support multiexec will be listed
522 : : */
523 : :
524 : 12223 : case T_HashState:
525 : 12223 : result = MultiExecHash((HashState *) node);
526 : 12221 : break;
527 : :
7445 528 : 10151 : case T_BitmapIndexScanState:
529 : 10151 : result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node);
530 : 10151 : break;
531 : :
532 : 97 : case T_BitmapAndState:
533 : 97 : result = MultiExecBitmapAnd((BitmapAndState *) node);
534 : 97 : break;
535 : :
536 : 152 : case T_BitmapOrState:
537 : 152 : result = MultiExecBitmapOr((BitmapOrState *) node);
538 : 152 : break;
539 : :
7448 tgl@sss.pgh.pa.us 540 :UBC 0 : default:
541 [ # # ]: 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
542 : : result = NULL;
543 : : break;
544 : : }
545 : :
7448 tgl@sss.pgh.pa.us 546 :CBC 22621 : return result;
547 : : }
548 : :
549 : :
550 : : /* ----------------------------------------------------------------
551 : : * ExecEndNode
552 : : *
553 : : * Recursively cleans up all the nodes in the plan rooted
554 : : * at 'node'.
555 : : *
556 : : * After this operation, the query plan will not be able to be
557 : : * processed any further. This should be called only after
558 : : * the query plan has been fully executed.
559 : : * ----------------------------------------------------------------
560 : : */
561 : : void
8065 bruce@momjian.us 562 : 749607 : ExecEndNode(PlanState *node)
563 : : {
564 : : /*
565 : : * do nothing when we get to the end of a leaf on tree.
566 : : */
10226 567 [ + + ]: 749607 : if (node == NULL)
568 : 123292 : return;
569 : :
570 : : /*
571 : : * Make sure there's enough stack available. Need to check here, in
572 : : * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
573 : : * guaranteed that ExecProcNode() is reached for all nodes.
574 : : */
2973 andres@anarazel.de 575 : 626315 : check_stack_depth();
576 : :
8245 tgl@sss.pgh.pa.us 577 [ + + ]: 626315 : if (node->chgParam != NULL)
578 : : {
579 : 3913 : bms_free(node->chgParam);
580 : 3913 : node->chgParam = NULL;
581 : : }
582 : :
10226 bruce@momjian.us 583 [ + + + + : 626315 : switch (nodeTag(node))
+ + + + +
+ + + + +
+ + + + +
+ + + + -
+ + + + +
+ + + + +
+ + + + +
+ - ]
584 : : {
585 : : /*
586 : : * control nodes
587 : : */
8311 tgl@sss.pgh.pa.us 588 : 128228 : case T_ResultState:
589 : 128228 : ExecEndResult((ResultState *) node);
10225 bruce@momjian.us 590 : 128228 : break;
591 : :
3153 andres@anarazel.de 592 : 6166 : case T_ProjectSetState:
593 : 6166 : ExecEndProjectSet((ProjectSetState *) node);
594 : 6166 : break;
595 : :
5810 tgl@sss.pgh.pa.us 596 : 53204 : case T_ModifyTableState:
597 : 53204 : ExecEndModifyTable((ModifyTableState *) node);
598 : 53204 : break;
599 : :
8311 600 : 8510 : case T_AppendState:
601 : 8510 : ExecEndAppend((AppendState *) node);
10225 bruce@momjian.us 602 : 8510 : break;
603 : :
5441 tgl@sss.pgh.pa.us 604 : 296 : case T_MergeAppendState:
605 : 296 : ExecEndMergeAppend((MergeAppendState *) node);
606 : 296 : break;
607 : :
6181 608 : 463 : case T_RecursiveUnionState:
609 : 463 : ExecEndRecursiveUnion((RecursiveUnionState *) node);
610 : 463 : break;
611 : :
7445 612 : 121 : case T_BitmapAndState:
613 : 121 : ExecEndBitmapAnd((BitmapAndState *) node);
614 : 121 : break;
615 : :
616 : 209 : case T_BitmapOrState:
617 : 209 : ExecEndBitmapOr((BitmapOrState *) node);
618 : 209 : break;
619 : :
620 : : /*
621 : : * scan nodes
622 : : */
8311 623 : 111028 : case T_SeqScanState:
624 : 111028 : ExecEndSeqScan((SeqScanState *) node);
10225 bruce@momjian.us 625 : 111028 : break;
626 : :
3767 simon@2ndQuadrant.co 627 : 133 : case T_SampleScanState:
628 : 133 : ExecEndSampleScan((SampleScanState *) node);
629 : 133 : break;
630 : :
3629 rhaas@postgresql.org 631 : 538 : case T_GatherState:
632 : 538 : ExecEndGather((GatherState *) node);
633 : 538 : break;
634 : :
3103 635 : 171 : case T_GatherMergeState:
636 : 171 : ExecEndGatherMerge((GatherMergeState *) node);
637 : 171 : break;
638 : :
8311 tgl@sss.pgh.pa.us 639 : 81984 : case T_IndexScanState:
640 : 81984 : ExecEndIndexScan((IndexScanState *) node);
10225 bruce@momjian.us 641 : 81984 : break;
642 : :
5079 tgl@sss.pgh.pa.us 643 : 7782 : case T_IndexOnlyScanState:
644 : 7782 : ExecEndIndexOnlyScan((IndexOnlyScanState *) node);
645 : 7782 : break;
646 : :
7445 647 : 10592 : case T_BitmapIndexScanState:
648 : 10592 : ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
649 : 10592 : break;
650 : :
651 : 10259 : case T_BitmapHeapScanState:
652 : 10259 : ExecEndBitmapHeapScan((BitmapHeapScanState *) node);
653 : 10259 : break;
654 : :
8311 655 : 351 : case T_TidScanState:
656 : 351 : ExecEndTidScan((TidScanState *) node);
9108 657 : 351 : break;
658 : :
1652 drowley@postgresql.o 659 : 101 : case T_TidRangeScanState:
660 : 101 : ExecEndTidRangeScan((TidRangeScanState *) node);
661 : 101 : break;
662 : :
8311 tgl@sss.pgh.pa.us 663 : 5419 : case T_SubqueryScanState:
664 : 5419 : ExecEndSubqueryScan((SubqueryScanState *) node);
9108 665 : 5419 : break;
666 : :
8311 667 : 31383 : case T_FunctionScanState:
668 : 31383 : ExecEndFunctionScan((FunctionScanState *) node);
8518 669 : 31383 : break;
670 : :
3104 alvherre@alvh.no-ip. 671 : 254 : case T_TableFuncScanState:
672 : 254 : ExecEndTableFuncScan((TableFuncScanState *) node);
673 : 254 : break;
674 : :
6181 tgl@sss.pgh.pa.us 675 : 2109 : case T_CteScanState:
676 : 2109 : ExecEndCteScan((CteScanState *) node);
677 : 2109 : break;
678 : :
5312 679 : 980 : case T_ForeignScanState:
680 : 980 : ExecEndForeignScan((ForeignScanState *) node);
681 : 980 : break;
682 : :
3956 rhaas@postgresql.org 683 :UBC 0 : case T_CustomScanState:
684 : 0 : ExecEndCustomScan((CustomScanState *) node);
685 : 0 : break;
686 : :
687 : : /*
688 : : * join nodes
689 : : */
8311 tgl@sss.pgh.pa.us 690 :CBC 47792 : case T_NestLoopState:
691 : 47792 : ExecEndNestLoop((NestLoopState *) node);
10225 bruce@momjian.us 692 : 47792 : break;
693 : :
8311 tgl@sss.pgh.pa.us 694 : 3754 : case T_MergeJoinState:
695 : 3754 : ExecEndMergeJoin((MergeJoinState *) node);
9108 696 : 3754 : break;
697 : :
8311 698 : 16544 : case T_HashJoinState:
699 : 16544 : ExecEndHashJoin((HashJoinState *) node);
9108 700 : 16544 : break;
701 : :
702 : : /*
703 : : * materialization nodes
704 : : */
8311 705 : 2323 : case T_MaterialState:
706 : 2323 : ExecEndMaterial((MaterialState *) node);
10225 bruce@momjian.us 707 : 2323 : break;
708 : :
8311 tgl@sss.pgh.pa.us 709 : 39374 : case T_SortState:
710 : 39374 : ExecEndSort((SortState *) node);
10225 bruce@momjian.us 711 : 39374 : break;
712 : :
1979 tomas.vondra@postgre 713 : 535 : case T_IncrementalSortState:
714 : 535 : ExecEndIncrementalSort((IncrementalSortState *) node);
715 : 535 : break;
716 : :
1515 drowley@postgresql.o 717 : 1020 : case T_MemoizeState:
718 : 1020 : ExecEndMemoize((MemoizeState *) node);
1618 719 : 1020 : break;
720 : :
8311 tgl@sss.pgh.pa.us 721 : 123 : case T_GroupState:
722 : 123 : ExecEndGroup((GroupState *) node);
10225 bruce@momjian.us 723 : 123 : break;
724 : :
8311 tgl@sss.pgh.pa.us 725 : 21952 : case T_AggState:
726 : 21952 : ExecEndAgg((AggState *) node);
9102 727 : 21952 : break;
728 : :
6096 729 : 1207 : case T_WindowAggState:
730 : 1207 : ExecEndWindowAgg((WindowAggState *) node);
731 : 1207 : break;
732 : :
8311 733 : 2819 : case T_UniqueState:
734 : 2819 : ExecEndUnique((UniqueState *) node);
9081 735 : 2819 : break;
736 : :
8311 737 : 16544 : case T_HashState:
738 : 16544 : ExecEndHash((HashState *) node);
10225 bruce@momjian.us 739 : 16544 : break;
740 : :
8311 tgl@sss.pgh.pa.us 741 : 331 : case T_SetOpState:
742 : 331 : ExecEndSetOp((SetOpState *) node);
743 : 331 : break;
744 : :
5808 745 : 4046 : case T_LockRowsState:
746 : 4046 : ExecEndLockRows((LockRowsState *) node);
747 : 4046 : break;
748 : :
8311 749 : 2436 : case T_LimitState:
750 : 2436 : ExecEndLimit((LimitState *) node);
10225 bruce@momjian.us 751 : 2436 : break;
752 : :
753 : : /* No clean up actions for these nodes. */
709 amitlan@postgresql.o 754 : 5234 : case T_ValuesScanState:
755 : : case T_NamedTuplestoreScanState:
756 : : case T_WorkTableScanState:
757 : 5234 : break;
758 : :
10225 bruce@momjian.us 759 :UBC 0 : default:
8083 tgl@sss.pgh.pa.us 760 [ # # ]: 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
761 : : break;
762 : : }
763 : : }
764 : :
765 : : /*
766 : : * ExecShutdownNode
767 : : *
768 : : * Give execution nodes a chance to stop asynchronous resource consumption
769 : : * and release any resources still held.
770 : : */
771 : : void
3629 rhaas@postgresql.org 772 :CBC 261098 : ExecShutdownNode(PlanState *node)
773 : : {
1083 tgl@sss.pgh.pa.us 774 : 261098 : (void) ExecShutdownNode_walker(node, NULL);
775 : 261098 : }
776 : :
777 : : static bool
778 : 595121 : ExecShutdownNode_walker(PlanState *node, void *context)
779 : : {
3629 rhaas@postgresql.org 780 [ - + ]: 595121 : if (node == NULL)
3629 rhaas@postgresql.org 781 :UBC 0 : return false;
782 : :
2973 andres@anarazel.de 783 :CBC 595121 : check_stack_depth();
784 : :
785 : : /*
786 : : * Treat the node as running while we shut it down, but only if it's run
787 : : * at least once already. We don't expect much CPU consumption during
788 : : * node shutdown, but in the case of Gather or Gather Merge, we may shut
789 : : * down workers at this stage. If so, their buffer usage will get
790 : : * propagated into pgBufferUsage at this point, and we want to make sure
791 : : * that it gets associated with the Gather node. We skip this if the node
792 : : * has never been executed, so as to avoid incorrectly making it appear
793 : : * that it has.
794 : : */
2591 akapila@postgresql.o 795 [ + + + + ]: 595121 : if (node->instrument && node->instrument->running)
796 : 4437 : InstrStartNode(node->instrument);
797 : :
1083 tgl@sss.pgh.pa.us 798 : 595121 : planstate_tree_walker(node, ExecShutdownNode_walker, context);
799 : :
3629 rhaas@postgresql.org 800 [ + + - + : 595121 : switch (nodeTag(node))
+ + + ]
801 : : {
802 : 315 : case T_GatherState:
3607 803 : 315 : ExecShutdownGather((GatherState *) node);
3629 804 : 315 : break;
3114 805 : 568 : case T_ForeignScanState:
806 : 568 : ExecShutdownForeignScan((ForeignScanState *) node);
807 : 568 : break;
3114 rhaas@postgresql.org 808 :UBC 0 : case T_CustomScanState:
809 : 0 : ExecShutdownCustomScan((CustomScanState *) node);
810 : 0 : break;
3103 rhaas@postgresql.org 811 :CBC 66 : case T_GatherMergeState:
812 : 66 : ExecShutdownGatherMerge((GatherMergeState *) node);
813 : 66 : break;
2832 andres@anarazel.de 814 : 14663 : case T_HashState:
815 : 14663 : ExecShutdownHash((HashState *) node);
816 : 14663 : break;
2817 817 : 14663 : case T_HashJoinState:
818 : 14663 : ExecShutdownHashJoin((HashJoinState *) node);
819 : 14663 : break;
3629 rhaas@postgresql.org 820 : 564846 : default:
821 : 564846 : break;
822 : : }
823 : :
824 : : /* Stop the node if we started it above, reporting 0 tuples. */
2591 akapila@postgresql.o 825 [ + + + + ]: 595121 : if (node->instrument && node->instrument->running)
826 : 4437 : InstrStopNode(node->instrument, 0);
827 : :
3118 rhaas@postgresql.org 828 : 595121 : return false;
829 : : }
830 : :
831 : : /*
832 : : * ExecSetTupleBound
833 : : *
834 : : * Set a tuple bound for a planstate node. This lets child plan nodes
835 : : * optimize based on the knowledge that the maximum number of tuples that
836 : : * their parent will demand is limited. The tuple bound for a node may
837 : : * only be changed between scans (i.e., after node initialization or just
838 : : * before an ExecReScan call).
839 : : *
840 : : * Any negative tuples_needed value means "no limit", which should be the
841 : : * default assumption when this is not called at all for a particular node.
842 : : *
843 : : * Note: if this is called repeatedly on a plan tree, the exact same set
844 : : * of nodes must be updated with the new limit each time; be careful that
845 : : * only unchanging conditions are tested here.
846 : : */
847 : : void
2930 848 : 33817 : ExecSetTupleBound(int64 tuples_needed, PlanState *child_node)
849 : : {
850 : : /*
851 : : * Since this function recurses, in principle we should check stack depth
852 : : * here. In practice, it's probably pointless since the earlier node
853 : : * initialization tree traversal would surely have consumed more stack.
854 : : */
855 : :
856 [ + + ]: 33817 : if (IsA(child_node, SortState))
857 : : {
858 : : /*
859 : : * If it is a Sort node, notify it that it can use bounded sort.
860 : : *
861 : : * Note: it is the responsibility of nodeSort.c to react properly to
862 : : * changes of these parameters. If we ever redesign this, it'd be a
863 : : * good idea to integrate this signaling with the parameter-change
864 : : * mechanism.
865 : : */
866 : 635 : SortState *sortState = (SortState *) child_node;
867 : :
1979 tomas.vondra@postgre 868 [ + + ]: 635 : if (tuples_needed < 0)
869 : : {
870 : : /* make sure flag gets reset if needed upon rescan */
871 : 146 : sortState->bounded = false;
872 : : }
873 : : else
874 : : {
875 : 489 : sortState->bounded = true;
876 : 489 : sortState->bound = tuples_needed;
877 : : }
878 : : }
879 [ + + ]: 33182 : else if (IsA(child_node, IncrementalSortState))
880 : : {
881 : : /*
882 : : * If it is an IncrementalSort node, notify it that it can use bounded
883 : : * sort.
884 : : *
885 : : * Note: it is the responsibility of nodeIncrementalSort.c to react
886 : : * properly to changes of these parameters. If we ever redesign this,
887 : : * it'd be a good idea to integrate this signaling with the
888 : : * parameter-change mechanism.
889 : : */
890 : 73 : IncrementalSortState *sortState = (IncrementalSortState *) child_node;
891 : :
2930 rhaas@postgresql.org 892 [ - + ]: 73 : if (tuples_needed < 0)
893 : : {
894 : : /* make sure flag gets reset if needed upon rescan */
2930 rhaas@postgresql.org 895 :UBC 0 : sortState->bounded = false;
896 : : }
897 : : else
898 : : {
2930 rhaas@postgresql.org 899 :CBC 73 : sortState->bounded = true;
900 : 73 : sortState->bound = tuples_needed;
901 : : }
902 : : }
2346 tgl@sss.pgh.pa.us 903 [ + + ]: 33109 : else if (IsA(child_node, AppendState))
904 : : {
905 : : /*
906 : : * If it is an Append, we can apply the bound to any nodes that are
907 : : * children of the Append, since the Append surely need read no more
908 : : * than that many tuples from any one input.
909 : : */
910 : 80 : AppendState *aState = (AppendState *) child_node;
911 : : int i;
912 : :
913 [ + + ]: 254 : for (i = 0; i < aState->as_nplans; i++)
914 : 174 : ExecSetTupleBound(tuples_needed, aState->appendplans[i]);
915 : : }
2930 rhaas@postgresql.org 916 [ + + ]: 33029 : else if (IsA(child_node, MergeAppendState))
917 : : {
918 : : /*
919 : : * If it is a MergeAppend, we can apply the bound to any nodes that
920 : : * are children of the MergeAppend, since the MergeAppend surely need
921 : : * read no more than that many tuples from any one input.
922 : : */
923 : 30 : MergeAppendState *maState = (MergeAppendState *) child_node;
924 : : int i;
925 : :
926 [ + + ]: 120 : for (i = 0; i < maState->ms_nplans; i++)
927 : 90 : ExecSetTupleBound(tuples_needed, maState->mergeplans[i]);
928 : : }
929 [ + + ]: 32999 : else if (IsA(child_node, ResultState))
930 : : {
931 : : /*
932 : : * Similarly, for a projecting Result, we can apply the bound to its
933 : : * child node.
934 : : *
935 : : * If Result supported qual checking, we'd have to punt on seeing a
936 : : * qual. Note that having a resconstantqual is not a showstopper: if
937 : : * that condition succeeds it affects nothing, while if it fails, no
938 : : * rows will be demanded from the Result child anyway.
939 : : */
940 [ + + ]: 321 : if (outerPlanState(child_node))
941 : 51 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
942 : : }
943 [ + + ]: 32678 : else if (IsA(child_node, SubqueryScanState))
944 : : {
945 : : /*
946 : : * We can also descend through SubqueryScan, but only if it has no
947 : : * qual (otherwise it might discard rows).
948 : : */
949 : 47 : SubqueryScanState *subqueryState = (SubqueryScanState *) child_node;
950 : :
951 [ + + ]: 47 : if (subqueryState->ss.ps.qual == NULL)
952 : 36 : ExecSetTupleBound(tuples_needed, subqueryState->subplan);
953 : : }
954 [ - + ]: 32631 : else if (IsA(child_node, GatherState))
955 : : {
956 : : /*
957 : : * A Gather node can propagate the bound to its workers. As with
958 : : * MergeAppend, no one worker could possibly need to return more
959 : : * tuples than the Gather itself needs to.
960 : : *
961 : : * Note: As with Sort, the Gather node is responsible for reacting
962 : : * properly to changes to this parameter.
963 : : */
2930 rhaas@postgresql.org 964 :UBC 0 : GatherState *gstate = (GatherState *) child_node;
965 : :
966 : 0 : gstate->tuples_needed = tuples_needed;
967 : :
968 : : /* Also pass down the bound to our own copy of the child plan */
969 : 0 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
970 : : }
2930 rhaas@postgresql.org 971 [ + + ]:CBC 32631 : else if (IsA(child_node, GatherMergeState))
972 : : {
973 : : /* Same comments as for Gather */
974 : 15 : GatherMergeState *gstate = (GatherMergeState *) child_node;
975 : :
976 : 15 : gstate->tuples_needed = tuples_needed;
977 : :
978 : 15 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
979 : : }
980 : :
981 : : /*
982 : : * In principle we could descend through any plan node type that is
983 : : * certain not to discard or combine input rows; but on seeing a node that
984 : : * can do that, we can't propagate the bound any further. For the moment
985 : : * it's unclear that any other cases are worth checking here.
986 : : */
987 : 33817 : }
|