>From 7cb5839dd7751bcdcae6e4cbf69cfd24af10a694 Mon Sep 17 00:00:00 2001
From: Daniel Bausch <bausch@dvs.tu-darmstadt.de>
Date: Wed, 23 Oct 2013 09:45:11 +0200
Subject: [PATCH 2/4] Fix index-only scan and rescan

Prefetching heap data for index-only scans does not make any sense and
it uses a different field (itup), nevertheless.  Deactivate the prefetch
logic for index-only scans.

Reset xs_done and the queue on rescan, so we find tuples again.
Remember last prefetch to detect correlation.
---
 src/backend/access/index/indexam.c | 85 +++++++++++++++++++++-----------------
 1 file changed, 47 insertions(+), 38 deletions(-)

diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 1c54ef5..d8a4622 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -353,6 +353,12 @@ index_rescan(IndexScanDesc scan,
 
 	scan->kill_prior_tuple = false;		/* for safety */
 
+#ifdef USE_PREFETCH
+	/* I think, it does not hurt to remember xs_last_prefetch */
+	scan->xs_prefetch_head = scan->xs_prefetch_tail = -1;
+	scan->xs_done = false;
+#endif
+
 	FunctionCall5(procedure,
 				  PointerGetDatum(scan),
 				  PointerGetDatum(keys),
@@ -508,7 +514,47 @@ index_getnext_tid(IndexScanDesc scan, ScanDirection direction)
 	Assert(TransactionIdIsValid(RecentGlobalXmin));
 
 #ifdef USE_PREFETCH
-	while (!scan->xs_done && index_prefetch_queue_space(scan) > 0) {
+	if (!scan->xs_want_itup)
+	{
+		while (!scan->xs_done && index_prefetch_queue_space(scan) > 0) {
+			/*
+			 * The AM's amgettuple proc finds the next index entry matching
+			 * the scan keys, and puts the TID into scan->xs_ctup.t_self.  It
+			 * should also set scan->xs_recheck and possibly scan->xs_itup,
+			 * though we pay no attention to those fields here.
+			 */
+			found = DatumGetBool(FunctionCall2(procedure,
+											   PointerGetDatum(scan),
+											   Int32GetDatum(direction)));
+			if (found)
+			{
+				index_prefetch_queue_push(scan, &scan->xs_ctup.t_self);
+				pf_block = ItemPointerGetBlockNumber(&scan->xs_ctup.t_self);
+				/* prefetch only if not the current buffer and not exactly the
+				 * previously prefetched buffer (heuristic random detection)
+				 * because sequential read-ahead would be redundant */
+				if ((!BufferIsValid(scan->xs_cbuf) ||
+					 pf_block != BufferGetBlockNumber(scan->xs_cbuf)) &&
+					pf_block != scan->xs_last_prefetch)
+				{
+					PrefetchBuffer(scan->heapRelation, MAIN_FORKNUM, pf_block);
+					scan->xs_last_prefetch = pf_block;
+				}
+			}
+			else
+				scan->xs_done = true;
+		}
+		from_queue = index_prefetch_queue_pop(scan);
+		if (from_queue)
+		{
+			scan->xs_ctup.t_self = *from_queue;
+			found = true;
+		}
+		else
+			found = false;
+	}
+	else
+#endif
 		/*
 		 * The AM's amgettuple proc finds the next index entry matching the
 		 * scan keys, and puts the TID into scan->xs_ctup.t_self.  It should
@@ -518,43 +564,6 @@ index_getnext_tid(IndexScanDesc scan, ScanDirection direction)
 		found = DatumGetBool(FunctionCall2(procedure,
 										   PointerGetDatum(scan),
 										   Int32GetDatum(direction)));
-		if (found)
-		{
-			index_prefetch_queue_push(scan, &scan->xs_ctup.t_self);
-			pf_block = ItemPointerGetBlockNumber(&scan->xs_ctup.t_self);
-			/* prefetch only if not the current buffer and not exactly the
-			 * previously prefetched buffer (heuristic random detection)
-			 * because sequential read-ahead would be redundant */
-			if ((!BufferIsValid(scan->xs_cbuf) ||
-				 pf_block != BufferGetBlockNumber(scan->xs_cbuf)) &&
-				pf_block != scan->xs_last_prefetch)
-			{
-				PrefetchBuffer(scan->heapRelation, MAIN_FORKNUM, pf_block);
-				scan->xs_last_prefetch = pf_block;
-			}
-		}
-		else
-			scan->xs_done = true;
-	}
-	from_queue = index_prefetch_queue_pop(scan);
-	if (from_queue)
-	{
-		scan->xs_ctup.t_self = *from_queue;
-		found = true;
-	}
-	else
-		found = false;
-#else
-	/*
-	 * The AM's amgettuple proc finds the next index entry matching the scan
-	 * keys, and puts the TID into scan->xs_ctup.t_self.  It should also set
-	 * scan->xs_recheck and possibly scan->xs_itup, though we pay no attention
-	 * to those fields here.
-	 */
-	found = DatumGetBool(FunctionCall2(procedure,
-									   PointerGetDatum(scan),
-									   Int32GetDatum(direction)));
-#endif
 
 	/* Reset kill flag immediately for safety */
 	scan->kill_prior_tuple = false;
-- 
2.0.5

