From 6e67a65cc2e621424b5e6aa3e7b7524a02a54802 Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Sat, 30 Dec 2017 14:13:06 +0500
Subject: [PATCH] Count tuples correctly during GiST VACUUM of partial index

---
 src/backend/access/gist/gistvacuum.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index 891e3144ca..1fc80ff42d 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -16,6 +16,7 @@
 
 #include "access/genam.h"
 #include "access/gist_private.h"
+#include "access/htup_details.h"
 #include "commands/vacuum.h"
 #include "miscadmin.h"
 #include "storage/indexfsm.h"
@@ -34,7 +35,9 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 	BlockNumber npages,
 				blkno;
 	BlockNumber totFreePages;
-	bool		needLock;
+	bool		needLock,
+				shouldcount = false;
+	uint64_t	tuples_count = 0;
 
 	/* No-op in ANALYZE ONLY mode */
 	if (info->analyze_only)
@@ -47,12 +50,13 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 		/* use heap's tuple count */
 		stats->num_index_tuples = info->num_heap_tuples;
 		stats->estimated_count = info->estimated_count;
-
-		/*
-		 * XXX the above is wrong if index is partial.  Would it be OK to just
-		 * return NULL, or is there work we must do below?
-		 */
+		/* Unless it is estimate or index is partial  */
+		if (rel->rd_indextuple == NULL)
+			RelationInitIndexAccessInfo(rel);
+		shouldcount = !heap_attisnull(rel->rd_indextuple, Anum_pg_index_indpred) || info->estimated_count;
 	}
+	else
+		shouldcount = stats->estimated_count;
 
 	/*
 	 * Need lock unless it's local to this backend.
@@ -84,12 +88,25 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 			totFreePages++;
 			RecordFreeIndexPage(rel, blkno);
 		}
+		else
+		{
+			if (shouldcount && GistPageIsLeaf(page))
+			{
+				tuples_count += PageGetMaxOffsetNumber(page);
+			}
+		}
 		UnlockReleaseBuffer(buffer);
 	}
 
 	/* Finally, vacuum the FSM */
 	IndexFreeSpaceMapVacuum(info->index);
 
+	if (shouldcount)
+	{
+		stats->num_index_tuples = tuples_count;
+		stats->estimated_count = false;
+	}
+
 	/* return statistics */
 	stats->pages_free = totFreePages;
 	if (needLock)
-- 
2.14.3 (Apple Git-98)

