LCOV - code coverage report
Current view: top level - src/backend/executor - nodeSeqscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 16beta1 Lines: 69 69 100.0 %
Date: 2023-06-06 08:12:15 Functions: 10 10 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * nodeSeqscan.c
       4             :  *    Support routines for sequential scans of relations.
       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/nodeSeqscan.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : /*
      16             :  * INTERFACE ROUTINES
      17             :  *      ExecSeqScan             sequentially scans a relation.
      18             :  *      ExecSeqNext             retrieve next tuple in sequential order.
      19             :  *      ExecInitSeqScan         creates and initializes a seqscan node.
      20             :  *      ExecEndSeqScan          releases any storage allocated.
      21             :  *      ExecReScanSeqScan       rescans the relation
      22             :  *
      23             :  *      ExecSeqScanEstimate     estimates DSM space needed for parallel scan
      24             :  *      ExecSeqScanInitializeDSM initialize DSM for parallel scan
      25             :  *      ExecSeqScanReInitializeDSM reinitialize DSM for fresh parallel scan
      26             :  *      ExecSeqScanInitializeWorker attach to DSM info in parallel worker
      27             :  */
      28             : #include "postgres.h"
      29             : 
      30             : #include "access/relscan.h"
      31             : #include "access/tableam.h"
      32             : #include "executor/execdebug.h"
      33             : #include "executor/nodeSeqscan.h"
      34             : #include "utils/rel.h"
      35             : 
      36             : static TupleTableSlot *SeqNext(SeqScanState *node);
      37             : 
      38             : /* ----------------------------------------------------------------
      39             :  *                      Scan Support
      40             :  * ----------------------------------------------------------------
      41             :  */
      42             : 
      43             : /* ----------------------------------------------------------------
      44             :  *      SeqNext
      45             :  *
      46             :  *      This is a workhorse for ExecSeqScan
      47             :  * ----------------------------------------------------------------
      48             :  */
      49             : static TupleTableSlot *
      50    72438398 : SeqNext(SeqScanState *node)
      51             : {
      52             :     TableScanDesc scandesc;
      53             :     EState     *estate;
      54             :     ScanDirection direction;
      55             :     TupleTableSlot *slot;
      56             : 
      57             :     /*
      58             :      * get information from the estate and scan state
      59             :      */
      60    72438398 :     scandesc = node->ss.ss_currentScanDesc;
      61    72438398 :     estate = node->ss.ps.state;
      62    72438398 :     direction = estate->es_direction;
      63    72438398 :     slot = node->ss.ss_ScanTupleSlot;
      64             : 
      65    72438398 :     if (scandesc == NULL)
      66             :     {
      67             :         /*
      68             :          * We reach here if the scan is not parallel, or if we're serially
      69             :          * executing a scan that was planned to be parallel.
      70             :          */
      71      152710 :         scandesc = table_beginscan(node->ss.ss_currentRelation,
      72             :                                    estate->es_snapshot,
      73             :                                    0, NULL);
      74      152710 :         node->ss.ss_currentScanDesc = scandesc;
      75             :     }
      76             : 
      77             :     /*
      78             :      * get the next tuple from the table
      79             :      */
      80    72438398 :     if (table_scan_getnextslot(scandesc, direction, slot))
      81    71561276 :         return slot;
      82      877102 :     return NULL;
      83             : }
      84             : 
      85             : /*
      86             :  * SeqRecheck -- access method routine to recheck a tuple in EvalPlanQual
      87             :  */
      88             : static bool
      89         212 : SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
      90             : {
      91             :     /*
      92             :      * Note that unlike IndexScan, SeqScan never use keys in heap_beginscan
      93             :      * (and this is very bad) - so, here we do not check are keys ok or not.
      94             :      */
      95         212 :     return true;
      96             : }
      97             : 
      98             : /* ----------------------------------------------------------------
      99             :  *      ExecSeqScan(node)
     100             :  *
     101             :  *      Scans the relation sequentially and returns the next qualifying
     102             :  *      tuple.
     103             :  *      We call the ExecScan() routine and pass it the appropriate
     104             :  *      access method functions.
     105             :  * ----------------------------------------------------------------
     106             :  */
     107             : static TupleTableSlot *
     108    46321360 : ExecSeqScan(PlanState *pstate)
     109             : {
     110    46321360 :     SeqScanState *node = castNode(SeqScanState, pstate);
     111             : 
     112    46321360 :     return ExecScan(&node->ss,
     113             :                     (ExecScanAccessMtd) SeqNext,
     114             :                     (ExecScanRecheckMtd) SeqRecheck);
     115             : }
     116             : 
     117             : 
     118             : /* ----------------------------------------------------------------
     119             :  *      ExecInitSeqScan
     120             :  * ----------------------------------------------------------------
     121             :  */
     122             : SeqScanState *
     123      186820 : ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
     124             : {
     125             :     SeqScanState *scanstate;
     126             : 
     127             :     /*
     128             :      * Once upon a time it was possible to have an outerPlan of a SeqScan, but
     129             :      * not any more.
     130             :      */
     131             :     Assert(outerPlan(node) == NULL);
     132             :     Assert(innerPlan(node) == NULL);
     133             : 
     134             :     /*
     135             :      * create state structure
     136             :      */
     137      186820 :     scanstate = makeNode(SeqScanState);
     138      186820 :     scanstate->ss.ps.plan = (Plan *) node;
     139      186820 :     scanstate->ss.ps.state = estate;
     140      186820 :     scanstate->ss.ps.ExecProcNode = ExecSeqScan;
     141             : 
     142             :     /*
     143             :      * Miscellaneous initialization
     144             :      *
     145             :      * create expression context for node
     146             :      */
     147      186820 :     ExecAssignExprContext(estate, &scanstate->ss.ps);
     148             : 
     149             :     /*
     150             :      * open the scan relation
     151             :      */
     152      186808 :     scanstate->ss.ss_currentRelation =
     153      186820 :         ExecOpenScanRelation(estate,
     154             :                              node->scan.scanrelid,
     155             :                              eflags);
     156             : 
     157             :     /* and create slot with the appropriate rowtype */
     158      186808 :     ExecInitScanTupleSlot(estate, &scanstate->ss,
     159      186808 :                           RelationGetDescr(scanstate->ss.ss_currentRelation),
     160             :                           table_slot_callbacks(scanstate->ss.ss_currentRelation));
     161             : 
     162             :     /*
     163             :      * Initialize result type and projection.
     164             :      */
     165      186808 :     ExecInitResultTypeTL(&scanstate->ss.ps);
     166      186808 :     ExecAssignScanProjectionInfo(&scanstate->ss);
     167             : 
     168             :     /*
     169             :      * initialize child expressions
     170             :      */
     171      186808 :     scanstate->ss.ps.qual =
     172      186808 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
     173             : 
     174      186808 :     return scanstate;
     175             : }
     176             : 
     177             : /* ----------------------------------------------------------------
     178             :  *      ExecEndSeqScan
     179             :  *
     180             :  *      frees any storage allocated through C routines.
     181             :  * ----------------------------------------------------------------
     182             :  */
     183             : void
     184      184634 : ExecEndSeqScan(SeqScanState *node)
     185             : {
     186             :     TableScanDesc scanDesc;
     187             : 
     188             :     /*
     189             :      * get information from node
     190             :      */
     191      184634 :     scanDesc = node->ss.ss_currentScanDesc;
     192             : 
     193             :     /*
     194             :      * Free the exprcontext
     195             :      */
     196      184634 :     ExecFreeExprContext(&node->ss.ps);
     197             : 
     198             :     /*
     199             :      * clean out the tuple table
     200             :      */
     201      184634 :     if (node->ss.ps.ps_ResultTupleSlot)
     202      101234 :         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     203      184634 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
     204             : 
     205             :     /*
     206             :      * close heap scan
     207             :      */
     208      184634 :     if (scanDesc != NULL)
     209      154478 :         table_endscan(scanDesc);
     210      184634 : }
     211             : 
     212             : /* ----------------------------------------------------------------
     213             :  *                      Join Support
     214             :  * ----------------------------------------------------------------
     215             :  */
     216             : 
     217             : /* ----------------------------------------------------------------
     218             :  *      ExecReScanSeqScan
     219             :  *
     220             :  *      Rescans the relation.
     221             :  * ----------------------------------------------------------------
     222             :  */
     223             : void
     224      755246 : ExecReScanSeqScan(SeqScanState *node)
     225             : {
     226             :     TableScanDesc scan;
     227             : 
     228      755246 :     scan = node->ss.ss_currentScanDesc;
     229             : 
     230      755246 :     if (scan != NULL)
     231      737626 :         table_rescan(scan,      /* scan desc */
     232             :                      NULL);     /* new scan keys */
     233             : 
     234      755246 :     ExecScanReScan((ScanState *) node);
     235      755246 : }
     236             : 
     237             : /* ----------------------------------------------------------------
     238             :  *                      Parallel Scan Support
     239             :  * ----------------------------------------------------------------
     240             :  */
     241             : 
     242             : /* ----------------------------------------------------------------
     243             :  *      ExecSeqScanEstimate
     244             :  *
     245             :  *      Compute the amount of space we'll need in the parallel
     246             :  *      query DSM, and inform pcxt->estimator about our needs.
     247             :  * ----------------------------------------------------------------
     248             :  */
     249             : void
     250         892 : ExecSeqScanEstimate(SeqScanState *node,
     251             :                     ParallelContext *pcxt)
     252             : {
     253         892 :     EState     *estate = node->ss.ps.state;
     254             : 
     255         892 :     node->pscan_len = table_parallelscan_estimate(node->ss.ss_currentRelation,
     256             :                                                   estate->es_snapshot);
     257         892 :     shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
     258         892 :     shm_toc_estimate_keys(&pcxt->estimator, 1);
     259         892 : }
     260             : 
     261             : /* ----------------------------------------------------------------
     262             :  *      ExecSeqScanInitializeDSM
     263             :  *
     264             :  *      Set up a parallel heap scan descriptor.
     265             :  * ----------------------------------------------------------------
     266             :  */
     267             : void
     268         892 : ExecSeqScanInitializeDSM(SeqScanState *node,
     269             :                          ParallelContext *pcxt)
     270             : {
     271         892 :     EState     *estate = node->ss.ps.state;
     272             :     ParallelTableScanDesc pscan;
     273             : 
     274         892 :     pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
     275         892 :     table_parallelscan_initialize(node->ss.ss_currentRelation,
     276             :                                   pscan,
     277             :                                   estate->es_snapshot);
     278         892 :     shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
     279         892 :     node->ss.ss_currentScanDesc =
     280         892 :         table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
     281         892 : }
     282             : 
     283             : /* ----------------------------------------------------------------
     284             :  *      ExecSeqScanReInitializeDSM
     285             :  *
     286             :  *      Reset shared state before beginning a fresh scan.
     287             :  * ----------------------------------------------------------------
     288             :  */
     289             : void
     290         228 : ExecSeqScanReInitializeDSM(SeqScanState *node,
     291             :                            ParallelContext *pcxt)
     292             : {
     293             :     ParallelTableScanDesc pscan;
     294             : 
     295         228 :     pscan = node->ss.ss_currentScanDesc->rs_parallel;
     296         228 :     table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
     297         228 : }
     298             : 
     299             : /* ----------------------------------------------------------------
     300             :  *      ExecSeqScanInitializeWorker
     301             :  *
     302             :  *      Copy relevant information from TOC into planstate.
     303             :  * ----------------------------------------------------------------
     304             :  */
     305             : void
     306        2654 : ExecSeqScanInitializeWorker(SeqScanState *node,
     307             :                             ParallelWorkerContext *pwcxt)
     308             : {
     309             :     ParallelTableScanDesc pscan;
     310             : 
     311        2654 :     pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
     312        2654 :     node->ss.ss_currentScanDesc =
     313        2654 :         table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
     314        2654 : }

Generated by: LCOV version 1.14