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

📄 nodeindexscan.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * nodeIndexscan.c *	  Routines to support indexed scans of relations * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.104.2.1 2005/11/22 18:23:09 momjian Exp $ * *------------------------------------------------------------------------- *//* * INTERFACE ROUTINES *		ExecIndexScan			scans a relation using indices *		ExecIndexNext			using index to retrieve next tuple *		ExecInitIndexScan		creates and initializes state info. *		ExecIndexReScan			rescans the indexed relation. *		ExecEndIndexScan		releases all storage. *		ExecIndexMarkPos		marks scan position. *		ExecIndexRestrPos		restores scan position. */#include "postgres.h"#include "access/genam.h"#include "access/heapam.h"#include "executor/execdebug.h"#include "executor/nodeIndexscan.h"#include "miscadmin.h"#include "nodes/nodeFuncs.h"#include "optimizer/clauses.h"#include "parser/parsetree.h"#include "utils/memutils.h"static TupleTableSlot *IndexNext(IndexScanState *node);/* ---------------------------------------------------------------- *		IndexNext * *		Retrieve a tuple from the IndexScan node's currentRelation *		using the index specified in the IndexScanState information. * ---------------------------------------------------------------- */static TupleTableSlot *IndexNext(IndexScanState *node){	EState	   *estate;	ExprContext *econtext;	ScanDirection direction;	IndexScanDesc scandesc;	Index		scanrelid;	HeapTuple	tuple;	TupleTableSlot *slot;	/*	 * extract necessary information from index scan node	 */	estate = node->ss.ps.state;	direction = estate->es_direction;	/* flip direction if this is an overall backward scan */	if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indexorderdir))	{		if (ScanDirectionIsForward(direction))			direction = BackwardScanDirection;		else if (ScanDirectionIsBackward(direction))			direction = ForwardScanDirection;	}	scandesc = node->iss_ScanDesc;	econtext = node->ss.ps.ps_ExprContext;	slot = node->ss.ss_ScanTupleSlot;	scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid;	/*	 * Clear any reference to the previously returned tuple.  The idea here is	 * to not have the tuple slot be the last holder of a pin on that tuple's	 * buffer; if it is, we'll need a separate visit to the bufmgr to release	 * the buffer.	By clearing here, we get to have the release done by	 * ReleaseAndReadBuffer inside index_getnext.	 */	ExecClearTuple(slot);	/*	 * 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 IndexScan --> NewNode	 * switching in Init/ReScan plan...	 */	if (estate->es_evTuple != NULL &&		estate->es_evTuple[scanrelid - 1] != NULL)	{		if (estate->es_evTupleNull[scanrelid - 1])			return slot;		/* return empty slot */		ExecStoreTuple(estate->es_evTuple[scanrelid - 1],					   slot, InvalidBuffer, false);		/* Does the tuple meet the indexqual condition? */		econtext->ecxt_scantuple = slot;		ResetExprContext(econtext);		if (!ExecQual(node->indexqualorig, econtext, false))			ExecClearTuple(slot);		/* would not be returned by scan */		/* Flag for the next call that no more tuples */		estate->es_evTupleNull[scanrelid - 1] = true;		return slot;	}	/*	 * ok, now that we have what we need, fetch the next tuple.	 */	if ((tuple = index_getnext(scandesc, direction)) != NULL)	{		/*		 * Store the scanned tuple in the scan tuple slot of the scan state.		 * Note: we pass 'false' because tuples returned by amgetnext are		 * pointers onto disk pages and must not be pfree()'d.		 */		ExecStoreTuple(tuple,	/* tuple to store */					   slot,	/* slot to store in */					   scandesc->xs_cbuf,		/* buffer containing tuple */					   false);	/* don't pfree */		return slot;	}	/*	 * if we get here it means the index scan failed so we are at the end of	 * the scan..	 */	return ExecClearTuple(slot);}/* ---------------------------------------------------------------- *		ExecIndexScan(node) * ---------------------------------------------------------------- */TupleTableSlot *ExecIndexScan(IndexScanState *node){	/*	 * If we have runtime keys and they've not already been set up, do it now.	 */	if (node->iss_RuntimeKeyInfo && !node->iss_RuntimeKeysReady)		ExecReScan((PlanState *) node, NULL);	/*	 * use IndexNext as access method	 */	return ExecScan(&node->ss, (ExecScanAccessMtd) IndexNext);}/* ---------------------------------------------------------------- *		ExecIndexReScan(node) * *		Recalculates the value of the scan keys whose value depends on *		information known at runtime and rescans the indexed relation. *		Updating the scan key was formerly done separately in *		ExecUpdateIndexScanKeys. Integrating it into ReScan makes *		rescans of indices and relations/general streams more uniform. * ---------------------------------------------------------------- */voidExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt){	EState	   *estate;	ExprContext *econtext;	ScanKey		scanKeys;	ExprState **runtimeKeyInfo;	int			numScanKeys;	Index		scanrelid;	estate = node->ss.ps.state;	econtext = node->iss_RuntimeContext;		/* context for runtime keys */	scanKeys = node->iss_ScanKeys;	runtimeKeyInfo = node->iss_RuntimeKeyInfo;	numScanKeys = node->iss_NumScanKeys;	scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid;	if (econtext)	{		/*		 * If we are being passed an outer tuple, save it for runtime key		 * calc.  We also need to link it into the "regular" per-tuple		 * econtext, so it can be used during indexqualorig evaluations.		 */		if (exprCtxt != NULL)		{			ExprContext *stdecontext;			econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;			stdecontext = node->ss.ps.ps_ExprContext;			stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple;		}		/*		 * Reset the runtime-key context so we don't leak memory as each outer		 * tuple is scanned.  Note this assumes that we will recalculate *all*		 * runtime keys on each call.		 */		ResetExprContext(econtext);	}	/*	 * If we are doing runtime key calculations (ie, the index keys depend on	 * data from an outer scan), compute the new key values	 */	if (runtimeKeyInfo)	{		ExecIndexEvalRuntimeKeys(econtext,								 runtimeKeyInfo,								 scanKeys,								 numScanKeys);		node->iss_RuntimeKeysReady = true;	}	/* 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;	}	/* reset index scan */	index_rescan(node->iss_ScanDesc, scanKeys);}/* * ExecIndexEvalRuntimeKeys *		Evaluate any runtime key values, and update the scankeys. */voidExecIndexEvalRuntimeKeys(ExprContext *econtext,						 ExprState **run_keys,						 ScanKey scan_keys,						 int n_keys){	int			j;	for (j = 0; j < n_keys; j++)	{		/*		 * If we have a run-time key, then extract the run-time expression and		 * evaluate it with respect to the current outer tuple.  We then stick		 * the result into the scan key.		 *		 * Note: the result of the eval could be a pass-by-ref value that's		 * stored in the outer scan's tuple, not in		 * econtext->ecxt_per_tuple_memory.  We assume that the outer tuple		 * will stay put throughout our scan.  If this is wrong, we could copy		 * the result into our context explicitly, but I think that's not		 * necessary...		 */		if (run_keys[j] != NULL)		{			Datum		scanvalue;			bool		isNull;			scanvalue = ExecEvalExprSwitchContext(run_keys[j],												  econtext,												  &isNull,												  NULL);			scan_keys[j].sk_argument = scanvalue;			if (isNull)				scan_keys[j].sk_flags |= SK_ISNULL;			else				scan_keys[j].sk_flags &= ~SK_ISNULL;		}	}}/* ---------------------------------------------------------------- *		ExecEndIndexScan * ---------------------------------------------------------------- */voidExecEndIndexScan(IndexScanState *node){	Relation	indexRelationDesc;	IndexScanDesc indexScanDesc;	Relation	relation;	/*	 * extract information from the node	 */	indexRelationDesc = node->iss_RelationDesc;	indexScanDesc = node->iss_ScanDesc;	relation = node->ss.ss_currentRelation;	/*	 * Free the exprcontext(s) ... now dead code, see ExecFreeExprContext	 */#ifdef NOT_USED	ExecFreeExprContext(&node->ss.ps);	if (node->iss_RuntimeContext)		FreeExprContext(node->iss_RuntimeContext);#endif	/*	 * clear out tuple table slots	 */	ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);	ExecClearTuple(node->ss.ss_ScanTupleSlot);	/*	 * close the index relation	 */	index_endscan(indexScanDesc);	index_close(indexRelationDesc);	/*	 * close the heap relation.	 *	 * Currently, we do not release the AccessShareLock acquired by	 * ExecInitIndexScan.  This lock should be held till end of transaction.	 * (There is a faction that considers this too much locking, however.)	 */	heap_close(relation, NoLock);}/* ---------------------------------------------------------------- *		ExecIndexMarkPos * ---------------------------------------------------------------- */voidExecIndexMarkPos(IndexScanState *node){	index_markpos(node->iss_ScanDesc);

⌨️ 快捷键说明

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