Skip to content
Snippets Groups Projects
Select Git revision
  • benchmark-tools
  • postgres-lambda
  • master default
  • REL9_4_25
  • REL9_5_20
  • REL9_6_16
  • REL_10_11
  • REL_11_6
  • REL_12_1
  • REL_12_0
  • REL_12_RC1
  • REL_12_BETA4
  • REL9_4_24
  • REL9_5_19
  • REL9_6_15
  • REL_10_10
  • REL_11_5
  • REL_12_BETA3
  • REL9_4_23
  • REL9_5_18
  • REL9_6_14
  • REL_10_9
  • REL_11_4
23 results

nodeSeqscan.c

Blame
  • nodeSeqscan.c 8.91 KiB
    /*-------------------------------------------------------------------------
     *
     * nodeSeqscan.c
     *	  Support routines for sequential scans of relations.
     *
     * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
     * Portions Copyright (c) 1994, Regents of the University of California
     *
     *
     * IDENTIFICATION
     *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.41 2002/12/15 16:17:46 tgl Exp $
     *
     *-------------------------------------------------------------------------
     */
    /*
     * INTERFACE ROUTINES
     *		ExecSeqScan				sequentially scans a relation.
     *		ExecSeqNext				retrieve next tuple in sequential order.
     *		ExecInitSeqScan			creates and initializes a seqscan node.
     *		ExecEndSeqScan			releases any storage allocated.
     *		ExecSeqReScan			rescans the relation
     *		ExecSeqMarkPos			marks scan position
     *		ExecSeqRestrPos			restores scan position
     */
    #include "postgres.h"
    
    #include "access/heapam.h"
    #include "executor/execdebug.h"
    #include "executor/nodeSeqscan.h"
    #include "parser/parsetree.h"
    
    static void InitScanRelation(SeqScanState *node, EState *estate);
    static TupleTableSlot *SeqNext(SeqScanState *node);
    
    /* ----------------------------------------------------------------
     *						Scan Support
     * ----------------------------------------------------------------
     */
    /* ----------------------------------------------------------------
     *		SeqNext
     *
     *		This is a workhorse for ExecSeqScan
     * ----------------------------------------------------------------
     */
    static TupleTableSlot *
    SeqNext(SeqScanState *node)
    {
    	HeapTuple	tuple;
    	HeapScanDesc scandesc;
    	Index		scanrelid;
    	EState	   *estate;
    	ScanDirection direction;
    	TupleTableSlot *slot;
    
    	/*
    	 * get information from the estate and scan state
    	 */
    	estate = node->ps.state;
    	scandesc = node->ss_currentScanDesc;
    	scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
    	direction = estate->es_direction;
    	slot = node->ss_ScanTupleSlot;
    
    	/*
    	 * Check if we are evaluating PlanQual for tuple of this relation.
    	 * Additional checking is not good, but no other way for now. We could
    	 * introduce new nodes for this case and handle SeqScan --> NewNode
    	 * switching in Init/ReScan plan...
    	 */
    	if (estate->es_evTuple != NULL &&
    		estate->es_evTuple[scanrelid - 1] != NULL)
    	{
    		ExecClearTuple(slot);
    		if (estate->es_evTupleNull[scanrelid - 1])
    			return slot;		/* return empty slot */
    
    		ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
    					   slot, InvalidBuffer, false);
    
    		/*
    		 * Note that unlike IndexScan, SeqScan never use keys in
    		 * heap_beginscan (and this is very bad) - so, here we do not
    		 * check are keys ok or not.
    		 */
    
    		/* Flag for the next call that no more tuples */
    		estate->es_evTupleNull[scanrelid - 1] = true;
    		return (slot);
    	}
    
    	/*
    	 * get the next tuple from the access methods
    	 */
    	tuple = heap_getnext(scandesc, direction);
    
    	/*
    	 * save the tuple and the buffer returned to us by the access methods
    	 * in our scan tuple slot and return the slot.	Note: we pass 'false'
    	 * because tuples returned by heap_getnext() are pointers onto disk
    	 * pages and were not created with palloc() and so should not be
    	 * pfree()'d.  Note also that ExecStoreTuple will increment the
    	 * refcount of the buffer; the refcount will not be dropped until the
    	 * tuple table slot is cleared.
    	 */
    
    	slot = ExecStoreTuple(tuple,	/* tuple to store */
    						  slot, /* slot to store in */
    						  scandesc->rs_cbuf,	/* buffer associated with
    												 * this tuple */
    						  false);		/* don't pfree this pointer */
    
    	return slot;
    }
    
    /* ----------------------------------------------------------------
     *		ExecSeqScan(node)
     *
     *		Scans the relation sequentially and returns the next qualifying
     *		tuple.
     *		It calls the ExecScan() routine and passes it the access method
     *		which retrieve tuples sequentially.
     *
     */
    
    TupleTableSlot *
    ExecSeqScan(SeqScanState *node)
    {
    	/*
    	 * use SeqNext as access method
    	 */
    	return ExecScan((ScanState *) node, (ExecScanAccessMtd) SeqNext);
    }
    
    /* ----------------------------------------------------------------
     *		InitScanRelation
     *
     *		This does the initialization for scan relations and
     *		subplans of scans.
     * ----------------------------------------------------------------
     */
    static void
    InitScanRelation(SeqScanState *node, EState *estate)
    {
    	Index		relid;
    	List	   *rangeTable;
    	RangeTblEntry *rtentry;
    	Oid			reloid;
    	Relation	currentRelation;
    	HeapScanDesc currentScanDesc;
    
    	/*
    	 * get the relation object id from the relid'th entry in the range
    	 * table, open that relation and initialize the scan state.
    	 *
    	 * We acquire AccessShareLock for the duration of the scan.
    	 */
    	relid = ((SeqScan *) node->ps.plan)->scanrelid;
    	rangeTable = estate->es_range_table;
    	rtentry = rt_fetch(relid, rangeTable);
    	reloid = rtentry->relid;
    
    	currentRelation = heap_open(reloid, AccessShareLock);
    
    	currentScanDesc = heap_beginscan(currentRelation,
    									 estate->es_snapshot,
    									 0,
    									 NULL);
    
    	node->ss_currentRelation = currentRelation;
    	node->ss_currentScanDesc = currentScanDesc;
    
    	ExecAssignScanType(node, RelationGetDescr(currentRelation), false);
    }
    
    
    /* ----------------------------------------------------------------
     *		ExecInitSeqScan
     * ----------------------------------------------------------------
     */
    SeqScanState *
    ExecInitSeqScan(SeqScan *node, EState *estate)
    {
    	SeqScanState *scanstate;
    
    	/*
    	 * Once upon a time it was possible to have an outerPlan of a SeqScan,
    	 * but not any more.
    	 */
    	Assert(outerPlan(node) == NULL);
    	Assert(innerPlan(node) == NULL);
    
    	/*
    	 * create state structure
    	 */
    	scanstate = makeNode(SeqScanState);
    	scanstate->ps.plan = (Plan *) node;
    	scanstate->ps.state = estate;
    
    	/*
    	 * Miscellaneous initialization
    	 *
    	 * create expression context for node
    	 */
    	ExecAssignExprContext(estate, &scanstate->ps);
    
    	/*
    	 * initialize child expressions
    	 */
    	scanstate->ps.targetlist = (List *)
    		ExecInitExpr((Expr *) node->plan.targetlist,
    					 (PlanState *) scanstate);
    	scanstate->ps.qual = (List *)
    		ExecInitExpr((Expr *) node->plan.qual,
    					 (PlanState *) scanstate);
    
    #define SEQSCAN_NSLOTS 2
    
    	/*
    	 * tuple table initialization
    	 */
    	ExecInitResultTupleSlot(estate, &scanstate->ps);
    	ExecInitScanTupleSlot(estate, scanstate);
    
    	/*
    	 * initialize scan relation
    	 */
    	InitScanRelation(scanstate, estate);
    
    	scanstate->ps.ps_TupFromTlist = false;
    
    	/*
    	 * initialize tuple type
    	 */
    	ExecAssignResultTypeFromTL(&scanstate->ps);
    	ExecAssignProjectionInfo(&scanstate->ps);
    
    	return scanstate;
    }
    
    int
    ExecCountSlotsSeqScan(SeqScan *node)
    {
    	return ExecCountSlotsNode(outerPlan(node)) +
    		ExecCountSlotsNode(innerPlan(node)) +
    		SEQSCAN_NSLOTS;
    }
    
    /* ----------------------------------------------------------------
     *		ExecEndSeqScan
     *
     *		frees any storage allocated through C routines.
     * ----------------------------------------------------------------
     */
    void
    ExecEndSeqScan(SeqScanState *node)
    {
    	Relation	relation;
    	HeapScanDesc scanDesc;
    
    	/*
    	 * get information from node
    	 */
    	relation = node->ss_currentRelation;
    	scanDesc = node->ss_currentScanDesc;
    
    	/*
    	 * Free the exprcontext
    	 */
    	ExecFreeExprContext(&node->ps);
    
    	/*
    	 * clean out the tuple table
    	 */
    	ExecClearTuple(node->ps.ps_ResultTupleSlot);
    	ExecClearTuple(node->ss_ScanTupleSlot);
    
    	/*
    	 * close heap scan
    	 */
    	heap_endscan(scanDesc);
    
    	/*
    	 * close the heap relation.
    	 *
    	 * Currently, we do not release the AccessShareLock acquired by
    	 * InitScanRelation.  This lock should be held till end of
    	 * transaction. (There is a faction that considers this too much
    	 * locking, however.)
    	 */
    	heap_close(relation, NoLock);
    }
    
    /* ----------------------------------------------------------------
     *						Join Support
     * ----------------------------------------------------------------
     */
    
    /* ----------------------------------------------------------------
     *		ExecSeqReScan
     *
     *		Rescans the relation.
     * ----------------------------------------------------------------
     */
    void
    ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt)
    {
    	EState	   *estate;
    	Index		scanrelid;
    	HeapScanDesc scan;
    
    	estate = node->ps.state;
    	scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
    
    	/* If this is re-scanning of PlanQual ... */
    	if (estate->es_evTuple != NULL &&
    		estate->es_evTuple[scanrelid - 1] != NULL)
    	{
    		estate->es_evTupleNull[scanrelid - 1] = false;
    		return;
    	}
    
    	scan = node->ss_currentScanDesc;
    
    	heap_rescan(scan,			/* scan desc */
    				NULL);			/* new scan keys */
    }
    
    /* ----------------------------------------------------------------
     *		ExecSeqMarkPos(node)
     *
     *		Marks scan position.
     * ----------------------------------------------------------------
     */
    void
    ExecSeqMarkPos(SeqScanState *node)
    {
    	HeapScanDesc scan;
    
    	scan = node->ss_currentScanDesc;
    	heap_markpos(scan);
    }
    
    /* ----------------------------------------------------------------
     *		ExecSeqRestrPos
     *
     *		Restores scan position.
     * ----------------------------------------------------------------
     */
    void
    ExecSeqRestrPos(SeqScanState *node)
    {
    	HeapScanDesc scan;
    
    	scan = node->ss_currentScanDesc;
    	heap_restrpos(scan);
    }