From 188cb93e30e9984d8cc0e16ef225300c89edd10b Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@bowt.ie>
Date: Mon, 23 Dec 2024 11:57:20 -0500
Subject: [PATCH v1] nbtree: Detect more unsatisfiable RowCompare NULL cases.

---
 src/backend/access/nbtree/nbtsearch.c | 16 ++++++----------
 src/backend/access/nbtree/nbtutils.c  |  7 +++++++
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 0cd046613..a3cf2ed7a 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -1178,21 +1178,17 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 		{
 			/*
 			 * Row comparison header: look to the first row member instead.
-			 *
 			 * The member scankeys are already in insertion format (ie, they
-			 * have sk_func = 3-way-comparison function), but we have to watch
-			 * out for nulls, which _bt_preprocess_keys didn't check. A null
-			 * in the first row member makes the condition unmatchable, just
-			 * like qual_ok = false.
+			 * have sk_func = 3-way-comparison function).
 			 */
 			ScanKey		subkey = (ScanKey) DatumGetPointer(cur->sk_argument);
 
+			/*
+			 * Cannot be a NULL in the leading key, since _bt_preprocess_keys
+			 * would have already marked the qual as unsatisfiable
+			 */
 			Assert(subkey->sk_flags & SK_ROW_MEMBER);
-			if (subkey->sk_flags & SK_ISNULL)
-			{
-				_bt_parallel_done(scan);
-				return false;
-			}
+			Assert(!(subkey->sk_flags & SK_ISNULL));
 			memcpy(inskey.scankeys + i, subkey, sizeof(ScanKeyData));
 
 			/*
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index afff7d639..2ed163f35 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -3371,6 +3371,13 @@ _bt_fix_scankey_strategy(ScanKey skey, int16 *indoption)
 	{
 		ScanKey		subkey = (ScanKey) DatumGetPointer(skey->sk_argument);
 
+		if (subkey->sk_flags & SK_ISNULL)
+		{
+			/* leading key is NULL, so qual cannot be satisfied */
+			Assert(subkey->sk_flags & SK_ROW_MEMBER);
+			return false;
+		}
+
 		for (;;)
 		{
 			Assert(subkey->sk_flags & SK_ROW_MEMBER);
-- 
2.45.2

