From 1f1e5f5a1a20ea2ed028a543688b31781956581b Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Mon, 11 Dec 2023 17:49:05 +0200 Subject: [PATCH 2/2] Fix requiredOppositeDir bug Instead of relying on _bt_first(), rely on the first matched item on the page. Reported-by: Bug: Discussion: Author: Reviewed-by: Tested-by: Backpatch-through: --- src/backend/access/nbtree/nbtsearch.c | 13 +++++++------ src/backend/access/nbtree/nbtutils.c | 6 ++++-- src/include/access/nbtree.h | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 410180587e0..7bdd6bf11c4 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -1541,6 +1541,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, bool continuescan; int indnatts; bool requiredMatchedByPrecheck; + bool haveFirstMatch = false; /* * We must have the buffer pinned and locked, but the usual macro can't be @@ -1626,7 +1627,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, * otherwise. */ (void) _bt_checkkeys(scan, itup, indnatts, dir, - &requiredMatchedByPrecheck, false); + &requiredMatchedByPrecheck, false, NULL); } else { @@ -1659,7 +1660,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, itup = (IndexTuple) PageGetItem(page, iid); passes_quals = _bt_checkkeys(scan, itup, indnatts, dir, - &continuescan, requiredMatchedByPrecheck); + &continuescan, requiredMatchedByPrecheck, &haveFirstMatch); /* * If the result of prechecking required keys was true, then in @@ -1668,7 +1669,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, */ Assert(!requiredMatchedByPrecheck || passes_quals == _bt_checkkeys(scan, itup, indnatts, dir, - &continuescan, false)); + &continuescan, false, NULL)); if (passes_quals) { /* tuple passes all scan key conditions */ @@ -1726,7 +1727,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, int truncatt; truncatt = BTreeTupleGetNAtts(itup, scan->indexRelation); - _bt_checkkeys(scan, itup, truncatt, dir, &continuescan, false); + _bt_checkkeys(scan, itup, truncatt, dir, &continuescan, false, NULL); } if (!continuescan) @@ -1778,7 +1779,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, itup = (IndexTuple) PageGetItem(page, iid); passes_quals = _bt_checkkeys(scan, itup, indnatts, dir, - &continuescan, requiredMatchedByPrecheck); + &continuescan, requiredMatchedByPrecheck, &haveFirstMatch); /* * If the result of prechecking required keys was true, then in @@ -1787,7 +1788,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, */ Assert(!requiredMatchedByPrecheck || passes_quals == _bt_checkkeys(scan, itup, indnatts, dir, - &continuescan, false)); + &continuescan, false, NULL)); if (passes_quals && tuple_alive) { /* tuple passes all scan key conditions */ diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index 1510b97fbe1..0a8e94473ba 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -1378,7 +1378,7 @@ _bt_mark_scankey_required(ScanKey skey) bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts, ScanDirection dir, bool *continuescan, - bool requiredMatchedByPrecheck) + bool requiredMatchedByPrecheck, bool *haveFirstMatch) { TupleDesc tupdesc; BTScanOpaque so; @@ -1411,7 +1411,7 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts, requiredSameDir = true; else if (((key->sk_flags & SK_BT_REQFWD) && ScanDirectionIsBackward(dir)) || ((key->sk_flags & SK_BT_REQBKWD) && ScanDirectionIsForward(dir))) - requiredOppositeDir = true; + requiredOppositeDir = haveFirstMatch && *haveFirstMatch; /* * Is the key required for scanning for either forward or backward @@ -1561,6 +1561,8 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts, } /* If we get here, the tuple passes all index quals. */ + if (haveFirstMatch) + *haveFirstMatch = true; return true; } diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 2e33523b08a..7704a1dc709 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -1256,7 +1256,7 @@ extern void _bt_restore_array_keys(IndexScanDesc scan); extern void _bt_preprocess_keys(IndexScanDesc scan); extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts, ScanDirection dir, bool *continuescan, - bool requiredMatchedByPrecheck); + bool requiredMatchedByPrecheck, bool *haveFirstMatch); extern void _bt_killitems(IndexScanDesc scan); extern BTCycleId _bt_vacuum_cycleid(Relation rel); extern BTCycleId _bt_start_vacuum(Relation rel); -- 2.39.3 (Apple Git-145)