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-2017, 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/nodeIndexonlyscan.h"
92 : #include "executor/nodeIndexscan.h"
93 : #include "executor/nodeLimit.h"
94 : #include "executor/nodeLockRows.h"
95 : #include "executor/nodeMaterial.h"
96 : #include "executor/nodeMergeAppend.h"
97 : #include "executor/nodeMergejoin.h"
98 : #include "executor/nodeModifyTable.h"
99 : #include "executor/nodeNamedtuplestorescan.h"
100 : #include "executor/nodeNestloop.h"
101 : #include "executor/nodeProjectSet.h"
102 : #include "executor/nodeRecursiveunion.h"
103 : #include "executor/nodeResult.h"
104 : #include "executor/nodeSamplescan.h"
105 : #include "executor/nodeSeqscan.h"
106 : #include "executor/nodeSetOp.h"
107 : #include "executor/nodeSort.h"
108 : #include "executor/nodeSubplan.h"
109 : #include "executor/nodeSubqueryscan.h"
110 : #include "executor/nodeTableFuncscan.h"
111 : #include "executor/nodeTidscan.h"
112 : #include "executor/nodeUnique.h"
113 : #include "executor/nodeValuesscan.h"
114 : #include "executor/nodeWindowAgg.h"
115 : #include "executor/nodeWorktablescan.h"
116 : #include "nodes/nodeFuncs.h"
117 : #include "miscadmin.h"
118 :
119 :
120 : static TupleTableSlot *ExecProcNodeFirst(PlanState *node);
121 : static TupleTableSlot *ExecProcNodeInstr(PlanState *node);
122 :
123 :
124 : /* ------------------------------------------------------------------------
125 : * ExecInitNode
126 : *
127 : * Recursively initializes all the nodes in the plan tree rooted
128 : * at 'node'.
129 : *
130 : * Inputs:
131 : * 'node' is the current node of the plan produced by the query planner
132 : * 'estate' is the shared execution state for the plan tree
133 : * 'eflags' is a bitwise OR of flag bits described in executor.h
134 : *
135 : * Returns a PlanState node corresponding to the given Plan node.
136 : * ------------------------------------------------------------------------
137 : */
138 : PlanState *
139 63651 : ExecInitNode(Plan *node, EState *estate, int eflags)
140 : {
141 : PlanState *result;
142 : List *subps;
143 : ListCell *l;
144 :
145 : /*
146 : * do nothing when we get to the end of a leaf on tree.
147 : */
148 63651 : if (node == NULL)
149 11295 : return NULL;
150 :
151 : /*
152 : * Make sure there's enough stack available. Need to check here, in
153 : * addition to ExecProcNode() (via ExecProcNodeFirst()), to ensure the
154 : * stack isn't overrun while initializing the node tree.
155 : */
156 52356 : check_stack_depth();
157 :
158 52356 : switch (nodeTag(node))
159 : {
160 : /*
161 : * control nodes
162 : */
163 : case T_Result:
164 11846 : result = (PlanState *) ExecInitResult((Result *) node,
165 : estate, eflags);
166 11844 : break;
167 :
168 : case T_ProjectSet:
169 227 : result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
170 : estate, eflags);
171 227 : break;
172 :
173 : case T_ModifyTable:
174 4484 : result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
175 : estate, eflags);
176 4484 : break;
177 :
178 : case T_Append:
179 602 : result = (PlanState *) ExecInitAppend((Append *) node,
180 : estate, eflags);
181 602 : break;
182 :
183 : case T_MergeAppend:
184 34 : result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
185 : estate, eflags);
186 34 : break;
187 :
188 : case T_RecursiveUnion:
189 40 : result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
190 : estate, eflags);
191 40 : break;
192 :
193 : case T_BitmapAnd:
194 3 : result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
195 : estate, eflags);
196 3 : break;
197 :
198 : case T_BitmapOr:
199 17 : result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
200 : estate, eflags);
201 17 : break;
202 :
203 : /*
204 : * scan nodes
205 : */
206 : case T_SeqScan:
207 10154 : result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
208 : estate, eflags);
209 10152 : break;
210 :
211 : case T_SampleScan:
212 36 : result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
213 : estate, eflags);
214 36 : break;
215 :
216 : case T_IndexScan:
217 6377 : result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
218 : estate, eflags);
219 6377 : break;
220 :
221 : case T_IndexOnlyScan:
222 785 : result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
223 : estate, eflags);
224 785 : break;
225 :
226 : case T_BitmapIndexScan:
227 1657 : result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
228 : estate, eflags);
229 1657 : break;
230 :
231 : case T_BitmapHeapScan:
232 1632 : result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
233 : estate, eflags);
234 1632 : break;
235 :
236 : case T_TidScan:
237 74 : result = (PlanState *) ExecInitTidScan((TidScan *) node,
238 : estate, eflags);
239 74 : break;
240 :
241 : case T_SubqueryScan:
242 287 : result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
243 : estate, eflags);
244 287 : break;
245 :
246 : case T_FunctionScan:
247 1468 : result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
248 : estate, eflags);
249 1468 : break;
250 :
251 : case T_TableFuncScan:
252 22 : result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
253 : estate, eflags);
254 22 : break;
255 :
256 : case T_ValuesScan:
257 587 : result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
258 : estate, eflags);
259 587 : break;
260 :
261 : case T_CteScan:
262 162 : result = (PlanState *) ExecInitCteScan((CteScan *) node,
263 : estate, eflags);
264 162 : break;
265 :
266 : case T_NamedTuplestoreScan:
267 59 : result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node,
268 : estate, eflags);
269 59 : break;
270 :
271 : case T_WorkTableScan:
272 40 : result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
273 : estate, eflags);
274 40 : break;
275 :
276 : case T_ForeignScan:
277 0 : result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
278 : estate, eflags);
279 0 : break;
280 :
281 : case T_CustomScan:
282 0 : result = (PlanState *) ExecInitCustomScan((CustomScan *) node,
283 : estate, eflags);
284 0 : break;
285 :
286 : /*
287 : * join nodes
288 : */
289 : case T_NestLoop:
290 2225 : result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
291 : estate, eflags);
292 2225 : break;
293 :
294 : case T_MergeJoin:
295 168 : result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
296 : estate, eflags);
297 168 : break;
298 :
299 : case T_HashJoin:
300 1361 : result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
301 : estate, eflags);
302 1361 : break;
303 :
304 : /*
305 : * materialization nodes
306 : */
307 : case T_Material:
308 219 : result = (PlanState *) ExecInitMaterial((Material *) node,
309 : estate, eflags);
310 219 : break;
311 :
312 : case T_Sort:
313 2867 : result = (PlanState *) ExecInitSort((Sort *) node,
314 : estate, eflags);
315 2866 : break;
316 :
317 : case T_Group:
318 11 : result = (PlanState *) ExecInitGroup((Group *) node,
319 : estate, eflags);
320 11 : break;
321 :
322 : case T_Agg:
323 2664 : result = (PlanState *) ExecInitAgg((Agg *) node,
324 : estate, eflags);
325 2664 : break;
326 :
327 : case T_WindowAgg:
328 140 : result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
329 : estate, eflags);
330 140 : break;
331 :
332 : case T_Unique:
333 53 : result = (PlanState *) ExecInitUnique((Unique *) node,
334 : estate, eflags);
335 53 : break;
336 :
337 : case T_Gather:
338 26 : result = (PlanState *) ExecInitGather((Gather *) node,
339 : estate, eflags);
340 26 : break;
341 :
342 : case T_GatherMerge:
343 8 : result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
344 : estate, eflags);
345 8 : break;
346 :
347 : case T_Hash:
348 1361 : result = (PlanState *) ExecInitHash((Hash *) node,
349 : estate, eflags);
350 1361 : break;
351 :
352 : case T_SetOp:
353 37 : result = (PlanState *) ExecInitSetOp((SetOp *) node,
354 : estate, eflags);
355 37 : break;
356 :
357 : case T_LockRows:
358 363 : result = (PlanState *) ExecInitLockRows((LockRows *) node,
359 : estate, eflags);
360 363 : break;
361 :
362 : case T_Limit:
363 260 : result = (PlanState *) ExecInitLimit((Limit *) node,
364 : estate, eflags);
365 260 : break;
366 :
367 : default:
368 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
369 : result = NULL; /* keep compiler quiet */
370 : break;
371 : }
372 :
373 : /*
374 : * Add a wrapper around the ExecProcNode callback that checks stack depth
375 : * during the first execution.
376 : */
377 52351 : result->ExecProcNodeReal = result->ExecProcNode;
378 52351 : result->ExecProcNode = ExecProcNodeFirst;
379 :
380 : /*
381 : * Initialize any initPlans present in this node. The planner put them in
382 : * a separate list for us.
383 : */
384 52351 : subps = NIL;
385 54217 : foreach(l, node->initPlan)
386 : {
387 1866 : SubPlan *subplan = (SubPlan *) lfirst(l);
388 : SubPlanState *sstate;
389 :
390 1866 : Assert(IsA(subplan, SubPlan));
391 1866 : sstate = ExecInitSubPlan(subplan, result);
392 1866 : subps = lappend(subps, sstate);
393 : }
394 52351 : result->initPlan = subps;
395 :
396 : /* Set up instrumentation for this node if requested */
397 52351 : if (estate->es_instrument)
398 18 : result->instrument = InstrAlloc(1, estate->es_instrument);
399 :
400 52351 : return result;
401 : }
402 :
403 :
404 : /*
405 : * ExecProcNode wrapper that performs some one-time checks, before calling
406 : * the relevant node method (possibly via an instrumentation wrapper).
407 : */
408 : static TupleTableSlot *
409 43723 : ExecProcNodeFirst(PlanState *node)
410 : {
411 : /*
412 : * Perform stack depth check during the first execution of the node. We
413 : * only do so the first time round because it turns out to not be cheap on
414 : * some common architectures (eg. x86). This relies on the assumption
415 : * that ExecProcNode calls for a given plan node will always be made at
416 : * roughly the same stack depth.
417 : */
418 43723 : check_stack_depth();
419 :
420 : /*
421 : * If instrumentation is required, change the wrapper to one that just
422 : * does instrumentation. Otherwise we can dispense with all wrappers and
423 : * have ExecProcNode() directly call the relevant function from now on.
424 : */
425 43723 : if (node->instrument)
426 18 : node->ExecProcNode = ExecProcNodeInstr;
427 : else
428 43705 : node->ExecProcNode = node->ExecProcNodeReal;
429 :
430 43723 : return node->ExecProcNode(node);
431 : }
432 :
433 :
434 : /*
435 : * ExecProcNode wrapper that performs instrumentation calls. By keeping
436 : * this a separate function, we avoid overhead in the normal case where
437 : * no instrumentation is wanted.
438 : */
439 : static TupleTableSlot *
440 20043 : ExecProcNodeInstr(PlanState *node)
441 : {
442 : TupleTableSlot *result;
443 :
444 20043 : InstrStartNode(node->instrument);
445 :
446 20043 : result = node->ExecProcNodeReal(node);
447 :
448 20041 : InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
449 :
450 20041 : return result;
451 : }
452 :
453 :
454 : /* ----------------------------------------------------------------
455 : * MultiExecProcNode
456 : *
457 : * Execute a node that doesn't return individual tuples
458 : * (it might return a hashtable, bitmap, etc). Caller should
459 : * check it got back the expected kind of Node.
460 : *
461 : * This has essentially the same responsibilities as ExecProcNode,
462 : * but it does not do InstrStartNode/InstrStopNode (mainly because
463 : * it can't tell how many returned tuples to count). Each per-node
464 : * function must provide its own instrumentation support.
465 : * ----------------------------------------------------------------
466 : */
467 : Node *
468 2129 : MultiExecProcNode(PlanState *node)
469 : {
470 : Node *result;
471 :
472 2129 : check_stack_depth();
473 :
474 2129 : CHECK_FOR_INTERRUPTS();
475 :
476 2129 : if (node->chgParam != NULL) /* something changed */
477 233 : ExecReScan(node); /* let ReScan handle this */
478 :
479 2129 : switch (nodeTag(node))
480 : {
481 : /*
482 : * Only node types that actually support multiexec will be listed
483 : */
484 :
485 : case T_HashState:
486 1007 : result = MultiExecHash((HashState *) node);
487 1007 : break;
488 :
489 : case T_BitmapIndexScanState:
490 1113 : result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node);
491 1113 : break;
492 :
493 : case T_BitmapAndState:
494 2 : result = MultiExecBitmapAnd((BitmapAndState *) node);
495 2 : break;
496 :
497 : case T_BitmapOrState:
498 7 : result = MultiExecBitmapOr((BitmapOrState *) node);
499 7 : break;
500 :
501 : default:
502 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
503 : result = NULL;
504 : break;
505 : }
506 :
507 2129 : return result;
508 : }
509 :
510 :
511 : /* ----------------------------------------------------------------
512 : * ExecEndNode
513 : *
514 : * Recursively cleans up all the nodes in the plan rooted
515 : * at 'node'.
516 : *
517 : * After this operation, the query plan will not be able to be
518 : * processed any further. This should be called only after
519 : * the query plan has been fully executed.
520 : * ----------------------------------------------------------------
521 : */
522 : void
523 56888 : ExecEndNode(PlanState *node)
524 : {
525 : /*
526 : * do nothing when we get to the end of a leaf on tree.
527 : */
528 56888 : if (node == NULL)
529 65173 : return;
530 :
531 : /*
532 : * Make sure there's enough stack available. Need to check here, in
533 : * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not
534 : * guaranteed that ExecProcNode() is reached for all nodes.
535 : */
536 48603 : check_stack_depth();
537 :
538 48603 : if (node->chgParam != NULL)
539 : {
540 398 : bms_free(node->chgParam);
541 398 : node->chgParam = NULL;
542 : }
543 :
544 48603 : switch (nodeTag(node))
545 : {
546 : /*
547 : * control nodes
548 : */
549 : case T_ResultState:
550 8836 : ExecEndResult((ResultState *) node);
551 8836 : break;
552 :
553 : case T_ProjectSetState:
554 219 : ExecEndProjectSet((ProjectSetState *) node);
555 219 : break;
556 :
557 : case T_ModifyTableState:
558 4161 : ExecEndModifyTable((ModifyTableState *) node);
559 4161 : break;
560 :
561 : case T_AppendState:
562 591 : ExecEndAppend((AppendState *) node);
563 591 : break;
564 :
565 : case T_MergeAppendState:
566 34 : ExecEndMergeAppend((MergeAppendState *) node);
567 34 : break;
568 :
569 : case T_RecursiveUnionState:
570 40 : ExecEndRecursiveUnion((RecursiveUnionState *) node);
571 40 : break;
572 :
573 : case T_BitmapAndState:
574 3 : ExecEndBitmapAnd((BitmapAndState *) node);
575 3 : break;
576 :
577 : case T_BitmapOrState:
578 17 : ExecEndBitmapOr((BitmapOrState *) node);
579 17 : break;
580 :
581 : /*
582 : * scan nodes
583 : */
584 : case T_SeqScanState:
585 9973 : ExecEndSeqScan((SeqScanState *) node);
586 9973 : break;
587 :
588 : case T_SampleScanState:
589 30 : ExecEndSampleScan((SampleScanState *) node);
590 30 : break;
591 :
592 : case T_GatherState:
593 25 : ExecEndGather((GatherState *) node);
594 25 : break;
595 :
596 : case T_GatherMergeState:
597 8 : ExecEndGatherMerge((GatherMergeState *) node);
598 8 : break;
599 :
600 : case T_IndexScanState:
601 6339 : ExecEndIndexScan((IndexScanState *) node);
602 6339 : break;
603 :
604 : case T_IndexOnlyScanState:
605 777 : ExecEndIndexOnlyScan((IndexOnlyScanState *) node);
606 777 : break;
607 :
608 : case T_BitmapIndexScanState:
609 1653 : ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
610 1653 : break;
611 :
612 : case T_BitmapHeapScanState:
613 1628 : ExecEndBitmapHeapScan((BitmapHeapScanState *) node);
614 1628 : break;
615 :
616 : case T_TidScanState:
617 55 : ExecEndTidScan((TidScanState *) node);
618 55 : break;
619 :
620 : case T_SubqueryScanState:
621 287 : ExecEndSubqueryScan((SubqueryScanState *) node);
622 287 : break;
623 :
624 : case T_FunctionScanState:
625 1385 : ExecEndFunctionScan((FunctionScanState *) node);
626 1385 : break;
627 :
628 : case T_TableFuncScanState:
629 22 : ExecEndTableFuncScan((TableFuncScanState *) node);
630 22 : break;
631 :
632 : case T_ValuesScanState:
633 581 : ExecEndValuesScan((ValuesScanState *) node);
634 581 : break;
635 :
636 : case T_CteScanState:
637 159 : ExecEndCteScan((CteScanState *) node);
638 159 : break;
639 :
640 : case T_NamedTuplestoreScanState:
641 59 : ExecEndNamedTuplestoreScan((NamedTuplestoreScanState *) node);
642 59 : break;
643 :
644 : case T_WorkTableScanState:
645 40 : ExecEndWorkTableScan((WorkTableScanState *) node);
646 40 : break;
647 :
648 : case T_ForeignScanState:
649 0 : ExecEndForeignScan((ForeignScanState *) node);
650 0 : break;
651 :
652 : case T_CustomScanState:
653 0 : ExecEndCustomScan((CustomScanState *) node);
654 0 : break;
655 :
656 : /*
657 : * join nodes
658 : */
659 : case T_NestLoopState:
660 2221 : ExecEndNestLoop((NestLoopState *) node);
661 2221 : break;
662 :
663 : case T_MergeJoinState:
664 167 : ExecEndMergeJoin((MergeJoinState *) node);
665 167 : break;
666 :
667 : case T_HashJoinState:
668 1354 : ExecEndHashJoin((HashJoinState *) node);
669 1354 : break;
670 :
671 : /*
672 : * materialization nodes
673 : */
674 : case T_MaterialState:
675 215 : ExecEndMaterial((MaterialState *) node);
676 215 : break;
677 :
678 : case T_SortState:
679 2863 : ExecEndSort((SortState *) node);
680 2863 : break;
681 :
682 : case T_GroupState:
683 11 : ExecEndGroup((GroupState *) node);
684 11 : break;
685 :
686 : case T_AggState:
687 2655 : ExecEndAgg((AggState *) node);
688 2655 : break;
689 :
690 : case T_WindowAggState:
691 138 : ExecEndWindowAgg((WindowAggState *) node);
692 138 : break;
693 :
694 : case T_UniqueState:
695 53 : ExecEndUnique((UniqueState *) node);
696 53 : break;
697 :
698 : case T_HashState:
699 1354 : ExecEndHash((HashState *) node);
700 1354 : break;
701 :
702 : case T_SetOpState:
703 37 : ExecEndSetOp((SetOpState *) node);
704 37 : break;
705 :
706 : case T_LockRowsState:
707 359 : ExecEndLockRows((LockRowsState *) node);
708 359 : break;
709 :
710 : case T_LimitState:
711 254 : ExecEndLimit((LimitState *) node);
712 254 : break;
713 :
714 : default:
715 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
716 : break;
717 : }
718 : }
719 :
720 : /*
721 : * ExecShutdownNode
722 : *
723 : * Give execution nodes a chance to stop asynchronous resource consumption
724 : * and release any resources still held. Currently, this is only used for
725 : * parallel query, but we might want to extend it to other cases also (e.g.
726 : * FDW). We might also want to call it sooner, as soon as it's evident that
727 : * no more rows will be needed (e.g. when a Limit is filled) rather than only
728 : * at the end of ExecutorRun.
729 : */
730 : bool
731 45869 : ExecShutdownNode(PlanState *node)
732 : {
733 45869 : if (node == NULL)
734 0 : return false;
735 :
736 45869 : check_stack_depth();
737 :
738 45869 : planstate_tree_walker(node, ExecShutdownNode, NULL);
739 :
740 45869 : switch (nodeTag(node))
741 : {
742 : case T_GatherState:
743 12 : ExecShutdownGather((GatherState *) node);
744 12 : break;
745 : case T_ForeignScanState:
746 0 : ExecShutdownForeignScan((ForeignScanState *) node);
747 0 : break;
748 : case T_CustomScanState:
749 0 : ExecShutdownCustomScan((CustomScanState *) node);
750 0 : break;
751 : case T_GatherMergeState:
752 4 : ExecShutdownGatherMerge((GatherMergeState *) node);
753 4 : break;
754 : default:
755 45853 : break;
756 : }
757 :
758 45869 : return false;
759 : }
760 :
761 : /*
762 : * ExecSetTupleBound
763 : *
764 : * Set a tuple bound for a planstate node. This lets child plan nodes
765 : * optimize based on the knowledge that the maximum number of tuples that
766 : * their parent will demand is limited. The tuple bound for a node may
767 : * only be changed between scans (i.e., after node initialization or just
768 : * before an ExecReScan call).
769 : *
770 : * Any negative tuples_needed value means "no limit", which should be the
771 : * default assumption when this is not called at all for a particular node.
772 : *
773 : * Note: if this is called repeatedly on a plan tree, the exact same set
774 : * of nodes must be updated with the new limit each time; be careful that
775 : * only unchanging conditions are tested here.
776 : */
777 : void
778 456 : ExecSetTupleBound(int64 tuples_needed, PlanState *child_node)
779 : {
780 : /*
781 : * Since this function recurses, in principle we should check stack depth
782 : * here. In practice, it's probably pointless since the earlier node
783 : * initialization tree traversal would surely have consumed more stack.
784 : */
785 :
786 456 : if (IsA(child_node, SortState))
787 : {
788 : /*
789 : * If it is a Sort node, notify it that it can use bounded sort.
790 : *
791 : * Note: it is the responsibility of nodeSort.c to react properly to
792 : * changes of these parameters. If we ever redesign this, it'd be a
793 : * good idea to integrate this signaling with the parameter-change
794 : * mechanism.
795 : */
796 99 : SortState *sortState = (SortState *) child_node;
797 :
798 99 : if (tuples_needed < 0)
799 : {
800 : /* make sure flag gets reset if needed upon rescan */
801 2 : sortState->bounded = false;
802 : }
803 : else
804 : {
805 97 : sortState->bounded = true;
806 97 : sortState->bound = tuples_needed;
807 : }
808 : }
809 357 : else if (IsA(child_node, MergeAppendState))
810 : {
811 : /*
812 : * If it is a MergeAppend, we can apply the bound to any nodes that
813 : * are children of the MergeAppend, since the MergeAppend surely need
814 : * read no more than that many tuples from any one input.
815 : */
816 11 : MergeAppendState *maState = (MergeAppendState *) child_node;
817 : int i;
818 :
819 43 : for (i = 0; i < maState->ms_nplans; i++)
820 32 : ExecSetTupleBound(tuples_needed, maState->mergeplans[i]);
821 : }
822 346 : else if (IsA(child_node, ResultState))
823 : {
824 : /*
825 : * Similarly, for a projecting Result, we can apply the bound to its
826 : * child node.
827 : *
828 : * If Result supported qual checking, we'd have to punt on seeing a
829 : * qual. Note that having a resconstantqual is not a showstopper: if
830 : * that condition succeeds it affects nothing, while if it fails, no
831 : * rows will be demanded from the Result child anyway.
832 : */
833 53 : if (outerPlanState(child_node))
834 15 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
835 : }
836 293 : else if (IsA(child_node, SubqueryScanState))
837 : {
838 : /*
839 : * We can also descend through SubqueryScan, but only if it has no
840 : * qual (otherwise it might discard rows).
841 : */
842 2 : SubqueryScanState *subqueryState = (SubqueryScanState *) child_node;
843 :
844 2 : if (subqueryState->ss.ps.qual == NULL)
845 2 : ExecSetTupleBound(tuples_needed, subqueryState->subplan);
846 : }
847 291 : else if (IsA(child_node, GatherState))
848 : {
849 : /*
850 : * A Gather node can propagate the bound to its workers. As with
851 : * MergeAppend, no one worker could possibly need to return more
852 : * tuples than the Gather itself needs to.
853 : *
854 : * Note: As with Sort, the Gather node is responsible for reacting
855 : * properly to changes to this parameter.
856 : */
857 0 : GatherState *gstate = (GatherState *) child_node;
858 :
859 0 : gstate->tuples_needed = tuples_needed;
860 :
861 : /* Also pass down the bound to our own copy of the child plan */
862 0 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
863 : }
864 291 : else if (IsA(child_node, GatherMergeState))
865 : {
866 : /* Same comments as for Gather */
867 2 : GatherMergeState *gstate = (GatherMergeState *) child_node;
868 :
869 2 : gstate->tuples_needed = tuples_needed;
870 :
871 2 : ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
872 : }
873 :
874 : /*
875 : * In principle we could descend through any plan node type that is
876 : * certain not to discard or combine input rows; but on seeing a node that
877 : * can do that, we can't propagate the bound any further. For the moment
878 : * it's unclear that any other cases are worth checking here.
879 : */
880 456 : }
|