LCOV - code coverage report
Current view: top level - src/backend/executor - nodeSubqueryscan.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 94.4 % 36 34
Test Date: 2026-02-28 23:15:01 Functions: 83.3 % 6 5
Legend: Lines:     hit not hit

            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       640696 : SubqueryNext(SubqueryScanState *node)
      47              : {
      48              :     TupleTableSlot *slot;
      49              : 
      50              :     /*
      51              :      * Get the next tuple from the sub-query.
      52              :      */
      53       640696 :     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       640690 :     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       540273 : ExecSubqueryScan(PlanState *pstate)
      84              : {
      85       540273 :     SubqueryScanState *node = castNode(SubqueryScanState, pstate);
      86              : 
      87       540273 :     return ExecScan(&node->ss,
      88              :                     (ExecScanAccessMtd) SubqueryNext,
      89              :                     (ExecScanRecheckMtd) SubqueryRecheck);
      90              : }
      91              : 
      92              : /* ----------------------------------------------------------------
      93              :  *      ExecInitSubqueryScan
      94              :  * ----------------------------------------------------------------
      95              :  */
      96              : SubqueryScanState *
      97        11885 : 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        11885 :     subquerystate = makeNode(SubqueryScanState);
     112        11885 :     subquerystate->ss.ps.plan = (Plan *) node;
     113        11885 :     subquerystate->ss.ps.state = estate;
     114        11885 :     subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
     115              : 
     116              :     /*
     117              :      * Miscellaneous initialization
     118              :      *
     119              :      * create expression context for node
     120              :      */
     121        11885 :     ExecAssignExprContext(estate, &subquerystate->ss.ps);
     122              : 
     123              :     /*
     124              :      * initialize subquery
     125              :      */
     126        11885 :     subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
     127              : 
     128              :     /*
     129              :      * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
     130              :      */
     131        11885 :     ExecInitScanTupleSlot(estate, &subquerystate->ss,
     132              :                           ExecGetResultType(subquerystate->subplan),
     133              :                           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        11885 :     subquerystate->ss.ps.scanopsset = true;
     140        11885 :     subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
     141              :                                                         &subquerystate->ss.ps.scanopsfixed);
     142        11885 :     subquerystate->ss.ps.resultopsset = true;
     143        11885 :     subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
     144        11885 :     subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
     145              : 
     146              :     /*
     147              :      * Initialize result type and projection.
     148              :      */
     149        11885 :     ExecInitResultTypeTL(&subquerystate->ss.ps);
     150        11885 :     ExecAssignScanProjectionInfo(&subquerystate->ss);
     151              : 
     152              :     /*
     153              :      * initialize child expressions
     154              :      */
     155        11885 :     subquerystate->ss.ps.qual =
     156        11885 :         ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
     157              : 
     158        11885 :     return subquerystate;
     159              : }
     160              : 
     161              : /* ----------------------------------------------------------------
     162              :  *      ExecEndSubqueryScan
     163              :  *
     164              :  *      frees any storage allocated through C routines.
     165              :  * ----------------------------------------------------------------
     166              :  */
     167              : void
     168        11879 : ExecEndSubqueryScan(SubqueryScanState *node)
     169              : {
     170              :     /*
     171              :      * close down subquery
     172              :      */
     173        11879 :     ExecEndNode(node->subplan);
     174        11879 : }
     175              : 
     176              : /* ----------------------------------------------------------------
     177              :  *      ExecReScanSubqueryScan
     178              :  *
     179              :  *      Rescans the relation.
     180              :  * ----------------------------------------------------------------
     181              :  */
     182              : void
     183          238 : ExecReScanSubqueryScan(SubqueryScanState *node)
     184              : {
     185          238 :     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          238 :     if (node->ss.ps.chgParam != NULL)
     193          219 :         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          238 :     if (node->subplan->chgParam == NULL)
     200           64 :         ExecReScan(node->subplan);
     201          238 : }
        

Generated by: LCOV version 2.0-1