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

📄 indexam.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * indexam.c *	  general index access method routines * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.101.2.1 2008/09/11 14:01:35 alvherre Exp $ * * INTERFACE ROUTINES *		index_open		- open an index relation by relation OID *		index_close		- close an index relation *		index_beginscan - start a scan of an index with amgettuple *		index_beginscan_multi - start a scan of an index with amgetmulti *		index_rescan	- restart a scan of an index *		index_endscan	- end a scan *		index_insert	- insert an index tuple into a relation *		index_markpos	- mark a scan position *		index_restrpos	- restore a scan position *		index_getnext	- get the next tuple from a scan *		index_getmulti	- get multiple tuples from a scan *		index_bulk_delete	- bulk deletion of index tuples *		index_vacuum_cleanup	- post-deletion cleanup of an index *		index_getprocid - get a support procedure OID *		index_getprocinfo - get a support procedure's lookup info * * NOTES *		This file contains the index_ routines which used *		to be a scattered collection of stuff in access/genam. * * * old comments *		Scans are implemented as follows: * *		`0' represents an invalid item pointer. *		`-' represents an unknown item pointer. *		`X' represents a known item pointers. *		`+' represents known or invalid item pointers. *		`*' represents any item pointers. * *		State is represented by a triple of these symbols in the order of *		previous, current, next.  Note that the case of reverse scans works *		identically. * *				State	Result *		(1)		+ + -	+ 0 0			(if the next item pointer is invalid) *		(2)				+ X -			(otherwise) *		(3)		* 0 0	* 0 0			(no change) *		(4)		+ X 0	X 0 0			(shift) *		(5)		* + X	+ X -			(shift, add unknown) * *		All other states cannot occur. * *		Note: It would be possible to cache the status of the previous and *			  next item pointer using the flags. * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/heapam.h"#include "access/transam.h"#include "pgstat.h"#include "utils/relcache.h"/* ---------------------------------------------------------------- *					macros used in index_ routines * ---------------------------------------------------------------- */#define RELATION_CHECKS \( \	AssertMacro(RelationIsValid(indexRelation)), \	AssertMacro(PointerIsValid(indexRelation->rd_am)) \)#define SCAN_CHECKS \( \	AssertMacro(IndexScanIsValid(scan)), \	AssertMacro(RelationIsValid(scan->indexRelation)), \	AssertMacro(PointerIsValid(scan->indexRelation->rd_am)) \)#define GET_REL_PROCEDURE(pname) \do { \	procedure = &indexRelation->rd_aminfo->pname; \	if (!OidIsValid(procedure->fn_oid)) \	{ \		RegProcedure	procOid = indexRelation->rd_am->pname; \		if (!RegProcedureIsValid(procOid)) \			elog(ERROR, "invalid %s regproc", CppAsString(pname)); \		fmgr_info_cxt(procOid, procedure, indexRelation->rd_indexcxt); \	} \} while(0)#define GET_SCAN_PROCEDURE(pname) \do { \	procedure = &scan->indexRelation->rd_aminfo->pname; \	if (!OidIsValid(procedure->fn_oid)) \	{ \		RegProcedure	procOid = scan->indexRelation->rd_am->pname; \		if (!RegProcedureIsValid(procOid)) \			elog(ERROR, "invalid %s regproc", CppAsString(pname)); \		fmgr_info_cxt(procOid, procedure, scan->indexRelation->rd_indexcxt); \	} \} while(0)static IndexScanDesc index_beginscan_internal(Relation indexRelation,						 int nkeys, ScanKey key);/* ---------------------------------------------------------------- *				   index_ interface functions * ---------------------------------------------------------------- *//* ---------------- *		index_open - open an index relation by relation OID * *		If lockmode is not "NoLock", the specified kind of lock is *		obtained on the index.	(Generally, NoLock should only be *		used if the caller knows it has some appropriate lock on the *		index already.) * *		An error is raised if the index does not exist. * *		This is a convenience routine adapted for indexscan use. *		Some callers may prefer to use relation_open directly. * ---------------- */Relationindex_open(Oid relationId, LOCKMODE lockmode){	Relation	r;	r = relation_open(relationId, lockmode);	if (r->rd_rel->relkind != RELKIND_INDEX)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not an index",						RelationGetRelationName(r))));	return r;}/* ---------------- *		index_close - close an index relation * *		If lockmode is not "NoLock", we then release the specified lock. * *		Note that it is often sensible to hold a lock beyond index_close; *		in that case, the lock is released automatically at xact end. * ---------------- */voidindex_close(Relation relation, LOCKMODE lockmode){	LockRelId	relid = relation->rd_lockInfo.lockRelId;	Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);	/* The relcache does the real work... */	RelationClose(relation);	if (lockmode != NoLock)		UnlockRelationId(&relid, lockmode);}/* ---------------- *		index_insert - insert an index tuple into a relation * ---------------- */boolindex_insert(Relation indexRelation,			 Datum *values,			 bool *isnull,			 ItemPointer heap_t_ctid,			 Relation heapRelation,			 bool check_uniqueness){	FmgrInfo   *procedure;	RELATION_CHECKS;	GET_REL_PROCEDURE(aminsert);	/*	 * have the am's insert proc do all the work.	 */	return DatumGetBool(FunctionCall6(procedure,									  PointerGetDatum(indexRelation),									  PointerGetDatum(values),									  PointerGetDatum(isnull),									  PointerGetDatum(heap_t_ctid),									  PointerGetDatum(heapRelation),									  BoolGetDatum(check_uniqueness)));}/* * index_beginscan - start a scan of an index with amgettuple * * Note: heapRelation may be NULL if there is no intention of calling * index_getnext on this scan; index_getnext_indexitem will not use the * heapRelation link (nor the snapshot).  However, the caller had better * be holding some kind of lock on the heap relation in any case, to ensure * no one deletes it (or the index) out from under us.	Caller must also * be holding a lock on the index. */IndexScanDescindex_beginscan(Relation heapRelation,				Relation indexRelation,				Snapshot snapshot,				int nkeys, ScanKey key){	IndexScanDesc scan;	scan = index_beginscan_internal(indexRelation, nkeys, key);	/*	 * Save additional parameters into the scandesc.  Everything else was set	 * up by RelationGetIndexScan.	 */	scan->is_multiscan = false;	scan->heapRelation = heapRelation;	scan->xs_snapshot = snapshot;	return scan;}/* * index_beginscan_multi - start a scan of an index with amgetmulti * * As above, caller had better be holding some lock on the parent heap * relation, even though it's not explicitly mentioned here. */IndexScanDescindex_beginscan_multi(Relation indexRelation,					  Snapshot snapshot,					  int nkeys, ScanKey key){	IndexScanDesc scan;	scan = index_beginscan_internal(indexRelation, nkeys, key);	/*	 * Save additional parameters into the scandesc.  Everything else was set	 * up by RelationGetIndexScan.	 */	scan->is_multiscan = true;	scan->xs_snapshot = snapshot;	return scan;}/* * index_beginscan_internal --- common code for index_beginscan variants */static IndexScanDescindex_beginscan_internal(Relation indexRelation,						 int nkeys, ScanKey key){	IndexScanDesc scan;	FmgrInfo   *procedure;	RELATION_CHECKS;	GET_REL_PROCEDURE(ambeginscan);	/*	 * We hold a reference count to the relcache entry throughout the scan.	 */	RelationIncrementReferenceCount(indexRelation);	/*	 * Tell the AM to open a scan.	 */	scan = (IndexScanDesc)		DatumGetPointer(FunctionCall3(procedure,									  PointerGetDatum(indexRelation),									  Int32GetDatum(nkeys),									  PointerGetDatum(key)));	return scan;}/* ---------------- *		index_rescan  - (re)start a scan of an index * * The caller may specify a new set of scankeys (but the number of keys * cannot change).	To restart the scan without changing keys, pass NULL * for the key array. * * Note that this is also called when first starting an indexscan; * see RelationGetIndexScan.  Keys *must* be passed in that case, * unless scan->numberOfKeys is zero. * ---------------- */voidindex_rescan(IndexScanDesc scan, ScanKey key){	FmgrInfo   *procedure;	SCAN_CHECKS;	GET_SCAN_PROCEDURE(amrescan);	/* Release any held pin on a heap page */	if (BufferIsValid(scan->xs_cbuf))	{		ReleaseBuffer(scan->xs_cbuf);		scan->xs_cbuf = InvalidBuffer;	}	scan->xs_next_hot = InvalidOffsetNumber;	scan->kill_prior_tuple = false;		/* for safety */	FunctionCall2(procedure,				  PointerGetDatum(scan),				  PointerGetDatum(key));}/* ---------------- *		index_endscan - end a scan * ---------------- */voidindex_endscan(IndexScanDesc scan){	FmgrInfo   *procedure;	SCAN_CHECKS;	GET_SCAN_PROCEDURE(amendscan);	/* Release any held pin on a heap page */	if (BufferIsValid(scan->xs_cbuf))	{		ReleaseBuffer(scan->xs_cbuf);		scan->xs_cbuf = InvalidBuffer;	}	/* End the AM's scan */	FunctionCall1(procedure, PointerGetDatum(scan));	/* Release index refcount acquired by index_beginscan */	RelationDecrementReferenceCount(scan->indexRelation);	/* Release the scan data structure itself */	IndexScanEnd(scan);}/* ---------------- *		index_markpos  - mark a scan position * ---------------- */voidindex_markpos(IndexScanDesc scan){	FmgrInfo   *procedure;	SCAN_CHECKS;	GET_SCAN_PROCEDURE(ammarkpos);	FunctionCall1(procedure, PointerGetDatum(scan));}/* ---------------- *		index_restrpos	- restore a scan position * * NOTE: this only restores the internal scan state of the index AM. * The current result tuple (scan->xs_ctup) doesn't change.  See comments * for ExecRestrPos(). * * NOTE: in the presence of HOT chains, mark/restore only works correctly * if the scan's snapshot is MVCC-safe; that ensures that there's at most one * returnable tuple in each HOT chain, and so restoring the prior state at the * granularity of the index AM is sufficient.  Since the only current user * of mark/restore functionality is nodeMergejoin.c, this effectively means * that merge-join plans only work for MVCC snapshots.	This could be fixed * if necessary, but for now it seems unimportant. * ---------------- */voidindex_restrpos(IndexScanDesc scan){	FmgrInfo   *procedure;	Assert(IsMVCCSnapshot(scan->xs_snapshot));	SCAN_CHECKS;	GET_SCAN_PROCEDURE(amrestrpos);	scan->xs_next_hot = InvalidOffsetNumber;	scan->kill_prior_tuple = false;		/* for safety */	FunctionCall1(procedure, PointerGetDatum(scan));}/* ---------------- *		index_getnext - get the next heap tuple from a scan * * The result is the next heap tuple satisfying the scan keys and the * snapshot, or NULL if no more matching tuples exist.	On success, * the buffer containing the heap tuple is pinned (the pin will be dropped * at the next index_getnext or index_endscan). * ---------------- */HeapTupleindex_getnext(IndexScanDesc scan, ScanDirection direction){	HeapTuple	heapTuple = &scan->xs_ctup;	ItemPointer tid = &heapTuple->t_self;	FmgrInfo   *procedure;	SCAN_CHECKS;	GET_SCAN_PROCEDURE(amgettuple);	Assert(TransactionIdIsValid(RecentGlobalXmin));	/*	 * We always reset xs_hot_dead; if we are here then either we are just	 * starting the scan, or we previously returned a visible tuple, and in	 * either case it's inappropriate to kill the prior index entry.	 */	scan->xs_hot_dead = false;	for (;;)	{		OffsetNumber offnum;		bool		at_chain_start;		Page		dp;		if (scan->xs_next_hot != InvalidOffsetNumber)		{			/*			 * We are resuming scan of a HOT chain after having returned an			 * earlier member.	Must still hold pin on current heap page.

⌨️ 快捷键说明

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