Skip to content

Commit 714780d

Browse files
Fix btmarkpos/btrestrpos array key wraparound bug.
nbtree's mark/restore processing failed to correctly handle an edge case involving array key advancement and related search-type scan key state. Scans with ScalarArrayScalarArrayOpExpr quals requiring mark/restore processing (for a merge join) could incorrectly conclude that an affected array/scan key must not have advanced during the time between marking and restoring the scan's position. As a result of all this, array key handling within btrestrpos could skip a required call to _bt_preprocess_keys(). This confusion allowed later primitive index scans to overlook tuples matching the true current array keys. The scan's search-type scan keys would still have spurious values corresponding to the final array element(s) -- not values matching the first/now-current array element(s). To fix, remember that "array key wraparound" has taken place during the ongoing btrescan in a flag variable stored in the scan's state, and use that information at the point where btrestrpos decides if another call to _bt_preprocess_keys is required. Oversight in commit 70bc583, which taught nbtree to handle array keys during mark/restore processing, but missed this subtlety. That commit was itself a bug fix for an issue in commit 9e8da0f, which taught nbtree to handle ScalarArrayOpExpr quals natively. Author: Peter Geoghegan <pg@bowt.ie> Discussion: https://postgr.es/m/CAH2-WzkgP3DDRJxw6DgjCxo-cu-DKrvjEv_ArkP2ctBJatDCYg@mail.gmail.com Backpatch: 11- (all supported branches).
1 parent 9f71e10 commit 714780d

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

src/backend/access/nbtree/nbtree.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ btbeginscan(Relation rel, int nkeys, int norderbys)
364364
so->keyData = NULL;
365365

366366
so->arrayKeyData = NULL; /* assume no array keys for now */
367+
so->arraysStarted = false;
367368
so->numArrayKeys = 0;
368369
so->arrayKeys = NULL;
369370
so->arrayContext = NULL;

src/backend/access/nbtree/nbtutils.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,8 @@ _bt_start_array_keys(IndexScanDesc scan, ScanDirection dir)
539539
curArrayKey->cur_elem = 0;
540540
skey->sk_argument = curArrayKey->elem_values[curArrayKey->cur_elem];
541541
}
542+
543+
so->arraysStarted = true;
542544
}
543545

544546
/*
@@ -598,6 +600,14 @@ _bt_advance_array_keys(IndexScanDesc scan, ScanDirection dir)
598600
if (scan->parallel_scan != NULL)
599601
_bt_parallel_advance_array_keys(scan);
600602

603+
/*
604+
* When no new array keys were found, the scan is "past the end" of the
605+
* array keys. _bt_start_array_keys can still "restart" the array keys if
606+
* a rescan is required.
607+
*/
608+
if (!found)
609+
so->arraysStarted = false;
610+
601611
return found;
602612
}
603613

@@ -651,8 +661,13 @@ _bt_restore_array_keys(IndexScanDesc scan)
651661
* If we changed any keys, we must redo _bt_preprocess_keys. That might
652662
* sound like overkill, but in cases with multiple keys per index column
653663
* it seems necessary to do the full set of pushups.
664+
*
665+
* Also do this whenever the scan's set of array keys "wrapped around" at
666+
* the end of the last primitive index scan. There won't have been a call
667+
* to _bt_preprocess_keys from some other place following wrap around, so
668+
* we do it for ourselves.
654669
*/
655-
if (changed)
670+
if (changed || !so->arraysStarted)
656671
{
657672
_bt_preprocess_keys(scan);
658673
/* The mark should have been set on a consistent set of keys... */

src/include/access/nbtree.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,8 @@ typedef struct BTScanOpaqueData
10431043

10441044
/* workspace for SK_SEARCHARRAY support */
10451045
ScanKey arrayKeyData; /* modified copy of scan->keyData */
1046+
bool arraysStarted; /* Started array keys, but have yet to "reach
1047+
* past the end" of all arrays? */
10461048
int numArrayKeys; /* number of equality-type array keys (-1 if
10471049
* there are any unsatisfiable array keys) */
10481050
int arrayKeyCount; /* count indicating number of array scan keys

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy