diff --git a/src/backend/access/gin/ginbtree.c b/src/backend/access/gin/ginbtree.c index 0d93c52e04..c4801d5cd8 100644 --- a/src/backend/access/gin/ginbtree.c +++ b/src/backend/access/gin/ginbtree.c @@ -452,6 +452,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats) } } + btree->prepareDownlink(btree, stack->buffer); btree->isDelete = FALSE; /* search parent to lock */ diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c index 67d748bd71..fbdde1dc02 100644 --- a/src/backend/access/gin/gindatapage.c +++ b/src/backend/access/gin/gindatapage.c @@ -580,12 +580,20 @@ dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRe rdata[1].len = MAXALIGN(maxoff * sizeofitem); rdata[1].next = NULL; - /* Prepare a downlink tuple for insertion to the parent */ + return lpage; +} + +/* + * Prepare the state in 'btree' for inserting a downlink for given buffer. + */ +static void +dataPrepareDownlink(GinBtree btree, Buffer lbuf) +{ + Page lpage = BufferGetPage(lbuf); + PostingItemSetBlockNumber(&(btree->pitem), BufferGetBlockNumber(lbuf)); btree->pitem.key = *GinDataPageGetRightBound(lpage); - btree->rightblkno = BufferGetBlockNumber(rbuf); - - return lpage; + btree->rightblkno = GinPageGetOpaque(lpage)->rightlink; } /* @@ -704,6 +712,7 @@ ginPrepareDataScan(GinBtree btree, Relation index) btree->placeToPage = dataPlaceToPage; btree->splitPage = dataSplitPage; btree->fillRoot = ginDataFillRoot; + btree->prepareDownlink = dataPrepareDownlink; btree->isData = TRUE; btree->isDelete = FALSE; diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c index a22fd32d9d..ec0114e7d3 100644 --- a/src/backend/access/gin/ginentrypage.c +++ b/src/backend/access/gin/ginentrypage.c @@ -570,8 +570,7 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR Size lsize = 0, size; char *ptr; - IndexTuple itup, - leftrightmost = NULL; + IndexTuple itup; Page page; Page lpage = PageGetTempPageCopy(BufferGetPage(lbuf)); Page rpage = BufferGetPage(rbuf); @@ -635,7 +634,6 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR } else { - leftrightmost = itup; lsize += MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData); } @@ -645,11 +643,6 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR ptr += MAXALIGN(IndexTupleSize(itup)); } - btree->entry = GinFormInteriorTuple(leftrightmost, lpage, - BufferGetBlockNumber(lbuf)); - - btree->rightblkno = BufferGetBlockNumber(rbuf); - data.node = btree->index->rd_node; data.rootBlkno = InvalidBlockNumber; data.lblkno = BufferGetBlockNumber(lbuf); @@ -674,19 +667,20 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR } /* - * return newly allocated rightmost tuple + * Prepare the state in 'btree' for inserting a downlink for given buffer. */ -IndexTuple -ginPageGetLinkItup(Buffer buf) +static void +entryPrepareDownlink(GinBtree btree, Buffer lbuf) { - IndexTuple itup, - nitup; - Page page = BufferGetPage(buf); + Page lpage = BufferGetPage(lbuf); + IndexTuple itup; - itup = getRightMostTuple(page); - nitup = GinFormInteriorTuple(itup, page, BufferGetBlockNumber(buf)); + itup = getRightMostTuple(lpage); - return nitup; + btree->entry = GinFormInteriorTuple(itup, + lpage, + BufferGetBlockNumber(lbuf)); + btree->rightblkno = GinPageGetOpaque(lpage)->rightlink; } /* @@ -696,17 +690,21 @@ ginPageGetLinkItup(Buffer buf) void ginEntryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf) { - Page page; + Page page = BufferGetPage(root); + Page lpage = BufferGetPage(lbuf); + Page rpage = BufferGetPage(rbuf); IndexTuple itup; - page = BufferGetPage(root); - - itup = ginPageGetLinkItup(lbuf); + itup = GinFormInteriorTuple(getRightMostTuple(lpage), + lpage, + BufferGetBlockNumber(lbuf)); if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber) elog(ERROR, "failed to add item to index root page"); pfree(itup); - itup = ginPageGetLinkItup(rbuf); + itup = GinFormInteriorTuple(getRightMostTuple(rpage), + rpage, + BufferGetBlockNumber(rbuf)); if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber) elog(ERROR, "failed to add item to index root page"); pfree(itup); @@ -736,6 +734,7 @@ ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum, btree->placeToPage = entryPlaceToPage; btree->splitPage = entrySplitPage; btree->fillRoot = ginEntryFillRoot; + btree->prepareDownlink = entryPrepareDownlink; btree->isData = FALSE; btree->fullScan = FALSE; diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c index 4d0ccb876f..ddac343061 100644 --- a/src/backend/access/gin/ginxlog.c +++ b/src/backend/access/gin/ginxlog.c @@ -799,31 +799,20 @@ ginContinueSplit(ginIncompleteSplit *split) ginPrepareEntryScan(&btree, InvalidOffsetNumber, (Datum) 0, GIN_CAT_NULL_KEY, &ginstate); - btree.entry = ginPageGetLinkItup(buffer); } else { - Page page = BufferGetPage(buffer); - ginPrepareDataScan(&btree, reln); - - PostingItemSetBlockNumber(&(btree.pitem), split->leftBlkno); - if (GinPageIsLeaf(page)) - btree.pitem.key = *GinDataPageGetItemPointer(page, - GinPageGetOpaque(page)->maxoff); - else - btree.pitem.key = GinDataPageGetPostingItem(page, - GinPageGetOpaque(page)->maxoff)->key; } - btree.rightblkno = split->rightBlkno; - stack.blkno = split->leftBlkno; stack.buffer = buffer; stack.off = InvalidOffsetNumber; stack.parent = NULL; ginFindParents(&btree, &stack, split->rootBlkno); + + btree.prepareDownlink(&btree, buffer); ginInsertValue(&btree, stack.parent, NULL); FreeFakeRelcacheEntry(reln); diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index 7491d7cf0c..39529353d1 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -487,6 +487,7 @@ typedef struct GinBtreeData OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber); bool (*placeToPage) (GinBtree, Buffer, OffsetNumber, XLogRecData **); Page (*splitPage) (GinBtree, Buffer, Buffer, OffsetNumber, XLogRecData **); + void (*prepareDownlink) (GinBtree, Buffer); void (*fillRoot) (GinBtree, Buffer, Buffer, Buffer); bool isData; @@ -529,7 +530,6 @@ extern void ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum, Datum key, GinNullCategory category, GinState *ginstate); extern void ginEntryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf); -extern IndexTuple ginPageGetLinkItup(Buffer buf); /* gindatapage.c */ extern BlockNumber createPostingTree(Relation index,