LCOV - code coverage report
Current view: top level - src/backend/executor - nodeSubqueryscan.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 94.4 % 36 34
Test Date: 2026-07-12 21:15:34 Functions: 83.3 % 6 5
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 100.0 % 4 4

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * nodeSubqueryscan.c
       4                 :             :  *    Support routines for scanning subqueries (subselects in rangetable).
       5                 :             :  *
       6                 :             :  * This is just enough different from sublinks (nodeSubplan.c) to mean that
       7                 :             :  * we need two sets of code.  Ought to look at trying to unify the cases.
       8                 :             :  *
       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/nodeSubqueryscan.c
      16                 :             :  *
      17                 :             :  *-------------------------------------------------------------------------
      18                 :             :  */
      19                 :             : /*
      20                 :             :  * INTERFACE ROUTINES
      21                 :             :  *      ExecSubqueryScan            scans a subquery.
      22                 :             :  *      ExecSubqueryNext            retrieve next tuple in sequential order.
      23                 :             :  *      ExecInitSubqueryScan        creates and initializes a subqueryscan node.
      24                 :             :  *      ExecEndSubqueryScan         releases any storage allocated.
      25                 :             :  *      ExecReScanSubqueryScan      rescans the relation
      26                 :             :  *
      27                 :             :  */
      28                 :             : #include "postgres.h"
      29                 :             : 
      30                 :             : #include "executor/executor.h"
      31                 :             : #include "executor/nodeSubqueryscan.h"
      32                 :             : 
      33                 :             : static TupleTableSlot *SubqueryNext(SubqueryScanState *node);
      34                 :             : 
      35                 :             : /* ----------------------------------------------------------------
      36                 :             :  *                      Scan Support
      37                 :             :  * ----------------------------------------------------------------
      38                 :             :  */
      39                 :             : /* ----------------------------------------------------------------
      40                 :             :  *      SubqueryNext
      41                 :             :  *
      42                 :             :  *      This is a workhorse for ExecSubqueryScan
      43                 :             :  * ----------------------------------------------------------------
      44                 :             :  */
      45                 :             : static TupleTableSlot *
      46                 :     1029992 : SubqueryNext(SubqueryScanState *node)
      47                 :             : {
      48                 :             :     TupleTableSlot *slot;
      49                 :             : 
      50                 :             :     /*
      51                 :             :      * Get the next tuple from the sub-query.
      52                 :             :      */
      53                 :     1029992 :     slot = ExecProcNode(node->subplan);
      54                 :             : 
      55                 :             :     /*
      56                 :             :      * We just return the subplan's result slot, rather than expending extra
      57                 :             :      * cycles for ExecCopySlot().  (Our own ScanTupleSlot is used only for
      58                 :             :      * EvalPlanQual rechecks.)
      59                 :             :      */
      60                 :     1029986 :     return slot;
      61                 :             : }
      62                 :             : 
      63                 :             : /*
      64                 :             :  * SubqueryRecheck -- access method routine to recheck a tuple in EvalPlanQual
      65                 :             :  */
      66                 :             : static bool
      67                 :           0 : SubqueryRecheck(SubqueryScanState *node, TupleTableSlot *slot)
      68                 :             : {
      69                 :             :     /* nothing to check */
      70                 :           0 :     return true;
      71                 :             : }
      72                 :             : 
      73                 :             : /* ----------------------------------------------------------------
      74                 :             :  *      ExecSubqueryScan(node)
      75                 :             :  *
      76                 :             :  *      Scans the subquery sequentially and returns the next qualifying
      77                 :             :  *      tuple.
      78                 :             :  *      We call the ExecScan() routine and pass it the appropriate
      79                 :             :  *      access method functions.
      80                 :             :  * ----------------------------------------------------------------
      81                 :             :  */
      82                 :             : static TupleTableSlot *
      83                 :      871846 : ExecSubqueryScan(PlanState *pstate)
      84                 :             : {
      85                 :      871846 :     SubqueryScanState *node = castNode(SubqueryScanState, pstate);
      86                 :             : 
      87                 :      871846 :     return ExecScan(&node->ss,
      88                 :             :                     (ExecScanAccessMtd) SubqueryNext,
      89                 :             :                     (ExecScanRecheckMtd) SubqueryRecheck);
      90                 :             : }
      91                 :             : 
      92                 :             : /* ----------------------------------------------------------------
      93                 :             :  *      ExecInitSubqueryScan
      94                 :             :  * ----------------------------------------------------------------
      95                 :             :  */
      96                 :             : SubqueryScanState *
      97                 :       13880 : ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
      98                 :             : {
      99                 :             :     SubqueryScanState *subquerystate;
     100                 :             : 
     101                 :             :     /* check for unsupported flags */
     102                 :             :     Assert(!(eflags & EXEC_FLAG_MARK));
     103                 :             : 
     104                 :             :     /* SubqueryScan should not have any "normal" children */
     105                 :             :     Assert(outerPlan(node) == NULL);
     106                 :             :     Assert(innerPlan(node) == NULL);
     107                 :             : 
     108                 :             :     /*
     109                 :             :      * create state structure
     110                 :             :      */
     111                 :       13880 :     subquerystate = makeNode(SubqueryScanState);
     112                 :       13880 :     subquerystate->ss.ps.plan = (Plan *) node;
     113                 :       13880 :     subquerystate->ss.ps.state = estate;
     114                 :       13880 :     subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
     115                 :             : 
     116                 :             :     /*
     117                 :             :      * Miscellaneous initialization
     118                 :             :      *
     119                 :             :      * create expression context for node
     120                 :             :      */
     121                 :       13880 :     ExecAssignExprContext(estate, &subquerystate->ss.ps);
     122                 :             : 
     123                 :             :     /*
     124                 :             :      * initialize subquery
     125                 :             :      */
     126                 :       13880 :     subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
     127                 :             : 
     128                 :             :     /*
     129                 :             :      * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
     130                 :             :      */
     131                 :       13880 :     ExecInitScanTupleSlot(estate, &subquerystate->ss,
     132                 :             :                           ExecGetResultType(subquerystate->subplan),
     133                 :             :                           ExecGetResultSlotOps(subquerystate->subplan, NULL),
     134                 :             :                           0);
     135                 :             : 
     136                 :             :     /*
     137                 :             :      * The slot used as the scantuple isn't the slot above (outside of EPQ),
     138                 :             :      * but the one from the node below.
     139                 :             :      */
     140                 :       13880 :     subquerystate->ss.ps.scanopsset = true;
     141                 :       13880 :     subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
     142                 :             :                                                         &subquerystate->ss.ps.scanopsfixed);
     143                 :       13880 :     subquerystate->ss.ps.resultopsset = true;
     144                 :       13880 :     subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
     145                 :       13880 :     subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
     146                 :             : 
     147                 :             :     /*
     148                 :             :      * Initialize result type and projection.
     149                 :             :      */
     150                 :       13880 :     ExecInitResultTypeTL(&subquerystate->ss.ps);
     151                 :       13880 :     ExecAssignScanProjectionInfo(&subquerystate->ss);
     152                 :             : 
     153                 :             :     /*
     154                 :             :      * initialize child expressions
     155                 :             :      */
     156                 :       13880 :     subquerystate->ss.ps.qual =
     157                 :       13880 :         ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
     158                 :             : 
     159                 :       13880 :     return subquerystate;
     160                 :             : }
     161                 :             : 
     162                 :             : /* ----------------------------------------------------------------
     163                 :             :  *      ExecEndSubqueryScan
     164                 :             :  *
     165                 :             :  *      frees any storage allocated through C routines.
     166                 :             :  * ----------------------------------------------------------------
     167                 :             :  */
     168                 :             : void
     169                 :       13874 : ExecEndSubqueryScan(SubqueryScanState *node)
     170                 :             : {
     171                 :             :     /*
     172                 :             :      * close down subquery
     173                 :             :      */
     174                 :       13874 :     ExecEndNode(node->subplan);
     175                 :       13874 : }
     176                 :             : 
     177                 :             : /* ----------------------------------------------------------------
     178                 :             :  *      ExecReScanSubqueryScan
     179                 :             :  *
     180                 :             :  *      Rescans the relation.
     181                 :             :  * ----------------------------------------------------------------
     182                 :             :  */
     183                 :             : void
     184                 :         467 : ExecReScanSubqueryScan(SubqueryScanState *node)
     185                 :             : {
     186                 :         467 :     ExecScanReScan(&node->ss);
     187                 :             : 
     188                 :             :     /*
     189                 :             :      * ExecReScan doesn't know about my subplan, so I have to do
     190                 :             :      * changed-parameter signaling myself.  This is just as well, because the
     191                 :             :      * subplan has its own memory context in which its chgParam state lives.
     192                 :             :      */
     193         [ +  + ]:         467 :     if (node->ss.ps.chgParam != NULL)
     194                 :         382 :         UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
     195                 :             : 
     196                 :             :     /*
     197                 :             :      * if chgParam of subnode is not null then plan will be re-scanned by
     198                 :             :      * first ExecProcNode.
     199                 :             :      */
     200         [ +  + ]:         467 :     if (node->subplan->chgParam == NULL)
     201                 :         145 :         ExecReScan(node->subplan);
     202                 :         467 : }
        

Generated by: LCOV version 2.0-1