aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/nbtree/nbtsearch.c15
-rw-r--r--src/backend/access/nbtree/nbtutils.c13
-rw-r--r--src/include/access/nbtree.h1
3 files changed, 21 insertions, 8 deletions
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index c33438c4bbd..b082cc80f6c 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -1568,6 +1568,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum,
Assert(!P_IGNORE(opaque));
Assert(BTScanPosIsPinned(so->currPos));
+ Assert(!so->needPrimScan);
if (scan->parallel_scan)
{
@@ -1594,7 +1595,6 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum,
maxoff = PageGetMaxOffsetNumber(page);
/* initialize page-level state that we'll pass to _bt_checkkeys */
- pstate.dir = dir;
pstate.minoff = minoff;
pstate.maxoff = maxoff;
pstate.finaltup = NULL;
@@ -2088,7 +2088,7 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
*/
if (so->needPrimScan)
{
- if (ScanDirectionIsForward(dir))
+ if (ScanDirectionIsForward(so->currPos.dir))
so->markPos.moreRight = true;
else
so->markPos.moreLeft = true;
@@ -2109,6 +2109,15 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
else
blkno = so->currPos.prevPage;
lastcurrblkno = so->currPos.currPage;
+
+ /*
+ * Cancel primitive index scans that were scheduled when the call to
+ * _bt_readpage for currPos happened to use the opposite direction to
+ * the one that we're stepping in now. (It's okay to leave the scan's
+ * array keys as-is, since the next _bt_readpage will advance them.)
+ */
+ if (so->currPos.dir != dir)
+ so->needPrimScan = false;
}
else
{
@@ -2118,6 +2127,8 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
*/
if (!_bt_parallel_seize(scan, &blkno, &lastcurrblkno, false))
return false;
+
+ Assert(!so->needPrimScan);
}
return _bt_readnextpage(scan, blkno, lastcurrblkno, dir);
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 76be65123c8..20227989c6d 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -1800,7 +1800,7 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate,
{
BTScanOpaque so = (BTScanOpaque) scan->opaque;
Relation rel = scan->indexRelation;
- ScanDirection dir = pstate ? pstate->dir : ForwardScanDirection;
+ ScanDirection dir = so->currPos.dir;
int arrayidx = 0;
bool beyond_end_advance = false,
has_required_opposite_direction_only = false,
@@ -2400,8 +2400,10 @@ new_prim_scan:
/*
* End this primitive index scan, but schedule another.
*
- * Note: If the scan direction happens to change, this scheduled primitive
- * index scan won't go ahead after all.
+ * Note: We make a soft assumption that the current scan direction will
+ * also be used within _bt_next, when it is asked to step off this page.
+ * It is up to _bt_next to cancel this scheduled primitive index scan
+ * whenever it steps to a page in the direction opposite currPos.dir.
*/
pstate->continuescan = false; /* Tell _bt_readpage we're done... */
so->needPrimScan = true; /* ...but call _bt_first again */
@@ -3458,7 +3460,7 @@ _bt_checkkeys(IndexScanDesc scan, BTReadPageState *pstate, bool arrayKeys,
{
TupleDesc tupdesc = RelationGetDescr(scan->indexRelation);
BTScanOpaque so = (BTScanOpaque) scan->opaque;
- ScanDirection dir = pstate->dir;
+ ScanDirection dir = so->currPos.dir;
int ikey = 0;
bool res;
@@ -4062,7 +4064,8 @@ static void
_bt_checkkeys_look_ahead(IndexScanDesc scan, BTReadPageState *pstate,
int tupnatts, TupleDesc tupdesc)
{
- ScanDirection dir = pstate->dir;
+ BTScanOpaque so = (BTScanOpaque) scan->opaque;
+ ScanDirection dir = so->currPos.dir;
OffsetNumber aheadoffnum;
IndexTuple ahead;
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index 5fb523ecec3..123fba624db 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -1078,7 +1078,6 @@ typedef BTScanOpaqueData *BTScanOpaque;
typedef struct BTReadPageState
{
/* Input parameters, set by _bt_readpage for _bt_checkkeys */
- ScanDirection dir; /* current scan direction */
OffsetNumber minoff; /* Lowest non-pivot tuple's offset */
OffsetNumber maxoff; /* Highest non-pivot tuple's offset */
IndexTuple finaltup; /* Needed by scans with array keys */