diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c index f017de0cdc8c1c257a2f8d36a7ddd82cb8a689f2..2c6447d7faa14c0c1f79feba3eb84fd7e7fcdc38 100644 --- a/src/backend/access/gin/gindatapage.c +++ b/src/backend/access/gin/gindatapage.c @@ -105,7 +105,7 @@ dataLocateItem(GinBtree btree, GinBtreeStack *stack) { OffsetNumber mid = low + ((high - low) / 2); - pitem = (PostingItem *) GinDataPageGetItem(page, mid); + pitem = GinDataPageGetPostingItem(page, mid); if (mid == maxoff) { @@ -117,7 +117,7 @@ dataLocateItem(GinBtree btree, GinBtreeStack *stack) } else { - pitem = (PostingItem *) GinDataPageGetItem(page, mid); + pitem = GinDataPageGetPostingItem(page, mid); result = ginCompareItemPointers(btree->items + btree->curitem, &(pitem->key)); } @@ -135,7 +135,7 @@ dataLocateItem(GinBtree btree, GinBtreeStack *stack) Assert(high >= FirstOffsetNumber && high <= maxoff); stack->off = high; - pitem = (PostingItem *) GinDataPageGetItem(page, high); + pitem = GinDataPageGetPostingItem(page, high); return PostingItemGetBlockNumber(pitem); } @@ -176,7 +176,8 @@ dataLocateLeafItem(GinBtree btree, GinBtreeStack *stack) { OffsetNumber mid = low + ((high - low) / 2); - result = ginCompareItemPointers(btree->items + btree->curitem, (ItemPointer) GinDataPageGetItem(page, mid)); + result = ginCompareItemPointers(btree->items + btree->curitem, + GinDataPageGetItemPointer(page, mid)); if (result == 0) { @@ -210,7 +211,7 @@ dataFindChildPtr(GinBtree btree, Page page, BlockNumber blkno, OffsetNumber stor /* if page isn't changed, we return storedOff */ if (storedOff >= FirstOffsetNumber && storedOff <= maxoff) { - pitem = (PostingItem *) GinDataPageGetItem(page, storedOff); + pitem = GinDataPageGetPostingItem(page, storedOff); if (PostingItemGetBlockNumber(pitem) == blkno) return storedOff; @@ -220,7 +221,7 @@ dataFindChildPtr(GinBtree btree, Page page, BlockNumber blkno, OffsetNumber stor */ for (i = storedOff + 1; i <= maxoff; i++) { - pitem = (PostingItem *) GinDataPageGetItem(page, i); + pitem = GinDataPageGetPostingItem(page, i); if (PostingItemGetBlockNumber(pitem) == blkno) return i; } @@ -231,7 +232,7 @@ dataFindChildPtr(GinBtree btree, Page page, BlockNumber blkno, OffsetNumber stor /* last chance */ for (i = FirstOffsetNumber; i <= maxoff; i++) { - pitem = (PostingItem *) GinDataPageGetItem(page, i); + pitem = GinDataPageGetPostingItem(page, i); if (PostingItemGetBlockNumber(pitem) == blkno) return i; } @@ -251,33 +252,62 @@ dataGetLeftMostPage(GinBtree btree, Page page) Assert(GinPageIsData(page)); Assert(GinPageGetOpaque(page)->maxoff >= FirstOffsetNumber); - pitem = (PostingItem *) GinDataPageGetItem(page, FirstOffsetNumber); + pitem = GinDataPageGetPostingItem(page, FirstOffsetNumber); return PostingItemGetBlockNumber(pitem); } /* - * add ItemPointer or PostingItem to page. data should point to - * correct value! depending on leaf or non-leaf page + * add ItemPointer to a leaf page. */ void -GinDataPageAddItem(Page page, void *data, OffsetNumber offset) +GinDataPageAddItemPointer(Page page, ItemPointer data, OffsetNumber offset) { OffsetNumber maxoff = GinPageGetOpaque(page)->maxoff; char *ptr; + Assert(GinPageIsLeaf(page)); + + if (offset == InvalidOffsetNumber) + { + ptr = (char *) GinDataPageGetItemPointer(page, maxoff + 1); + } + else + { + ptr = (char *) GinDataPageGetItemPointer(page, offset); + if (maxoff + 1 - offset != 0) + memmove(ptr + sizeof(ItemPointerData), + ptr, + (maxoff - offset + 1) * sizeof(ItemPointerData)); + } + memcpy(ptr, data, sizeof(ItemPointerData)); + + GinPageGetOpaque(page)->maxoff++; +} + +/* + * add PostingItem to a non-leaf page. + */ +void +GinDataPageAddPostingItem(Page page, PostingItem *data, OffsetNumber offset) +{ + OffsetNumber maxoff = GinPageGetOpaque(page)->maxoff; + char *ptr; + + Assert(!GinPageIsLeaf(page)); + if (offset == InvalidOffsetNumber) { - ptr = GinDataPageGetItem(page, maxoff + 1); + ptr = (char *) GinDataPageGetPostingItem(page, maxoff + 1); } else { - ptr = GinDataPageGetItem(page, offset); + ptr = (char *) GinDataPageGetPostingItem(page, offset); if (maxoff + 1 - offset != 0) - memmove(ptr + GinSizeOfDataPageItem(page), + memmove(ptr + sizeof(PostingItem), ptr, - (maxoff - offset + 1) * GinSizeOfDataPageItem(page)); + (maxoff - offset + 1) * sizeof(PostingItem)); } - memcpy(ptr, data, GinSizeOfDataPageItem(page)); + memcpy(ptr, data, sizeof(PostingItem)); GinPageGetOpaque(page)->maxoff++; } @@ -294,7 +324,8 @@ GinPageDeletePostingItem(Page page, OffsetNumber offset) Assert(offset >= FirstOffsetNumber && offset <= maxoff); if (offset != maxoff) - memmove(GinDataPageGetItem(page, offset), GinDataPageGetItem(page, offset + 1), + memmove(GinDataPageGetPostingItem(page, offset), + GinDataPageGetPostingItem(page, offset + 1), sizeof(PostingItem) * (maxoff - offset)); GinPageGetOpaque(page)->maxoff--; @@ -342,7 +373,7 @@ dataPrepareData(GinBtree btree, Page page, OffsetNumber off) if (!GinPageIsLeaf(page) && btree->rightblkno != InvalidBlockNumber) { - PostingItem *pitem = (PostingItem *) GinDataPageGetItem(page, off); + PostingItem *pitem = GinDataPageGetPostingItem(page, off); PostingItemSetBlockNumber(pitem, btree->rightblkno); ret = btree->rightblkno; @@ -418,7 +449,7 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda while (btree->curitem < btree->nitem) { - GinDataPageAddItem(page, btree->items + btree->curitem, off); + GinDataPageAddItemPointer(page, btree->items + btree->curitem, off); off++; btree->curitem++; } @@ -427,12 +458,12 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda } else { - GinDataPageAddItem(page, btree->items + btree->curitem, off); + GinDataPageAddItemPointer(page, btree->items + btree->curitem, off); btree->curitem++; } } else - GinDataPageAddItem(page, &(btree->pitem), off); + GinDataPageAddPostingItem(page, &(btree->pitem), off); } /* @@ -448,6 +479,7 @@ dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRe OffsetNumber separator; ItemPointer bound; Page lpage = PageGetTempPageCopy(BufferGetPage(lbuf)); + bool isleaf = GinPageIsLeaf(lpage); ItemPointerData oldbound = *GinDataPageGetRightBound(lpage); int sizeofitem = GinSizeOfDataPageItem(lpage); OffsetNumber maxoff = GinPageGetOpaque(lpage)->maxoff; @@ -469,10 +501,20 @@ dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRe InvalidOffsetNumber : PostingItemGetBlockNumber(&(btree->pitem)); data.updateBlkno = dataPrepareData(btree, lpage, off); - memcpy(vector, GinDataPageGetItem(lpage, FirstOffsetNumber), - maxoff * sizeofitem); + if (isleaf) + { + memcpy(vector, + GinDataPageGetItemPointer(lpage, FirstOffsetNumber), + maxoff * sizeof(ItemPointerData)); + } + else + { + memcpy(vector, + GinDataPageGetPostingItem(lpage, FirstOffsetNumber), + maxoff * sizeof(PostingItem)); + } - if (GinPageIsLeaf(lpage) && GinPageRightMost(lpage) && off > GinPageGetOpaque(lpage)->maxoff) + if (isleaf && GinPageRightMost(lpage) && off > GinPageGetOpaque(lpage)->maxoff) { nCopied = 0; while (btree->curitem < btree->nitem && @@ -491,7 +533,7 @@ dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRe ptr = vector + (off - 1) * sizeofitem; if (maxoff + 1 - off != 0) memmove(ptr + sizeofitem, ptr, (maxoff - off + 1) * sizeofitem); - if (GinPageIsLeaf(lpage)) + if (isleaf) { memcpy(ptr, btree->items + btree->curitem, sizeofitem); btree->curitem++; @@ -514,19 +556,32 @@ dataSplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogRe GinInitPage(rpage, GinPageGetOpaque(lpage)->flags, pageSize); GinInitPage(lpage, GinPageGetOpaque(rpage)->flags, pageSize); - memcpy(GinDataPageGetItem(lpage, FirstOffsetNumber), vector, separator * sizeofitem); + if (isleaf) + memcpy(GinDataPageGetItemPointer(lpage, FirstOffsetNumber), + vector, separator * sizeof(ItemPointerData)); + else + memcpy(GinDataPageGetPostingItem(lpage, FirstOffsetNumber), + vector, separator * sizeof(PostingItem)); + GinPageGetOpaque(lpage)->maxoff = separator; - memcpy(GinDataPageGetItem(rpage, FirstOffsetNumber), - vector + separator * sizeofitem, (maxoff - separator) * sizeofitem); + if (isleaf) + memcpy(GinDataPageGetItemPointer(rpage, FirstOffsetNumber), + vector + separator * sizeof(ItemPointerData), + (maxoff - separator) * sizeof(ItemPointerData)); + else + memcpy(GinDataPageGetPostingItem(rpage, FirstOffsetNumber), + vector + separator * sizeof(PostingItem), + (maxoff - separator) * sizeof(PostingItem)); + GinPageGetOpaque(rpage)->maxoff = maxoff - separator; PostingItemSetBlockNumber(&(btree->pitem), BufferGetBlockNumber(lbuf)); if (GinPageIsLeaf(lpage)) - btree->pitem.key = *(ItemPointerData *) GinDataPageGetItem(lpage, + btree->pitem.key = *GinDataPageGetItemPointer(lpage, GinPageGetOpaque(lpage)->maxoff); else - btree->pitem.key = ((PostingItem *) GinDataPageGetItem(lpage, - GinPageGetOpaque(lpage)->maxoff))->key; + btree->pitem.key = GinDataPageGetPostingItem(lpage, + GinPageGetOpaque(lpage)->maxoff)->key; btree->rightblkno = BufferGetBlockNumber(rbuf); /* set up right bound for left page */ @@ -576,11 +631,11 @@ ginDataFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf) li.key = *GinDataPageGetRightBound(lpage); PostingItemSetBlockNumber(&li, BufferGetBlockNumber(lbuf)); - GinDataPageAddItem(page, &li, InvalidOffsetNumber); + GinDataPageAddPostingItem(page, &li, InvalidOffsetNumber); ri.key = *GinDataPageGetRightBound(rpage); PostingItemSetBlockNumber(&ri, BufferGetBlockNumber(rbuf)); - GinDataPageAddItem(page, &ri, InvalidOffsetNumber); + GinDataPageAddPostingItem(page, &ri, InvalidOffsetNumber); } void diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c index cb17d383bc845a5c922dc2cfdfdc83df2ab9eb41..cb779aa7f74e7beb4f066368413918c5eff11a9a 100644 --- a/src/backend/access/gin/ginget.c +++ b/src/backend/access/gin/ginget.c @@ -83,7 +83,7 @@ findItemInPostingPage(Page page, ItemPointer item, OffsetNumber *off) */ for (*off = FirstOffsetNumber; *off <= maxoff; (*off)++) { - res = ginCompareItemPointers(item, (ItemPointer) GinDataPageGetItem(page, *off)); + res = ginCompareItemPointers(item, GinDataPageGetItemPointer(page, *off)); if (res <= 0) return true; @@ -154,7 +154,7 @@ scanPostingTree(Relation index, GinScanEntry scanEntry, GinPageGetOpaque(page)->maxoff >= FirstOffsetNumber) { tbm_add_tuples(scanEntry->matchBitmap, - (ItemPointer) GinDataPageGetItem(page, FirstOffsetNumber), + GinDataPageGetItemPointer(page, FirstOffsetNumber), GinPageGetOpaque(page)->maxoff, false); scanEntry->predictNumberResult += GinPageGetOpaque(page)->maxoff; } @@ -467,7 +467,8 @@ restartScanEntry: */ entry->list = (ItemPointerData *) palloc(BLCKSZ); entry->nlist = GinPageGetOpaque(page)->maxoff; - memcpy(entry->list, GinDataPageGetItem(page, FirstOffsetNumber), + memcpy(entry->list, + GinDataPageGetItemPointer(page, FirstOffsetNumber), GinPageGetOpaque(page)->maxoff * sizeof(ItemPointerData)); LockBuffer(entry->buffer, GIN_UNLOCK); @@ -587,8 +588,9 @@ entryGetNextItem(GinState *ginstate, GinScanEntry entry) * Found position equal to or greater than stored */ entry->nlist = GinPageGetOpaque(page)->maxoff; - memcpy(entry->list, GinDataPageGetItem(page, FirstOffsetNumber), - GinPageGetOpaque(page)->maxoff * sizeof(ItemPointerData)); + memcpy(entry->list, + GinDataPageGetItemPointer(page, FirstOffsetNumber), + GinPageGetOpaque(page)->maxoff * sizeof(ItemPointerData)); LockBuffer(entry->buffer, GIN_UNLOCK); diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c index b84d3a30de39b135897355b98ba6f5c4f86d8ffb..bda9c60279ac5e30998be9af766229432516f083 100644 --- a/src/backend/access/gin/ginvacuum.c +++ b/src/backend/access/gin/ginvacuum.c @@ -210,7 +210,7 @@ ginVacuumPostingTreeLeaves(GinVacuumState *gvs, BlockNumber blkno, bool isRoot, for (i = FirstOffsetNumber; i <= GinPageGetOpaque(page)->maxoff; i++) { - PostingItem *pitem = (PostingItem *) GinDataPageGetItem(page, i); + PostingItem *pitem = GinDataPageGetPostingItem(page, i); if (ginVacuumPostingTreeLeaves(gvs, PostingItemGetBlockNumber(pitem), FALSE, NULL)) isChildHasVoid = TRUE; @@ -283,7 +283,7 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn #ifdef USE_ASSERT_CHECKING do { - PostingItem *tod = (PostingItem *) GinDataPageGetItem(parentPage, myoff); + PostingItem *tod = GinDataPageGetPostingItem(parentPage, myoff); Assert(PostingItemGetBlockNumber(tod) == deleteBlkno); } while (0); @@ -422,7 +422,7 @@ ginScanToDelete(GinVacuumState *gvs, BlockNumber blkno, bool isRoot, DataPageDel me->blkno = blkno; for (i = FirstOffsetNumber; i <= GinPageGetOpaque(page)->maxoff; i++) { - PostingItem *pitem = (PostingItem *) GinDataPageGetItem(page, i); + PostingItem *pitem = GinDataPageGetPostingItem(page, i); if (ginScanToDelete(gvs, PostingItemGetBlockNumber(pitem), FALSE, me, i)) i--; diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c index 5daabb0eef9885dda57adc9c0dd0fcdc9d2292d0..4d0ccb876f21f5971c2940e772ce9ffb9645f5f1 100644 --- a/src/backend/access/gin/ginxlog.c +++ b/src/backend/access/gin/ginxlog.c @@ -189,7 +189,7 @@ ginRedoInsert(XLogRecPtr lsn, XLogRecord *record) Assert(data->updateBlkno == InvalidBlockNumber); for (i = 0; i < data->nitem; i++) - GinDataPageAddItem(page, items + i, data->offset + i); + GinDataPageAddItemPointer(page, &items[i], data->offset + i); } else { @@ -200,13 +200,13 @@ ginRedoInsert(XLogRecPtr lsn, XLogRecord *record) if (data->updateBlkno != InvalidBlockNumber) { /* update link to right page after split */ - pitem = (PostingItem *) GinDataPageGetItem(page, data->offset); + pitem = GinDataPageGetPostingItem(page, data->offset); PostingItemSetBlockNumber(pitem, data->updateBlkno); } pitem = (PostingItem *) (XLogRecGetData(record) + sizeof(ginxlogInsert)); - GinDataPageAddItem(page, pitem, data->offset); + GinDataPageAddPostingItem(page, pitem, data->offset); } } else @@ -286,22 +286,28 @@ ginRedoSplit(XLogRecPtr lsn, XLogRecord *record) for (i = 0; i < data->separator; i++) { - GinDataPageAddItem(lpage, ptr, InvalidOffsetNumber); + if (data->isLeaf) + GinDataPageAddItemPointer(lpage, (ItemPointer) ptr, InvalidOffsetNumber); + else + GinDataPageAddPostingItem(lpage, (PostingItem *) ptr, InvalidOffsetNumber); ptr += sizeofitem; } for (i = data->separator; i < data->nitem; i++) { - GinDataPageAddItem(rpage, ptr, InvalidOffsetNumber); + if (data->isLeaf) + GinDataPageAddItemPointer(rpage, (ItemPointer) ptr, InvalidOffsetNumber); + else + GinDataPageAddPostingItem(rpage, (PostingItem *) ptr, InvalidOffsetNumber); ptr += sizeofitem; } /* set up right key */ bound = GinDataPageGetRightBound(lpage); if (data->isLeaf) - *bound = *(ItemPointerData *) GinDataPageGetItem(lpage, GinPageGetOpaque(lpage)->maxoff); + *bound = *GinDataPageGetItemPointer(lpage, GinPageGetOpaque(lpage)->maxoff); else - *bound = ((PostingItem *) GinDataPageGetItem(lpage, GinPageGetOpaque(lpage)->maxoff))->key; + *bound = GinDataPageGetPostingItem(lpage, GinPageGetOpaque(lpage)->maxoff)->key; bound = GinDataPageGetRightBound(rpage); *bound = data->rightbound; @@ -803,11 +809,11 @@ ginContinueSplit(ginIncompleteSplit *split) PostingItemSetBlockNumber(&(btree.pitem), split->leftBlkno); if (GinPageIsLeaf(page)) - btree.pitem.key = *(ItemPointerData *) GinDataPageGetItem(page, - GinPageGetOpaque(page)->maxoff); + btree.pitem.key = *GinDataPageGetItemPointer(page, + GinPageGetOpaque(page)->maxoff); else - btree.pitem.key = ((PostingItem *) GinDataPageGetItem(page, - GinPageGetOpaque(page)->maxoff))->key; + btree.pitem.key = GinDataPageGetPostingItem(page, + GinPageGetOpaque(page)->maxoff)->key; } btree.rightblkno = split->rightBlkno; diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index c603521c9574fda6331889c5034ac956f86b2cff..7af3a870c7511bd4be9bc1288fa9bbeeb48587d0 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -232,10 +232,14 @@ typedef signed char GinNullCategory; #define GinDataPageGetRightBound(page) ((ItemPointer) PageGetContents(page)) #define GinDataPageGetData(page) \ (PageGetContents(page) + MAXALIGN(sizeof(ItemPointerData))) +/* non-leaf pages contain PostingItems */ +#define GinDataPageGetPostingItem(page, i) \ + ((PostingItem *) (GinDataPageGetData(page) + ((i)-1) * sizeof(PostingItem))) +/* leaf pages contain ItemPointers */ +#define GinDataPageGetItemPointer(page, i) \ + ((ItemPointer) (GinDataPageGetData(page) + ((i)-1) * sizeof(ItemPointerData))) #define GinSizeOfDataPageItem(page) \ (GinPageIsLeaf(page) ? sizeof(ItemPointerData) : sizeof(PostingItem)) -#define GinDataPageGetItem(page,i) \ - (GinDataPageGetData(page) + ((i)-1) * GinSizeOfDataPageItem(page)) #define GinDataPageGetFreeSpace(page) \ (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) \ @@ -534,7 +538,8 @@ extern uint32 ginMergeItemPointers(ItemPointerData *dst, ItemPointerData *a, uint32 na, ItemPointerData *b, uint32 nb); -extern void GinDataPageAddItem(Page page, void *data, OffsetNumber offset); +extern void GinDataPageAddItemPointer(Page page, ItemPointer data, OffsetNumber offset); +extern void GinDataPageAddPostingItem(Page page, PostingItem *data, OffsetNumber offset); extern void GinPageDeletePostingItem(Page page, OffsetNumber offset); typedef struct