LCOV - code coverage report
Current view: top level - src/backend/executor - nodeResult.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 79.7 % 59 47
Test Date: 2026-02-17 17:20:33 Functions: 66.7 % 6 4
Legend: Lines:     hit not hit

            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       591696 : ExecResult(PlanState *pstate)
      68              : {
      69       591696 :     ResultState *node = castNode(ResultState, pstate);
      70              :     TupleTableSlot *outerTupleSlot;
      71              :     PlanState  *outerPlan;
      72              :     ExprContext *econtext;
      73              : 
      74       591696 :     CHECK_FOR_INTERRUPTS();
      75              : 
      76       591694 :     econtext = node->ps.ps_ExprContext;
      77              : 
      78              :     /*
      79              :      * check constant qualifications like (2 > 1), if not already done
      80              :      */
      81       591694 :     if (node->rs_checkqual)
      82              :     {
      83         8735 :         bool        qualResult = ExecQual(node->resconstantqual, econtext);
      84              : 
      85         8735 :         node->rs_checkqual = false;
      86         8735 :         if (!qualResult)
      87              :         {
      88         5198 :             node->rs_done = true;
      89         5198 :             return NULL;
      90              :         }
      91              :     }
      92              : 
      93              :     /*
      94              :      * Reset per-tuple memory context to free any expression evaluation
      95              :      * storage allocated in the previous tuple cycle.
      96              :      */
      97       586496 :     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       586496 :     if (!node->rs_done)
     106              :     {
     107       467422 :         outerPlan = outerPlanState(node);
     108              : 
     109       467422 :         if (outerPlan != NULL)
     110              :         {
     111              :             /*
     112              :              * retrieve tuples from the outer plan until there are no more.
     113              :              */
     114       306769 :             outerTupleSlot = ExecProcNode(outerPlan);
     115              : 
     116       306762 :             if (TupIsNull(outerTupleSlot))
     117         4214 :                 return NULL;
     118              : 
     119              :             /*
     120              :              * prepare to compute projection expressions, which will expect to
     121              :              * access the input tuples as varno OUTER.
     122              :              */
     123       302548 :             econtext->ecxt_outertuple = outerTupleSlot;
     124              :         }
     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       160653 :             node->rs_done = true;
     132              :         }
     133              : 
     134              :         /* form the result tuple using ExecProject(), and return it */
     135       463201 :         return ExecProject(node->ps.ps_ProjInfo);
     136              :     }
     137              : 
     138       119074 :     return NULL;
     139              : }
     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       144841 : ExecInitResult(Result *node, EState *estate, int eflags)
     181              : {
     182              :     ResultState *resstate;
     183              : 
     184              :     /* check for unsupported flags */
     185              :     Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)) ||
     186              :            outerPlan(node) != NULL);
     187              : 
     188              :     /*
     189              :      * create state structure
     190              :      */
     191       144841 :     resstate = makeNode(ResultState);
     192       144841 :     resstate->ps.plan = (Plan *) node;
     193       144841 :     resstate->ps.state = estate;
     194       144841 :     resstate->ps.ExecProcNode = ExecResult;
     195              : 
     196       144841 :     resstate->rs_done = false;
     197       144841 :     resstate->rs_checkqual = (node->resconstantqual != NULL);
     198              : 
     199              :     /*
     200              :      * Miscellaneous initialization
     201              :      *
     202              :      * create expression context for node
     203              :      */
     204       144841 :     ExecAssignExprContext(estate, &resstate->ps);
     205              : 
     206              :     /*
     207              :      * initialize child nodes
     208              :      */
     209       144841 :     outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags);
     210              : 
     211              :     /*
     212              :      * we don't use inner plan
     213              :      */
     214              :     Assert(innerPlan(node) == NULL);
     215              : 
     216              :     /*
     217              :      * Initialize result slot, type and projection.
     218              :      */
     219       144841 :     ExecInitResultTupleSlotTL(&resstate->ps, &TTSOpsVirtual);
     220       144841 :     ExecAssignProjectionInfo(&resstate->ps, NULL);
     221              : 
     222              :     /*
     223              :      * initialize child expressions
     224              :      */
     225       144807 :     resstate->ps.qual =
     226       144807 :         ExecInitQual(node->plan.qual, (PlanState *) resstate);
     227       144807 :     resstate->resconstantqual =
     228       144807 :         ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate);
     229              : 
     230       144807 :     return resstate;
     231              : }
     232              : 
     233              : /* ----------------------------------------------------------------
     234              :  *      ExecEndResult
     235              :  *
     236              :  *      frees up storage allocated through C routines
     237              :  * ----------------------------------------------------------------
     238              :  */
     239              : void
     240       136224 : ExecEndResult(ResultState *node)
     241              : {
     242              :     /*
     243              :      * shut down subplans
     244              :      */
     245       136224 :     ExecEndNode(outerPlanState(node));
     246       136224 : }
     247              : 
     248              : void
     249        31941 : ExecReScanResult(ResultState *node)
     250              : {
     251        31941 :     PlanState  *outerPlan = outerPlanState(node);
     252              : 
     253        31941 :     node->rs_done = false;
     254        31941 :     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        31941 :     if (outerPlan && outerPlan->chgParam == NULL)
     261           60 :         ExecReScan(outerPlan);
     262        31941 : }
        

Generated by: LCOV version 2.0-1