From 4884272644e6772a3f5ae9d87fae2236e5ac1f01 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Mon, 23 Sep 2019 20:28:20 -0700 Subject: [PATCH v17 5/5] Reintroduce unique index support --- src/backend/access/nbtree/nbtinsert.c | 70 +++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index eb9655bb78..1912fe9ee4 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -434,15 +434,36 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel, if (!ItemIdIsDead(curitemid)) { ItemPointerData htid; + bool posting; bool all_dead; + bool posting_all_dead; + int npost; + if (_bt_compare(rel, itup_key, page, offset) != 0) break; /* we're past all the equal tuples */ /* okay, we gotta fetch the heap tuple ... */ curitup = (IndexTuple) PageGetItem(page, curitemid); - Assert(!BTreeTupleIsPosting(curitup)); - htid = curitup->t_tid; + + if (!BTreeTupleIsPosting(curitup)) + { + htid = curitup->t_tid; + posting = false; + posting_all_dead = true; + } + else + { + posting = true; + /* Initial assumption */ + posting_all_dead = true; + } + + npost = 0; +doposttup: + if (posting) + htid = *BTreeTupleGetPostingN(curitup, npost); + /* * If we are doing a recheck, we expect to find the tuple we @@ -453,6 +474,9 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel, ItemPointerCompare(&htid, &itup->t_tid) == 0) { found = true; + posting_all_dead = false; + if (posting) + goto nextpost; } /* @@ -518,8 +542,7 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel, * not part of this chain because it had a different index * entry. */ - htid = itup->t_tid; - if (table_index_fetch_tuple_check(heapRel, &htid, + if (table_index_fetch_tuple_check(heapRel, &itup->t_tid, SnapshotSelf, NULL)) { /* Normal case --- it's still live */ @@ -577,7 +600,7 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel, RelationGetRelationName(rel)))); } } - else if (all_dead) + else if (all_dead && !posting) { /* * The conflicting tuple (or whole HOT chain) is dead to @@ -596,6 +619,35 @@ _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel, else MarkBufferDirtyHint(insertstate->buf, true); } + else if (posting) + { +nextpost: + if (!all_dead) + posting_all_dead = false; + + /* Iterate over single posting list tuple */ + npost++; + if (npost < BTreeTupleGetNPosting(curitup)) + goto doposttup; + + /* + * Mark posting tuple dead if all hot chains whose root is + * contained in posting tuple have tuples that are all + * dead + */ + if (posting_all_dead) + { + ItemIdMarkDead(curitemid); + opaque->btpo_flags |= BTP_HAS_GARBAGE; + + if (nbuf != InvalidBuffer) + MarkBufferDirtyHint(nbuf, true); + else + MarkBufferDirtyHint(insertstate->buf, true); + } + + /* Move on to next index tuple */ + } } } @@ -770,7 +822,7 @@ _bt_findinsertloc(Relation rel, insertstate->bounds_valid = false; } - if (!checkingunique && PageGetFreeSpace(page) < insertstate->itemsz) + if (PageGetFreeSpace(page) < insertstate->itemsz) { _bt_dedup_one_page(rel, insertstate->buf, heapRel, insertstate->itemsz); @@ -2615,12 +2667,10 @@ _bt_dedup_one_page(Relation rel, Buffer buffer, Relation heapRel, Size pagesaving = 0; /* - * Don't use deduplication for indexes with INCLUDEd columns and unique - * indexes + * Don't use deduplication for indexes with INCLUDEd columns */ deduplicate = (IndexRelationGetNumberOfKeyAttributes(rel) == - IndexRelationGetNumberOfAttributes(rel) && - !rel->rd_index->indisunique); + IndexRelationGetNumberOfAttributes(rel)); if (!deduplicate) return; -- 2.17.1