From 1d0969b8b11a62226f4441d1b3a335832fdffac7 Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@bowt.ie>
Date: Sat, 4 May 2019 12:27:31 -0700
Subject: [PATCH] Remove nbtree half-dead internal page check.

Internal nbtree pages are never marked half-dead by VACUUM following
commit efada2b8e92, which made nbtree page deletion more robust.  It
follows that VACUUM cannot possibly benefit from checking if an internal
page is half-dead as part of assessing if it's safe to delete the
internal page to its left.  The same VACUUM operation will report the
same half-dead internal page as corrupt when it processes it directly a
little later on.

Remove the useless check, and add a comment explaining why it's safe to
rely on a similar leaf-level check to transitively detect if internal
pages are pending deletion.  Both checks were added by bugfix commit
8da31837803 a couple of months after commit efada2b8e92 went in,
following a report of a failing sanity check.

Discussion: https://postgr.es/m/CAH2-Wz=_Xvv8byzK_LvY4ci76OgsHCQzoKF7We8yG9waO7j6rA@mail.gmail.com
---
 src/backend/access/nbtree/nbtpage.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 8ade165f7a..84011438a0 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -1301,17 +1301,6 @@ _bt_lock_branch_parent(Relation rel, BlockNumber child, BTStack stack,
 				_bt_relbuf(rel, lbuf);
 			}
 
-			/*
-			 * Perform the same check on this internal level that
-			 * _bt_mark_page_halfdead performed on the leaf level.
-			 */
-			if (_bt_is_page_halfdead(rel, *rightsib))
-			{
-				elog(DEBUG1, "could not delete page %u because its right sibling %u is half-dead",
-					 parent, *rightsib);
-				return false;
-			}
-
 			return _bt_lock_branch_parent(rel, parent, stack->bts_parent,
 										  topparent, topoff, target, rightsib);
 		}
@@ -1622,6 +1611,15 @@ _bt_mark_page_halfdead(Relation rel, Buffer leafbuf, BTStack stack)
 	 * be deleted too, and the same condition applies recursively to it. We
 	 * have to check this condition all the way up before trying to delete,
 	 * and lock the final parent of the to-be-deleted branch.
+	 *
+	 * However, we don't need to repeat the above _bt_is_page_halfdead() check
+	 * on parent/ancestor pages because of the rightmost restriction. The
+	 * check will apply to a right "cousin" page rather than a simple right
+	 * sibling page in cases where we actually go on to perform internal page
+	 * deletion. The cousin page is representative of the left edge of the
+	 * subtree to the right as a whole.  (Besides, internal pages are never
+	 * marked half-dead, so it isn't even possible to directly assess if an
+	 * internal page is part of a to-be-deleted branch.)
 	 */
 	rightsib = leafrightsib;
 	target = leafblkno;
-- 
2.17.1

