⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nodeseqscan.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * nodeSeqscan.c *	  Support routines for sequential scans of relations. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.18 1999/05/25 16:08:46 momjian 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 *		ExecMarkPos				marks scan position *		ExecRestrPos			restores scan position * */#include "postgres.h"#include "executor/executor.h"#include "executor/execdebug.h"#include "executor/nodeSeqscan.h"#include "access/heapam.h"#include "parser/parsetree.h"#include "nodes/print.h"static Oid InitScanRelation(SeqScan *node, EState *estate,				 CommonScanState *scanstate, Plan *outerPlan);static TupleTableSlot *SeqNext(SeqScan *node);/* ---------------------------------------------------------------- *						Scan Support * ---------------------------------------------------------------- *//* ---------------------------------------------------------------- *		SeqNext * *		This is a workhorse for ExecSeqScan * ---------------------------------------------------------------- */static TupleTableSlot *SeqNext(SeqScan *node){	HeapTuple	tuple;	HeapScanDesc scandesc;	CommonScanState *scanstate;	EState	   *estate;	ScanDirection direction;	TupleTableSlot *slot;	/* ----------------	 *	get information from the estate and scan state	 * ----------------	 */	estate = node->plan.state;	scanstate = node->scanstate;	scandesc = scanstate->css_currentScanDesc;	direction = estate->es_direction;	slot = scanstate->css_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[node->scanrelid - 1] != NULL)	{		slot->ttc_buffer = InvalidBuffer;		slot->ttc_shouldFree = false;		if (estate->es_evTupleNull[node->scanrelid - 1])		{			slot->val = NULL;	/* must not free tuple! */			return (slot);		}		slot->val = estate->es_evTuple[node->scanrelid - 1];		/*		 * Note that unlike IndexScan, SeqScan never use keys in		 * heap_beginscan (and this is very bad) - so, here we have not		 * check are keys ok or not.		 */		/* Flag for the next call that no more tuples */		estate->es_evTupleNull[node->scanrelid - 1] = true;		return (slot);	}	/* ----------------	 *	get the next tuple from the access methods	 * ----------------	 */	tuple = heap_getnext(scandesc, ScanDirectionIsBackward(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.	 * ----------------	 */	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 */	/* ----------------	 *	XXX -- mao says:  The sequential scan for heap relations will	 *	automatically unpin the buffer this tuple is on when we cross	 *	a page boundary.  The clearslot code also does this.  We bump	 *	the pin count on the page here, since we actually have two	 *	pointers to it -- one in the scan desc and one in the tuple	 *	table slot.  --mar 20 91	 * ----------------	 */	ExecIncrSlotBufferRefcnt(slot);	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(SeqScan *node){	TupleTableSlot *slot;	Plan	   *outerPlan;	S_printf("ExecSeqScan: scanning node: ");	S_nodeDisplay(node);	/* ----------------	 * if there is an outer subplan, get a tuple from it	 * else, scan the relation	 * ----------------	 */	if ((outerPlan = outerPlan((Plan *) node)) != NULL)		slot = ExecProcNode(outerPlan, (Plan *) node);	else		slot = ExecScan(node, SeqNext);	S1_printf("ExecSeqScan: returned tuple slot: %d\n", slot);	return slot;}/* ---------------------------------------------------------------- *		InitScanRelation * *		This does the initialization for scan relations and *		subplans of scans. * ---------------------------------------------------------------- */static OidInitScanRelation(SeqScan *node, EState *estate,				 CommonScanState *scanstate, Plan *outerPlan){	Index		relid;	List	   *rangeTable;	RangeTblEntry *rtentry;	Oid			reloid;	ScanDirection direction;	Relation	currentRelation;	HeapScanDesc currentScanDesc;	RelationInfo *resultRelationInfo;	if (outerPlan == NULL)	{		/* ----------------		 * if the outer node is nil then we are doing a simple		 * sequential scan of a relation...		 *		 * get the relation object id from the relid'th entry		 * in the range table, open that relation and initialize		 * the scan state...		 * ----------------		 */		relid = node->scanrelid;		rangeTable = estate->es_range_table;		rtentry = rt_fetch(relid, rangeTable);		reloid = rtentry->relid;		direction = estate->es_direction;		resultRelationInfo = estate->es_result_relation_info;		ExecOpenScanR(reloid,	/* relation */					  0,		/* nkeys */					  NULL,		/* scan key */					  0,		/* is index */					  direction,/* scan direction */					  estate->es_snapshot,					  &currentRelation, /* return: rel desc */					  (Pointer *) &currentScanDesc);	/* return: scan desc */		scanstate->css_currentRelation = currentRelation;		scanstate->css_currentScanDesc = currentScanDesc;		ExecAssignScanType(scanstate,						   RelationGetDescr(currentRelation));	}	else	{		/* ----------------		 *	 otherwise we are scanning tuples from the		 *	 outer subplan so we initialize the outer plan		 *	 and nullify		 * ----------------		 */		ExecInitNode(outerPlan, estate, (Plan *) node);		node->scanrelid = 0;		scanstate->css_currentRelation = NULL;		scanstate->css_currentScanDesc = NULL;		ExecAssignScanType(scanstate, NULL);		reloid = InvalidOid;	}	/* ----------------	 *	return the relation	 * ----------------	 */	return reloid;}/* ---------------------------------------------------------------- *		ExecInitSeqScan * * old comments *		Creates the run-time state information for the seqscan node *		and sets the relation id to contain relevant descriptors. * *		If there is a outer subtree (sort), the outer subtree *		is initialized and the relation id is set to the descriptors *		returned by the subtree. * ---------------------------------------------------------------- */boolExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent){	CommonScanState *scanstate;	Plan	   *outerPlan;	Oid			reloid;	HeapScanDesc scandesc;	/* ----------------	 *	assign the node's execution state	 * ----------------	 */	node->plan.state = estate;	/* ----------------	 *	 create new CommonScanState for node	 * ----------------	 */	scanstate = makeNode(CommonScanState);	node->scanstate = scanstate;	/* ----------------	 *	Miscellanious initialization	 *	 *		 +	assign node's base_id	 *		 +	create expression context for node	 * ----------------	 */	ExecAssignNodeBaseInfo(estate, &scanstate->cstate, parent);	ExecAssignExprContext(estate, &scanstate->cstate);#define SEQSCAN_NSLOTS 3	/* ----------------	 *	tuple table initialization	 * ----------------	 */	ExecInitResultTupleSlot(estate, &scanstate->cstate);	ExecInitScanTupleSlot(estate, scanstate);	/* ----------------	 *	initialize scan relation or outer subplan	 * ----------------	 */	outerPlan = outerPlan((Plan *) node);	reloid = InitScanRelation(node, estate, scanstate, outerPlan);	scandesc = scanstate->css_currentScanDesc;	scanstate->cstate.cs_TupFromTlist = false;	/* ----------------	 *	initialize tuple type	 * ----------------	 */	ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);	ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);	return TRUE;}intExecCountSlotsSeqScan(SeqScan *node){	return ExecCountSlotsNode(outerPlan(node)) +	ExecCountSlotsNode(innerPlan(node)) +	SEQSCAN_NSLOTS;}/* ---------------------------------------------------------------- *		ExecEndSeqScan * *		frees any storage allocated through C routines. *|		...and also closes relations and/or shuts down outer subplan *|		-cim 8/14/89 * ---------------------------------------------------------------- */voidExecEndSeqScan(SeqScan *node){	CommonScanState *scanstate;	Plan	   *outerPlan;	/* ----------------	 *	get information from node	 * ----------------	 */	scanstate = node->scanstate;	/* ----------------	 *	Free the projection info and the scan attribute info	 *	 *	Note: we don't ExecFreeResultType(scanstate)	 *		  because the rule manager depends on the tupType	 *		  returned by ExecMain().  So for now, this	 *		  is freed at end-transaction time.  -cim 6/2/91	 * ----------------	 */	ExecFreeProjectionInfo(&scanstate->cstate);	/* ----------------	 * close scan relation	 * ----------------	 */	ExecCloseR((Plan *) node);	/* ----------------	 * clean up outer subtree (does nothing if there is no outerPlan)	 * ----------------	 */	outerPlan = outerPlan((Plan *) node);	ExecEndNode(outerPlan, (Plan *) node);	/* ----------------	 *	clean out the tuple table	 * ----------------	 */	ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);	ExecClearTuple(scanstate->css_ScanTupleSlot);}/* ---------------------------------------------------------------- *						Join Support * ---------------------------------------------------------------- *//* ---------------------------------------------------------------- *		ExecSeqReScan * *		Rescans the relation. * ---------------------------------------------------------------- */voidExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent){	CommonScanState *scanstate;	EState	   *estate;	Plan	   *outerPlan;	Relation	rel;	HeapScanDesc scan;	ScanDirection direction;	scanstate = node->scanstate;	estate = node->plan.state;	if ((outerPlan = outerPlan((Plan *) node)) != NULL)	{		/* we are scanning a subplan */		outerPlan = outerPlan((Plan *) node);		ExecReScan(outerPlan, exprCtxt, parent);	}	else/* otherwise, we are scanning a relation */	{		/* If this is re-scanning of PlanQual ... */		if (estate->es_evTuple != NULL &&			estate->es_evTuple[node->scanrelid - 1] != NULL)		{			estate->es_evTupleNull[node->scanrelid - 1] = false;			return;		}		rel = scanstate->css_currentRelation;		scan = scanstate->css_currentScanDesc;		direction = estate->es_direction;		scan = ExecReScanR(rel, scan, direction, 0, NULL);		scanstate->css_currentScanDesc = scan;	}}/* ---------------------------------------------------------------- *		ExecSeqMarkPos(node) * *		Marks scan position. * ---------------------------------------------------------------- */voidExecSeqMarkPos(SeqScan *node){	CommonScanState *scanstate;	Plan	   *outerPlan;	HeapScanDesc scan;	scanstate = node->scanstate;	/* ----------------	 *	if we are scanning a subplan then propagate	 *	the ExecMarkPos() request to the subplan	 * ----------------	 */	outerPlan = outerPlan((Plan *) node);	if (outerPlan)	{		ExecMarkPos(outerPlan);		return;	}	/* ----------------	 *	otherwise we are scanning a relation so mark the	 *	position using the access methods..	 *	 * ----------------	 */	scan = scanstate->css_currentScanDesc;	heap_markpos(scan);	return;}/* ---------------------------------------------------------------- *		ExecSeqRestrPos * *		Restores scan position. * ---------------------------------------------------------------- */voidExecSeqRestrPos(SeqScan *node){	CommonScanState *scanstate;	Plan	   *outerPlan;	HeapScanDesc scan;	scanstate = node->scanstate;	/* ----------------	 *	if we are scanning a subplan then propagate	 *	the ExecRestrPos() request to the subplan	 * ----------------	 */	outerPlan = outerPlan((Plan *) node);	if (outerPlan)	{		ExecRestrPos(outerPlan);		return;	}	/* ----------------	 *	otherwise we are scanning a relation so restore the	 *	position using the access methods..	 * ----------------	 */	scan = scanstate->css_currentScanDesc;	heap_restrpos(scan);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -