LCOV - code coverage report
Current view: top level - src/backend/executor - nodeSubqueryscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 38 40 95.0 %
Date: 2019-11-22 07:06: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-2019, 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/execdebug.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      961836 : SubqueryNext(SubqueryScanState *node)
      47             : {
      48             :     TupleTableSlot *slot;
      49             : 
      50             :     /*
      51             :      * Get the next tuple from the sub-query.
      52             :      */
      53      961836 :     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      961836 :     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      821508 : ExecSubqueryScan(PlanState *pstate)
      84             : {
      85      821508 :     SubqueryScanState *node = castNode(SubqueryScanState, pstate);
      86             : 
      87      821508 :     return ExecScan(&node->ss,
      88             :                     (ExecScanAccessMtd) SubqueryNext,
      89             :                     (ExecScanRecheckMtd) SubqueryRecheck);
      90             : }
      91             : 
      92             : /* ----------------------------------------------------------------
      93             :  *      ExecInitSubqueryScan
      94             :  * ----------------------------------------------------------------
      95             :  */
      96             : SubqueryScanState *
      97        2156 : 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        2156 :     subquerystate = makeNode(SubqueryScanState);
     112        2156 :     subquerystate->ss.ps.plan = (Plan *) node;
     113        2156 :     subquerystate->ss.ps.state = estate;
     114        2156 :     subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
     115             : 
     116             :     /*
     117             :      * Miscellaneous initialization
     118             :      *
     119             :      * create expression context for node
     120             :      */
     121        2156 :     ExecAssignExprContext(estate, &subquerystate->ss.ps);
     122             : 
     123             :     /*
     124             :      * initialize subquery
     125             :      */
     126        2156 :     subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
     127             : 
     128             :     /*
     129             :      * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
     130             :      */
     131        2156 :     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        2156 :     subquerystate->ss.ps.scanopsset = true;
     140        2156 :     subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
     141             :                                                         &subquerystate->ss.ps.scanopsfixed);
     142        2156 :     subquerystate->ss.ps.resultopsset = true;
     143        2156 :     subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
     144        2156 :     subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
     145             : 
     146             :     /*
     147             :      * Initialize result type and projection.
     148             :      */
     149        2156 :     ExecInitResultTypeTL(&subquerystate->ss.ps);
     150        2156 :     ExecAssignScanProjectionInfo(&subquerystate->ss);
     151             : 
     152             :     /*
     153             :      * initialize child expressions
     154             :      */
     155        2156 :     subquerystate->ss.ps.qual =
     156        2156 :         ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
     157             : 
     158        2156 :     return subquerystate;
     159             : }
     160             : 
     161             : /* ----------------------------------------------------------------
     162             :  *      ExecEndSubqueryScan
     163             :  *
     164             :  *      frees any storage allocated through C routines.
     165             :  * ----------------------------------------------------------------
     166             :  */
     167             : void
     168        2156 : ExecEndSubqueryScan(SubqueryScanState *node)
     169             : {
     170             :     /*
     171             :      * Free the exprcontext
     172             :      */
     173        2156 :     ExecFreeExprContext(&node->ss.ps);
     174             : 
     175             :     /*
     176             :      * clean out the upper tuple table
     177             :      */
     178        2156 :     if (node->ss.ps.ps_ResultTupleSlot)
     179        1916 :         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     180        2156 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
     181             : 
     182             :     /*
     183             :      * close down subquery
     184             :      */
     185        2156 :     ExecEndNode(node->subplan);
     186        2156 : }
     187             : 
     188             : /* ----------------------------------------------------------------
     189             :  *      ExecReScanSubqueryScan
     190             :  *
     191             :  *      Rescans the relation.
     192             :  * ----------------------------------------------------------------
     193             :  */
     194             : void
     195         262 : ExecReScanSubqueryScan(SubqueryScanState *node)
     196             : {
     197         262 :     ExecScanReScan(&node->ss);
     198             : 
     199             :     /*
     200             :      * ExecReScan doesn't know about my subplan, so I have to do
     201             :      * changed-parameter signaling myself.  This is just as well, because the
     202             :      * subplan has its own memory context in which its chgParam state lives.
     203             :      */
     204         262 :     if (node->ss.ps.chgParam != NULL)
     205         238 :         UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
     206             : 
     207             :     /*
     208             :      * if chgParam of subnode is not null then plan will be re-scanned by
     209             :      * first ExecProcNode.
     210             :      */
     211         262 :     if (node->subplan->chgParam == NULL)
     212          48 :         ExecReScan(node->subplan);
     213         262 : }

Generated by: LCOV version 1.13