I found another bug as a result of using amcheck on Heroku customer
databases. This time, the bug is in core Postgres. It's one of mine.

There was a thinko in tuplesort's abbreviation abort logic, causing
certain SortTuples to be spuriously marked NULL (and so, subsequently
sorted as a NULL tuple, despite not actually changing anything about
the representation of caller tuples). The attached patch fixes this
bug.

I noticed this following a complaint by amcheck about a tuple in the
wrong order on a leaf page in some random text index. The leaf page
was entirely full of NULL values, aside from this one tuple at some
seemingly random position. All non-NULL index tuples were of the kind
that you'd expect to trigger abbreviation to abort (many distinct
values, but with little entropy at the beginning).

I believe that this particular problem has been observed on a tiny
fraction of all databases tested, so I don't think it's very common in
the wild.

I'd be surprised if amcheck does not bring more bugs like this to my
attention before too long. We should work on improving it, so that we
have greater visibility into problems that occur in the field.
-- 
Peter Geoghegan
From d570b9bbfc00cbd861291f47425aa1da1bc32db5 Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <p...@bowt.ie>
Date: Fri, 19 Aug 2016 14:34:34 -0700
Subject: [PATCH] Fix thinko in abbreviated key abort code

Due to an error in the abbreviated key abort logic, the most recently
processed SortTuple could be incorrectly marked NULL, resulting in an
incorrect final sort order.

This bug may have resulted in corrupt B-Tree indexes in cases where
abbreviation is aborted.  In general, abbreviation is aborted due to a
lack of entropy in the abbreviated keys that were generated so far.
---
 src/backend/utils/sort/tuplesort.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 510565c..ae384a8 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -1443,7 +1443,7 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
 			mtup->datum1 = index_getattr(tuple,
 										 1,
 										 RelationGetDescr(state->indexRel),
-										 &stup.isnull1);
+										 &mtup->isnull1);
 		}
 	}
 
@@ -4271,7 +4271,7 @@ copytup_cluster(Tuplesortstate *state, SortTuple *stup, void *tup)
 			mtup->datum1 = heap_getattr(tuple,
 									  state->indexInfo->ii_KeyAttrNumbers[0],
 										state->tupDesc,
-										&stup->isnull1);
+										&mtup->isnull1);
 		}
 	}
 }
@@ -4588,7 +4588,7 @@ copytup_index(Tuplesortstate *state, SortTuple *stup, void *tup)
 			mtup->datum1 = index_getattr(tuple,
 										 1,
 										 RelationGetDescr(state->indexRel),
-										 &stup->isnull1);
+										 &mtup->isnull1);
 		}
 	}
 }
-- 
2.7.4

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to