LCOV - code coverage report
Current view: top level - src/backend/executor - nodeResult.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 82.6 % 69 57
Test Date: 2026-01-26 10:56:24 Functions: 66.7 % 6 4
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 57.9 % 38 22

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * nodeResult.c
       4                 :             :  *        support for constant nodes needing special code.
       5                 :             :  *
       6                 :             :  * DESCRIPTION
       7                 :             :  *
       8                 :             :  *              Result nodes are used in queries where no relations are scanned.
       9                 :             :  *              Examples of such queries are:
      10                 :             :  *
      11                 :             :  *                              select 1 * 2
      12                 :             :  *
      13                 :             :  *                              insert into emp values ('mike', 15000)
      14                 :             :  *
      15                 :             :  *              (Remember that in an INSERT or UPDATE, we need a plan tree that
      16                 :             :  *              generates the new rows.)
      17                 :             :  *
      18                 :             :  *              Result nodes are also used to optimise queries with constant
      19                 :             :  *              qualifications (ie, quals that do not depend on the scanned data),
      20                 :             :  *              such as:
      21                 :             :  *
      22                 :             :  *                              select * from emp where 2 > 1
      23                 :             :  *
      24                 :             :  *              In this case, the plan generated is
      25                 :             :  *
      26                 :             :  *                                              Result  (with 2 > 1 qual)
      27                 :             :  *                                              /
      28                 :             :  *                                 SeqScan (emp.*)
      29                 :             :  *
      30                 :             :  *              At runtime, the Result node evaluates the constant qual once,
      31                 :             :  *              which is shown by EXPLAIN as a One-Time Filter.  If it's
      32                 :             :  *              false, we can return an empty result set without running the
      33                 :             :  *              controlled plan at all.  If it's true, we run the controlled
      34                 :             :  *              plan normally and pass back the results.
      35                 :             :  *
      36                 :             :  *
      37                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      38                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      39                 :             :  *
      40                 :             :  * IDENTIFICATION
      41                 :             :  *        src/backend/executor/nodeResult.c
      42                 :             :  *
      43                 :             :  *-------------------------------------------------------------------------
      44                 :             :  */
      45                 :             : 
      46                 :             : #include "postgres.h"
      47                 :             : 
      48                 :             : #include "executor/executor.h"
      49                 :             : #include "executor/nodeResult.h"
      50                 :             : #include "miscadmin.h"
      51                 :             : 
      52                 :             : 
      53                 :             : /* ----------------------------------------------------------------
      54                 :             :  *              ExecResult(node)
      55                 :             :  *
      56                 :             :  *              returns the tuples from the outer plan which satisfy the
      57                 :             :  *              qualification clause.  Since result nodes with right
      58                 :             :  *              subtrees are never planned, we ignore the right subtree
      59                 :             :  *              entirely (for now).. -cim 10/7/89
      60                 :             :  *
      61                 :             :  *              The qualification containing only constant clauses are
      62                 :             :  *              checked first before any processing is done. It always returns
      63                 :             :  *              'nil' if the constant qualification is not satisfied.
      64                 :             :  * ----------------------------------------------------------------
      65                 :             :  */
      66                 :             : static TupleTableSlot *
      67                 :       91366 : ExecResult(PlanState *pstate)
      68                 :             : {
      69                 :       91366 :         ResultState *node = castNode(ResultState, pstate);
      70                 :       91366 :         TupleTableSlot *outerTupleSlot;
      71                 :       91366 :         PlanState  *outerPlan;
      72                 :       91366 :         ExprContext *econtext;
      73                 :             : 
      74         [ +  + ]:       91366 :         CHECK_FOR_INTERRUPTS();
      75                 :             : 
      76                 :       91366 :         econtext = node->ps.ps_ExprContext;
      77                 :             : 
      78                 :             :         /*
      79                 :             :          * check constant qualifications like (2 > 1), if not already done
      80                 :             :          */
      81         [ +  + ]:       91366 :         if (node->rs_checkqual)
      82                 :             :         {
      83                 :        2704 :                 bool            qualResult = ExecQual(node->resconstantqual, econtext);
      84                 :             : 
      85                 :        2704 :                 node->rs_checkqual = false;
      86         [ +  + ]:        2704 :                 if (!qualResult)
      87                 :             :                 {
      88                 :        1538 :                         node->rs_done = true;
      89                 :        1538 :                         return NULL;
      90                 :             :                 }
      91         [ +  + ]:        2704 :         }
      92                 :             : 
      93                 :             :         /*
      94                 :             :          * Reset per-tuple memory context to free any expression evaluation
      95                 :             :          * storage allocated in the previous tuple cycle.
      96                 :             :          */
      97                 :       89828 :         ResetExprContext(econtext);
      98                 :             : 
      99                 :             :         /*
     100                 :             :          * if rs_done is true then it means that we were asked to return a
     101                 :             :          * constant tuple and we already did the last time ExecResult() was
     102                 :             :          * called, OR that we failed the constant qual check. Either way, now we
     103                 :             :          * are through.
     104                 :             :          */
     105         [ +  + ]:       89828 :         if (!node->rs_done)
     106                 :             :         {
     107                 :       66527 :                 outerPlan = outerPlanState(node);
     108                 :             : 
     109         [ +  + ]:       66527 :                 if (outerPlan != NULL)
     110                 :             :                 {
     111                 :             :                         /*
     112                 :             :                          * retrieve tuples from the outer plan until there are no more.
     113                 :             :                          */
     114                 :       36476 :                         outerTupleSlot = ExecProcNode(outerPlan);
     115                 :             : 
     116   [ +  +  +  + ]:       36476 :                         if (TupIsNull(outerTupleSlot))
     117                 :        1256 :                                 return NULL;
     118                 :             : 
     119                 :             :                         /*
     120                 :             :                          * prepare to compute projection expressions, which will expect to
     121                 :             :                          * access the input tuples as varno OUTER.
     122                 :             :                          */
     123                 :       35220 :                         econtext->ecxt_outertuple = outerTupleSlot;
     124                 :       35220 :                 }
     125                 :             :                 else
     126                 :             :                 {
     127                 :             :                         /*
     128                 :             :                          * if we don't have an outer plan, then we are just generating the
     129                 :             :                          * results from a constant target list.  Do it only once.
     130                 :             :                          */
     131                 :       30051 :                         node->rs_done = true;
     132                 :             :                 }
     133                 :             : 
     134                 :             :                 /* form the result tuple using ExecProject(), and return it */
     135                 :       65271 :                 return ExecProject(node->ps.ps_ProjInfo);
     136                 :             :         }
     137                 :             : 
     138                 :       23301 :         return NULL;
     139                 :       91366 : }
     140                 :             : 
     141                 :             : /* ----------------------------------------------------------------
     142                 :             :  *              ExecResultMarkPos
     143                 :             :  * ----------------------------------------------------------------
     144                 :             :  */
     145                 :             : void
     146                 :           0 : ExecResultMarkPos(ResultState *node)
     147                 :             : {
     148                 :           0 :         PlanState  *outerPlan = outerPlanState(node);
     149                 :             : 
     150         [ #  # ]:           0 :         if (outerPlan != NULL)
     151                 :           0 :                 ExecMarkPos(outerPlan);
     152                 :             :         else
     153   [ #  #  #  # ]:           0 :                 elog(DEBUG2, "Result nodes do not support mark/restore");
     154                 :           0 : }
     155                 :             : 
     156                 :             : /* ----------------------------------------------------------------
     157                 :             :  *              ExecResultRestrPos
     158                 :             :  * ----------------------------------------------------------------
     159                 :             :  */
     160                 :             : void
     161                 :           0 : ExecResultRestrPos(ResultState *node)
     162                 :             : {
     163                 :           0 :         PlanState  *outerPlan = outerPlanState(node);
     164                 :             : 
     165         [ #  # ]:           0 :         if (outerPlan != NULL)
     166                 :           0 :                 ExecRestrPos(outerPlan);
     167                 :             :         else
     168   [ #  #  #  # ]:           0 :                 elog(ERROR, "Result nodes do not support mark/restore");
     169                 :           0 : }
     170                 :             : 
     171                 :             : /* ----------------------------------------------------------------
     172                 :             :  *              ExecInitResult
     173                 :             :  *
     174                 :             :  *              Creates the run-time state information for the result node
     175                 :             :  *              produced by the planner and initializes outer relations
     176                 :             :  *              (child nodes).
     177                 :             :  * ----------------------------------------------------------------
     178                 :             :  */
     179                 :             : ResultState *
     180                 :       24618 : ExecInitResult(Result *node, EState *estate, int eflags)
     181                 :             : {
     182                 :       24618 :         ResultState *resstate;
     183                 :             : 
     184                 :             :         /* check for unsupported flags */
     185   [ -  +  #  # ]:       24618 :         Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)) ||
     186                 :             :                    outerPlan(node) != NULL);
     187                 :             : 
     188                 :             :         /*
     189                 :             :          * create state structure
     190                 :             :          */
     191                 :       24618 :         resstate = makeNode(ResultState);
     192                 :       24618 :         resstate->ps.plan = (Plan *) node;
     193                 :       24618 :         resstate->ps.state = estate;
     194                 :       24618 :         resstate->ps.ExecProcNode = ExecResult;
     195                 :             : 
     196                 :       24618 :         resstate->rs_done = false;
     197                 :       24618 :         resstate->rs_checkqual = (node->resconstantqual != NULL);
     198                 :             : 
     199                 :             :         /*
     200                 :             :          * Miscellaneous initialization
     201                 :             :          *
     202                 :             :          * create expression context for node
     203                 :             :          */
     204                 :       24618 :         ExecAssignExprContext(estate, &resstate->ps);
     205                 :             : 
     206                 :             :         /*
     207                 :             :          * initialize child nodes
     208                 :             :          */
     209                 :       24618 :         outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags);
     210                 :             : 
     211                 :             :         /*
     212                 :             :          * we don't use inner plan
     213                 :             :          */
     214         [ +  - ]:       24618 :         Assert(innerPlan(node) == NULL);
     215                 :             : 
     216                 :             :         /*
     217                 :             :          * Initialize result slot, type and projection.
     218                 :             :          */
     219                 :       24618 :         ExecInitResultTupleSlotTL(&resstate->ps, &TTSOpsVirtual);
     220                 :       24618 :         ExecAssignProjectionInfo(&resstate->ps, NULL);
     221                 :             : 
     222                 :             :         /*
     223                 :             :          * initialize child expressions
     224                 :             :          */
     225                 :       24618 :         resstate->ps.qual =
     226                 :       24618 :                 ExecInitQual(node->plan.qual, (PlanState *) resstate);
     227                 :       24618 :         resstate->resconstantqual =
     228                 :       24618 :                 ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate);
     229                 :             : 
     230                 :       49236 :         return resstate;
     231                 :       24618 : }
     232                 :             : 
     233                 :             : /* ----------------------------------------------------------------
     234                 :             :  *              ExecEndResult
     235                 :             :  *
     236                 :             :  *              frees up storage allocated through C routines
     237                 :             :  * ----------------------------------------------------------------
     238                 :             :  */
     239                 :             : void
     240                 :       19535 : ExecEndResult(ResultState *node)
     241                 :             : {
     242                 :             :         /*
     243                 :             :          * shut down subplans
     244                 :             :          */
     245                 :       19535 :         ExecEndNode(outerPlanState(node));
     246                 :       19535 : }
     247                 :             : 
     248                 :             : void
     249                 :       10452 : ExecReScanResult(ResultState *node)
     250                 :             : {
     251                 :       10452 :         PlanState  *outerPlan = outerPlanState(node);
     252                 :             : 
     253                 :       10452 :         node->rs_done = false;
     254                 :       10452 :         node->rs_checkqual = (node->resconstantqual != NULL);
     255                 :             : 
     256                 :             :         /*
     257                 :             :          * If chgParam of subnode is not null then plan will be re-scanned by
     258                 :             :          * first ExecProcNode.
     259                 :             :          */
     260   [ +  +  +  + ]:       10452 :         if (outerPlan && outerPlan->chgParam == NULL)
     261                 :          19 :                 ExecReScan(outerPlan);
     262                 :       10452 : }
        

Generated by: LCOV version 2.3.2-1