LCOV - code coverage report
Current view: top level - src/backend/executor - nodeSeqscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 77 79 97.5 %
Date: 2017-09-29 15:12:54 Functions: 10 11 90.9 %
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-2017, 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 "executor/execdebug.h"
      32             : #include "executor/nodeSeqscan.h"
      33             : #include "utils/rel.h"
      34             : 
      35             : static void InitScanRelation(SeqScanState *node, EState *estate, int eflags);
      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     2256672 : SeqNext(SeqScanState *node)
      51             : {
      52             :     HeapTuple   tuple;
      53             :     HeapScanDesc scandesc;
      54             :     EState     *estate;
      55             :     ScanDirection direction;
      56             :     TupleTableSlot *slot;
      57             : 
      58             :     /*
      59             :      * get information from the estate and scan state
      60             :      */
      61     2256672 :     scandesc = node->ss.ss_currentScanDesc;
      62     2256672 :     estate = node->ss.ps.state;
      63     2256672 :     direction = estate->es_direction;
      64     2256672 :     slot = node->ss.ss_ScanTupleSlot;
      65             : 
      66     2256672 :     if (scandesc == NULL)
      67             :     {
      68             :         /*
      69             :          * We reach here if the scan is not parallel, or if we're executing a
      70             :          * scan that was intended to be parallel serially.
      71             :          */
      72        8488 :         scandesc = heap_beginscan(node->ss.ss_currentRelation,
      73             :                                   estate->es_snapshot,
      74             :                                   0, NULL);
      75        8488 :         node->ss.ss_currentScanDesc = scandesc;
      76             :     }
      77             : 
      78             :     /*
      79             :      * get the next tuple from the table
      80             :      */
      81     2256672 :     tuple = heap_getnext(scandesc, direction);
      82             : 
      83             :     /*
      84             :      * save the tuple and the buffer returned to us by the access methods in
      85             :      * our scan tuple slot and return the slot.  Note: we pass 'false' because
      86             :      * tuples returned by heap_getnext() are pointers onto disk pages and were
      87             :      * not created with palloc() and so should not be pfree()'d.  Note also
      88             :      * that ExecStoreTuple will increment the refcount of the buffer; the
      89             :      * refcount will not be dropped until the tuple table slot is cleared.
      90             :      */
      91     2256672 :     if (tuple)
      92     2247899 :         ExecStoreTuple(tuple,   /* tuple to store */
      93             :                        slot,    /* slot to store in */
      94             :                        scandesc->rs_cbuf,    /* buffer associated with this
      95             :                                              * tuple */
      96             :                        false);  /* don't pfree this pointer */
      97             :     else
      98        8773 :         ExecClearTuple(slot);
      99             : 
     100     2256672 :     return slot;
     101             : }
     102             : 
     103             : /*
     104             :  * SeqRecheck -- access method routine to recheck a tuple in EvalPlanQual
     105             :  */
     106             : static bool
     107           0 : SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
     108             : {
     109             :     /*
     110             :      * Note that unlike IndexScan, SeqScan never use keys in heap_beginscan
     111             :      * (and this is very bad) - so, here we do not check are keys ok or not.
     112             :      */
     113           0 :     return true;
     114             : }
     115             : 
     116             : /* ----------------------------------------------------------------
     117             :  *      ExecSeqScan(node)
     118             :  *
     119             :  *      Scans the relation sequentially and returns the next qualifying
     120             :  *      tuple.
     121             :  *      We call the ExecScan() routine and pass it the appropriate
     122             :  *      access method functions.
     123             :  * ----------------------------------------------------------------
     124             :  */
     125             : static TupleTableSlot *
     126     1403842 : ExecSeqScan(PlanState *pstate)
     127             : {
     128     1403842 :     SeqScanState *node = castNode(SeqScanState, pstate);
     129             : 
     130     1403842 :     return ExecScan(&node->ss,
     131             :                     (ExecScanAccessMtd) SeqNext,
     132             :                     (ExecScanRecheckMtd) SeqRecheck);
     133             : }
     134             : 
     135             : /* ----------------------------------------------------------------
     136             :  *      InitScanRelation
     137             :  *
     138             :  *      Set up to access the scan relation.
     139             :  * ----------------------------------------------------------------
     140             :  */
     141             : static void
     142       10154 : InitScanRelation(SeqScanState *node, EState *estate, int eflags)
     143             : {
     144             :     Relation    currentRelation;
     145             : 
     146             :     /*
     147             :      * get the relation object id from the relid'th entry in the range table,
     148             :      * open that relation and acquire appropriate lock on it.
     149             :      */
     150       10154 :     currentRelation = ExecOpenScanRelation(estate,
     151       10154 :                                            ((SeqScan *) node->ss.ps.plan)->scanrelid,
     152             :                                            eflags);
     153             : 
     154       10152 :     node->ss.ss_currentRelation = currentRelation;
     155             : 
     156             :     /* and report the scan tuple slot's rowtype */
     157       10152 :     ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
     158       10152 : }
     159             : 
     160             : 
     161             : /* ----------------------------------------------------------------
     162             :  *      ExecInitSeqScan
     163             :  * ----------------------------------------------------------------
     164             :  */
     165             : SeqScanState *
     166       10154 : ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
     167             : {
     168             :     SeqScanState *scanstate;
     169             : 
     170             :     /*
     171             :      * Once upon a time it was possible to have an outerPlan of a SeqScan, but
     172             :      * not any more.
     173             :      */
     174       10154 :     Assert(outerPlan(node) == NULL);
     175       10154 :     Assert(innerPlan(node) == NULL);
     176             : 
     177             :     /*
     178             :      * create state structure
     179             :      */
     180       10154 :     scanstate = makeNode(SeqScanState);
     181       10154 :     scanstate->ss.ps.plan = (Plan *) node;
     182       10154 :     scanstate->ss.ps.state = estate;
     183       10154 :     scanstate->ss.ps.ExecProcNode = ExecSeqScan;
     184             : 
     185             :     /*
     186             :      * Miscellaneous initialization
     187             :      *
     188             :      * create expression context for node
     189             :      */
     190       10154 :     ExecAssignExprContext(estate, &scanstate->ss.ps);
     191             : 
     192             :     /*
     193             :      * initialize child expressions
     194             :      */
     195       10154 :     scanstate->ss.ps.qual =
     196       10154 :         ExecInitQual(node->plan.qual, (PlanState *) scanstate);
     197             : 
     198             :     /*
     199             :      * tuple table initialization
     200             :      */
     201       10154 :     ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
     202       10154 :     ExecInitScanTupleSlot(estate, &scanstate->ss);
     203             : 
     204             :     /*
     205             :      * initialize scan relation
     206             :      */
     207       10154 :     InitScanRelation(scanstate, estate, eflags);
     208             : 
     209             :     /*
     210             :      * Initialize result tuple type and projection info.
     211             :      */
     212       10152 :     ExecAssignResultTypeFromTL(&scanstate->ss.ps);
     213       10152 :     ExecAssignScanProjectionInfo(&scanstate->ss);
     214             : 
     215       10152 :     return scanstate;
     216             : }
     217             : 
     218             : /* ----------------------------------------------------------------
     219             :  *      ExecEndSeqScan
     220             :  *
     221             :  *      frees any storage allocated through C routines.
     222             :  * ----------------------------------------------------------------
     223             :  */
     224             : void
     225        9973 : ExecEndSeqScan(SeqScanState *node)
     226             : {
     227             :     Relation    relation;
     228             :     HeapScanDesc scanDesc;
     229             : 
     230             :     /*
     231             :      * get information from node
     232             :      */
     233        9973 :     relation = node->ss.ss_currentRelation;
     234        9973 :     scanDesc = node->ss.ss_currentScanDesc;
     235             : 
     236             :     /*
     237             :      * Free the exprcontext
     238             :      */
     239        9973 :     ExecFreeExprContext(&node->ss.ps);
     240             : 
     241             :     /*
     242             :      * clean out the tuple table
     243             :      */
     244        9973 :     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     245        9973 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
     246             : 
     247             :     /*
     248             :      * close heap scan
     249             :      */
     250        9973 :     if (scanDesc != NULL)
     251        8400 :         heap_endscan(scanDesc);
     252             : 
     253             :     /*
     254             :      * close the heap relation.
     255             :      */
     256        9973 :     ExecCloseScanRelation(relation);
     257        9973 : }
     258             : 
     259             : /* ----------------------------------------------------------------
     260             :  *                      Join Support
     261             :  * ----------------------------------------------------------------
     262             :  */
     263             : 
     264             : /* ----------------------------------------------------------------
     265             :  *      ExecReScanSeqScan
     266             :  *
     267             :  *      Rescans the relation.
     268             :  * ----------------------------------------------------------------
     269             :  */
     270             : void
     271        1877 : ExecReScanSeqScan(SeqScanState *node)
     272             : {
     273             :     HeapScanDesc scan;
     274             : 
     275        1877 :     scan = node->ss.ss_currentScanDesc;
     276             : 
     277        1877 :     if (scan != NULL)
     278        1192 :         heap_rescan(scan,       /* scan desc */
     279             :                     NULL);      /* new scan keys */
     280             : 
     281        1877 :     ExecScanReScan((ScanState *) node);
     282        1877 : }
     283             : 
     284             : /* ----------------------------------------------------------------
     285             :  *                      Parallel Scan Support
     286             :  * ----------------------------------------------------------------
     287             :  */
     288             : 
     289             : /* ----------------------------------------------------------------
     290             :  *      ExecSeqScanEstimate
     291             :  *
     292             :  *      estimates the space required to serialize seqscan node.
     293             :  * ----------------------------------------------------------------
     294             :  */
     295             : void
     296          13 : ExecSeqScanEstimate(SeqScanState *node,
     297             :                     ParallelContext *pcxt)
     298             : {
     299          13 :     EState     *estate = node->ss.ps.state;
     300             : 
     301          13 :     node->pscan_len = heap_parallelscan_estimate(estate->es_snapshot);
     302          13 :     shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
     303          13 :     shm_toc_estimate_keys(&pcxt->estimator, 1);
     304          13 : }
     305             : 
     306             : /* ----------------------------------------------------------------
     307             :  *      ExecSeqScanInitializeDSM
     308             :  *
     309             :  *      Set up a parallel heap scan descriptor.
     310             :  * ----------------------------------------------------------------
     311             :  */
     312             : void
     313          13 : ExecSeqScanInitializeDSM(SeqScanState *node,
     314             :                          ParallelContext *pcxt)
     315             : {
     316          13 :     EState     *estate = node->ss.ps.state;
     317             :     ParallelHeapScanDesc pscan;
     318             : 
     319          13 :     pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
     320          13 :     heap_parallelscan_initialize(pscan,
     321             :                                  node->ss.ss_currentRelation,
     322             :                                  estate->es_snapshot);
     323          13 :     shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
     324          13 :     node->ss.ss_currentScanDesc =
     325          13 :         heap_beginscan_parallel(node->ss.ss_currentRelation, pscan);
     326          13 : }
     327             : 
     328             : /* ----------------------------------------------------------------
     329             :  *      ExecSeqScanReInitializeDSM
     330             :  *
     331             :  *      Reset shared state before beginning a fresh scan.
     332             :  * ----------------------------------------------------------------
     333             :  */
     334             : void
     335           2 : ExecSeqScanReInitializeDSM(SeqScanState *node,
     336             :                            ParallelContext *pcxt)
     337             : {
     338           2 :     HeapScanDesc scan = node->ss.ss_currentScanDesc;
     339             : 
     340           2 :     heap_parallelscan_reinitialize(scan->rs_parallel);
     341           2 : }
     342             : 
     343             : /* ----------------------------------------------------------------
     344             :  *      ExecSeqScanInitializeWorker
     345             :  *
     346             :  *      Copy relevant information from TOC into planstate.
     347             :  * ----------------------------------------------------------------
     348             :  */
     349             : void
     350          38 : ExecSeqScanInitializeWorker(SeqScanState *node, shm_toc *toc)
     351             : {
     352             :     ParallelHeapScanDesc pscan;
     353             : 
     354          38 :     pscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id, false);
     355          38 :     node->ss.ss_currentScanDesc =
     356          38 :         heap_beginscan_parallel(node->ss.ss_currentRelation, pscan);
     357          38 : }

Generated by: LCOV version 1.11