diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 70aca882e6c..589a49a2cea 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.134 2005/11/22 18:17:06 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.135 2005/12/07 19:37:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -288,21 +288,6 @@ btgettuple(PG_FUNCTION_ARGS) else res = _bt_first(scan, dir); - /* - * Skip killed tuples if asked to. - */ - if (scan->ignore_killed_tuples) - { - while (res) - { - offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData)); - page = BufferGetPage(so->btso_curbuf); - if (!ItemIdDeleted(PageGetItemId(page, offnum))) - break; - res = _bt_next(scan, dir); - } - } - /* * Save heap TID to use it in _bt_restscan. Then release the read lock on * the buffer so that we aren't blocking other backends. @@ -353,25 +338,6 @@ btgetmulti(PG_FUNCTION_ARGS) res = _bt_next(scan, ForwardScanDirection); else res = _bt_first(scan, ForwardScanDirection); - - /* - * Skip killed tuples if asked to. - */ - if (scan->ignore_killed_tuples) - { - while (res) - { - Page page; - OffsetNumber offnum; - - offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData)); - page = BufferGetPage(so->btso_curbuf); - if (!ItemIdDeleted(PageGetItemId(page, offnum))) - break; - res = _bt_next(scan, ForwardScanDirection); - } - } - if (!res) break; /* Save tuple ID, and continue scanning */ @@ -385,9 +351,8 @@ btgetmulti(PG_FUNCTION_ARGS) */ if (res) { - ((BTScanOpaque) scan->opaque)->curHeapIptr = scan->xs_ctup.t_self; - LockBuffer(((BTScanOpaque) scan->opaque)->btso_curbuf, - BUFFER_LOCK_UNLOCK); + so->curHeapIptr = scan->xs_ctup.t_self; + LockBuffer(so->btso_curbuf, BUFFER_LOCK_UNLOCK); } *returned_tids = ntids; diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index dd4f500842b..4cd79997292 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.98 2005/12/07 18:03:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.99 2005/12/07 19:37:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -423,8 +423,6 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) Page page; OffsetNumber offnum; ItemPointer current; - BTItem btitem; - IndexTuple itup; BTScanOpaque so; bool continuescan; @@ -445,13 +443,10 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) /* current is the next candidate tuple to return */ offnum = ItemPointerGetOffsetNumber(current); page = BufferGetPage(buf); - btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); - itup = &btitem->bti_itup; - if (_bt_checkkeys(scan, itup, dir, &continuescan)) + if (_bt_checkkeys(scan, page, offnum, dir, &continuescan)) { /* tuple passes all scan key conditions, so return it */ - scan->xs_ctup.t_self = itup->t_tid; return true; } @@ -485,8 +480,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) Page page; BTStack stack; OffsetNumber offnum; - BTItem btitem; - IndexTuple itup; ItemPointer current; BlockNumber blkno; StrategyNumber strat; @@ -848,14 +841,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) /* 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)) + if (_bt_checkkeys(scan, page, offnum, dir, &continuescan)) { /* yes, return it */ - scan->xs_ctup.t_self = itup->t_tid; res = true; } else if (continuescan) @@ -1215,8 +1205,6 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) OffsetNumber maxoff; OffsetNumber start; BlockNumber blkno; - BTItem btitem; - IndexTuple itup; BTScanOpaque so; bool res; bool continuescan; @@ -1284,16 +1272,12 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) page = BufferGetPage(buf); } - btitem = (BTItem) PageGetItem(page, PageGetItemId(page, start)); - itup = &(btitem->bti_itup); - /* * Okay, we are on the first or last tuple. Does it pass all the quals? */ - if (_bt_checkkeys(scan, itup, dir, &continuescan)) + if (_bt_checkkeys(scan, page, start, dir, &continuescan)) { /* yes, return it */ - scan->xs_ctup.t_self = itup->t_tid; res = true; } else if (continuescan) diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index f4c2243943b..7a18fcf0abb 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.66 2005/11/22 18:17:06 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.67 2005/12/07 19:37:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -477,30 +477,77 @@ _bt_preprocess_keys(IndexScanDesc scan) /* * Test whether an indextuple satisfies all the scankey conditions. * + * If so, copy its TID into scan->xs_ctup.t_self, and return TRUE. + * If not, return FALSE (xs_ctup is not changed). + * * If the tuple fails to pass the qual, we also determine whether there's * any need to continue the scan beyond this tuple, and set *continuescan * accordingly. See comments for _bt_preprocess_keys(), above, about how * this is done. + * + * scan: index scan descriptor + * page: buffer page containing index tuple + * offnum: offset number of index tuple (must be a valid item!) + * dir: direction we are scanning in + * continuescan: output parameter (will be set correctly in all cases) */ bool -_bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, +_bt_checkkeys(IndexScanDesc scan, + Page page, OffsetNumber offnum, ScanDirection dir, bool *continuescan) { - BTScanOpaque so = (BTScanOpaque) scan->opaque; - int keysz = so->numberOfKeys; - int ikey; + ItemId iid = PageGetItemId(page, offnum); + bool tuple_valid; + BTItem btitem; + IndexTuple tuple; TupleDesc tupdesc; + BTScanOpaque so; + int keysz; + int ikey; ScanKey key; - *continuescan = true; + *continuescan = true; /* default assumption */ - /* If no keys, always scan the whole index */ - if (keysz == 0) - return true; + /* + * If the scan specifies not to return killed tuples, then we treat + * a killed tuple as not passing the qual. Most of the time, it's a + * win to not bother examining the tuple's index keys, but just return + * immediately with continuescan = true to proceed to the next tuple. + * However, if this is the last tuple on the page, we should check + * the index keys to prevent uselessly advancing to the next page. + */ + if (scan->ignore_killed_tuples && ItemIdDeleted(iid)) + { + /* return immediately if there are more tuples on the page */ + if (ScanDirectionIsForward(dir)) + { + if (offnum < PageGetMaxOffsetNumber(page)) + return false; + } + else + { + BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page); + + if (offnum > P_FIRSTDATAKEY(opaque)) + return false; + } + /* + * OK, we want to check the keys, but we'll return FALSE even + * if the tuple passes the key tests. + */ + tuple_valid = false; + } + else + tuple_valid = true; + + btitem = (BTItem) PageGetItem(page, iid); + tuple = &btitem->bti_itup; IncrIndexProcessed(); tupdesc = RelationGetDescr(scan->indexRelation); + so = (BTScanOpaque) scan->opaque; + keysz = so->numberOfKeys; for (key = so->keyData, ikey = 0; ikey < keysz; key++, ikey++) { @@ -592,6 +639,9 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, } } - /* If we get here, the tuple passes all quals. */ - return true; + /* If we get here, the tuple passes all index quals. */ + if (tuple_valid) + scan->xs_ctup.t_self = tuple->t_tid; + + return tuple_valid; } diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 9cd00d554da..5a3ec5f1efe 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.88 2005/11/06 19:29:01 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.89 2005/12/07 19:37:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -467,8 +467,9 @@ extern ScanKey _bt_mkscankey_nodata(Relation rel); extern void _bt_freeskey(ScanKey skey); extern void _bt_freestack(BTStack stack); extern void _bt_preprocess_keys(IndexScanDesc scan); -extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, - ScanDirection dir, bool *continuescan); +extern bool _bt_checkkeys(IndexScanDesc scan, + Page page, OffsetNumber offnum, + ScanDirection dir, bool *continuescan); extern BTItem _bt_formitem(IndexTuple itup); /*