LCOV - code coverage report
Current view: top level - src/backend/executor - execProcnode.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 91.9 % 358 329
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 9 9
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 84.3 % 172 145

             Branch data     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/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 *
     142                 :      956305 : ExecInitNode(Plan *node, EState *estate, int eflags)
     143                 :             : {
     144                 :      956305 :         PlanState  *result;
     145                 :      956305 :         List       *subps;
     146                 :      956305 :         ListCell   *l;
     147                 :             : 
     148                 :             :         /*
     149                 :             :          * do nothing when we get to the end of a leaf on tree.
     150                 :             :          */
     151         [ +  + ]:      956305 :         if (node == NULL)
     152                 :       23000 :                 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                 :             :          */
     159                 :      933305 :         check_stack_depth();
     160                 :             : 
     161   [ +  -  +  +  :      933305 :         switch (nodeTag(node))
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  -  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  - ]
     162                 :             :         {
     163                 :             :                         /*
     164                 :             :                          * control nodes
     165                 :             :                          */
     166                 :             :                 case T_Result:
     167                 :       49236 :                         result = (PlanState *) ExecInitResult((Result *) node,
     168                 :       24618 :                                                                                                   estate, eflags);
     169                 :       24618 :                         break;
     170                 :             : 
     171                 :             :                 case T_ProjectSet:
     172                 :        4002 :                         result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
     173                 :        2001 :                                                                                                           estate, eflags);
     174                 :        2001 :                         break;
     175                 :             : 
     176                 :             :                 case T_ModifyTable:
     177                 :       20314 :                         result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
     178                 :       10157 :                                                                                                            estate, eflags);
     179                 :       10157 :                         break;
     180                 :             : 
     181                 :             :                 case T_Append:
     182                 :        5154 :                         result = (PlanState *) ExecInitAppend((Append *) node,
     183                 :        2577 :                                                                                                   estate, eflags);
     184                 :        2577 :                         break;
     185                 :             : 
     186                 :             :                 case T_MergeAppend:
     187                 :         192 :                         result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
     188                 :          96 :                                                                                                            estate, eflags);
     189                 :          96 :                         break;
     190                 :             : 
     191                 :             :                 case T_RecursiveUnion:
     192                 :         146 :                         result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
     193                 :          73 :                                                                                                                   estate, eflags);
     194                 :          73 :                         break;
     195                 :             : 
     196                 :             :                 case T_BitmapAnd:
     197                 :          34 :                         result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
     198                 :          17 :                                                                                                          estate, eflags);
     199                 :          17 :                         break;
     200                 :             : 
     201                 :             :                 case T_BitmapOr:
     202                 :          66 :                         result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
     203                 :          33 :                                                                                                         estate, eflags);
     204                 :          33 :                         break;
     205                 :             : 
     206                 :             :                         /*
     207                 :             :                          * scan nodes
     208                 :             :                          */
     209                 :             :                 case T_SeqScan:
     210                 :      656114 :                         result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
     211                 :      328057 :                                                                                                    estate, eflags);
     212                 :      328057 :                         break;
     213                 :             : 
     214                 :             :                 case T_SampleScan:
     215                 :          90 :                         result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
     216                 :          45 :                                                                                                           estate, eflags);
     217                 :          45 :                         break;
     218                 :             : 
     219                 :             :                 case T_IndexScan:
     220                 :      226308 :                         result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
     221                 :      113154 :                                                                                                          estate, eflags);
     222                 :      113154 :                         break;
     223                 :             : 
     224                 :             :                 case T_IndexOnlyScan:
     225                 :        3930 :                         result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
     226                 :        1965 :                                                                                                                  estate, eflags);
     227                 :        1965 :                         break;
     228                 :             : 
     229                 :             :                 case T_BitmapIndexScan:
     230                 :        5540 :                         result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
     231                 :        2770 :                                                                                                                    estate, eflags);
     232                 :        2770 :                         break;
     233                 :             : 
     234                 :             :                 case T_BitmapHeapScan:
     235                 :        5438 :                         result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
     236                 :        2719 :                                                                                                                   estate, eflags);
     237                 :        2719 :                         break;
     238                 :             : 
     239                 :             :                 case T_TidScan:
     240                 :         190 :                         result = (PlanState *) ExecInitTidScan((TidScan *) node,
     241                 :          95 :                                                                                                    estate, eflags);
     242                 :          95 :                         break;
     243                 :             : 
     244                 :             :                 case T_TidRangeScan:
     245                 :         700 :                         result = (PlanState *) ExecInitTidRangeScan((TidRangeScan *) node,
     246                 :         350 :                                                                                                                 estate, eflags);
     247                 :         350 :                         break;
     248                 :             : 
     249                 :             :                 case T_SubqueryScan:
     250                 :        3028 :                         result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
     251                 :        1514 :                                                                                                                 estate, eflags);
     252                 :        1514 :                         break;
     253                 :             : 
     254                 :             :                 case T_FunctionScan:
     255                 :       11148 :                         result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
     256                 :        5574 :                                                                                                                 estate, eflags);
     257                 :        5574 :                         break;
     258                 :             : 
     259                 :             :                 case T_TableFuncScan:
     260                 :         206 :                         result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
     261                 :         103 :                                                                                                                  estate, eflags);
     262                 :         103 :                         break;
     263                 :             : 
     264                 :             :                 case T_ValuesScan:
     265                 :        2500 :                         result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
     266                 :        1250 :                                                                                                           estate, eflags);
     267                 :        1250 :                         break;
     268                 :             : 
     269                 :             :                 case T_CteScan:
     270                 :         424 :                         result = (PlanState *) ExecInitCteScan((CteScan *) node,
     271                 :         212 :                                                                                                    estate, eflags);
     272                 :         212 :                         break;
     273                 :             : 
     274                 :             :                 case T_NamedTuplestoreScan:
     275                 :         226 :                         result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node,
     276                 :         113 :                                                                                                                            estate, eflags);
     277                 :         113 :                         break;
     278                 :             : 
     279                 :             :                 case T_WorkTableScan:
     280                 :         146 :                         result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
     281                 :          73 :                                                                                                                  estate, eflags);
     282                 :          73 :                         break;
     283                 :             : 
     284                 :             :                 case T_ForeignScan:
     285                 :           0 :                         result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
     286                 :           0 :                                                                                                            estate, eflags);
     287                 :           0 :                         break;
     288                 :             : 
     289                 :             :                 case T_CustomScan:
     290                 :           0 :                         result = (PlanState *) ExecInitCustomScan((CustomScan *) node,
     291                 :           0 :                                                                                                           estate, eflags);
     292                 :           0 :                         break;
     293                 :             : 
     294                 :             :                         /*
     295                 :             :                          * join nodes
     296                 :             :                          */
     297                 :             :                 case T_NestLoop:
     298                 :       18308 :                         result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
     299                 :        9154 :                                                                                                         estate, eflags);
     300                 :        9154 :                         break;
     301                 :             : 
     302                 :             :                 case T_MergeJoin:
     303                 :         964 :                         result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
     304                 :         482 :                                                                                                          estate, eflags);
     305                 :         482 :                         break;
     306                 :             : 
     307                 :             :                 case T_HashJoin:
     308                 :        6856 :                         result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
     309                 :        3428 :                                                                                                         estate, eflags);
     310                 :        3428 :                         break;
     311                 :             : 
     312                 :             :                         /*
     313                 :             :                          * materialization nodes
     314                 :             :                          */
     315                 :             :                 case T_Material:
     316                 :        1064 :                         result = (PlanState *) ExecInitMaterial((Material *) node,
     317                 :         532 :                                                                                                         estate, eflags);
     318                 :         532 :                         break;
     319                 :             : 
     320                 :             :                 case T_Sort:
     321                 :       18912 :                         result = (PlanState *) ExecInitSort((Sort *) node,
     322                 :        9456 :                                                                                                 estate, eflags);
     323                 :        9456 :                         break;
     324                 :             : 
     325                 :             :                 case T_IncrementalSort:
     326                 :         238 :                         result = (PlanState *) ExecInitIncrementalSort((IncrementalSort *) node,
     327                 :         119 :                                                                                                                    estate, eflags);
     328                 :         119 :                         break;
     329                 :             : 
     330                 :             :                 case T_Memoize:
     331                 :         434 :                         result = (PlanState *) ExecInitMemoize((Memoize *) node, estate,
     332                 :         217 :                                                                                                    eflags);
     333                 :         217 :                         break;
     334                 :             : 
     335                 :             :                 case T_Group:
     336                 :          78 :                         result = (PlanState *) ExecInitGroup((Group *) node,
     337                 :          39 :                                                                                                  estate, eflags);
     338                 :          39 :                         break;
     339                 :             : 
     340                 :             :                 case T_Agg:
     341                 :       11996 :                         result = (PlanState *) ExecInitAgg((Agg *) node,
     342                 :        5998 :                                                                                            estate, eflags);
     343                 :        5998 :                         break;
     344                 :             : 
     345                 :             :                 case T_WindowAgg:
     346                 :         914 :                         result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
     347                 :         457 :                                                                                                          estate, eflags);
     348                 :         457 :                         break;
     349                 :             : 
     350                 :             :                 case T_Unique:
     351                 :        1424 :                         result = (PlanState *) ExecInitUnique((Unique *) node,
     352                 :         712 :                                                                                                   estate, eflags);
     353                 :         712 :                         break;
     354                 :             : 
     355                 :             :                 case T_Gather:
     356                 :         386 :                         result = (PlanState *) ExecInitGather((Gather *) node,
     357                 :         193 :                                                                                                   estate, eflags);
     358                 :         193 :                         break;
     359                 :             : 
     360                 :             :                 case T_GatherMerge:
     361                 :         134 :                         result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
     362                 :          67 :                                                                                                            estate, eflags);
     363                 :          67 :                         break;
     364                 :             : 
     365                 :             :                 case T_Hash:
     366                 :        6856 :                         result = (PlanState *) ExecInitHash((Hash *) node,
     367                 :        3428 :                                                                                                 estate, eflags);
     368                 :        3428 :                         break;
     369                 :             : 
     370                 :             :                 case T_SetOp:
     371                 :         220 :                         result = (PlanState *) ExecInitSetOp((SetOp *) node,
     372                 :         110 :                                                                                                  estate, eflags);
     373                 :         110 :                         break;
     374                 :             : 
     375                 :             :                 case T_LockRows:
     376                 :      801664 :                         result = (PlanState *) ExecInitLockRows((LockRows *) node,
     377                 :      400832 :                                                                                                         estate, eflags);
     378                 :      400832 :                         break;
     379                 :             : 
     380                 :             :                 case T_Limit:
     381                 :        1030 :                         result = (PlanState *) ExecInitLimit((Limit *) node,
     382                 :         515 :                                                                                                  estate, eflags);
     383                 :         515 :                         break;
     384                 :             : 
     385                 :             :                 default:
     386   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
     387                 :           0 :                         result = NULL;          /* keep compiler quiet */
     388                 :           0 :                         break;
     389                 :             :         }
     390                 :             : 
     391                 :      933305 :         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                 :             :          */
     401                 :      933305 :         subps = NIL;
     402   [ +  +  +  +  :      934397 :         foreach(l, node->initPlan)
                   +  + ]
     403                 :             :         {
     404                 :        1092 :                 SubPlan    *subplan = (SubPlan *) lfirst(l);
     405                 :        1092 :                 SubPlanState *sstate;
     406                 :             : 
     407         [ +  - ]:        1092 :                 Assert(IsA(subplan, SubPlan));
     408         [ +  - ]:        1092 :                 Assert(subplan->args == NIL);
     409                 :        1092 :                 sstate = ExecInitSubPlan(subplan, result);
     410                 :        1092 :                 subps = lappend(subps, sstate);
     411                 :        1092 :         }
     412                 :      933305 :         result->initPlan = subps;
     413                 :             : 
     414                 :             :         /* Set up instrumentation for this node if requested */
     415         [ +  + ]:      933305 :         if (estate->es_instrument)
     416                 :        3420 :                 result->instrument = InstrAlloc(1, estate->es_instrument,
     417                 :        1710 :                                                                                 result->async_capable);
     418                 :             : 
     419                 :      933305 :         return result;
     420                 :      956305 : }
     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
     430                 :      933319 : 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                 :      933319 :         node->ExecProcNodeReal = function;
     439                 :      933319 :         node->ExecProcNode = ExecProcNodeFirst;
     440                 :      933319 : }
     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 *
     448                 :      907074 : 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                 :      907074 :         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                 :             :          */
     464         [ +  + ]:      907074 :         if (node->instrument)
     465                 :        1322 :                 node->ExecProcNode = ExecProcNodeInstr;
     466                 :             :         else
     467                 :      905752 :                 node->ExecProcNode = node->ExecProcNodeReal;
     468                 :             : 
     469                 :      907074 :         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                 :     2251945 : ExecProcNodeInstr(PlanState *node)
     480                 :             : {
     481                 :     2251945 :         TupleTableSlot *result;
     482                 :             : 
     483                 :     2251945 :         InstrStartNode(node->instrument);
     484                 :             : 
     485                 :     2251945 :         result = node->ExecProcNodeReal(node);
     486                 :             : 
     487         [ +  + ]:     2251945 :         InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
     488                 :             : 
     489                 :     4503890 :         return result;
     490                 :     2251945 : }
     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 *
     507                 :        3907 : MultiExecProcNode(PlanState *node)
     508                 :             : {
     509                 :        3907 :         Node       *result;
     510                 :             : 
     511                 :        3907 :         check_stack_depth();
     512                 :             : 
     513         [ +  - ]:        3907 :         CHECK_FOR_INTERRUPTS();
     514                 :             : 
     515         [ +  + ]:        3907 :         if (node->chgParam != NULL) /* something changed */
     516                 :         266 :                 ExecReScan(node);               /* let ReScan handle this */
     517                 :             : 
     518   [ +  +  +  +  :        3907 :         switch (nodeTag(node))
                      - ]
     519                 :             :         {
     520                 :             :                         /*
     521                 :             :                          * Only node types that actually support multiexec will be listed
     522                 :             :                          */
     523                 :             : 
     524                 :             :                 case T_HashState:
     525                 :        1905 :                         result = MultiExecHash((HashState *) node);
     526                 :        1905 :                         break;
     527                 :             : 
     528                 :             :                 case T_BitmapIndexScanState:
     529                 :        1984 :                         result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node);
     530                 :        1984 :                         break;
     531                 :             : 
     532                 :             :                 case T_BitmapAndState:
     533                 :           9 :                         result = MultiExecBitmapAnd((BitmapAndState *) node);
     534                 :           9 :                         break;
     535                 :             : 
     536                 :             :                 case T_BitmapOrState:
     537                 :           9 :                         result = MultiExecBitmapOr((BitmapOrState *) node);
     538                 :           9 :                         break;
     539                 :             : 
     540                 :             :                 default:
     541   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
     542                 :           0 :                         result = NULL;
     543                 :           0 :                         break;
     544                 :             :         }
     545                 :             : 
     546                 :        7814 :         return result;
     547                 :        3907 : }
     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
     562                 :      943355 : ExecEndNode(PlanState *node)
     563                 :             : {
     564                 :             :         /*
     565                 :             :          * do nothing when we get to the end of a leaf on tree.
     566                 :             :          */
     567         [ +  + ]:      943355 :         if (node == NULL)
     568                 :       17911 :                 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                 :             :          */
     575                 :      925444 :         check_stack_depth();
     576                 :             : 
     577         [ +  + ]:      925444 :         if (node->chgParam != NULL)
     578                 :             :         {
     579                 :        1201 :                 bms_free(node->chgParam);
     580                 :        1201 :                 node->chgParam = NULL;
     581                 :        1201 :         }
     582                 :             : 
     583   [ +  +  +  +  :      925444 :         switch (nodeTag(node))
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  -  -  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                   +  - ]
     584                 :             :         {
     585                 :             :                         /*
     586                 :             :                          * control nodes
     587                 :             :                          */
     588                 :             :                 case T_ResultState:
     589                 :       19535 :                         ExecEndResult((ResultState *) node);
     590                 :       19535 :                         break;
     591                 :             : 
     592                 :             :                 case T_ProjectSetState:
     593                 :        1762 :                         ExecEndProjectSet((ProjectSetState *) node);
     594                 :        1762 :                         break;
     595                 :             : 
     596                 :             :                 case T_ModifyTableState:
     597                 :        9478 :                         ExecEndModifyTable((ModifyTableState *) node);
     598                 :        9478 :                         break;
     599                 :             : 
     600                 :             :                 case T_AppendState:
     601                 :        2534 :                         ExecEndAppend((AppendState *) node);
     602                 :        2534 :                         break;
     603                 :             : 
     604                 :             :                 case T_MergeAppendState:
     605                 :          96 :                         ExecEndMergeAppend((MergeAppendState *) node);
     606                 :          96 :                         break;
     607                 :             : 
     608                 :             :                 case T_RecursiveUnionState:
     609                 :          73 :                         ExecEndRecursiveUnion((RecursiveUnionState *) node);
     610                 :          73 :                         break;
     611                 :             : 
     612                 :             :                 case T_BitmapAndState:
     613                 :          17 :                         ExecEndBitmapAnd((BitmapAndState *) node);
     614                 :          17 :                         break;
     615                 :             : 
     616                 :             :                 case T_BitmapOrState:
     617                 :          33 :                         ExecEndBitmapOr((BitmapOrState *) node);
     618                 :          33 :                         break;
     619                 :             : 
     620                 :             :                         /*
     621                 :             :                          * scan nodes
     622                 :             :                          */
     623                 :             :                 case T_SeqScanState:
     624                 :      327668 :                         ExecEndSeqScan((SeqScanState *) node);
     625                 :      327668 :                         break;
     626                 :             : 
     627                 :             :                 case T_SampleScanState:
     628                 :          39 :                         ExecEndSampleScan((SampleScanState *) node);
     629                 :          39 :                         break;
     630                 :             : 
     631                 :             :                 case T_GatherState:
     632                 :         191 :                         ExecEndGather((GatherState *) node);
     633                 :         191 :                         break;
     634                 :             : 
     635                 :             :                 case T_GatherMergeState:
     636                 :          67 :                         ExecEndGatherMerge((GatherMergeState *) node);
     637                 :          67 :                         break;
     638                 :             : 
     639                 :             :                 case T_IndexScanState:
     640                 :      113071 :                         ExecEndIndexScan((IndexScanState *) node);
     641                 :      113071 :                         break;
     642                 :             : 
     643                 :             :                 case T_IndexOnlyScanState:
     644                 :        1957 :                         ExecEndIndexOnlyScan((IndexOnlyScanState *) node);
     645                 :        1957 :                         break;
     646                 :             : 
     647                 :             :                 case T_BitmapIndexScanState:
     648                 :        2754 :                         ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
     649                 :        2754 :                         break;
     650                 :             : 
     651                 :             :                 case T_BitmapHeapScanState:
     652                 :        2703 :                         ExecEndBitmapHeapScan((BitmapHeapScanState *) node);
     653                 :        2703 :                         break;
     654                 :             : 
     655                 :             :                 case T_TidScanState:
     656                 :          75 :                         ExecEndTidScan((TidScanState *) node);
     657                 :          75 :                         break;
     658                 :             : 
     659                 :             :                 case T_TidRangeScanState:
     660                 :          61 :                         ExecEndTidRangeScan((TidRangeScanState *) node);
     661                 :          61 :                         break;
     662                 :             : 
     663                 :             :                 case T_SubqueryScanState:
     664                 :        1514 :                         ExecEndSubqueryScan((SubqueryScanState *) node);
     665                 :        1514 :                         break;
     666                 :             : 
     667                 :             :                 case T_FunctionScanState:
     668                 :        4790 :                         ExecEndFunctionScan((FunctionScanState *) node);
     669                 :        4790 :                         break;
     670                 :             : 
     671                 :             :                 case T_TableFuncScanState:
     672                 :          84 :                         ExecEndTableFuncScan((TableFuncScanState *) node);
     673                 :          84 :                         break;
     674                 :             : 
     675                 :             :                 case T_CteScanState:
     676                 :         209 :                         ExecEndCteScan((CteScanState *) node);
     677                 :         209 :                         break;
     678                 :             : 
     679                 :             :                 case T_ForeignScanState:
     680                 :           0 :                         ExecEndForeignScan((ForeignScanState *) node);
     681                 :           0 :                         break;
     682                 :             : 
     683                 :             :                 case T_CustomScanState:
     684                 :           0 :                         ExecEndCustomScan((CustomScanState *) node);
     685                 :           0 :                         break;
     686                 :             : 
     687                 :             :                         /*
     688                 :             :                          * join nodes
     689                 :             :                          */
     690                 :             :                 case T_NestLoopState:
     691                 :        9136 :                         ExecEndNestLoop((NestLoopState *) node);
     692                 :        9136 :                         break;
     693                 :             : 
     694                 :             :                 case T_MergeJoinState:
     695                 :         481 :                         ExecEndMergeJoin((MergeJoinState *) node);
     696                 :         481 :                         break;
     697                 :             : 
     698                 :             :                 case T_HashJoinState:
     699                 :        3412 :                         ExecEndHashJoin((HashJoinState *) node);
     700                 :        3412 :                         break;
     701                 :             : 
     702                 :             :                         /*
     703                 :             :                          * materialization nodes
     704                 :             :                          */
     705                 :             :                 case T_MaterialState:
     706                 :         524 :                         ExecEndMaterial((MaterialState *) node);
     707                 :         524 :                         break;
     708                 :             : 
     709                 :             :                 case T_SortState:
     710                 :        9429 :                         ExecEndSort((SortState *) node);
     711                 :        9429 :                         break;
     712                 :             : 
     713                 :             :                 case T_IncrementalSortState:
     714                 :         119 :                         ExecEndIncrementalSort((IncrementalSortState *) node);
     715                 :         119 :                         break;
     716                 :             : 
     717                 :             :                 case T_MemoizeState:
     718                 :         217 :                         ExecEndMemoize((MemoizeState *) node);
     719                 :         217 :                         break;
     720                 :             : 
     721                 :             :                 case T_GroupState:
     722                 :          39 :                         ExecEndGroup((GroupState *) node);
     723                 :          39 :                         break;
     724                 :             : 
     725                 :             :                 case T_AggState:
     726                 :        5978 :                         ExecEndAgg((AggState *) node);
     727                 :        5978 :                         break;
     728                 :             : 
     729                 :             :                 case T_WindowAggState:
     730                 :         423 :                         ExecEndWindowAgg((WindowAggState *) node);
     731                 :         423 :                         break;
     732                 :             : 
     733                 :             :                 case T_UniqueState:
     734                 :         712 :                         ExecEndUnique((UniqueState *) node);
     735                 :         712 :                         break;
     736                 :             : 
     737                 :             :                 case T_HashState:
     738                 :        3412 :                         ExecEndHash((HashState *) node);
     739                 :        3412 :                         break;
     740                 :             : 
     741                 :             :                 case T_SetOpState:
     742                 :         110 :                         ExecEndSetOp((SetOpState *) node);
     743                 :         110 :                         break;
     744                 :             : 
     745                 :             :                 case T_LockRowsState:
     746                 :      400828 :                         ExecEndLockRows((LockRowsState *) node);
     747                 :      400828 :                         break;
     748                 :             : 
     749                 :             :                 case T_LimitState:
     750                 :         506 :                         ExecEndLimit((LimitState *) node);
     751                 :         506 :                         break;
     752                 :             : 
     753                 :             :                         /* No clean up actions for these nodes. */
     754                 :             :                 case T_ValuesScanState:
     755                 :             :                 case T_NamedTuplestoreScanState:
     756                 :             :                 case T_WorkTableScanState:
     757                 :        1407 :                         break;
     758                 :             : 
     759                 :             :                 default:
     760   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
     761                 :           0 :                         break;
     762                 :             :         }
     763                 :      943355 : }
     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
     772                 :      445621 : ExecShutdownNode(PlanState *node)
     773                 :             : {
     774                 :      445621 :         (void) ExecShutdownNode_walker(node, NULL);
     775                 :      445621 : }
     776                 :             : 
     777                 :             : static bool
     778                 :      915738 : ExecShutdownNode_walker(PlanState *node, void *context)
     779                 :             : {
     780         [ +  - ]:      915738 :         if (node == NULL)
     781                 :           0 :                 return false;
     782                 :             : 
     783                 :      915738 :         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                 :             :          */
     795   [ +  +  +  + ]:      915738 :         if (node->instrument && node->instrument->running)
     796                 :        1449 :                 InstrStartNode(node->instrument);
     797                 :             : 
     798                 :      915738 :         planstate_tree_walker(node, ExecShutdownNode_walker, context);
     799                 :             : 
     800   [ +  -  -  +  :      915738 :         switch (nodeTag(node))
                +  +  + ]
     801                 :             :         {
     802                 :             :                 case T_GatherState:
     803                 :         105 :                         ExecShutdownGather((GatherState *) node);
     804                 :         105 :                         break;
     805                 :             :                 case T_ForeignScanState:
     806                 :           0 :                         ExecShutdownForeignScan((ForeignScanState *) node);
     807                 :           0 :                         break;
     808                 :             :                 case T_CustomScanState:
     809                 :           0 :                         ExecShutdownCustomScan((CustomScanState *) node);
     810                 :           0 :                         break;
     811                 :             :                 case T_GatherMergeState:
     812                 :          23 :                         ExecShutdownGatherMerge((GatherMergeState *) node);
     813                 :          23 :                         break;
     814                 :             :                 case T_HashState:
     815                 :        2809 :                         ExecShutdownHash((HashState *) node);
     816                 :        2809 :                         break;
     817                 :             :                 case T_HashJoinState:
     818                 :        2809 :                         ExecShutdownHashJoin((HashJoinState *) node);
     819                 :        2809 :                         break;
     820                 :             :                 default:
     821                 :      909992 :                         break;
     822                 :             :         }
     823                 :             : 
     824                 :             :         /* Stop the node if we started it above, reporting 0 tuples. */
     825   [ +  +  +  + ]:      915738 :         if (node->instrument && node->instrument->running)
     826                 :        1449 :                 InstrStopNode(node->instrument, 0);
     827                 :             : 
     828                 :      915738 :         return false;
     829                 :      915738 : }
     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
     848                 :       10982 : 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         [ +  + ]:       10982 :         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                 :         170 :                 SortState  *sortState = (SortState *) child_node;
     867                 :             : 
     868         [ +  + ]:         170 :                 if (tuples_needed < 0)
     869                 :             :                 {
     870                 :             :                         /* make sure flag gets reset if needed upon rescan */
     871                 :          50 :                         sortState->bounded = false;
     872                 :          50 :                 }
     873                 :             :                 else
     874                 :             :                 {
     875                 :         120 :                         sortState->bounded = true;
     876                 :         120 :                         sortState->bound = tuples_needed;
     877                 :             :                 }
     878                 :         170 :         }
     879         [ +  + ]:       10812 :         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                 :          24 :                 IncrementalSortState *sortState = (IncrementalSortState *) child_node;
     891                 :             : 
     892         [ -  + ]:          24 :                 if (tuples_needed < 0)
     893                 :             :                 {
     894                 :             :                         /* make sure flag gets reset if needed upon rescan */
     895                 :           0 :                         sortState->bounded = false;
     896                 :           0 :                 }
     897                 :             :                 else
     898                 :             :                 {
     899                 :          24 :                         sortState->bounded = true;
     900                 :          24 :                         sortState->bound = tuples_needed;
     901                 :             :                 }
     902                 :          24 :         }
     903         [ +  + ]:       10788 :         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                 :          21 :                 AppendState *aState = (AppendState *) child_node;
     911                 :          21 :                 int                     i;
     912                 :             : 
     913         [ +  + ]:          67 :                 for (i = 0; i < aState->as_nplans; i++)
     914                 :          46 :                         ExecSetTupleBound(tuples_needed, aState->appendplans[i]);
     915                 :          21 :         }
     916         [ +  + ]:       10767 :         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                 :          11 :                 MergeAppendState *maState = (MergeAppendState *) child_node;
     924                 :          11 :                 int                     i;
     925                 :             : 
     926         [ +  + ]:          44 :                 for (i = 0; i < maState->ms_nplans; i++)
     927                 :          33 :                         ExecSetTupleBound(tuples_needed, maState->mergeplans[i]);
     928                 :          11 :         }
     929         [ +  + ]:       10756 :         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         [ +  + ]:         101 :                 if (outerPlanState(child_node))
     941                 :          18 :                         ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
     942                 :         101 :         }
     943         [ +  + ]:       10655 :         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                 :           5 :                 SubqueryScanState *subqueryState = (SubqueryScanState *) child_node;
     950                 :             : 
     951         [ +  + ]:           5 :                 if (subqueryState->ss.ps.qual == NULL)
     952                 :           2 :                         ExecSetTupleBound(tuples_needed, subqueryState->subplan);
     953                 :           5 :         }
     954         [ -  + ]:       10650 :         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                 :             :                  */
     964                 :           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                 :           0 :         }
     971         [ +  + ]:       10650 :         else if (IsA(child_node, GatherMergeState))
     972                 :             :         {
     973                 :             :                 /* Same comments as for Gather */
     974                 :           5 :                 GatherMergeState *gstate = (GatherMergeState *) child_node;
     975                 :             : 
     976                 :           5 :                 gstate->tuples_needed = tuples_needed;
     977                 :             : 
     978                 :           5 :                 ExecSetTupleBound(tuples_needed, outerPlanState(child_node));
     979                 :           5 :         }
     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                 :       10982 : }
        

Generated by: LCOV version 2.3.2-1