LCOV - code coverage report
Current view: top level - src/backend/executor - execProcnode.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 94.7 % 380 360
Test Date: 2026-03-19 11:15:59 Functions: 100.0 % 9 9
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.0-1