LCOV - differential code coverage report
Current view: top level - src/backend/executor - nodeWorktablescan.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 96.2 % 52 50 2 50
Current Date: 2023-04-08 15:15:32 Functions: 83.3 % 6 5 1 5
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * nodeWorktablescan.c
       4                 :  *    routines to handle WorkTableScan nodes.
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/backend/executor/nodeWorktablescan.c
      12                 :  *
      13                 :  *-------------------------------------------------------------------------
      14                 :  */
      15                 : 
      16                 : #include "postgres.h"
      17                 : 
      18                 : #include "executor/execdebug.h"
      19                 : #include "executor/nodeWorktablescan.h"
      20                 : 
      21                 : static TupleTableSlot *WorkTableScanNext(WorkTableScanState *node);
      22                 : 
      23                 : /* ----------------------------------------------------------------
      24                 :  *      WorkTableScanNext
      25                 :  *
      26                 :  *      This is a workhorse for ExecWorkTableScan
      27                 :  * ----------------------------------------------------------------
      28                 :  */
      29                 : static TupleTableSlot *
      30 CBC       21134 : WorkTableScanNext(WorkTableScanState *node)
      31                 : {
      32                 :     TupleTableSlot *slot;
      33                 :     Tuplestorestate *tuplestorestate;
      34                 : 
      35                 :     /*
      36                 :      * get information from the estate and scan state
      37                 :      *
      38                 :      * Note: we intentionally do not support backward scan.  Although it would
      39                 :      * take only a couple more lines here, it would force nodeRecursiveunion.c
      40                 :      * to create the tuplestore with backward scan enabled, which has a
      41                 :      * performance cost.  In practice backward scan is never useful for a
      42                 :      * worktable plan node, since it cannot appear high enough in the plan
      43                 :      * tree of a scrollable cursor to be exposed to a backward-scan
      44                 :      * requirement.  So it's not worth expending effort to support it.
      45                 :      *
      46                 :      * Note: we are also assuming that this node is the only reader of the
      47                 :      * worktable.  Therefore, we don't need a private read pointer for the
      48                 :      * tuplestore, nor do we need to tell tuplestore_gettupleslot to copy.
      49                 :      */
      50           21134 :     Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
      51                 : 
      52           21134 :     tuplestorestate = node->rustate->working_table;
      53                 : 
      54                 :     /*
      55                 :      * Get the next tuple from tuplestore. Return NULL if no more tuples.
      56                 :      */
      57           21134 :     slot = node->ss.ss_ScanTupleSlot;
      58           21134 :     (void) tuplestore_gettupleslot(tuplestorestate, true, false, slot);
      59           21134 :     return slot;
      60                 : }
      61                 : 
      62                 : /*
      63                 :  * WorkTableScanRecheck -- access method routine to recheck a tuple in EvalPlanQual
      64                 :  */
      65                 : static bool
      66 UBC           0 : WorkTableScanRecheck(WorkTableScanState *node, TupleTableSlot *slot)
      67                 : {
      68                 :     /* nothing to check */
      69               0 :     return true;
      70                 : }
      71                 : 
      72                 : /* ----------------------------------------------------------------
      73                 :  *      ExecWorkTableScan(node)
      74                 :  *
      75                 :  *      Scans the worktable sequentially and returns the next qualifying tuple.
      76                 :  *      We call the ExecScan() routine and pass it the appropriate
      77                 :  *      access method functions.
      78                 :  * ----------------------------------------------------------------
      79                 :  */
      80                 : static TupleTableSlot *
      81 CBC       14127 : ExecWorkTableScan(PlanState *pstate)
      82                 : {
      83           14127 :     WorkTableScanState *node = castNode(WorkTableScanState, pstate);
      84                 : 
      85                 :     /*
      86                 :      * On the first call, find the ancestor RecursiveUnion's state via the
      87                 :      * Param slot reserved for it.  (We can't do this during node init because
      88                 :      * there are corner cases where we'll get the init call before the
      89                 :      * RecursiveUnion does.)
      90                 :      */
      91           14127 :     if (node->rustate == NULL)
      92                 :     {
      93             327 :         WorkTableScan *plan = (WorkTableScan *) node->ss.ps.plan;
      94             327 :         EState     *estate = node->ss.ps.state;
      95                 :         ParamExecData *param;
      96                 : 
      97             327 :         param = &(estate->es_param_exec_vals[plan->wtParam]);
      98             327 :         Assert(param->execPlan == NULL);
      99             327 :         Assert(!param->isnull);
     100             327 :         node->rustate = castNode(RecursiveUnionState, DatumGetPointer(param->value));
     101             327 :         Assert(node->rustate);
     102                 : 
     103                 :         /*
     104                 :          * The scan tuple type (ie, the rowtype we expect to find in the work
     105                 :          * table) is the same as the result rowtype of the ancestor
     106                 :          * RecursiveUnion node.  Note this depends on the assumption that
     107                 :          * RecursiveUnion doesn't allow projection.
     108                 :          */
     109             327 :         ExecAssignScanType(&node->ss,
     110             327 :                            ExecGetResultType(&node->rustate->ps));
     111                 : 
     112                 :         /*
     113                 :          * Now we can initialize the projection info.  This must be completed
     114                 :          * before we can call ExecScan().
     115                 :          */
     116             327 :         ExecAssignScanProjectionInfo(&node->ss);
     117                 :     }
     118                 : 
     119           14127 :     return ExecScan(&node->ss,
     120                 :                     (ExecScanAccessMtd) WorkTableScanNext,
     121                 :                     (ExecScanRecheckMtd) WorkTableScanRecheck);
     122                 : }
     123                 : 
     124                 : 
     125                 : /* ----------------------------------------------------------------
     126                 :  *      ExecInitWorkTableScan
     127                 :  * ----------------------------------------------------------------
     128                 :  */
     129                 : WorkTableScanState *
     130             354 : ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
     131                 : {
     132                 :     WorkTableScanState *scanstate;
     133                 : 
     134                 :     /* check for unsupported flags */
     135             354 :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
     136                 : 
     137                 :     /*
     138                 :      * WorkTableScan should not have any children.
     139                 :      */
     140             354 :     Assert(outerPlan(node) == NULL);
     141             354 :     Assert(innerPlan(node) == NULL);
     142                 : 
     143                 :     /*
     144                 :      * create new WorkTableScanState for node
     145                 :      */
     146             354 :     scanstate = makeNode(WorkTableScanState);
     147             354 :     scanstate->ss.ps.plan = (Plan *) node;
     148             354 :     scanstate->ss.ps.state = estate;
     149             354 :     scanstate->ss.ps.ExecProcNode = ExecWorkTableScan;
     150             354 :     scanstate->rustate = NULL;   /* we'll set this later */
     151                 : 
     152                 :     /*
     153                 :      * Miscellaneous initialization
     154                 :      *
     155                 :      * create expression context for node
     156                 :      */
     157             354 :     ExecAssignExprContext(estate, &scanstate->ss.ps);
     158                 : 
     159                 :     /*
     160                 :      * tuple table initialization
     161                 :      */
     162             354 :     ExecInitResultTypeTL(&scanstate->ss.ps);
     163                 : 
     164                 :     /* signal that return type is not yet known */
     165             354 :     scanstate->ss.ps.resultopsset = true;
     166             354 :     scanstate->ss.ps.resultopsfixed = false;
     167                 : 
     168             354 :     ExecInitScanTupleSlot(estate, &scanstate->ss, NULL, &TTSOpsMinimalTuple);
     169                 : 
     170                 :     /*
     171                 :      * initialize child expressions
     172                 :      */
     173             354 :     scanstate->ss.ps.qual =
     174             354 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
     175                 : 
     176                 :     /*
     177                 :      * Do not yet initialize projection info, see ExecWorkTableScan() for
     178                 :      * details.
     179                 :      */
     180                 : 
     181             354 :     return scanstate;
     182                 : }
     183                 : 
     184                 : /* ----------------------------------------------------------------
     185                 :  *      ExecEndWorkTableScan
     186                 :  *
     187                 :  *      frees any storage allocated through C routines.
     188                 :  * ----------------------------------------------------------------
     189                 :  */
     190                 : void
     191             354 : ExecEndWorkTableScan(WorkTableScanState *node)
     192                 : {
     193                 :     /*
     194                 :      * Free exprcontext
     195                 :      */
     196             354 :     ExecFreeExprContext(&node->ss.ps);
     197                 : 
     198                 :     /*
     199                 :      * clean out the tuple table
     200                 :      */
     201             354 :     if (node->ss.ps.ps_ResultTupleSlot)
     202             258 :         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     203             354 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
     204             354 : }
     205                 : 
     206                 : /* ----------------------------------------------------------------
     207                 :  *      ExecReScanWorkTableScan
     208                 :  *
     209                 :  *      Rescans the relation.
     210                 :  * ----------------------------------------------------------------
     211                 :  */
     212                 : void
     213            3104 : ExecReScanWorkTableScan(WorkTableScanState *node)
     214                 : {
     215            3104 :     if (node->ss.ps.ps_ResultTupleSlot)
     216            2942 :         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     217                 : 
     218            3104 :     ExecScanReScan(&node->ss);
     219                 : 
     220                 :     /* No need (or way) to rescan if ExecWorkTableScan not called yet */
     221            3104 :     if (node->rustate)
     222            3101 :         tuplestore_rescan(node->rustate->working_table);
     223            3104 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a