* its post-split version is treated as an extra step in either the
* insert or page split critical section.
*/
- Assert(isleaf && !ItemIdIsDead(itemid));
- Assert(itup_key->heapkeyspace && itup_key->allequalimage);
+ Assert(isleaf && itup_key->heapkeyspace && itup_key->allequalimage);
oposting = (IndexTuple) PageGetItem(page, itemid);
+ /*
+ * postingoff value comes from earlier call to _bt_binsrch_posting().
+ * Its binary search might think that a plain tuple must be a posting
+ * list tuple that needs to be split. This can happen with corruption
+ * involving an existing plain tuple that is a duplicate of the new
+ * item, up to and including its table TID. Check for that here in
+ * passing.
+ *
+ * Also verify that our caller has made sure that the existing posting
+ * list tuple does not have its LP_DEAD bit set.
+ */
+ if (!BTreeTupleIsPosting(oposting) || ItemIdIsDead(itemid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INDEX_CORRUPTED),
+ errmsg_internal("table tid from new index tuple (%u,%u) overlaps with invalid duplicate tuple at offset %u of block %u in index \"%s\"",
+ ItemPointerGetBlockNumber(&itup->t_tid),
+ ItemPointerGetOffsetNumber(&itup->t_tid),
+ BufferGetBlockNumber(buf), newitemoff,
+ RelationGetRelationName(rel))));
+
/* use a mutable copy of itup as our itup from here on */
origitup = itup;
itup = CopyIndexTuple(origitup);
* infrequently.
*/
if (unlikely(result == 0 && key->scantid != NULL))
+ {
+ /*
+ * postingoff should never be set more than once per leaf page
+ * binary search. That would mean that there are duplicate table
+ * TIDs in the index, which is never okay. Check for that here.
+ */
+ if (insertstate->postingoff != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INDEX_CORRUPTED),
+ errmsg_internal("table tid from new index tuple (%u,%u) cannot find insert offset between offsets %u and %u of block %u in index \"%s\"",
+ ItemPointerGetBlockNumber(key->scantid),
+ ItemPointerGetOffsetNumber(key->scantid),
+ low, stricthigh,
+ BufferGetBlockNumber(insertstate->buf),
+ RelationGetRelationName(rel))));
+
insertstate->postingoff = _bt_binsrch_posting(key, page, mid);
+ }
}
/*