From 5f2b071eb0abca3235980d7ae2630d730a47f9a1 Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@bowt.ie>
Date: Tue, 6 May 2025 13:58:59 -0400
Subject: [PATCH v2 1/2] nbtree: tighten up array recheck rules.

Be more conservative when performing a scheduled recheck of an nbtree
scan's array keys: perform/schedule another primitive scan in cases
where the next page's high key/finaltup has truncated attributes that
make it unclear just how close we are to the next leaf page with
matching tuples.

Author: Peter Geoghegan <pg@bowt.ie>
---
 src/backend/access/nbtree/nbtutils.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 517d37502..686adb9bb 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -2538,11 +2538,27 @@ _bt_scanbehind_checkkeys(IndexScanDesc scan, ScanDirection dir,
 	TupleDesc	tupdesc = RelationGetDescr(rel);
 	BTScanOpaque so = (BTScanOpaque) scan->opaque;
 	int			nfinaltupatts = BTreeTupleGetNAtts(finaltup, rel);
+	bool		scanBehind;
 
 	Assert(so->numArrayKeys);
 
 	if (_bt_tuple_before_array_skeys(scan, dir, finaltup, tupdesc,
-									 nfinaltupatts, false, 0, NULL))
+									 nfinaltupatts, false, 0, &scanBehind))
+		return false;
+
+	/*
+	 * If scanBehind was set, all of the untruncated attribute values from
+	 * finaltup that correspond to an array match the array's current element,
+	 * but there are other keys associated with truncated suffix attributes.
+	 * Array advancement must have incremented the scan's arrays on the
+	 * previous page, resulting in a set of array keys that happen to be an
+	 * exact match for the current page high key's untruncated prefix values.
+	 *
+	 * This page definitely doesn't contain tuples that the scan will need to
+	 * return.  The next page may or may not contain relevant tuples.  Handle
+	 * this by cutting our losses and starting a new primscan.
+	 */
+	if (scanBehind)
 		return false;
 
 	if (!so->oppositeDirCheck)
-- 
2.49.0

