LCOV - code coverage report
Current view: top level - src/backend/executor - nodeSubqueryscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 34 36 94.4 %
Date: 2024-04-16 10:10:56 Functions: 5 6 83.3 %
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-2024, 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     1801194 : SubqueryNext(SubqueryScanState *node)
      47             : {
      48             :     TupleTableSlot *slot;
      49             : 
      50             :     /*
      51             :      * Get the next tuple from the sub-query.
      52             :      */
      53     1801194 :     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     1801194 :     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     1609764 : ExecSubqueryScan(PlanState *pstate)
      84             : {
      85     1609764 :     SubqueryScanState *node = castNode(SubqueryScanState, pstate);
      86             : 
      87     1609764 :     return ExecScan(&node->ss,
      88             :                     (ExecScanAccessMtd) SubqueryNext,
      89             :                     (ExecScanRecheckMtd) SubqueryRecheck);
      90             : }
      91             : 
      92             : /* ----------------------------------------------------------------
      93             :  *      ExecInitSubqueryScan
      94             :  * ----------------------------------------------------------------
      95             :  */
      96             : SubqueryScanState *
      97       10456 : 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       10456 :     subquerystate = makeNode(SubqueryScanState);
     112       10456 :     subquerystate->ss.ps.plan = (Plan *) node;
     113       10456 :     subquerystate->ss.ps.state = estate;
     114       10456 :     subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
     115             : 
     116             :     /*
     117             :      * Miscellaneous initialization
     118             :      *
     119             :      * create expression context for node
     120             :      */
     121       10456 :     ExecAssignExprContext(estate, &subquerystate->ss.ps);
     122             : 
     123             :     /*
     124             :      * initialize subquery
     125             :      */
     126       10456 :     subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
     127             : 
     128             :     /*
     129             :      * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
     130             :      */
     131       10456 :     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       10456 :     subquerystate->ss.ps.scanopsset = true;
     140       10456 :     subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
     141             :                                                         &subquerystate->ss.ps.scanopsfixed);
     142       10456 :     subquerystate->ss.ps.resultopsset = true;
     143       10456 :     subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
     144       10456 :     subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
     145             : 
     146             :     /*
     147             :      * Initialize result type and projection.
     148             :      */
     149       10456 :     ExecInitResultTypeTL(&subquerystate->ss.ps);
     150       10456 :     ExecAssignScanProjectionInfo(&subquerystate->ss);
     151             : 
     152             :     /*
     153             :      * initialize child expressions
     154             :      */
     155       10456 :     subquerystate->ss.ps.qual =
     156       10456 :         ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
     157             : 
     158       10456 :     return subquerystate;
     159             : }
     160             : 
     161             : /* ----------------------------------------------------------------
     162             :  *      ExecEndSubqueryScan
     163             :  *
     164             :  *      frees any storage allocated through C routines.
     165             :  * ----------------------------------------------------------------
     166             :  */
     167             : void
     168       10456 : ExecEndSubqueryScan(SubqueryScanState *node)
     169             : {
     170             :     /*
     171             :      * close down subquery
     172             :      */
     173       10456 :     ExecEndNode(node->subplan);
     174       10456 : }
     175             : 
     176             : /* ----------------------------------------------------------------
     177             :  *      ExecReScanSubqueryScan
     178             :  *
     179             :  *      Rescans the relation.
     180             :  * ----------------------------------------------------------------
     181             :  */
     182             : void
     183        2186 : ExecReScanSubqueryScan(SubqueryScanState *node)
     184             : {
     185        2186 :     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        2186 :     if (node->ss.ps.chgParam != NULL)
     193        2172 :         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        2186 :     if (node->subplan->chgParam == NULL)
     200          68 :         ExecReScan(node->subplan);
     201        2186 : }

Generated by: LCOV version 1.14