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

📄 nbtsearch.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
	{		if (!PageIsEmpty(page) && offnum < maxoff)			offnum = OffsetNumberNext(offnum);		else		{			/* Walk right to the next page with data */			for (;;)			{				/* if we're at end of scan, release the buffer and return */				if (P_RIGHTMOST(opaque))				{					_bt_relbuf(rel, *bufP);					ItemPointerSetInvalid(current);					*bufP = so->btso_curbuf = InvalidBuffer;					return false;				}				/* step right one page */				blkno = opaque->btpo_next;				_bt_relbuf(rel, *bufP);				*bufP = _bt_getbuf(rel, blkno, BT_READ);				page = BufferGetPage(*bufP);				opaque = (BTPageOpaque) PageGetSpecialPointer(page);				if (!P_IGNORE(opaque))				{					maxoff = PageGetMaxOffsetNumber(page);					/* done if it's not empty */					offnum = P_FIRSTDATAKEY(opaque);					if (!PageIsEmpty(page) && offnum <= maxoff)						break;				}			}		}	}	else/* backwards scan */	{		if (offnum > P_FIRSTDATAKEY(opaque))			offnum = OffsetNumberPrev(offnum);		else		{			/*			 * Walk left to the next page with data.  This is much more			 * complex than the walk-right case because of the possibility			 * that the page to our left splits while we are in flight to			 * it, plus the possibility that the page we were on gets			 * deleted after we leave it.  See nbtree/README for details.			 */			for (;;)			{				*bufP = _bt_walk_left(rel, *bufP);				/* if we're at end of scan, return failure */				if (*bufP == InvalidBuffer)				{					ItemPointerSetInvalid(current);					so->btso_curbuf = InvalidBuffer;					return false;				}				page = BufferGetPage(*bufP);				opaque = (BTPageOpaque) PageGetSpecialPointer(page);				/*				 * Okay, we managed to move left to a non-deleted page.				 * Done if it's not half-dead and not empty.  Else loop				 * back and do it all again.				 */				if (!P_IGNORE(opaque))				{					maxoff = PageGetMaxOffsetNumber(page);					offnum = maxoff;					if (!PageIsEmpty(page) &&						maxoff >= P_FIRSTDATAKEY(opaque))						break;				}			}		}	}	/* Update scan state */	so->btso_curbuf = *bufP;	blkno = BufferGetBlockNumber(*bufP);	ItemPointerSet(current, blkno, offnum);	return true;}/* * _bt_walk_left() -- step left one page, if possible * * The given buffer must be pinned and read-locked.  This will be dropped * before stepping left.  On return, we have pin and read lock on the * returned page, instead. * * Returns InvalidBuffer if there is no page to the left (no lock is held * in that case). * * When working on a non-leaf level, it is possible for the returned page * to be half-dead; the caller should check that condition and step left * again if it's important. */static Buffer_bt_walk_left(Relation rel, Buffer buf){	Page		page;	BTPageOpaque opaque;	page = BufferGetPage(buf);	opaque = (BTPageOpaque) PageGetSpecialPointer(page);	for (;;)	{		BlockNumber obknum;		BlockNumber lblkno;		BlockNumber blkno;		int			tries;		/* if we're at end of tree, release buf and return failure */		if (P_LEFTMOST(opaque))		{			_bt_relbuf(rel, buf);			break;		}		/* remember original page we are stepping left from */		obknum = BufferGetBlockNumber(buf);		/* step left */		blkno = lblkno = opaque->btpo_prev;		_bt_relbuf(rel, buf);		buf = _bt_getbuf(rel, blkno, BT_READ);		page = BufferGetPage(buf);		opaque = (BTPageOpaque) PageGetSpecialPointer(page);		/*		 * If this isn't the page we want, walk right till we find what we		 * want --- but go no more than four hops (an arbitrary limit). If		 * we don't find the correct page by then, the most likely bet is		 * that the original page got deleted and isn't in the sibling		 * chain at all anymore, not that its left sibling got split more		 * than four times.		 *		 * Note that it is correct to test P_ISDELETED not P_IGNORE here,		 * because half-dead pages are still in the sibling chain.	Caller		 * must reject half-dead pages if wanted.		 */		tries = 0;		for (;;)		{			if (!P_ISDELETED(opaque) && opaque->btpo_next == obknum)			{				/* Found desired page, return it */				return buf;			}			if (P_RIGHTMOST(opaque) || ++tries > 4)				break;			blkno = opaque->btpo_next;			_bt_relbuf(rel, buf);			buf = _bt_getbuf(rel, blkno, BT_READ);			page = BufferGetPage(buf);			opaque = (BTPageOpaque) PageGetSpecialPointer(page);		}		/* Return to the original page to see what's up */		_bt_relbuf(rel, buf);		buf = _bt_getbuf(rel, obknum, BT_READ);		page = BufferGetPage(buf);		opaque = (BTPageOpaque) PageGetSpecialPointer(page);		if (P_ISDELETED(opaque))		{			/*			 * It was deleted.	Move right to first nondeleted page (there			 * must be one); that is the page that has acquired the			 * deleted one's keyspace, so stepping left from it will take			 * us where we want to be.			 */			for (;;)			{				if (P_RIGHTMOST(opaque))					elog(ERROR, "fell off the end of \"%s\"",						 RelationGetRelationName(rel));				blkno = opaque->btpo_next;				_bt_relbuf(rel, buf);				buf = _bt_getbuf(rel, blkno, BT_READ);				page = BufferGetPage(buf);				opaque = (BTPageOpaque) PageGetSpecialPointer(page);				if (!P_ISDELETED(opaque))					break;			}			/*			 * Now return to top of loop, resetting obknum to point to			 * this nondeleted page, and try again.			 */		}		else		{			/*			 * It wasn't deleted; the explanation had better be that the			 * page to the left got split or deleted. Without this check,			 * we'd go into an infinite loop if there's anything wrong.			 */			if (opaque->btpo_prev == lblkno)				elog(ERROR, "could not find left sibling in \"%s\"",					 RelationGetRelationName(rel));			/* Okay to try again with new lblkno value */		}	}	return InvalidBuffer;}/* * _bt_get_endpoint() -- Find the first or last page on a given tree level * * If the index is empty, we will return InvalidBuffer; any other failure * condition causes ereport().	We will not return a dead page. * * The returned buffer is pinned and read-locked. */Buffer_bt_get_endpoint(Relation rel, uint32 level, bool rightmost){	Buffer		buf;	Page		page;	BTPageOpaque opaque;	OffsetNumber offnum;	BlockNumber blkno;	BTItem		btitem;	IndexTuple	itup;	/*	 * If we are looking for a leaf page, okay to descend from fast root;	 * otherwise better descend from true root.  (There is no point in	 * being smarter about intermediate levels.)	 */	if (level == 0)		buf = _bt_getroot(rel, BT_READ);	else		buf = _bt_gettrueroot(rel);	if (!BufferIsValid(buf))	{		/* empty index... */		return InvalidBuffer;	}	page = BufferGetPage(buf);	opaque = (BTPageOpaque) PageGetSpecialPointer(page);	for (;;)	{		/*		 * If we landed on a deleted page, step right to find a live page		 * (there must be one).  Also, if we want the rightmost page, step		 * right if needed to get to it (this could happen if the page		 * split since we obtained a pointer to it).		 */		while (P_IGNORE(opaque) ||			   (rightmost && !P_RIGHTMOST(opaque)))		{			blkno = opaque->btpo_next;			if (blkno == P_NONE)				elog(ERROR, "fell off the end of \"%s\"",					 RelationGetRelationName(rel));			_bt_relbuf(rel, buf);			buf = _bt_getbuf(rel, blkno, BT_READ);			page = BufferGetPage(buf);			opaque = (BTPageOpaque) PageGetSpecialPointer(page);		}		/* Done? */		if (opaque->btpo.level == level)			break;		if (opaque->btpo.level < level)			elog(ERROR, "btree level %u not found", level);		/* Descend to leftmost or rightmost child page */		if (rightmost)			offnum = PageGetMaxOffsetNumber(page);		else			offnum = P_FIRSTDATAKEY(opaque);		btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));		itup = &(btitem->bti_itup);		blkno = ItemPointerGetBlockNumber(&(itup->t_tid));		_bt_relbuf(rel, buf);		buf = _bt_getbuf(rel, blkno, BT_READ);		page = BufferGetPage(buf);		opaque = (BTPageOpaque) PageGetSpecialPointer(page);	}	return buf;}/* *	_bt_endpoint() -- Find the first or last key in the index. * * This is used by _bt_first() to set up a scan when we've determined * that the scan must start at the beginning or end of the index (for * a forward or backward scan respectively). */static bool_bt_endpoint(IndexScanDesc scan, ScanDirection dir){	Relation	rel;	Buffer		buf;	Page		page;	BTPageOpaque opaque;	ItemPointer current;	OffsetNumber maxoff;	OffsetNumber start;	BlockNumber blkno;	BTItem		btitem;	IndexTuple	itup;	BTScanOpaque so;	bool		res;	bool		continuescan;	rel = scan->indexRelation;	current = &(scan->currentItemData);	so = (BTScanOpaque) scan->opaque;	/*	 * Scan down to the leftmost or rightmost leaf page.  This is a	 * simplified version of _bt_search().	We don't maintain a stack	 * since we know we won't need it.	 */	buf = _bt_get_endpoint(rel, 0, ScanDirectionIsBackward(dir));	if (!BufferIsValid(buf))	{		/* empty index... */		ItemPointerSetInvalid(current);		so->btso_curbuf = InvalidBuffer;		return false;	}	blkno = BufferGetBlockNumber(buf);	page = BufferGetPage(buf);	opaque = (BTPageOpaque) PageGetSpecialPointer(page);	Assert(P_ISLEAF(opaque));	maxoff = PageGetMaxOffsetNumber(page);	if (ScanDirectionIsForward(dir))	{		/* There could be dead pages to the left, so not this: */		/* Assert(P_LEFTMOST(opaque)); */		start = P_FIRSTDATAKEY(opaque);	}	else if (ScanDirectionIsBackward(dir))	{		Assert(P_RIGHTMOST(opaque));		start = PageGetMaxOffsetNumber(page);		if (start < P_FIRSTDATAKEY(opaque))		/* watch out for empty												 * page */			start = P_FIRSTDATAKEY(opaque);	}	else	{		elog(ERROR, "invalid scan direction: %d", (int) dir);		start = 0;				/* keep compiler quiet */	}	ItemPointerSet(current, blkno, start);	/* remember which buffer we have pinned */	so->btso_curbuf = buf;	/*	 * Left/rightmost page could be empty due to deletions, if so step	 * till we find a nonempty page.	 */	if (start > maxoff)	{		if (!_bt_step(scan, &buf, dir))			return false;		start = ItemPointerGetOffsetNumber(current);		page = BufferGetPage(buf);	}	btitem = (BTItem) PageGetItem(page, PageGetItemId(page, start));	itup = &(btitem->bti_itup);	/* see if we picked a winner */	if (_bt_checkkeys(scan, itup, dir, &continuescan))	{		/* yes, return it */		scan->xs_ctup.t_self = itup->t_tid;		res = true;	}	else if (continuescan)	{		/* no, but there might be another one that is */		res = _bt_next(scan, dir);	}	else	{		/* no tuples in the index match this scan key */		ItemPointerSetInvalid(current);		so->btso_curbuf = InvalidBuffer;		_bt_relbuf(rel, buf);		res = false;	}	return res;}

⌨️ 快捷键说明

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