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

📄 nbtsearch.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
			return true;		}		/* This tuple doesn't pass, but there might be more that do */	} while (continuescan);	/* No more items, so close down the current-item info */	ItemPointerSetInvalid(current);	so->btso_curbuf = InvalidBuffer;	_bt_relbuf(rel, buf);	return false;}/* *	_bt_first() -- Find the first item in a scan. * *		We need to be clever about the type of scan, the operation it's *		performing, and the tree ordering.	We find the *		first item in the tree that satisfies the qualification *		associated with the scan descriptor.  On exit, the page containing *		the current index tuple is read locked and pinned, and the scan's *		opaque data entry is updated to include the buffer. */bool_bt_first(IndexScanDesc scan, ScanDirection dir){	Relation	rel = scan->indexRelation;	BTScanOpaque so = (BTScanOpaque) scan->opaque;	Buffer		buf;	Page		page;	BTStack		stack;	OffsetNumber offnum;	BTItem		btitem;	IndexTuple	itup;	ItemPointer current;	BlockNumber blkno;	StrategyNumber strat;	bool		res;	int32		result;	bool		scanFromEnd;	bool		continuescan;	ScanKey		scankeys = NULL;	int			keysCount = 0;	int		   *nKeyIs = NULL;	int			i,				j;	StrategyNumber strat_total;	/*	 * Order the scan keys in our canonical fashion and eliminate any	 * redundant keys.	 */	_bt_orderkeys(scan);	/*	 * Quit now if _bt_orderkeys() discovered that the scan keys can never	 * be satisfied (eg, x == 1 AND x > 2).	 */	if (!so->qual_ok)		return false;	/*	 * Examine the scan keys to discover where we need to start the scan.	 */	scanFromEnd = false;	strat_total = BTEqualStrategyNumber;	if (so->numberOfKeys > 0)	{		nKeyIs = (int *) palloc(so->numberOfKeys * sizeof(int));		for (i = 0; i < so->numberOfKeys; i++)		{			AttrNumber	attno = so->keyData[i].sk_attno;			/* ignore keys for already-determined attrs */			if (attno <= keysCount)				continue;			/* if we didn't find a boundary for the preceding attr, quit */			if (attno > keysCount + 1)				break;			strat = _bt_getstrat(rel, attno,								 so->keyData[i].sk_procedure);			/*			 * Can we use this key as a starting boundary for this attr?			 *			 * We can use multiple keys if they look like, say, = >= = but we			 * have to stop after accepting a > or < boundary.			 */			if (strat == strat_total ||				strat == BTEqualStrategyNumber)				nKeyIs[keysCount++] = i;			else if (ScanDirectionIsBackward(dir) &&					 (strat == BTLessStrategyNumber ||					  strat == BTLessEqualStrategyNumber))			{				nKeyIs[keysCount++] = i;				strat_total = strat;				if (strat == BTLessStrategyNumber)					break;			}			else if (ScanDirectionIsForward(dir) &&					 (strat == BTGreaterStrategyNumber ||					  strat == BTGreaterEqualStrategyNumber))			{				nKeyIs[keysCount++] = i;				strat_total = strat;				if (strat == BTGreaterStrategyNumber)					break;			}		}		if (keysCount == 0)			scanFromEnd = true;	}	else		scanFromEnd = true;	/* if we just need to walk down one edge of the tree, do that */	if (scanFromEnd)	{		if (nKeyIs)			pfree(nKeyIs);		return _bt_endpoint(scan, dir);	}	/*	 * We want to start the scan somewhere within the index.  Set up a	 * scankey we can use to search for the correct starting point.	 */	scankeys = (ScanKey) palloc(keysCount * sizeof(ScanKeyData));	for (i = 0; i < keysCount; i++)	{		FmgrInfo   *procinfo;		j = nKeyIs[i];		/*		 * _bt_orderkeys disallows it, but it's place to add some code		 * later		 */		if (so->keyData[j].sk_flags & SK_ISNULL)		{			pfree(nKeyIs);			pfree(scankeys);			elog(ERROR, "btree doesn't support is(not)null, yet");			return false;		}		procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);		ScanKeyEntryInitializeWithInfo(scankeys + i,									   so->keyData[j].sk_flags,									   i + 1,									   procinfo,									   CurrentMemoryContext,									   so->keyData[j].sk_argument);	}	if (nKeyIs)		pfree(nKeyIs);	current = &(scan->currentItemData);	/*	 * Use the manufactured scan key to descend the tree and position	 * ourselves on the target leaf page.	 */	stack = _bt_search(rel, keysCount, scankeys, &buf, BT_READ);	/* don't need to keep the stack around... */	_bt_freestack(stack);	if (!BufferIsValid(buf))	{		/* Only get here if index is completely empty */		ItemPointerSetInvalid(current);		so->btso_curbuf = InvalidBuffer;		pfree(scankeys);		return false;	}	/* remember which buffer we have pinned */	so->btso_curbuf = buf;	blkno = BufferGetBlockNumber(buf);	page = BufferGetPage(buf);	/* position to the precise item on the page */	offnum = _bt_binsrch(rel, buf, keysCount, scankeys);	ItemPointerSet(current, blkno, offnum);	/*	 * At this point we are positioned at the first item >= scan key, or	 * possibly at the end of a page on which all the existing items are	 * less than the scan key and we know that everything on later pages	 * is greater than or equal to scan key.	 *	 * We could step forward in the latter case, but that'd be a waste of	 * time if we want to scan backwards.  So, it's now time to examine	 * the scan strategy to find the exact place to start the scan.	 *	 * Note: if _bt_step fails (meaning we fell off the end of the index in	 * one direction or the other), we either return false (no matches) or	 * call _bt_endpoint() to set up a scan starting at that index	 * endpoint, as appropriate for the desired scan type.	 *	 * it's yet other place to add some code later for is(not)null ...	 */	switch (strat_total)	{		case BTLessStrategyNumber:			/*			 * Back up one to arrive at last item < scankey			 */			if (!_bt_step(scan, &buf, BackwardScanDirection))			{				pfree(scankeys);				return false;			}			break;		case BTLessEqualStrategyNumber:			/*			 * We need to find the last item <= scankey, so step forward			 * till we find one > scankey, then step back one.			 */			if (offnum > PageGetMaxOffsetNumber(page))			{				if (!_bt_step(scan, &buf, ForwardScanDirection))				{					pfree(scankeys);					return _bt_endpoint(scan, dir);				}			}			for (;;)			{				offnum = ItemPointerGetOffsetNumber(current);				page = BufferGetPage(buf);				result = _bt_compare(rel, keysCount, scankeys, page, offnum);				if (result < 0)					break;				if (!_bt_step(scan, &buf, ForwardScanDirection))				{					pfree(scankeys);					return _bt_endpoint(scan, dir);				}			}			if (!_bt_step(scan, &buf, BackwardScanDirection))			{				pfree(scankeys);				return false;			}			break;		case BTEqualStrategyNumber:			/*			 * Make sure we are on the first equal item; might have to			 * step forward if currently at end of page.			 */			if (offnum > PageGetMaxOffsetNumber(page))			{				if (!_bt_step(scan, &buf, ForwardScanDirection))				{					pfree(scankeys);					return false;				}				offnum = ItemPointerGetOffsetNumber(current);				page = BufferGetPage(buf);			}			result = _bt_compare(rel, keysCount, scankeys, page, offnum);			if (result != 0)				goto nomatches; /* no equal items! */			/*			 * If a backward scan was specified, need to start with last			 * equal item not first one.			 */			if (ScanDirectionIsBackward(dir))			{				do				{					if (!_bt_step(scan, &buf, ForwardScanDirection))					{						pfree(scankeys);						return _bt_endpoint(scan, dir);					}					offnum = ItemPointerGetOffsetNumber(current);					page = BufferGetPage(buf);					result = _bt_compare(rel, keysCount, scankeys, page, offnum);				} while (result == 0);				if (!_bt_step(scan, &buf, BackwardScanDirection))					elog(ERROR, "equal items disappeared?");			}			break;		case BTGreaterEqualStrategyNumber:			/*			 * We want the first item >= scankey, which is where we are...			 * unless we're not anywhere at all...			 */			if (offnum > PageGetMaxOffsetNumber(page))			{				if (!_bt_step(scan, &buf, ForwardScanDirection))				{					pfree(scankeys);					return false;				}			}			break;		case BTGreaterStrategyNumber:			/*			 * We want the first item > scankey, so make sure we are on an			 * item and then step over any equal items.			 */			if (offnum > PageGetMaxOffsetNumber(page))			{				if (!_bt_step(scan, &buf, ForwardScanDirection))				{					pfree(scankeys);					return false;				}				offnum = ItemPointerGetOffsetNumber(current);				page = BufferGetPage(buf);			}			result = _bt_compare(rel, keysCount, scankeys, page, offnum);			while (result == 0)			{				if (!_bt_step(scan, &buf, ForwardScanDirection))				{					pfree(scankeys);					return false;				}				offnum = ItemPointerGetOffsetNumber(current);				page = BufferGetPage(buf);				result = _bt_compare(rel, keysCount, scankeys, page, offnum);			}			break;	}	/* okay, current item pointer for the scan is right */	offnum = ItemPointerGetOffsetNumber(current);	page = BufferGetPage(buf);	btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));	itup = &btitem->bti_itup;	/* is the first item actually acceptable? */	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 */nomatches:		ItemPointerSetInvalid(current);		so->btso_curbuf = InvalidBuffer;		_bt_relbuf(rel, buf);		res = false;	}	pfree(scankeys);	return res;}/* *	_bt_step() -- Step one item in the requested direction in a scan on *				  the tree. * *		*bufP is the current buffer (read-locked and pinned).  If we change *		pages, it's updated appropriately. * *		If successful, update scan's currentItemData and return true. *		If no adjacent record exists in the requested direction, *		release buffer pin/locks and return false. */bool_bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir){	Relation	rel = scan->indexRelation;	ItemPointer current = &(scan->currentItemData);	BTScanOpaque so = (BTScanOpaque) scan->opaque;	Page		page;	BTPageOpaque opaque;	OffsetNumber offnum,				maxoff;	BlockNumber blkno;	/*	 * Don't use ItemPointerGetOffsetNumber or you risk to get assertion	 * due to ability of ip_posid to be equal 0.	 */	offnum = current->ip_posid;	page = BufferGetPage(*bufP);	opaque = (BTPageOpaque) PageGetSpecialPointer(page);	maxoff = PageGetMaxOffsetNumber(page);	if (ScanDirectionIsForward(dir))

⌨️ 快捷键说明

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