@@ -42,6 +42,7 @@ static int_bt_setuppostingitems(BTScanOpaque so, int itemIndex,
4242static inline void _bt_savepostingitem (BTScanOpaque so ,int itemIndex ,
4343OffsetNumber offnum ,
4444ItemPointer heapTid ,int tupleOffset );
45+ static inline void _bt_returnitem (IndexScanDesc scan ,BTScanOpaque so );
4546static bool _bt_steppage (IndexScanDesc scan ,ScanDirection dir );
4647static bool _bt_readfirstpage (IndexScanDesc scan ,OffsetNumber offnum ,
4748ScanDirection dir );
@@ -867,8 +868,7 @@ _bt_compare(Relation rel,
867868 *matching tuple(s) on the page has been loaded into so->currPos. We'll
868869 *drop all locks and hold onto a pin on page's buffer, except when
869870 *_bt_drop_lock_and_maybe_pin dropped the pin to avoid blocking VACUUM.
870- *scan->xs_heaptid is set to the heap TID of the current tuple, and if
871- *requested, scan->xs_itup points to a copy of the index tuple.
871+ *_bt_returnitem sets the next item to return to scan on success exit.
872872 *
873873 * If there are no matching items in the index, we return false, with no
874874 * pins or locks held. so->currPos will remain invalid.
@@ -890,7 +890,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
890890ScanKeyData notnullkeys [INDEX_MAX_KEYS ];
891891int keysz = 0 ;
892892StrategyNumber strat_total ;
893- BTScanPosItem * currItem ;
894893
895894Assert (!BTScanPosIsValid (so -> currPos ));
896895
@@ -950,7 +949,9 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
950949 */
951950if (!_bt_readnextpage (scan ,blkno ,lastcurrblkno ,dir , true))
952951return false;
953- gotoreadcomplete ;
952+
953+ _bt_returnitem (scan ,so );
954+ return true;
954955}
955956}
956957else if (so -> numArrayKeys && !so -> needPrimScan )
@@ -1438,14 +1439,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
14381439if (!_bt_readfirstpage (scan ,offnum ,dir ))
14391440return false;
14401441
1441- readcomplete :
1442- /* OK, itemIndex says what to return */
1443- Assert (BTScanPosIsValid (so -> currPos ));
1444- currItem = & so -> currPos .items [so -> currPos .itemIndex ];
1445- scan -> xs_heaptid = currItem -> heapTid ;
1446- if (scan -> xs_want_itup )
1447- scan -> xs_itup = (IndexTuple ) (so -> currTuples + currItem -> tupleOffset );
1448-
1442+ _bt_returnitem (scan ,so );
14491443return true;
14501444}
14511445
@@ -1456,9 +1450,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
14561450 *but is not locked, and so->currPos.itemIndex identifies which item was
14571451 *previously returned.
14581452 *
1459- *On successful exit, scan->xs_heaptid is set to the TID of the next
1460- *heap tuple, and if requested, scan->xs_itup points to a copy of the
1461- *index tuple. so->currPos is updated as needed.
1453+ *On success exit, so->currPos is updated as needed, and _bt_returnitem
1454+ *sets the next item to return to the scan. so->currPos remains valid.
14621455 *
14631456 *On failure exit (no more tuples), we invalidate so->currPos. It'll
14641457 *still be possible for the scan to return tuples by changing direction,
@@ -1468,7 +1461,6 @@ bool
14681461_bt_next (IndexScanDesc scan ,ScanDirection dir )
14691462{
14701463BTScanOpaque so = (BTScanOpaque )scan -> opaque ;
1471- BTScanPosItem * currItem ;
14721464
14731465Assert (BTScanPosIsValid (so -> currPos ));
14741466
@@ -1493,13 +1485,7 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
14931485}
14941486}
14951487
1496- /* OK, itemIndex says what to return */
1497- Assert (BTScanPosIsValid (so -> currPos ));
1498- currItem = & so -> currPos .items [so -> currPos .itemIndex ];
1499- scan -> xs_heaptid = currItem -> heapTid ;
1500- if (scan -> xs_want_itup )
1501- scan -> xs_itup = (IndexTuple ) (so -> currTuples + currItem -> tupleOffset );
1502-
1488+ _bt_returnitem (scan ,so );
15031489return true;
15041490}
15051491
@@ -1560,10 +1546,13 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum,
15601546so -> currPos .currPage );
15611547}
15621548
1563- /* initialize remaining currPos fields(before moreLeft/moreRight) */
1549+ /* initialize remaining currPos fieldsrelated to current page */
15641550so -> currPos .lsn = BufferGetLSNAtomic (so -> currPos .buf );
15651551so -> currPos .dir = dir ;
15661552so -> currPos .nextTupleOffset = 0 ;
1553+ /* either moreLeft or moreRight should be set now (may be unset later) */
1554+ Assert (ScanDirectionIsForward (dir ) ?so -> currPos .moreRight :
1555+ so -> currPos .moreLeft );
15671556
15681557PredicateLockPage (rel ,so -> currPos .currPage ,scan -> xs_snapshot );
15691558
@@ -2002,6 +1991,26 @@ _bt_savepostingitem(BTScanOpaque so, int itemIndex, OffsetNumber offnum,
20021991currItem -> tupleOffset = tupleOffset ;
20031992}
20041993
1994+ /*
1995+ * Return the index item from so->currPos.items[so->currPos.itemIndex] to the
1996+ * index scan by setting the relevant fields in caller's index scan descriptor
1997+ */
1998+ static inline void
1999+ _bt_returnitem (IndexScanDesc scan ,BTScanOpaque so )
2000+ {
2001+ BTScanPosItem * currItem = & so -> currPos .items [so -> currPos .itemIndex ];
2002+
2003+ /* Most recent _bt_readpage must have succeeded */
2004+ Assert (BTScanPosIsValid (so -> currPos ));
2005+ Assert (so -> currPos .itemIndex >=so -> currPos .firstItem );
2006+ Assert (so -> currPos .itemIndex <=so -> currPos .lastItem );
2007+
2008+ /* Return next item, per amgettuple contract */
2009+ scan -> xs_heaptid = currItem -> heapTid ;
2010+ if (so -> currTuples )
2011+ scan -> xs_itup = (IndexTuple ) (so -> currTuples + currItem -> tupleOffset );
2012+ }
2013+
20052014/*
20062015 *_bt_steppage() -- Step to next page containing valid data for scan
20072016 *
@@ -2543,7 +2552,6 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
25432552Page page ;
25442553BTPageOpaque opaque ;
25452554OffsetNumber start ;
2546- BTScanPosItem * currItem ;
25472555
25482556Assert (!BTScanPosIsValid (so -> currPos ));
25492557
@@ -2593,12 +2601,6 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
25932601if (!_bt_readfirstpage (scan ,start ,dir ))
25942602return false;
25952603
2596- /* OK, itemIndex says what to return */
2597- Assert (BTScanPosIsValid (so -> currPos ));
2598- currItem = & so -> currPos .items [so -> currPos .itemIndex ];
2599- scan -> xs_heaptid = currItem -> heapTid ;
2600- if (scan -> xs_want_itup )
2601- scan -> xs_itup = (IndexTuple ) (so -> currTuples + currItem -> tupleOffset );
2602-
2604+ _bt_returnitem (scan ,so );
26032605return true;
26042606}