From ef92b82dbbd9f30c60ca3c8c2d3860ccd4e01987 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sun, 21 Dec 2003 17:52:34 +0000 Subject: [PATCH] Further cleanup in _bt_first: eliminate duplicate code paths. --- src/backend/access/nbtree/nbtsearch.c | 169 +++++++++++--------------- 1 file changed, 70 insertions(+), 99 deletions(-) diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index cc852984ce2..acdcf3e0a56 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.85 2003/12/21 03:00:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.86 2003/12/21 17:52:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -496,6 +496,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) StrategyNumber strat; bool res; bool nextkey; + bool goback; bool continuescan; ScanKey scankeys; ScanKey *startKeys = NULL; @@ -695,18 +696,41 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) pfree(startKeys); /* - * We want to locate either the first item >= boundary point, or - * first item > boundary point, depending on the initial-positioning - * strategy we just chose. + * Examine the selected initial-positioning strategy to determine + * exactly where we need to start the scan, and set flag variables + * to control the code below. + * + * If nextkey = false, _bt_search and _bt_binsrch will locate the + * first item >= scan key. If nextkey = true, they will locate the + * first item > scan key. + * + * If goback = true, we will then step back one item, while if + * goback = false, we will start the scan on the located item. + * + * it's yet other place to add some code later for is(not)null ... */ switch (strat_total) { case BTLessStrategyNumber: + /* + * Find first item >= scankey, then back up one to arrive at last + * item < scankey. (Note: this positioning strategy is only used + * for a backward scan, so that is always the correct starting + * position.) + */ nextkey = false; + goback = true; break; case BTLessEqualStrategyNumber: + /* + * Find first item > scankey, then back up one to arrive at last + * item <= scankey. (Note: this positioning strategy is only used + * for a backward scan, so that is always the correct starting + * position.) + */ nextkey = true; + goback = true; break; case BTEqualStrategyNumber: @@ -715,17 +739,41 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * equal item not first one. */ if (ScanDirectionIsBackward(dir)) + { + /* + * This is the same as the <= strategy. We will check + * at the end whether the found item is actually =. + */ nextkey = true; + goback = true; + } else + { + /* + * This is the same as the >= strategy. We will check + * at the end whether the found item is actually =. + */ nextkey = false; + goback = false; + } break; case BTGreaterEqualStrategyNumber: + /* + * Find first item >= scankey. (This is only used for + * forward scans.) + */ nextkey = false; + goback = false; break; case BTGreaterStrategyNumber: + /* + * Find first item > scankey. (This is only used for + * forward scans.) + */ nextkey = true; + goback = false; break; default: @@ -756,21 +804,18 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) /* 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, nextkey); + page = BufferGetPage(buf); + blkno = BufferGetBlockNumber(buf); ItemPointerSet(current, blkno, offnum); /* done with manufactured scankey, now */ pfree(scankeys); /* - * It's now time to examine the initial-positioning strategy to find the - * exact place to start the scan. - * * If nextkey = false, 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 @@ -781,103 +826,29 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * less than or equal to the scan key and we know that everything on * later pages is greater than scan key. * - * The actually desired starting point is either this item or an adjacent - * one, or in the end-of-page case it's the last item on this page or - * the first item on the next. We apply _bt_step if needed to get to + * The actually desired starting point is either this item or the prior + * one, or in the end-of-page case it's the first item on the next page + * or the last item on this page. We apply _bt_step if needed to get to * the right place. * - * Note: if _bt_step fails (meaning we fell off the end of the index in + * If _bt_step fails (meaning we fell off the end of the index in * one direction or the other), then there are no matches so we just * return false. - * - * it's yet other place to add some code later for is(not)null ... */ - switch (strat_total) + if (goback) { - case BTLessStrategyNumber: - - /* - * We are on first item >= scankey. - * - * Back up one to arrive at last item < scankey. (Note: this - * positioning strategy is only used for a backward scan, so - * that is always the correct starting position.) - */ - if (!_bt_step(scan, &buf, BackwardScanDirection)) - return false; - break; - - case BTLessEqualStrategyNumber: - - /* - * We are on first item > scankey. - * - * Back up one to arrive at last item <= scankey. (Note: this - * positioning strategy is only used for a backward scan, so - * that is always the correct starting position.) - */ - if (!_bt_step(scan, &buf, BackwardScanDirection)) + /* _bt_step will do the right thing if we are at end-of-page */ + if (!_bt_step(scan, &buf, BackwardScanDirection)) + return false; + } + else + { + /* If we're at end-of-page, must step forward to next page */ + if (offnum > PageGetMaxOffsetNumber(page)) + { + if (!_bt_step(scan, &buf, ForwardScanDirection)) return false; - break; - - case BTEqualStrategyNumber: - /* - * If a backward scan was specified, need to start with last - * equal item not first one. - */ - if (ScanDirectionIsBackward(dir)) - { - /* - * We are on first item > scankey. - * - * Back up one to arrive at last item <= scankey. - * We will check below to see if it is equal to scankey. - */ - if (!_bt_step(scan, &buf, BackwardScanDirection)) - return false; - } - else - { - /* - * We are on first item >= scankey. - * - * Make sure we are on a real item; might have to - * step forward if currently at end of page. - * We will check below to see if it is equal to scankey. - */ - if (offnum > PageGetMaxOffsetNumber(page)) - { - if (!_bt_step(scan, &buf, ForwardScanDirection)) - return false; - } - } - 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)) - return false; - } - break; - - case BTGreaterStrategyNumber: - - /* - * 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)) - return false; - } - break; + } } /* okay, current item pointer for the scan is right */ -- GitLab