LCOV - code coverage report
Current view: top level - src/backend/executor - nodeSeqscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 65 65 100.0 %
Date: 2024-11-21 10:14:43 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-2024, 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/executor.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    70889670 : 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    70889670 :     scandesc = node->ss.ss_currentScanDesc;
      61    70889670 :     estate = node->ss.ps.state;
      62    70889670 :     direction = estate->es_direction;
      63    70889670 :     slot = node->ss.ss_ScanTupleSlot;
      64             : 
      65    70889670 :     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      165156 :         scandesc = table_beginscan(node->ss.ss_currentRelation,
      72             :                                    estate->es_snapshot,
      73             :                                    0, NULL);
      74      165156 :         node->ss.ss_currentScanDesc = scandesc;
      75             :     }
      76             : 
      77             :     /*
      78             :      * get the next tuple from the table
      79             :      */
      80    70889670 :     if (table_scan_getnextslot(scandesc, direction, slot))
      81    69738812 :         return slot;
      82     1150842 :     return NULL;
      83             : }
      84             : 
      85             : /*
      86             :  * SeqRecheck -- access method routine to recheck a tuple in EvalPlanQual
      87             :  */
      88             : static bool
      89         238 : 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         238 :     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    45330770 : ExecSeqScan(PlanState *pstate)
     109             : {
     110    45330770 :     SeqScanState *node = castNode(SeqScanState, pstate);
     111             : 
     112    45330770 :     return ExecScan(&node->ss,
     113             :                     (ExecScanAccessMtd) SeqNext,
     114             :                     (ExecScanRecheckMtd) SeqRecheck);
     115             : }
     116             : 
     117             : 
     118             : /* ----------------------------------------------------------------
     119             :  *      ExecInitSeqScan
     120             :  * ----------------------------------------------------------------
     121             :  */
     122             : SeqScanState *
     123      204180 : 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      204180 :     scanstate = makeNode(SeqScanState);
     138      204180 :     scanstate->ss.ps.plan = (Plan *) node;
     139      204180 :     scanstate->ss.ps.state = estate;
     140      204180 :     scanstate->ss.ps.ExecProcNode = ExecSeqScan;
     141             : 
     142             :     /*
     143             :      * Miscellaneous initialization
     144             :      *
     145             :      * create expression context for node
     146             :      */
     147      204180 :     ExecAssignExprContext(estate, &scanstate->ss.ps);
     148             : 
     149             :     /*
     150             :      * open the scan relation
     151             :      */
     152      204168 :     scanstate->ss.ss_currentRelation =
     153      204180 :         ExecOpenScanRelation(estate,
     154             :                              node->scan.scanrelid,
     155             :                              eflags);
     156             : 
     157             :     /* and create slot with the appropriate rowtype */
     158      204168 :     ExecInitScanTupleSlot(estate, &scanstate->ss,
     159      204168 :                           RelationGetDescr(scanstate->ss.ss_currentRelation),
     160             :                           table_slot_callbacks(scanstate->ss.ss_currentRelation));
     161             : 
     162             :     /*
     163             :      * Initialize result type and projection.
     164             :      */
     165      204168 :     ExecInitResultTypeTL(&scanstate->ss.ps);
     166      204168 :     ExecAssignScanProjectionInfo(&scanstate->ss);
     167             : 
     168             :     /*
     169             :      * initialize child expressions
     170             :      */
     171      204168 :     scanstate->ss.ps.qual =
     172      204168 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
     173             : 
     174      204168 :     return scanstate;
     175             : }
     176             : 
     177             : /* ----------------------------------------------------------------
     178             :  *      ExecEndSeqScan
     179             :  *
     180             :  *      frees any storage allocated through C routines.
     181             :  * ----------------------------------------------------------------
     182             :  */
     183             : void
     184      201650 : ExecEndSeqScan(SeqScanState *node)
     185             : {
     186             :     TableScanDesc scanDesc;
     187             : 
     188             :     /*
     189             :      * get information from node
     190             :      */
     191      201650 :     scanDesc = node->ss.ss_currentScanDesc;
     192             : 
     193             :     /*
     194             :      * close heap scan
     195             :      */
     196      201650 :     if (scanDesc != NULL)
     197      166674 :         table_endscan(scanDesc);
     198      201650 : }
     199             : 
     200             : /* ----------------------------------------------------------------
     201             :  *                      Join Support
     202             :  * ----------------------------------------------------------------
     203             :  */
     204             : 
     205             : /* ----------------------------------------------------------------
     206             :  *      ExecReScanSeqScan
     207             :  *
     208             :  *      Rescans the relation.
     209             :  * ----------------------------------------------------------------
     210             :  */
     211             : void
     212     1022518 : ExecReScanSeqScan(SeqScanState *node)
     213             : {
     214             :     TableScanDesc scan;
     215             : 
     216     1022518 :     scan = node->ss.ss_currentScanDesc;
     217             : 
     218     1022518 :     if (scan != NULL)
     219     1000642 :         table_rescan(scan,      /* scan desc */
     220             :                      NULL);     /* new scan keys */
     221             : 
     222     1022518 :     ExecScanReScan((ScanState *) node);
     223     1022518 : }
     224             : 
     225             : /* ----------------------------------------------------------------
     226             :  *                      Parallel Scan Support
     227             :  * ----------------------------------------------------------------
     228             :  */
     229             : 
     230             : /* ----------------------------------------------------------------
     231             :  *      ExecSeqScanEstimate
     232             :  *
     233             :  *      Compute the amount of space we'll need in the parallel
     234             :  *      query DSM, and inform pcxt->estimator about our needs.
     235             :  * ----------------------------------------------------------------
     236             :  */
     237             : void
     238         900 : ExecSeqScanEstimate(SeqScanState *node,
     239             :                     ParallelContext *pcxt)
     240             : {
     241         900 :     EState     *estate = node->ss.ps.state;
     242             : 
     243         900 :     node->pscan_len = table_parallelscan_estimate(node->ss.ss_currentRelation,
     244             :                                                   estate->es_snapshot);
     245         900 :     shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
     246         900 :     shm_toc_estimate_keys(&pcxt->estimator, 1);
     247         900 : }
     248             : 
     249             : /* ----------------------------------------------------------------
     250             :  *      ExecSeqScanInitializeDSM
     251             :  *
     252             :  *      Set up a parallel heap scan descriptor.
     253             :  * ----------------------------------------------------------------
     254             :  */
     255             : void
     256         900 : ExecSeqScanInitializeDSM(SeqScanState *node,
     257             :                          ParallelContext *pcxt)
     258             : {
     259         900 :     EState     *estate = node->ss.ps.state;
     260             :     ParallelTableScanDesc pscan;
     261             : 
     262         900 :     pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
     263         900 :     table_parallelscan_initialize(node->ss.ss_currentRelation,
     264             :                                   pscan,
     265             :                                   estate->es_snapshot);
     266         900 :     shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
     267         900 :     node->ss.ss_currentScanDesc =
     268         900 :         table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
     269         900 : }
     270             : 
     271             : /* ----------------------------------------------------------------
     272             :  *      ExecSeqScanReInitializeDSM
     273             :  *
     274             :  *      Reset shared state before beginning a fresh scan.
     275             :  * ----------------------------------------------------------------
     276             :  */
     277             : void
     278         228 : ExecSeqScanReInitializeDSM(SeqScanState *node,
     279             :                            ParallelContext *pcxt)
     280             : {
     281             :     ParallelTableScanDesc pscan;
     282             : 
     283         228 :     pscan = node->ss.ss_currentScanDesc->rs_parallel;
     284         228 :     table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
     285         228 : }
     286             : 
     287             : /* ----------------------------------------------------------------
     288             :  *      ExecSeqScanInitializeWorker
     289             :  *
     290             :  *      Copy relevant information from TOC into planstate.
     291             :  * ----------------------------------------------------------------
     292             :  */
     293             : void
     294        2678 : ExecSeqScanInitializeWorker(SeqScanState *node,
     295             :                             ParallelWorkerContext *pwcxt)
     296             : {
     297             :     ParallelTableScanDesc pscan;
     298             : 
     299        2678 :     pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
     300        2678 :     node->ss.ss_currentScanDesc =
     301        2678 :         table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
     302        2678 : }

Generated by: LCOV version 1.14