diff options
Diffstat (limited to 'src/backend/access/nbtree/nbtsearch.c')
-rw-r--r-- | src/backend/access/nbtree/nbtsearch.c | 68 |
1 files changed, 54 insertions, 14 deletions
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 313e574f969..f4bea8cd537 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -26,6 +26,8 @@ static bool _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum); +static void _bt_saveitem(BTScanOpaque so, int itemIndex, + OffsetNumber offnum, IndexTuple itup); static bool _bt_steppage(IndexScanDesc scan, ScanDirection dir); static Buffer _bt_walk_left(Relation rel, Buffer buf); static bool _bt_endpoint(IndexScanDesc scan, ScanDirection dir); @@ -429,8 +431,9 @@ _bt_compare(Relation rel, * if backwards scan, the last item) in the tree that satisfies the * qualifications in the scan key. On success exit, the page containing * the current index tuple is pinned but not locked, and data about - * the matching tuple(s) on the page has been loaded into so->currPos, - * and scan->xs_ctup.t_self is set to the heap TID of the current tuple. + * the matching tuple(s) on the page has been loaded into so->currPos. + * scan->xs_ctup.t_self is set to the heap TID of the current tuple, + * and if requested, scan->xs_itup points to a copy of the index tuple. * * If there are no matching items in the index, we return FALSE, with no * pins or locks held. @@ -456,6 +459,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) int keysCount = 0; int i; StrategyNumber strat_total; + BTScanPosItem *currItem; pgstat_count_index_scan(rel); @@ -912,7 +916,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) LockBuffer(so->currPos.buf, BUFFER_LOCK_UNLOCK); /* OK, itemIndex says what to return */ - scan->xs_ctup.t_self = so->currPos.items[so->currPos.itemIndex].heapTid; + currItem = &so->currPos.items[so->currPos.itemIndex]; + scan->xs_ctup.t_self = currItem->heapTid; + if (scan->xs_want_itup) + scan->xs_itup = (IndexTuple) (so->currTuples + currItem->tupleOffset); return true; } @@ -925,7 +932,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * previously returned. * * On successful exit, scan->xs_ctup.t_self is set to the TID of the - * next heap tuple, and so->currPos is updated as needed. + * next heap tuple, and if requested, scan->xs_itup points to a copy of + * the index tuple. so->currPos is updated as needed. * * On failure exit (no more tuples), we release pin and set * so->currPos.buf to InvalidBuffer. @@ -934,6 +942,7 @@ bool _bt_next(IndexScanDesc scan, ScanDirection dir) { BTScanOpaque so = (BTScanOpaque) scan->opaque; + BTScanPosItem *currItem; /* * Advance to next tuple on current page; or if there's no more, try to @@ -967,7 +976,10 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) } /* OK, itemIndex says what to return */ - scan->xs_ctup.t_self = so->currPos.items[so->currPos.itemIndex].heapTid; + currItem = &so->currPos.items[so->currPos.itemIndex]; + scan->xs_ctup.t_self = currItem->heapTid; + if (scan->xs_want_itup) + scan->xs_itup = (IndexTuple) (so->currTuples + currItem->tupleOffset); return true; } @@ -996,6 +1008,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum) OffsetNumber minoff; OffsetNumber maxoff; int itemIndex; + IndexTuple itup; bool continuescan; /* we must have the buffer pinned and locked */ @@ -1013,6 +1026,9 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum) */ so->currPos.nextPage = opaque->btpo_next; + /* initialize tuple workspace to empty */ + so->currPos.nextTupleOffset = 0; + if (ScanDirectionIsForward(dir)) { /* load items[] in ascending order */ @@ -1022,12 +1038,11 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum) while (offnum <= maxoff) { - if (_bt_checkkeys(scan, page, offnum, dir, &continuescan)) + itup = _bt_checkkeys(scan, page, offnum, dir, &continuescan); + if (itup != NULL) { /* tuple passes all scan key conditions, so remember it */ - /* _bt_checkkeys put the heap ptr into scan->xs_ctup.t_self */ - so->currPos.items[itemIndex].heapTid = scan->xs_ctup.t_self; - so->currPos.items[itemIndex].indexOffset = offnum; + _bt_saveitem(so, itemIndex, offnum, itup); itemIndex++; } if (!continuescan) @@ -1054,13 +1069,12 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum) while (offnum >= minoff) { - if (_bt_checkkeys(scan, page, offnum, dir, &continuescan)) + itup = _bt_checkkeys(scan, page, offnum, dir, &continuescan); + if (itup != NULL) { /* tuple passes all scan key conditions, so remember it */ - /* _bt_checkkeys put the heap ptr into scan->xs_ctup.t_self */ itemIndex--; - so->currPos.items[itemIndex].heapTid = scan->xs_ctup.t_self; - so->currPos.items[itemIndex].indexOffset = offnum; + _bt_saveitem(so, itemIndex, offnum, itup); } if (!continuescan) { @@ -1081,6 +1095,25 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum) return (so->currPos.firstItem <= so->currPos.lastItem); } +/* Save an index item into so->currPos.items[itemIndex] */ +static void +_bt_saveitem(BTScanOpaque so, int itemIndex, + OffsetNumber offnum, IndexTuple itup) +{ + BTScanPosItem *currItem = &so->currPos.items[itemIndex]; + + currItem->heapTid = itup->t_tid; + currItem->indexOffset = offnum; + if (so->currTuples) + { + Size itupsz = IndexTupleSize(itup); + + currItem->tupleOffset = so->currPos.nextTupleOffset; + memcpy(so->currTuples + so->currPos.nextTupleOffset, itup, itupsz); + so->currPos.nextTupleOffset += MAXALIGN(itupsz); + } +} + /* * _bt_steppage() -- Step to next page containing valid data for scan * @@ -1119,6 +1152,9 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir) memcpy(&so->markPos, &so->currPos, offsetof(BTScanPosData, items[1]) + so->currPos.lastItem * sizeof(BTScanPosItem)); + if (so->markTuples) + memcpy(so->markTuples, so->currTuples, + so->currPos.nextTupleOffset); so->markPos.itemIndex = so->markItemIndex; so->markItemIndex = -1; } @@ -1428,6 +1464,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) Page page; BTPageOpaque opaque; OffsetNumber start; + BTScanPosItem *currItem; /* * Scan down to the leftmost or rightmost leaf page. This is a simplified @@ -1505,7 +1542,10 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) LockBuffer(so->currPos.buf, BUFFER_LOCK_UNLOCK); /* OK, itemIndex says what to return */ - scan->xs_ctup.t_self = so->currPos.items[so->currPos.itemIndex].heapTid; + currItem = &so->currPos.items[so->currPos.itemIndex]; + scan->xs_ctup.t_self = currItem->heapTid; + if (scan->xs_want_itup) + scan->xs_itup = (IndexTuple) (so->currTuples + currItem->tupleOffset); return true; } |