Header And Logo

PostgreSQL
| The world's most advanced open source database.

nodeSeqscan.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeSeqscan.c
00004  *    Support routines for sequential scans of relations.
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/executor/nodeSeqscan.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 /*
00016  * INTERFACE ROUTINES
00017  *      ExecSeqScan             sequentially scans a relation.
00018  *      ExecSeqNext             retrieve next tuple in sequential order.
00019  *      ExecInitSeqScan         creates and initializes a seqscan node.
00020  *      ExecEndSeqScan          releases any storage allocated.
00021  *      ExecReScanSeqScan       rescans the relation
00022  *      ExecSeqMarkPos          marks scan position
00023  *      ExecSeqRestrPos         restores scan position
00024  */
00025 #include "postgres.h"
00026 
00027 #include "access/relscan.h"
00028 #include "executor/execdebug.h"
00029 #include "executor/nodeSeqscan.h"
00030 #include "utils/rel.h"
00031 
00032 static void InitScanRelation(SeqScanState *node, EState *estate, int eflags);
00033 static TupleTableSlot *SeqNext(SeqScanState *node);
00034 
00035 /* ----------------------------------------------------------------
00036  *                      Scan Support
00037  * ----------------------------------------------------------------
00038  */
00039 
00040 /* ----------------------------------------------------------------
00041  *      SeqNext
00042  *
00043  *      This is a workhorse for ExecSeqScan
00044  * ----------------------------------------------------------------
00045  */
00046 static TupleTableSlot *
00047 SeqNext(SeqScanState *node)
00048 {
00049     HeapTuple   tuple;
00050     HeapScanDesc scandesc;
00051     EState     *estate;
00052     ScanDirection direction;
00053     TupleTableSlot *slot;
00054 
00055     /*
00056      * get information from the estate and scan state
00057      */
00058     scandesc = node->ss_currentScanDesc;
00059     estate = node->ps.state;
00060     direction = estate->es_direction;
00061     slot = node->ss_ScanTupleSlot;
00062 
00063     /*
00064      * get the next tuple from the table
00065      */
00066     tuple = heap_getnext(scandesc, direction);
00067 
00068     /*
00069      * save the tuple and the buffer returned to us by the access methods in
00070      * our scan tuple slot and return the slot.  Note: we pass 'false' because
00071      * tuples returned by heap_getnext() are pointers onto disk pages and were
00072      * not created with palloc() and so should not be pfree()'d.  Note also
00073      * that ExecStoreTuple will increment the refcount of the buffer; the
00074      * refcount will not be dropped until the tuple table slot is cleared.
00075      */
00076     if (tuple)
00077         ExecStoreTuple(tuple,   /* tuple to store */
00078                        slot,    /* slot to store in */
00079                        scandesc->rs_cbuf,       /* buffer associated with this
00080                                                  * tuple */
00081                        false);  /* don't pfree this pointer */
00082     else
00083         ExecClearTuple(slot);
00084 
00085     return slot;
00086 }
00087 
00088 /*
00089  * SeqRecheck -- access method routine to recheck a tuple in EvalPlanQual
00090  */
00091 static bool
00092 SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
00093 {
00094     /*
00095      * Note that unlike IndexScan, SeqScan never use keys in heap_beginscan
00096      * (and this is very bad) - so, here we do not check are keys ok or not.
00097      */
00098     return true;
00099 }
00100 
00101 /* ----------------------------------------------------------------
00102  *      ExecSeqScan(node)
00103  *
00104  *      Scans the relation sequentially and returns the next qualifying
00105  *      tuple.
00106  *      We call the ExecScan() routine and pass it the appropriate
00107  *      access method functions.
00108  * ----------------------------------------------------------------
00109  */
00110 TupleTableSlot *
00111 ExecSeqScan(SeqScanState *node)
00112 {
00113     return ExecScan((ScanState *) node,
00114                     (ExecScanAccessMtd) SeqNext,
00115                     (ExecScanRecheckMtd) SeqRecheck);
00116 }
00117 
00118 /* ----------------------------------------------------------------
00119  *      InitScanRelation
00120  *
00121  *      Set up to access the scan relation.
00122  * ----------------------------------------------------------------
00123  */
00124 static void
00125 InitScanRelation(SeqScanState *node, EState *estate, int eflags)
00126 {
00127     Relation    currentRelation;
00128     HeapScanDesc currentScanDesc;
00129 
00130     /*
00131      * get the relation object id from the relid'th entry in the range table,
00132      * open that relation and acquire appropriate lock on it.
00133      */
00134     currentRelation = ExecOpenScanRelation(estate,
00135                                      ((SeqScan *) node->ps.plan)->scanrelid,
00136                                            eflags);
00137 
00138     /* initialize a heapscan */
00139     currentScanDesc = heap_beginscan(currentRelation,
00140                                      estate->es_snapshot,
00141                                      0,
00142                                      NULL);
00143 
00144     node->ss_currentRelation = currentRelation;
00145     node->ss_currentScanDesc = currentScanDesc;
00146 
00147     /* and report the scan tuple slot's rowtype */
00148     ExecAssignScanType(node, RelationGetDescr(currentRelation));
00149 }
00150 
00151 
00152 /* ----------------------------------------------------------------
00153  *      ExecInitSeqScan
00154  * ----------------------------------------------------------------
00155  */
00156 SeqScanState *
00157 ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
00158 {
00159     SeqScanState *scanstate;
00160 
00161     /*
00162      * Once upon a time it was possible to have an outerPlan of a SeqScan, but
00163      * not any more.
00164      */
00165     Assert(outerPlan(node) == NULL);
00166     Assert(innerPlan(node) == NULL);
00167 
00168     /*
00169      * create state structure
00170      */
00171     scanstate = makeNode(SeqScanState);
00172     scanstate->ps.plan = (Plan *) node;
00173     scanstate->ps.state = estate;
00174 
00175     /*
00176      * Miscellaneous initialization
00177      *
00178      * create expression context for node
00179      */
00180     ExecAssignExprContext(estate, &scanstate->ps);
00181 
00182     /*
00183      * initialize child expressions
00184      */
00185     scanstate->ps.targetlist = (List *)
00186         ExecInitExpr((Expr *) node->plan.targetlist,
00187                      (PlanState *) scanstate);
00188     scanstate->ps.qual = (List *)
00189         ExecInitExpr((Expr *) node->plan.qual,
00190                      (PlanState *) scanstate);
00191 
00192     /*
00193      * tuple table initialization
00194      */
00195     ExecInitResultTupleSlot(estate, &scanstate->ps);
00196     ExecInitScanTupleSlot(estate, scanstate);
00197 
00198     /*
00199      * initialize scan relation
00200      */
00201     InitScanRelation(scanstate, estate, eflags);
00202 
00203     scanstate->ps.ps_TupFromTlist = false;
00204 
00205     /*
00206      * Initialize result tuple type and projection info.
00207      */
00208     ExecAssignResultTypeFromTL(&scanstate->ps);
00209     ExecAssignScanProjectionInfo(scanstate);
00210 
00211     return scanstate;
00212 }
00213 
00214 /* ----------------------------------------------------------------
00215  *      ExecEndSeqScan
00216  *
00217  *      frees any storage allocated through C routines.
00218  * ----------------------------------------------------------------
00219  */
00220 void
00221 ExecEndSeqScan(SeqScanState *node)
00222 {
00223     Relation    relation;
00224     HeapScanDesc scanDesc;
00225 
00226     /*
00227      * get information from node
00228      */
00229     relation = node->ss_currentRelation;
00230     scanDesc = node->ss_currentScanDesc;
00231 
00232     /*
00233      * Free the exprcontext
00234      */
00235     ExecFreeExprContext(&node->ps);
00236 
00237     /*
00238      * clean out the tuple table
00239      */
00240     ExecClearTuple(node->ps.ps_ResultTupleSlot);
00241     ExecClearTuple(node->ss_ScanTupleSlot);
00242 
00243     /*
00244      * close heap scan
00245      */
00246     heap_endscan(scanDesc);
00247 
00248     /*
00249      * close the heap relation.
00250      */
00251     ExecCloseScanRelation(relation);
00252 }
00253 
00254 /* ----------------------------------------------------------------
00255  *                      Join Support
00256  * ----------------------------------------------------------------
00257  */
00258 
00259 /* ----------------------------------------------------------------
00260  *      ExecReScanSeqScan
00261  *
00262  *      Rescans the relation.
00263  * ----------------------------------------------------------------
00264  */
00265 void
00266 ExecReScanSeqScan(SeqScanState *node)
00267 {
00268     HeapScanDesc scan;
00269 
00270     scan = node->ss_currentScanDesc;
00271 
00272     heap_rescan(scan,           /* scan desc */
00273                 NULL);          /* new scan keys */
00274 
00275     ExecScanReScan((ScanState *) node);
00276 }
00277 
00278 /* ----------------------------------------------------------------
00279  *      ExecSeqMarkPos(node)
00280  *
00281  *      Marks scan position.
00282  * ----------------------------------------------------------------
00283  */
00284 void
00285 ExecSeqMarkPos(SeqScanState *node)
00286 {
00287     HeapScanDesc scan = node->ss_currentScanDesc;
00288 
00289     heap_markpos(scan);
00290 }
00291 
00292 /* ----------------------------------------------------------------
00293  *      ExecSeqRestrPos
00294  *
00295  *      Restores scan position.
00296  * ----------------------------------------------------------------
00297  */
00298 void
00299 ExecSeqRestrPos(SeqScanState *node)
00300 {
00301     HeapScanDesc scan = node->ss_currentScanDesc;
00302 
00303     /*
00304      * Clear any reference to the previously returned tuple.  This is needed
00305      * because the slot is simply pointing at scan->rs_cbuf, which
00306      * heap_restrpos will change; we'd have an internally inconsistent slot if
00307      * we didn't do this.
00308      */
00309     ExecClearTuple(node->ss_ScanTupleSlot);
00310 
00311     heap_restrpos(scan);
00312 }