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

📄 rtget.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * rtget.c *	  fetch tuples from an rtree scan. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/access/rtree/rtget.c,v 1.13.2.1 1999/08/02 05:24:43 scrappy Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/iqual.h"#include "access/rtree.h"static OffsetNumber findnext(IndexScanDesc s, Page p, OffsetNumber n,		 ScanDirection dir);static RetrieveIndexResult rtscancache(IndexScanDesc s, ScanDirection dir);static RetrieveIndexResult rtfirst(IndexScanDesc s, ScanDirection dir);static RetrieveIndexResult rtnext(IndexScanDesc s, ScanDirection dir);static ItemPointer rtheapptr(Relation r, ItemPointer itemp);RetrieveIndexResultrtgettuple(IndexScanDesc s, ScanDirection dir){	RetrieveIndexResult res;	/* if we have it cached in the scan desc, just return the value */	if ((res = rtscancache(s, dir)) != (RetrieveIndexResult) NULL)		return res;	/* not cached, so we'll have to do some work */	if (ItemPointerIsValid(&(s->currentItemData)))		res = rtnext(s, dir);	else		res = rtfirst(s, dir);	return res;}static RetrieveIndexResultrtfirst(IndexScanDesc s, ScanDirection dir){	Buffer		b;	Page		p;	OffsetNumber n;	OffsetNumber maxoff;	RetrieveIndexResult res;	RTreePageOpaque po;	RTreeScanOpaque so;	RTSTACK    *stk;	BlockNumber blk;	IndexTuple	it;	b = ReadBuffer(s->relation, P_ROOT);	p = BufferGetPage(b);	po = (RTreePageOpaque) PageGetSpecialPointer(p);	so = (RTreeScanOpaque) s->opaque;	for (;;)	{		maxoff = PageGetMaxOffsetNumber(p);		if (ScanDirectionIsBackward(dir))			n = findnext(s, p, maxoff, dir);		else			n = findnext(s, p, FirstOffsetNumber, dir);		while (n < FirstOffsetNumber || n > maxoff)		{			ReleaseBuffer(b);			if (so->s_stack == (RTSTACK *) NULL)				return (RetrieveIndexResult) NULL;			stk = so->s_stack;			b = ReadBuffer(s->relation, stk->rts_blk);			p = BufferGetPage(b);			po = (RTreePageOpaque) PageGetSpecialPointer(p);			maxoff = PageGetMaxOffsetNumber(p);			if (ScanDirectionIsBackward(dir))				n = OffsetNumberPrev(stk->rts_child);			else				n = OffsetNumberNext(stk->rts_child);			so->s_stack = stk->rts_parent;			pfree(stk);			n = findnext(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 = (RTSTACK *) palloc(sizeof(RTSTACK));			stk->rts_child = n;			stk->rts_blk = BufferGetBlockNumber(b);			stk->rts_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 = (RTreePageOpaque) PageGetSpecialPointer(p);		}	}}static RetrieveIndexResultrtnext(IndexScanDesc s, ScanDirection dir){	Buffer		b;	Page		p;	OffsetNumber n;	OffsetNumber maxoff;	RetrieveIndexResult res;	RTreePageOpaque po;	RTreeScanOpaque so;	RTSTACK    *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 = (RTreePageOpaque) PageGetSpecialPointer(p);	so = (RTreeScanOpaque) s->opaque;	for (;;)	{		maxoff = PageGetMaxOffsetNumber(p);		n = findnext(s, p, n, dir);		while (n < FirstOffsetNumber || n > maxoff)		{			ReleaseBuffer(b);			if (so->s_stack == (RTSTACK *) NULL)				return (RetrieveIndexResult) NULL;			stk = so->s_stack;			b = ReadBuffer(s->relation, stk->rts_blk);			p = BufferGetPage(b);			maxoff = PageGetMaxOffsetNumber(p);			po = (RTreePageOpaque) PageGetSpecialPointer(p);			if (ScanDirectionIsBackward(dir))				n = OffsetNumberPrev(stk->rts_child);			else				n = OffsetNumberNext(stk->rts_child);			so->s_stack = stk->rts_parent;			pfree(stk);			n = findnext(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 = (RTSTACK *) palloc(sizeof(RTSTACK));			stk->rts_child = n;			stk->rts_blk = BufferGetBlockNumber(b);			stk->rts_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 = (RTreePageOpaque) PageGetSpecialPointer(p);			if (ScanDirectionIsBackward(dir))				n = PageGetMaxOffsetNumber(p);			else				n = FirstOffsetNumber;		}	}}static OffsetNumberfindnext(IndexScanDesc s, Page p, OffsetNumber n, ScanDirection dir){	OffsetNumber maxoff;	IndexTuple	it;	RTreePageOpaque po;	RTreeScanOpaque so;	maxoff = PageGetMaxOffsetNumber(p);	po = (RTreePageOpaque) PageGetSpecialPointer(p);	so = (RTreeScanOpaque) s->opaque;	/*	 * 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 & RTS_CURBEFORE)	{		so->s_flags &= ~RTS_CURBEFORE;		n = OffsetNumberPrev(n);	}	while (n >= FirstOffsetNumber && n <= maxoff)	{		it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));		if (po->flags & F_LEAF)		{			if (index_keytest(it,							  RelationGetDescr(s->relation),							  s->numberOfKeys, s->keyData))				break;		}		else		{			if (index_keytest(it,							  RelationGetDescr(s->relation),							  so->s_internalNKey, so->s_internalKey))				break;		}		if (ScanDirectionIsBackward(dir))			n = OffsetNumberPrev(n);		else			n = OffsetNumberNext(n);	}	return n;}static RetrieveIndexResultrtscancache(IndexScanDesc s, ScanDirection dir){	RetrieveIndexResult res;	ItemPointer ip;	if (!(ScanDirectionIsNoMovement(dir)		  && ItemPointerIsValid(&(s->currentItemData))))	{		return (RetrieveIndexResult) NULL;	}	ip = rtheapptr(s->relation, &(s->currentItemData));	if (ItemPointerIsValid(ip))		res = FormRetrieveIndexResult(&(s->currentItemData), ip);	else		res = (RetrieveIndexResult) NULL;	pfree(ip);	return res;}/* *	rtheapptr returns the item pointer to the tuple in the heap relation *	for which itemp is the index relation item pointer. */static ItemPointerrtheapptr(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 + -