LCOV - code coverage report
Current view: top level - src/backend/executor - nodeSubqueryscan.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 95.7 % 47 45
Test Date: 2026-01-26 10:56:24 Functions: 83.3 % 6 5
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 70.0 % 10 7

             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                 :       62130 : SubqueryNext(SubqueryScanState *node)
      47                 :             : {
      48                 :       62130 :         TupleTableSlot *slot;
      49                 :             : 
      50                 :             :         /*
      51                 :             :          * Get the next tuple from the sub-query.
      52                 :             :          */
      53                 :       62130 :         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                 :      124260 :         return slot;
      61                 :       62130 : }
      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                 :       37877 : ExecSubqueryScan(PlanState *pstate)
      84                 :             : {
      85                 :       37877 :         SubqueryScanState *node = castNode(SubqueryScanState, pstate);
      86                 :             : 
      87                 :       75754 :         return ExecScan(&node->ss,
      88                 :             :                                         (ExecScanAccessMtd) SubqueryNext,
      89                 :             :                                         (ExecScanRecheckMtd) SubqueryRecheck);
      90                 :       37877 : }
      91                 :             : 
      92                 :             : /* ----------------------------------------------------------------
      93                 :             :  *              ExecInitSubqueryScan
      94                 :             :  * ----------------------------------------------------------------
      95                 :             :  */
      96                 :             : SubqueryScanState *
      97                 :        1514 : ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
      98                 :             : {
      99                 :        1514 :         SubqueryScanState *subquerystate;
     100                 :             : 
     101                 :             :         /* check for unsupported flags */
     102         [ +  - ]:        1514 :         Assert(!(eflags & EXEC_FLAG_MARK));
     103                 :             : 
     104                 :             :         /* SubqueryScan should not have any "normal" children */
     105         [ +  - ]:        1514 :         Assert(outerPlan(node) == NULL);
     106         [ +  - ]:        1514 :         Assert(innerPlan(node) == NULL);
     107                 :             : 
     108                 :             :         /*
     109                 :             :          * create state structure
     110                 :             :          */
     111                 :        1514 :         subquerystate = makeNode(SubqueryScanState);
     112                 :        1514 :         subquerystate->ss.ps.plan = (Plan *) node;
     113                 :        1514 :         subquerystate->ss.ps.state = estate;
     114                 :        1514 :         subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
     115                 :             : 
     116                 :             :         /*
     117                 :             :          * Miscellaneous initialization
     118                 :             :          *
     119                 :             :          * create expression context for node
     120                 :             :          */
     121                 :        1514 :         ExecAssignExprContext(estate, &subquerystate->ss.ps);
     122                 :             : 
     123                 :             :         /*
     124                 :             :          * initialize subquery
     125                 :             :          */
     126                 :        1514 :         subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
     127                 :             : 
     128                 :             :         /*
     129                 :             :          * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
     130                 :             :          */
     131                 :        3028 :         ExecInitScanTupleSlot(estate, &subquerystate->ss,
     132                 :        1514 :                                                   ExecGetResultType(subquerystate->subplan),
     133                 :        1514 :                                                   ExecGetResultSlotOps(subquerystate->subplan, NULL));
     134                 :             : 
     135                 :             :         /*
     136                 :             :          * The slot used as the scantuple isn't the slot above (outside of EPQ),
     137                 :             :          * but the one from the node below.
     138                 :             :          */
     139                 :        1514 :         subquerystate->ss.ps.scanopsset = true;
     140                 :        3028 :         subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
     141                 :        1514 :                                                                                                                 &subquerystate->ss.ps.scanopsfixed);
     142                 :        1514 :         subquerystate->ss.ps.resultopsset = true;
     143                 :        1514 :         subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
     144                 :        1514 :         subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
     145                 :             : 
     146                 :             :         /*
     147                 :             :          * Initialize result type and projection.
     148                 :             :          */
     149                 :        1514 :         ExecInitResultTypeTL(&subquerystate->ss.ps);
     150                 :        1514 :         ExecAssignScanProjectionInfo(&subquerystate->ss);
     151                 :             : 
     152                 :             :         /*
     153                 :             :          * initialize child expressions
     154                 :             :          */
     155                 :        1514 :         subquerystate->ss.ps.qual =
     156                 :        1514 :                 ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
     157                 :             : 
     158                 :        3028 :         return subquerystate;
     159                 :        1514 : }
     160                 :             : 
     161                 :             : /* ----------------------------------------------------------------
     162                 :             :  *              ExecEndSubqueryScan
     163                 :             :  *
     164                 :             :  *              frees any storage allocated through C routines.
     165                 :             :  * ----------------------------------------------------------------
     166                 :             :  */
     167                 :             : void
     168                 :        1514 : ExecEndSubqueryScan(SubqueryScanState *node)
     169                 :             : {
     170                 :             :         /*
     171                 :             :          * close down subquery
     172                 :             :          */
     173                 :        1514 :         ExecEndNode(node->subplan);
     174                 :        1514 : }
     175                 :             : 
     176                 :             : /* ----------------------------------------------------------------
     177                 :             :  *              ExecReScanSubqueryScan
     178                 :             :  *
     179                 :             :  *              Rescans the relation.
     180                 :             :  * ----------------------------------------------------------------
     181                 :             :  */
     182                 :             : void
     183                 :          68 : ExecReScanSubqueryScan(SubqueryScanState *node)
     184                 :             : {
     185                 :          68 :         ExecScanReScan(&node->ss);
     186                 :             : 
     187                 :             :         /*
     188                 :             :          * ExecReScan doesn't know about my subplan, so I have to do
     189                 :             :          * changed-parameter signaling myself.  This is just as well, because the
     190                 :             :          * subplan has its own memory context in which its chgParam state lives.
     191                 :             :          */
     192         [ +  + ]:          68 :         if (node->ss.ps.chgParam != NULL)
     193                 :          62 :                 UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
     194                 :             : 
     195                 :             :         /*
     196                 :             :          * if chgParam of subnode is not null then plan will be re-scanned by
     197                 :             :          * first ExecProcNode.
     198                 :             :          */
     199         [ +  + ]:          68 :         if (node->subplan->chgParam == NULL)
     200                 :          21 :                 ExecReScan(node->subplan);
     201                 :          68 : }
        

Generated by: LCOV version 2.3.2-1