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

📄 gistget.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * gistget.c *	  fetch tuples from a GiST scan. * * * * IDENTIFICATION *	  /usr/local/devel/pglite/cvs/src/backend/access/gisr/gistget.c,v 1.9.1 1996/11/21 01:00:00 vadim Exp * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/gist.h"#include "executor/execdebug.h"static OffsetNumber gistfindnext(IndexScanDesc s, Page p, OffsetNumber n,			 ScanDirection dir);static RetrieveIndexResult gistscancache(IndexScanDesc s, ScanDirection dir);static RetrieveIndexResult gistfirst(IndexScanDesc s, ScanDirection dir);static RetrieveIndexResult gistnext(IndexScanDesc s, ScanDirection dir);static ItemPointer gistheapptr(Relation r, ItemPointer itemp);static bool gistindex_keytest(IndexTuple tuple, TupleDesc tupdesc,				  int scanKeySize, ScanKey key, GISTSTATE *giststate,				  Relation r, Page p, OffsetNumber offset);RetrieveIndexResultgistgettuple(IndexScanDesc s, ScanDirection dir){	RetrieveIndexResult res;	/* if we have it cached in the scan desc, just return the value */	if ((res = gistscancache(s, dir)) != (RetrieveIndexResult) NULL)		return res;	/* not cached, so we'll have to do some work */	if (ItemPointerIsValid(&(s->currentItemData)))		res = gistnext(s, dir);	else		res = gistfirst(s, dir);	return res;}static RetrieveIndexResultgistfirst(IndexScanDesc s, ScanDirection dir){	Buffer		b;	Page		p;	OffsetNumber n;	OffsetNumber maxoff;	RetrieveIndexResult res;	GISTPageOpaque po;	GISTScanOpaque so;	GISTSTACK  *stk;	BlockNumber blk;	IndexTuple	it;	b = ReadBuffer(s->relation, GISTP_ROOT);	p = BufferGetPage(b);	po = (GISTPageOpaque) PageGetSpecialPointer(p);	so = (GISTScanOpaque) s->opaque;	for (;;)	{		maxoff = PageGetMaxOffsetNumber(p);		if (ScanDirectionIsBackward(dir))			n = gistfindnext(s, p, maxoff, dir);		else			n = gistfindnext(s, p, FirstOffsetNumber, dir);		while (n < FirstOffsetNumber || n > maxoff)		{			ReleaseBuffer(b);			if (so->s_stack == (GISTSTACK *) NULL)				return (RetrieveIndexResult) NULL;			stk = so->s_stack;			b = ReadBuffer(s->relation, stk->gs_blk);			p = BufferGetPage(b);			po = (GISTPageOpaque) PageGetSpecialPointer(p);			maxoff = PageGetMaxOffsetNumber(p);			if (ScanDirectionIsBackward(dir))				n = OffsetNumberPrev(stk->gs_child);			else				n = OffsetNumberNext(stk->gs_child);			so->s_stack = stk->gs_parent;			pfree(stk);			n = gistfindnext(s, p, n, dir);		}		if (po->flags & F_LEAF)		{			ItemPointerSet(&(s->currentItemData), BufferGetBlockNumber(b), n);			it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));			res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));			ReleaseBuffer(b);			return res;		}		else		{			stk = (GISTSTACK *) palloc(sizeof(GISTSTACK));			stk->gs_child = n;			stk->gs_blk = BufferGetBlockNumber(b);			stk->gs_parent = so->s_stack;			so->s_stack = stk;			it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));			blk = ItemPointerGetBlockNumber(&(it->t_tid));			ReleaseBuffer(b);			b = ReadBuffer(s->relation, blk);			p = BufferGetPage(b);			po = (GISTPageOpaque) PageGetSpecialPointer(p);		}	}}static RetrieveIndexResultgistnext(IndexScanDesc s, ScanDirection dir){	Buffer		b;	Page		p;	OffsetNumber n;	OffsetNumber maxoff;	RetrieveIndexResult res;	GISTPageOpaque po;	GISTScanOpaque so;	GISTSTACK  *stk;	BlockNumber blk;	IndexTuple	it;	blk = ItemPointerGetBlockNumber(&(s->currentItemData));	n = ItemPointerGetOffsetNumber(&(s->currentItemData));	if (ScanDirectionIsForward(dir))		n = OffsetNumberNext(n);	else		n = OffsetNumberPrev(n);	b = ReadBuffer(s->relation, blk);	p = BufferGetPage(b);	po = (GISTPageOpaque) PageGetSpecialPointer(p);	so = (GISTScanOpaque) s->opaque;	for (;;)	{		maxoff = PageGetMaxOffsetNumber(p);		n = gistfindnext(s, p, n, dir);		while (n < FirstOffsetNumber || n > maxoff)		{			ReleaseBuffer(b);			if (so->s_stack == (GISTSTACK *) NULL)				return (RetrieveIndexResult) NULL;			stk = so->s_stack;			b = ReadBuffer(s->relation, stk->gs_blk);			p = BufferGetPage(b);			maxoff = PageGetMaxOffsetNumber(p);			po = (GISTPageOpaque) PageGetSpecialPointer(p);			if (ScanDirectionIsBackward(dir))				n = OffsetNumberPrev(stk->gs_child);			else				n = OffsetNumberNext(stk->gs_child);			so->s_stack = stk->gs_parent;			pfree(stk);			n = gistfindnext(s, p, n, dir);		}		if (po->flags & F_LEAF)		{			ItemPointerSet(&(s->currentItemData), BufferGetBlockNumber(b), n);			it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));			res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));			ReleaseBuffer(b);			return res;		}		else		{			stk = (GISTSTACK *) palloc(sizeof(GISTSTACK));			stk->gs_child = n;			stk->gs_blk = BufferGetBlockNumber(b);			stk->gs_parent = so->s_stack;			so->s_stack = stk;			it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));			blk = ItemPointerGetBlockNumber(&(it->t_tid));			ReleaseBuffer(b);			b = ReadBuffer(s->relation, blk);			p = BufferGetPage(b);			po = (GISTPageOpaque) PageGetSpecialPointer(p);			if (ScanDirectionIsBackward(dir))				n = PageGetMaxOffsetNumber(p);			else				n = FirstOffsetNumber;		}	}}/* Similar to index_keytest, but decompresses the key in the IndexTuple */static boolgistindex_keytest(IndexTuple tuple,				  TupleDesc tupdesc,				  int scanKeySize,				  ScanKey key,				  GISTSTATE *giststate,				  Relation r,				  Page p,				  OffsetNumber offset){	bool		isNull;	Datum		datum;	int			test;	GISTENTRY	de;	IncrIndexProcessed();	while (scanKeySize > 0)	{		datum = index_getattr(tuple,							  1,							  tupdesc,							  &isNull);		gistdentryinit(giststate, &de, (char *) datum, r, p, offset,					   IndexTupleSize(tuple) - sizeof(IndexTupleData),					   FALSE);		if (isNull)		{			/* XXX eventually should check if SK_ISNULL */			return false;		}		if (key[0].sk_flags & SK_COMMUTE)		{			test = (*fmgr_faddr(&key[0].sk_func))				(DatumGetPointer(key[0].sk_argument),				 &de, key[0].sk_procedure) ? 1 : 0;		}		else		{			test = (*fmgr_faddr(&key[0].sk_func))				(&de,				 DatumGetPointer(key[0].sk_argument),				 key[0].sk_procedure) ? 1 : 0;		}		if (!test == !(key[0].sk_flags & SK_NEGATE))			return false;		scanKeySize -= 1;		key++;	}	return true;}static OffsetNumbergistfindnext(IndexScanDesc s, Page p, OffsetNumber n, ScanDirection dir){	OffsetNumber maxoff;	char	   *it;	GISTPageOpaque po;	GISTScanOpaque so;	GISTSTATE  *giststate;	maxoff = PageGetMaxOffsetNumber(p);	po = (GISTPageOpaque) PageGetSpecialPointer(p);	so = (GISTScanOpaque) s->opaque;	giststate = so->giststate;	/*	 * If we modified the index during the scan, we may have a pointer to	 * a ghost tuple, before the scan.	If this is the case, back up one.	 */	if (so->s_flags & GS_CURBEFORE)	{		so->s_flags &= ~GS_CURBEFORE;		n = OffsetNumberPrev(n);	}	while (n >= FirstOffsetNumber && n <= maxoff)	{		it = (char *) PageGetItem(p, PageGetItemId(p, n));		if (gistindex_keytest((IndexTuple) it,							  RelationGetDescr(s->relation),							  s->numberOfKeys, s->keyData, giststate,							  s->relation, p, n))			break;		if (ScanDirectionIsBackward(dir))			n = OffsetNumberPrev(n);		else			n = OffsetNumberNext(n);	}	return n;}static RetrieveIndexResultgistscancache(IndexScanDesc s, ScanDirection dir){	RetrieveIndexResult res;	ItemPointer ip;	if (!(ScanDirectionIsNoMovement(dir)		  && ItemPointerIsValid(&(s->currentItemData))))	{		return (RetrieveIndexResult) NULL;	}	ip = gistheapptr(s->relation, &(s->currentItemData));	if (ItemPointerIsValid(ip))		res = FormRetrieveIndexResult(&(s->currentItemData), ip);	else		res = (RetrieveIndexResult) NULL;	pfree(ip);	return res;}/* *	gistheapptr returns the item pointer to the tuple in the heap relation *	for which itemp is the index relation item pointer. */static ItemPointergistheapptr(Relation r, ItemPointer itemp){	Buffer		b;	Page		p;	IndexTuple	it;	ItemPointer ip;	OffsetNumber n;	ip = (ItemPointer) palloc(sizeof(ItemPointerData));	if (ItemPointerIsValid(itemp))	{		b = ReadBuffer(r, ItemPointerGetBlockNumber(itemp));		p = BufferGetPage(b);		n = ItemPointerGetOffsetNumber(itemp);		it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));		memmove((char *) ip, (char *) &(it->t_tid),				sizeof(ItemPointerData));		ReleaseBuffer(b);	}	else		ItemPointerSetInvalid(ip);	return ip;}

⌨️ 快捷键说明

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