From e16c6f024718cf854f5b76a4a2ed402f1a7911f1 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Wed, 10 Dec 2025 20:50:47 -0500 Subject: [PATCH] Clarify why _bt_killitems sorts its items array. Make it clear why _bt_killitems sorts the scan's so->killedItems[] array. Also add an assertion to the _bt_killitems loop (that iterates through this array) to verify it accesses tuples in leaf page order. Follow-up to commit bfb335df58. Author: Peter Geoghegan Suggested-by: Victor Yegorov Discussion: https://postgr.es/m/CAGnEboirgArezZDNeFrR8FOGvKF-Xok333s2iVwWi65gZf8MEA@mail.gmail.com --- src/backend/access/nbtree/nbtutils.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index 16e23a517b2..a451d48e11e 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -222,11 +222,12 @@ _bt_killitems(IndexScanDesc scan) so->numKilled = 0; /* - * so->killedItems[] is in whatever order the scan returned items in. - * Items will appear in descending order during backwards scans. And - * scrollable cursor scans might have duplicate items. + * We need to iterate through so->killedItems[] in leaf page order; the + * loop below expects this (when marking posting list tuples, at least). + * so->killedItems[] is now in whatever order the scan returned items in. + * Scrollable cursor scans might have even saved the same item/TID twice. * - * Sort and uniqueify so->killedItems[] to deal with all this. + * Sort and unique-ify so->killedItems[] to deal with all this. */ if (numKilled > 1) { @@ -271,6 +272,7 @@ _bt_killitems(IndexScanDesc scan) minoff = P_FIRSTDATAKEY(opaque); maxoff = PageGetMaxOffsetNumber(page); + /* Iterate through so->killedItems[] in leaf page order */ for (int i = 0; i < numKilled; i++) { int itemIndex = so->killedItems[i]; @@ -279,6 +281,9 @@ _bt_killitems(IndexScanDesc scan) Assert(itemIndex >= so->currPos.firstItem && itemIndex <= so->currPos.lastItem); + Assert(i == 0 || + offnum >= so->currPos.items[so->killedItems[i - 1]].indexOffset); + if (offnum < minoff) continue; /* pure paranoia */ while (offnum <= maxoff) -- 2.39.5