From e4b50f956cf18bc728cf40c5938899af0cf20b16 Mon Sep 17 00:00:00 2001
From: ejrh <ejrh00@gmail.com>
Date: Mon, 4 Feb 2019 17:58:29 +1300
Subject: [PATCH 2/4] Support backward scans over restricted ranges in heap
 access method

This is required for backward TID scans, including those caused by a FETCH LAST command.
---
 src/backend/access/heap/heapam.c | 48 +++++++++++++++++++++++++++++++++-------
 1 file changed, 40 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index dc34993..45864cd 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -563,11 +563,27 @@ heapgettup(HeapScanDesc scan,
 			 * forward scanners.
 			 */
 			scan->rs_syncscan = false;
-			/* start from last page of the scan */
-			if (scan->rs_startblock > 0)
-				page = scan->rs_startblock - 1;
+
+			/*
+			 * When scanning the whole relation, start from the last page of
+			 * the scan.
+			 */
+			if (scan->rs_numblocks == InvalidBlockNumber)
+			{
+				if (scan->rs_startblock > 0)
+					page = scan->rs_startblock - 1;
+				else
+					page = scan->rs_nblocks - 1;
+			}
 			else
-				page = scan->rs_nblocks - 1;
+			{
+				/*
+				 * Otherwise, if scanning just a subset of the relation, start
+				 * at the final block in the range.
+				 */
+				page = scan->rs_startblock + scan->rs_numblocks - 1;
+			}
+
 			heapgetpage(scan, page);
 		}
 		else
@@ -864,11 +880,27 @@ heapgettup_pagemode(HeapScanDesc scan,
 			 * forward scanners.
 			 */
 			scan->rs_syncscan = false;
-			/* start from last page of the scan */
-			if (scan->rs_startblock > 0)
-				page = scan->rs_startblock - 1;
+
+			/*
+			 * When scanning the whole relation, start from the last page of
+			 * the scan.
+			 */
+			if (scan->rs_numblocks == InvalidBlockNumber)
+			{
+				if (scan->rs_startblock > 0)
+					page = scan->rs_startblock - 1;
+				else
+					page = scan->rs_nblocks - 1;
+			}
 			else
-				page = scan->rs_nblocks - 1;
+			{
+				/*
+				 * Otherwise, if scanning just a subset of the relation, start
+				 * at the final block in the range.
+				 */
+				page = scan->rs_startblock + scan->rs_numblocks - 1;
+			}
+
 			heapgetpage(scan, page);
 		}
 		else
-- 
2.7.4

