📄 ginentrypage.c
字号:
/*------------------------------------------------------------------------- * * ginentrypage.c * page utilities routines for the postgres inverted index access method. * * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.12 2008/01/01 19:45:46 momjian Exp $ *------------------------------------------------------------------------- */#include "postgres.h"#include "access/gin.h"#include "access/tuptoaster.h"/* * forms tuple for entry tree. On leaf page, Index tuple has * non-traditional layout. Tuple may contain posting list or * root blocknumber of posting tree. Macros GinIsPostingTre: (itup) / GinSetPostingTree(itup, blkno) * 1) Posting list * - itup->t_info & INDEX_SIZE_MASK contains size of tuple as usual * - ItemPointerGetBlockNumber(&itup->t_tid) contains original * size of tuple (without posting list). * Macroses: GinGetOrigSizePosting(itup) / GinSetOrigSizePosting(itup,n) * - ItemPointerGetOffsetNumber(&itup->t_tid) contains number * of elements in posting list (number of heap itempointer) * Macroses: GinGetNPosting(itup) / GinSetNPosting(itup,n) * - After usual part of tuple there is a posting list * Macros: GinGetPosting(itup) * 2) Posting tree * - itup->t_info & INDEX_SIZE_MASK contains size of tuple as usual * - ItemPointerGetBlockNumber(&itup->t_tid) contains block number of * root of posting tree * - ItemPointerGetOffsetNumber(&itup->t_tid) contains magic number GIN_TREE_POSTING */IndexTupleGinFormTuple(GinState *ginstate, Datum key, ItemPointerData *ipd, uint32 nipd){ bool isnull = FALSE; IndexTuple itup; itup = index_form_tuple(ginstate->tupdesc, &key, &isnull); GinSetOrigSizePosting(itup, IndexTupleSize(itup)); if (nipd > 0) { uint32 newsize = MAXALIGN(SHORTALIGN(IndexTupleSize(itup)) + sizeof(ItemPointerData) * nipd); if (newsize >= INDEX_SIZE_MASK) return NULL; if (newsize > TOAST_INDEX_TARGET && nipd > 1) return NULL; itup = repalloc(itup, newsize); /* set new size */ itup->t_info &= ~INDEX_SIZE_MASK; itup->t_info |= newsize; if (ipd) memcpy(GinGetPosting(itup), ipd, sizeof(ItemPointerData) * nipd); GinSetNPosting(itup, nipd); } else { GinSetNPosting(itup, 0); } return itup;}/* * Entry tree is a "static", ie tuple never deletes from it, * so we don't use right bound, we use rightest key instead. */static IndexTuplegetRightMostTuple(Page page){ OffsetNumber maxoff = PageGetMaxOffsetNumber(page); return (IndexTuple) PageGetItem(page, PageGetItemId(page, maxoff));}DatumginGetHighKey(GinState *ginstate, Page page){ IndexTuple itup; bool isnull; itup = getRightMostTuple(page); return index_getattr(itup, FirstOffsetNumber, ginstate->tupdesc, &isnull);}static boolentryIsMoveRight(GinBtree btree, Page page){ Datum highkey; if (GinPageRightMost(page)) return FALSE; highkey = ginGetHighKey(btree->ginstate, page); if (compareEntries(btree->ginstate, btree->entryValue, highkey) > 0) return TRUE; return FALSE;}/* * Find correct tuple in non-leaf page. It supposed that * page correctly choosen and searching value SHOULD be on page */static BlockNumberentryLocateEntry(GinBtree btree, GinBtreeStack *stack){ OffsetNumber low, high, maxoff; IndexTuple itup = NULL; int result; Page page = BufferGetPage(stack->buffer); Assert(!GinPageIsLeaf(page)); Assert(!GinPageIsData(page)); if (btree->fullScan) { stack->off = FirstOffsetNumber; stack->predictNumber *= PageGetMaxOffsetNumber(page); return btree->getLeftMostPage(btree, page); } low = FirstOffsetNumber; maxoff = high = PageGetMaxOffsetNumber(page); Assert(high >= low); high++; while (high > low) { OffsetNumber mid = low + ((high - low) / 2); if (mid == maxoff && GinPageRightMost(page)) /* Right infinity */ result = -1; else { bool isnull; itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, mid)); result = compareEntries(btree->ginstate, btree->entryValue, index_getattr(itup, FirstOffsetNumber, btree->ginstate->tupdesc, &isnull)); } if (result == 0) { stack->off = mid; Assert(GinItemPointerGetBlockNumber(&(itup)->t_tid) != GIN_ROOT_BLKNO); return GinItemPointerGetBlockNumber(&(itup)->t_tid); } else if (result > 0) low = mid + 1; else high = mid; } Assert(high >= FirstOffsetNumber && high <= maxoff); stack->off = high; itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, high)); Assert(GinItemPointerGetBlockNumber(&(itup)->t_tid) != GIN_ROOT_BLKNO); return GinItemPointerGetBlockNumber(&(itup)->t_tid);}/* * Searches correct position for value on leaf page. * Page should be corrrectly choosen. * Returns true if value found on page. */static boolentryLocateLeafEntry(GinBtree btree, GinBtreeStack *stack){ Page page = BufferGetPage(stack->buffer); OffsetNumber low, high; IndexTuple itup; Assert(GinPageIsLeaf(page)); Assert(!GinPageIsData(page)); if (btree->fullScan) { stack->off = FirstOffsetNumber; return TRUE; } low = FirstOffsetNumber; high = PageGetMaxOffsetNumber(page); if (high < low) { stack->off = FirstOffsetNumber; return false; } high++; while (high > low) { OffsetNumber mid = low + ((high - low) / 2); bool isnull; int result; itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, mid)); result = compareEntries(btree->ginstate, btree->entryValue, index_getattr(itup, FirstOffsetNumber, btree->ginstate->tupdesc, &isnull)); if (result == 0) { stack->off = mid; return true; } else if (result > 0) low = mid + 1; else high = mid; } stack->off = high; return false;}static OffsetNumberentryFindChildPtr(GinBtree btree, Page page, BlockNumber blkno, OffsetNumber storedOff){ OffsetNumber i, maxoff = PageGetMaxOffsetNumber(page); IndexTuple itup; Assert(!GinPageIsLeaf(page)); Assert(!GinPageIsData(page)); /* if page isn't changed, we returns storedOff */ if (storedOff >= FirstOffsetNumber && storedOff <= maxoff) { itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, storedOff)); if (GinItemPointerGetBlockNumber(&(itup)->t_tid) == blkno) return storedOff; /* * we hope, that needed pointer goes to right. It's true if there * wasn't a deletion */ for (i = storedOff + 1; i <= maxoff; i++) { itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, i)); if (GinItemPointerGetBlockNumber(&(itup)->t_tid) == blkno) return i; } maxoff = storedOff - 1; } /* last chance */ for (i = FirstOffsetNumber; i <= maxoff; i++) { itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, i)); if (GinItemPointerGetBlockNumber(&(itup)->t_tid) == blkno) return i; } return InvalidOffsetNumber;}static BlockNumberentryGetLeftMostPage(GinBtree btree, Page page){ IndexTuple itup; Assert(!GinPageIsLeaf(page)); Assert(!GinPageIsData(page)); Assert(PageGetMaxOffsetNumber(page) >= FirstOffsetNumber); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, FirstOffsetNumber)); return GinItemPointerGetBlockNumber(&(itup)->t_tid);}static boolentryIsEnoughSpace(GinBtree btree, Buffer buf, OffsetNumber off){ Size itupsz = 0; Page page = BufferGetPage(buf); Assert(btree->entry); Assert(!GinPageIsData(page)); if (btree->isDelete) { IndexTuple itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -