PostgreSQL Source Code git master
Functions
ginentrypage.c File Reference
#include "postgres.h"
#include "access/gin_private.h"
#include "access/ginxlog.h"
#include "access/xloginsert.h"
#include "utils/rel.h"
Include dependency graph for ginentrypage.c:

Go to the source code of this file.

Functions

static void  entrySplitPage (GinBtree btree, Buffer origbuf, GinBtreeStack *stack, GinBtreeEntryInsertData *insertData, BlockNumber updateblkno, Page *newlpage, Page *newrpage)
 
IndexTuple  GinFormTuple (GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, Pointer data, Size dataSize, int nipd, bool errorTooBig)
 
 
static IndexTuple  GinFormInteriorTuple (IndexTuple itup, Page page, BlockNumber childblk)
 
 
static bool  entryIsMoveRight (GinBtree btree, Page page)
 
 
static bool  entryLocateLeafEntry (GinBtree btree, GinBtreeStack *stack)
 
static OffsetNumber  entryFindChildPtr (GinBtree btree, Page page, BlockNumber blkno, OffsetNumber storedOff)
 
 
static bool  entryIsEnoughSpace (GinBtree btree, Buffer buf, OffsetNumber off, GinBtreeEntryInsertData *insertData)
 
static void  entryPreparePage (GinBtree btree, Page page, OffsetNumber off, GinBtreeEntryInsertData *insertData, BlockNumber updateblkno)
 
static GinPlaceToPageRC  entryBeginPlaceToPage (GinBtree btree, Buffer buf, GinBtreeStack *stack, void *insertPayload, BlockNumber updateblkno, void **ptp_workspace, Page *newlpage, Page *newrpage)
 
static void  entryExecPlaceToPage (GinBtree btree, Buffer buf, GinBtreeStack *stack, void *insertPayload, BlockNumber updateblkno, void *ptp_workspace)
 
static void *  entryPrepareDownlink (GinBtree btree, Buffer lbuf)
 
void  ginEntryFillRoot (GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage)
 
void  ginPrepareEntryScan (GinBtree btree, OffsetNumber attnum, Datum key, GinNullCategory category, GinState *ginstate)
 

Function Documentation

entryBeginPlaceToPage()

static GinPlaceToPageRC entryBeginPlaceToPage ( GinBtree  btree,
Buffer  buf,
GinBtreeStackstack,
void *  insertPayload,
BlockNumber  updateblkno,
void **  ptp_workspace,
Pagenewlpage,
Pagenewrpage 
)
static

Definition at line 527 of file ginentrypage.c.

531{
532 GinBtreeEntryInsertData *insertData = insertPayload;
533 OffsetNumber off = stack->off;
534
535 /* If it doesn't fit, deal with split case */
536 if (!entryIsEnoughSpace(btree, buf, off, insertData))
537 {
538 entrySplitPage(btree, buf, stack, insertData, updateblkno,
539 newlpage, newrpage);
540 return GPTP_SPLIT;
541 }
542
543 /* Else, we're ready to proceed with insertion */
544 return GPTP_INSERT;
545}
@ GPTP_INSERT
Definition: gin_private.h:147
@ GPTP_SPLIT
Definition: gin_private.h:148
static void entrySplitPage(GinBtree btree, Buffer origbuf, GinBtreeStack *stack, GinBtreeEntryInsertData *insertData, BlockNumber updateblkno, Page *newlpage, Page *newrpage)
Definition: ginentrypage.c:602
static bool entryIsEnoughSpace(GinBtree btree, Buffer buf, OffsetNumber off, GinBtreeEntryInsertData *insertData)
Definition: ginentrypage.c:459
uint16 OffsetNumber
Definition: off.h:24
static char * buf
Definition: pg_test_fsync.c:72
OffsetNumber off
Definition: gin_private.h:134

References buf, entryIsEnoughSpace(), entrySplitPage(), GPTP_INSERT, GPTP_SPLIT, and GinBtreeStack::off.

Referenced by ginPrepareEntryScan().

entryExecPlaceToPage()

static void entryExecPlaceToPage ( GinBtree  btree,
Buffer  buf,
GinBtreeStackstack,
void *  insertPayload,
BlockNumber  updateblkno,
void *  ptp_workspace 
)
static

Definition at line 554 of file ginentrypage.c.

557{
558 GinBtreeEntryInsertData *insertData = insertPayload;
559 Page page = BufferGetPage(buf);
560 OffsetNumber off = stack->off;
561 OffsetNumber placed;
562
563 entryPreparePage(btree, page, off, insertData, updateblkno);
564
565 placed = PageAddItem(page,
566 (Item) insertData->entry,
567 IndexTupleSize(insertData->entry),
568 off, false, false);
569 if (placed != off)
570 elog(ERROR, "failed to add item to index page in \"%s\"",
572
574
575 if (RelationNeedsWAL(btree->index) && !btree->isBuild)
576 {
577 /*
578 * This must be static, because it has to survive until XLogInsert,
579 * and we can't palloc here. Ugly, but the XLogInsert infrastructure
580 * isn't reentrant anyway.
581 */
583
584 data.isDelete = insertData->isDelete;
585 data.offset = off;
586
589 offsetof(ginxlogInsertEntry, tuple));
590 XLogRegisterBufData(0, insertData->entry,
591 IndexTupleSize(insertData->entry));
592 }
593}
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2921
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:417
PageData * Page
Definition: bufpage.h:82
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:472
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
static void entryPreparePage(GinBtree btree, Page page, OffsetNumber off, GinBtreeEntryInsertData *insertData, BlockNumber updateblkno)
Definition: ginentrypage.c:490
Pointer Item
Definition: item.h:17
static Size IndexTupleSize(const IndexTupleData *itup)
Definition: itup.h:71
const void * data
#define RelationGetRelationName(relation)
Definition: rel.h:548
#define RelationNeedsWAL(relation)
Definition: rel.h:637
bool isBuild
Definition: gin_private.h:172
Relation index
Definition: gin_private.h:168
void XLogRegisterBufData(uint8 block_id, const void *data, uint32 len)
Definition: xloginsert.c:405
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:242
#define REGBUF_STANDARD
Definition: xloginsert.h:35

References buf, BufferGetPage(), data, elog, GinBtreeEntryInsertData::entry, entryPreparePage(), ERROR, GinBtreeData::index, IndexTupleSize(), GinBtreeData::isBuild, GinBtreeEntryInsertData::isDelete, MarkBufferDirty(), GinBtreeStack::off, PageAddItem, REGBUF_STANDARD, RelationGetRelationName, RelationNeedsWAL, XLogRegisterBufData(), and XLogRegisterBuffer().

Referenced by ginPrepareEntryScan().

entryFindChildPtr()

static OffsetNumber entryFindChildPtr ( GinBtree  btree,
Page  page,
BlockNumber  blkno,
OffsetNumber  storedOff 
)
static

Definition at line 405 of file ginentrypage.c.

406{
408 maxoff = PageGetMaxOffsetNumber(page);
409 IndexTuple itup;
410
411 Assert(!GinPageIsLeaf(page));
412 Assert(!GinPageIsData(page));
413
414 /* if page isn't changed, we returns storedOff */
415 if (storedOff >= FirstOffsetNumber && storedOff <= maxoff)
416 {
417 itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, storedOff));
418 if (GinGetDownlink(itup) == blkno)
419 return storedOff;
420
421 /*
422 * we hope, that needed pointer goes to right. It's true if there
423 * wasn't a deletion
424 */
425 for (i = storedOff + 1; i <= maxoff; i++)
426 {
427 itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));
428 if (GinGetDownlink(itup) == blkno)
429 return i;
430 }
431 maxoff = storedOff - 1;
432 }
433
434 /* last chance */
435 for (i = FirstOffsetNumber; i <= maxoff; i++)
436 {
437 itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));
438 if (GinGetDownlink(itup) == blkno)
439 return i;
440 }
441
442 return InvalidOffsetNumber;
443}
static Item PageGetItem(const PageData *page, const ItemIdData *itemId)
Definition: bufpage.h:354
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:244
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition: bufpage.h:372
#define GinGetDownlink(itup)
Definition: ginblock.h:257
#define GinPageIsData(page)
Definition: ginblock.h:115
#define GinPageIsLeaf(page)
Definition: ginblock.h:112
Assert(PointerIsAligned(start, uint64))
i
int i
Definition: isn.c:77
IndexTupleData * IndexTuple
Definition: itup.h:53
#define InvalidOffsetNumber
Definition: off.h:26
#define FirstOffsetNumber
Definition: off.h:27

References Assert(), FirstOffsetNumber, GinGetDownlink, GinPageIsData, GinPageIsLeaf, i, InvalidOffsetNumber, PageGetItem(), PageGetItemId(), and PageGetMaxOffsetNumber().

Referenced by ginPrepareEntryScan().

entryGetLeftMostPage()

static BlockNumber entryGetLeftMostPage ( GinBtree  btree,
Page  page 
)
static

Definition at line 446 of file ginentrypage.c.

447{
448 IndexTuple itup;
449
450 Assert(!GinPageIsLeaf(page));
451 Assert(!GinPageIsData(page));
453
455 return GinGetDownlink(itup);
456}

References Assert(), FirstOffsetNumber, GinGetDownlink, GinPageIsData, GinPageIsLeaf, PageGetItem(), PageGetItemId(), and PageGetMaxOffsetNumber().

Referenced by ginPrepareEntryScan().

entryIsEnoughSpace()

static bool entryIsEnoughSpace ( GinBtree  btree,
Buffer  buf,
OffsetNumber  off,
GinBtreeEntryInsertDatainsertData 
)
static

Definition at line 459 of file ginentrypage.c.

461{
462 Size releasedsz = 0;
463 Size addedsz;
464 Page page = BufferGetPage(buf);
465
466 Assert(insertData->entry);
467 Assert(!GinPageIsData(page));
468
469 if (insertData->isDelete)
470 {
471 IndexTuple itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off));
472
473 releasedsz = MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData);
474 }
475
476 addedsz = MAXALIGN(IndexTupleSize(insertData->entry)) + sizeof(ItemIdData);
477
478 if (PageGetFreeSpace(page) + releasedsz >= addedsz)
479 return true;
480
481 return false;
482}
Size PageGetFreeSpace(const PageData *page)
Definition: bufpage.c:906
#define MAXALIGN(LEN)
Definition: c.h:810
size_t Size
Definition: c.h:610
struct ItemIdData ItemIdData

References Assert(), buf, BufferGetPage(), GinBtreeEntryInsertData::entry, GinPageIsData, IndexTupleSize(), GinBtreeEntryInsertData::isDelete, MAXALIGN, PageGetFreeSpace(), PageGetItem(), and PageGetItemId().

Referenced by entryBeginPlaceToPage().

entryIsMoveRight()

static bool entryIsMoveRight ( GinBtree  btree,
Page  page 
)
static

Definition at line 243 of file ginentrypage.c.

244{
245 IndexTuple itup;
247 Datum key;
248 GinNullCategory category;
249
250 if (GinPageRightMost(page))
251 return false;
252
253 itup = getRightMostTuple(page);
254 attnum = gintuple_get_attrnum(btree->ginstate, itup);
255 key = gintuple_get_key(btree->ginstate, itup, &category);
256
258 btree->entryAttnum, btree->entryKey, btree->entryCategory,
259 attnum, key, category) > 0)
260 return true;
261
262 return false;
263}
signed char GinNullCategory
Definition: ginblock.h:206
#define GinPageRightMost(page)
Definition: ginblock.h:129
static IndexTuple getRightMostTuple(Page page)
Definition: ginentrypage.c:235
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Definition: ginutil.c:231
int ginCompareAttEntries(GinState *ginstate, OffsetNumber attnuma, Datum a, GinNullCategory categorya, OffsetNumber attnumb, Datum b, GinNullCategory categoryb)
Definition: ginutil.c:415
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
Definition: ginutil.c:264
int16 attnum
Definition: pg_attribute.h:74
uint64_t Datum
Definition: postgres.h:70
Datum entryKey
Definition: gin_private.h:176
GinState * ginstate
Definition: gin_private.h:170
GinNullCategory entryCategory
Definition: gin_private.h:177
OffsetNumber entryAttnum
Definition: gin_private.h:175

References attnum, GinBtreeData::entryAttnum, GinBtreeData::entryCategory, GinBtreeData::entryKey, getRightMostTuple(), ginCompareAttEntries(), GinPageRightMost, GinBtreeData::ginstate, gintuple_get_attrnum(), gintuple_get_key(), and sort-test::key.

Referenced by ginPrepareEntryScan().

entryLocateEntry()

static BlockNumber entryLocateEntry ( GinBtree  btree,
GinBtreeStackstack 
)
static

Definition at line 270 of file ginentrypage.c.

271{
272 OffsetNumber low,
273 high,
274 maxoff;
275 IndexTuple itup = NULL;
276 int result;
277 Page page = BufferGetPage(stack->buffer);
278
279 Assert(!GinPageIsLeaf(page));
280 Assert(!GinPageIsData(page));
281
282 if (btree->fullScan)
283 {
284 stack->off = FirstOffsetNumber;
286 return btree->getLeftMostChild(btree, page);
287 }
288
289 low = FirstOffsetNumber;
290 maxoff = high = PageGetMaxOffsetNumber(page);
291 Assert(high >= low);
292
293 high++;
294
295 while (high > low)
296 {
297 OffsetNumber mid = low + ((high - low) / 2);
298
299 if (mid == maxoff && GinPageRightMost(page))
300 {
301 /* Right infinity */
302 result = -1;
303 }
304 else
305 {
307 Datum key;
308 GinNullCategory category;
309
310 itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, mid));
311 attnum = gintuple_get_attrnum(btree->ginstate, itup);
312 key = gintuple_get_key(btree->ginstate, itup, &category);
313 result = ginCompareAttEntries(btree->ginstate,
314 btree->entryAttnum,
315 btree->entryKey,
316 btree->entryCategory,
317 attnum, key, category);
318 }
319
320 if (result == 0)
321 {
322 stack->off = mid;
324 return GinGetDownlink(itup);
325 }
326 else if (result > 0)
327 low = mid + 1;
328 else
329 high = mid;
330 }
331
332 Assert(high >= FirstOffsetNumber && high <= maxoff);
333
334 stack->off = high;
335 itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, high));
337 return GinGetDownlink(itup);
338}
#define GIN_ROOT_BLKNO
Definition: ginblock.h:52
BlockNumber(* getLeftMostChild)(GinBtree, Page)
Definition: gin_private.h:155
bool fullScan
Definition: gin_private.h:171
uint32 predictNumber
Definition: gin_private.h:137
Buffer buffer
Definition: gin_private.h:133

References Assert(), attnum, GinBtreeStack::buffer, BufferGetPage(), GinBtreeData::entryAttnum, GinBtreeData::entryCategory, GinBtreeData::entryKey, FirstOffsetNumber, GinBtreeData::fullScan, GinBtreeData::getLeftMostChild, GIN_ROOT_BLKNO, ginCompareAttEntries(), GinGetDownlink, GinPageIsData, GinPageIsLeaf, GinPageRightMost, GinBtreeData::ginstate, gintuple_get_attrnum(), gintuple_get_key(), sort-test::key, GinBtreeStack::off, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), and GinBtreeStack::predictNumber.

Referenced by ginPrepareEntryScan().

entryLocateLeafEntry()

static bool entryLocateLeafEntry ( GinBtree  btree,
GinBtreeStackstack 
)
static

Definition at line 346 of file ginentrypage.c.

347{
348 Page page = BufferGetPage(stack->buffer);
349 OffsetNumber low,
350 high;
351
352 Assert(GinPageIsLeaf(page));
353 Assert(!GinPageIsData(page));
354
355 if (btree->fullScan)
356 {
357 stack->off = FirstOffsetNumber;
358 return true;
359 }
360
361 low = FirstOffsetNumber;
362 high = PageGetMaxOffsetNumber(page);
363
364 if (high < low)
365 {
366 stack->off = FirstOffsetNumber;
367 return false;
368 }
369
370 high++;
371
372 while (high > low)
373 {
374 OffsetNumber mid = low + ((high - low) / 2);
375 IndexTuple itup;
377 Datum key;
378 GinNullCategory category;
379 int result;
380
381 itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, mid));
382 attnum = gintuple_get_attrnum(btree->ginstate, itup);
383 key = gintuple_get_key(btree->ginstate, itup, &category);
384 result = ginCompareAttEntries(btree->ginstate,
385 btree->entryAttnum,
386 btree->entryKey,
387 btree->entryCategory,
388 attnum, key, category);
389 if (result == 0)
390 {
391 stack->off = mid;
392 return true;
393 }
394 else if (result > 0)
395 low = mid + 1;
396 else
397 high = mid;
398 }
399
400 stack->off = high;
401 return false;
402}

References Assert(), attnum, GinBtreeStack::buffer, BufferGetPage(), GinBtreeData::entryAttnum, GinBtreeData::entryCategory, GinBtreeData::entryKey, FirstOffsetNumber, GinBtreeData::fullScan, ginCompareAttEntries(), GinPageIsData, GinPageIsLeaf, GinBtreeData::ginstate, gintuple_get_attrnum(), gintuple_get_key(), sort-test::key, GinBtreeStack::off, PageGetItem(), PageGetItemId(), and PageGetMaxOffsetNumber().

Referenced by ginPrepareEntryScan().

entryPrepareDownlink()

static void * entryPrepareDownlink ( GinBtree  btree,
Buffer  lbuf 
)
static

Definition at line 702 of file ginentrypage.c.

703{
704 GinBtreeEntryInsertData *insertData;
705 Page lpage = BufferGetPage(lbuf);
706 BlockNumber lblkno = BufferGetBlockNumber(lbuf);
707 IndexTuple itup;
708
709 itup = getRightMostTuple(lpage);
710
711 insertData = palloc(sizeof(GinBtreeEntryInsertData));
712 insertData->entry = GinFormInteriorTuple(itup, lpage, lblkno);
713 insertData->isDelete = false;
714
715 return insertData;
716}
uint32 BlockNumber
Definition: block.h:31
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:4198
static IndexTuple GinFormInteriorTuple(IndexTuple itup, Page page, BlockNumber childblk)
Definition: ginentrypage.c:201
void * palloc(Size size)
Definition: mcxt.c:1365

References BufferGetBlockNumber(), BufferGetPage(), GinBtreeEntryInsertData::entry, getRightMostTuple(), GinFormInteriorTuple(), GinBtreeEntryInsertData::isDelete, and palloc().

Referenced by ginPrepareEntryScan().

entryPreparePage()

static void entryPreparePage ( GinBtree  btree,
Page  page,
OffsetNumber  off,
GinBtreeEntryInsertDatainsertData,
BlockNumber  updateblkno 
)
static

Definition at line 490 of file ginentrypage.c.

492{
493 Assert(insertData->entry);
494 Assert(!GinPageIsData(page));
495
496 if (insertData->isDelete)
497 {
498 Assert(GinPageIsLeaf(page));
499 PageIndexTupleDelete(page, off);
500 }
501
502 if (!GinPageIsLeaf(page) && updateblkno != InvalidBlockNumber)
503 {
504 IndexTuple itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off));
505
506 GinSetDownlink(itup, updateblkno);
507 }
508}
#define InvalidBlockNumber
Definition: block.h:33
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:1051
#define GinSetDownlink(itup, blkno)
Definition: ginblock.h:258

References Assert(), GinBtreeEntryInsertData::entry, GinPageIsData, GinPageIsLeaf, GinSetDownlink, InvalidBlockNumber, GinBtreeEntryInsertData::isDelete, PageGetItem(), PageGetItemId(), and PageIndexTupleDelete().

Referenced by entryExecPlaceToPage(), and entrySplitPage().

entrySplitPage()

static void entrySplitPage ( GinBtree  btree,
Buffer  origbuf,
GinBtreeStackstack,
GinBtreeEntryInsertDatainsertData,
BlockNumber  updateblkno,
Pagenewlpage,
Pagenewrpage 
)
static

Definition at line 602 of file ginentrypage.c.

607{
608 OffsetNumber off = stack->off;
610 maxoff,
612 Size totalsize = 0;
613 Size lsize = 0,
614 size;
615 char *ptr;
616 IndexTuple itup;
617 Page page;
618 Page lpage = PageGetTempPageCopy(BufferGetPage(origbuf));
619 Page rpage = PageGetTempPageCopy(BufferGetPage(origbuf));
620 Size pageSize = PageGetPageSize(lpage);
621 PGAlignedBlock tupstore[2]; /* could need 2 pages' worth of tuples */
622
623 entryPreparePage(btree, lpage, off, insertData, updateblkno);
624
625 /*
626 * First, append all the existing tuples and the new tuple we're inserting
627 * one after another in a temporary workspace.
628 */
629 maxoff = PageGetMaxOffsetNumber(lpage);
630 ptr = tupstore[0].data;
631 for (i = FirstOffsetNumber; i <= maxoff; i++)
632 {
633 if (i == off)
634 {
635 size = MAXALIGN(IndexTupleSize(insertData->entry));
636 memcpy(ptr, insertData->entry, size);
637 ptr += size;
638 totalsize += size + sizeof(ItemIdData);
639 }
640
641 itup = (IndexTuple) PageGetItem(lpage, PageGetItemId(lpage, i));
642 size = MAXALIGN(IndexTupleSize(itup));
643 memcpy(ptr, itup, size);
644 ptr += size;
645 totalsize += size + sizeof(ItemIdData);
646 }
647
648 if (off == maxoff + 1)
649 {
650 size = MAXALIGN(IndexTupleSize(insertData->entry));
651 memcpy(ptr, insertData->entry, size);
652 ptr += size;
653 totalsize += size + sizeof(ItemIdData);
654 }
655
656 /*
657 * Initialize the left and right pages, and copy all the tuples back to
658 * them.
659 */
660 GinInitPage(rpage, GinPageGetOpaque(lpage)->flags, pageSize);
661 GinInitPage(lpage, GinPageGetOpaque(rpage)->flags, pageSize);
662
663 ptr = tupstore[0].data;
664 maxoff++;
665 lsize = 0;
666
667 page = lpage;
668 for (i = FirstOffsetNumber; i <= maxoff; i++)
669 {
670 itup = (IndexTuple) ptr;
671
672 /*
673 * Decide where to split. We try to equalize the pages' total data
674 * size, not number of tuples.
675 */
676 if (lsize > totalsize / 2)
677 {
679 separator = i - 1;
680 page = rpage;
681 }
682 else
683 {
684 lsize += MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData);
685 }
686
687 if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
688 elog(ERROR, "failed to add item to index page in \"%s\"",
690 ptr += MAXALIGN(IndexTupleSize(itup));
691 }
692
693 /* return temp pages to caller */
694 *newlpage = lpage;
695 *newrpage = rpage;
696}
Page PageGetTempPageCopy(const PageData *page)
Definition: bufpage.c:381
static Size PageGetPageSize(const PageData *page)
Definition: bufpage.h:277
#define GinPageGetOpaque(page)
Definition: ginblock.h:110
void GinInitPage(Page page, uint32 f, Size pageSize)
Definition: ginutil.c:343
Definition: print.h:106
char data[BLCKSZ]
Definition: c.h:1118

References BufferGetPage(), PGAlignedBlock::data, elog, GinBtreeEntryInsertData::entry, entryPreparePage(), ERROR, FirstOffsetNumber, GinInitPage(), GinPageGetOpaque, i, GinBtreeData::index, IndexTupleSize(), InvalidOffsetNumber, MAXALIGN, GinBtreeStack::off, PageAddItem, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), PageGetPageSize(), PageGetTempPageCopy(), and RelationGetRelationName.

Referenced by entryBeginPlaceToPage().

getRightMostTuple()

static IndexTuple getRightMostTuple ( Page  page )
static

Definition at line 235 of file ginentrypage.c.

236{
238
239 return (IndexTuple) PageGetItem(page, PageGetItemId(page, maxoff));
240}

References PageGetItem(), PageGetItemId(), and PageGetMaxOffsetNumber().

Referenced by entryIsMoveRight(), entryPrepareDownlink(), and ginEntryFillRoot().

ginEntryFillRoot()

void ginEntryFillRoot ( GinBtree  btree,
Page  root,
BlockNumber  lblkno,
Page  lpage,
BlockNumber  rblkno,
Page  rpage 
)

Definition at line 723 of file ginentrypage.c.

726{
727 IndexTuple itup;
728
729 itup = GinFormInteriorTuple(getRightMostTuple(lpage), lpage, lblkno);
730 if (PageAddItem(root, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
731 elog(ERROR, "failed to add item to index root page");
732 pfree(itup);
733
734 itup = GinFormInteriorTuple(getRightMostTuple(rpage), rpage, rblkno);
735 if (PageAddItem(root, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
736 elog(ERROR, "failed to add item to index root page");
737 pfree(itup);
738}
void pfree(void *pointer)
Definition: mcxt.c:1594
tree ctl root
Definition: radixtree.h:1857

References elog, ERROR, getRightMostTuple(), GinFormInteriorTuple(), IndexTupleSize(), InvalidOffsetNumber, PageAddItem, pfree(), and root.

Referenced by ginPrepareEntryScan().

GinFormInteriorTuple()

static IndexTuple GinFormInteriorTuple ( IndexTuple  itup,
Page  page,
BlockNumber  childblk 
)
static

Definition at line 201 of file ginentrypage.c.

202{
203 IndexTuple nitup;
204
205 if (GinPageIsLeaf(page) && !GinIsPostingTree(itup))
206 {
207 /* Tuple contains a posting list, just copy stuff before that */
208 uint32 origsize = GinGetPostingOffset(itup);
209
210 origsize = MAXALIGN(origsize);
211 nitup = (IndexTuple) palloc(origsize);
212 memcpy(nitup, itup, origsize);
213 /* ... be sure to fix the size header field ... */
214 nitup->t_info &= ~INDEX_SIZE_MASK;
215 nitup->t_info |= origsize;
216 }
217 else
218 {
219 /* Copy the tuple as-is */
220 nitup = (IndexTuple) palloc(IndexTupleSize(itup));
221 memcpy(nitup, itup, IndexTupleSize(itup));
222 }
223
224 /* Now insert the correct downlink */
225 GinSetDownlink(nitup, childblk);
226
227 return nitup;
228}
uint32_t uint32
Definition: c.h:538
#define GinIsPostingTree(itup)
Definition: ginblock.h:231
#define GinGetPostingOffset(itup)
Definition: ginblock.h:236
unsigned short t_info
Definition: itup.h:49

References GinGetPostingOffset, GinIsPostingTree, GinPageIsLeaf, GinSetDownlink, IndexTupleSize(), MAXALIGN, palloc(), and IndexTupleData::t_info.

Referenced by entryPrepareDownlink(), and ginEntryFillRoot().

GinFormTuple()

IndexTuple GinFormTuple ( GinStateginstate,
OffsetNumber  attnum,
Datum  key,
GinNullCategory  category,
Pointer  data,
Size  dataSize,
int  nipd,
bool  errorTooBig 
)

Definition at line 44 of file ginentrypage.c.

48{
49 Datum datums[2];
50 bool isnull[2];
51 IndexTuple itup;
52 uint32 newsize;
53
54 /* Build the basic tuple: optional column number, plus key datum */
55 if (ginstate->oneCol)
56 {
57 datums[0] = key;
58 isnull[0] = (category != GIN_CAT_NORM_KEY);
59 }
60 else
61 {
62 datums[0] = UInt16GetDatum(attnum);
63 isnull[0] = false;
64 datums[1] = key;
65 isnull[1] = (category != GIN_CAT_NORM_KEY);
66 }
67
68 itup = index_form_tuple(ginstate->tupdesc[attnum - 1], datums, isnull);
69
70 /*
71 * Determine and store offset to the posting list, making sure there is
72 * room for the category byte if needed.
73 *
74 * Note: because index_form_tuple MAXALIGNs the tuple size, there may well
75 * be some wasted pad space. Is it worth recomputing the data length to
76 * prevent that? That would also allow us to Assert that the real data
77 * doesn't overlap the GinNullCategory byte, which this code currently
78 * takes on faith.
79 */
80 newsize = IndexTupleSize(itup);
81
82 if (IndexTupleHasNulls(itup))
83 {
84 uint32 minsize;
85
86 Assert(category != GIN_CAT_NORM_KEY);
87 minsize = GinCategoryOffset(itup, ginstate) + sizeof(GinNullCategory);
88 newsize = Max(newsize, minsize);
89 }
90
91 newsize = SHORTALIGN(newsize);
92
93 GinSetPostingOffset(itup, newsize);
94 GinSetNPosting(itup, nipd);
95
96 /*
97 * Add space needed for posting list, if any. Then check that the tuple
98 * won't be too big to store.
99 */
100 newsize += dataSize;
101
102 newsize = MAXALIGN(newsize);
103
104 if (newsize > GinMaxItemSize)
105 {
106 if (errorTooBig)
108 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
109 errmsg("index row size %zu exceeds maximum %zu for index \"%s\"",
110 (Size) newsize, (Size) GinMaxItemSize,
111 RelationGetRelationName(ginstate->index))));
112 pfree(itup);
113 return NULL;
114 }
115
116 /*
117 * Resize tuple if needed
118 */
119 if (newsize != IndexTupleSize(itup))
120 {
121 itup = repalloc(itup, newsize);
122
123 /*
124 * PostgreSQL 9.3 and earlier did not clear this new space, so we
125 * might find uninitialized padding when reading tuples from disk.
126 */
127 memset((char *) itup + IndexTupleSize(itup),
128 0, newsize - IndexTupleSize(itup));
129 /* set new size in tuple header */
130 itup->t_info &= ~INDEX_SIZE_MASK;
131 itup->t_info |= newsize;
132 }
133
134 /*
135 * Copy in the posting list, if provided
136 */
137 if (data)
138 {
139 char *ptr = GinGetPosting(itup);
140
141 memcpy(ptr, data, dataSize);
142 }
143
144 /*
145 * Insert category byte, if needed
146 */
147 if (category != GIN_CAT_NORM_KEY)
148 {
150 GinSetNullCategory(itup, ginstate, category);
151 }
152 return itup;
153}
#define Max(x, y)
Definition: c.h:997
#define SHORTALIGN(LEN)
Definition: c.h:806
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereport(elevel,...)
Definition: elog.h:150
#define GinCategoryOffset(itup, ginstate)
Definition: ginblock.h:217
#define GinGetPosting(itup)
Definition: ginblock.h:238
#define GIN_CAT_NORM_KEY
Definition: ginblock.h:208
#define GinSetNPosting(itup, n)
Definition: ginblock.h:229
#define GinSetPostingOffset(itup, n)
Definition: ginblock.h:237
#define GinSetNullCategory(itup, ginstate, c)
Definition: ginblock.h:222
#define GinMaxItemSize
Definition: ginblock.h:248
IndexTuple index_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: indextuple.c:44
static bool IndexTupleHasNulls(const IndexTupleData *itup)
Definition: itup.h:77
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
static Datum UInt16GetDatum(uint16 X)
Definition: postgres.h:202
bool oneCol
Definition: gin_private.h:60
TupleDesc tupdesc[INDEX_MAX_KEYS]
Definition: gin_private.h:74
Relation index
Definition: gin_private.h:59

References Assert(), attnum, data, ereport, errcode(), errmsg(), ERROR, GIN_CAT_NORM_KEY, GinCategoryOffset, GinGetPosting, GinMaxItemSize, GinSetNPosting, GinSetNullCategory, GinSetPostingOffset, GinState::index, index_form_tuple(), IndexTupleHasNulls(), IndexTupleSize(), sort-test::key, Max, MAXALIGN, GinState::oneCol, pfree(), RelationGetRelationName, repalloc(), SHORTALIGN, IndexTupleData::t_info, GinState::tupdesc, and UInt16GetDatum().

Referenced by addItemPointersToLeafTuple(), buildFreshLeafTuple(), ginHeapTupleFastCollect(), and ginVacuumEntryPage().

ginPrepareEntryScan()

void ginPrepareEntryScan ( GinBtree  btree,
OffsetNumber  attnum,
Datum  key,
GinNullCategory  category,
GinStateginstate 
)

Definition at line 747 of file ginentrypage.c.

750{
751 memset(btree, 0, sizeof(GinBtreeData));
752
753 btree->index = ginstate->index;
754 btree->rootBlkno = GIN_ROOT_BLKNO;
755 btree->ginstate = ginstate;
756
764 btree->fillRoot = ginEntryFillRoot;
766
767 btree->isData = false;
768 btree->fullScan = false;
769 btree->isBuild = false;
770
771 btree->entryAttnum = attnum;
772 btree->entryKey = key;
773 btree->entryCategory = category;
774}
void ginEntryFillRoot(GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage)
Definition: ginentrypage.c:723
static bool entryLocateLeafEntry(GinBtree btree, GinBtreeStack *stack)
Definition: ginentrypage.c:346
static bool entryIsMoveRight(GinBtree btree, Page page)
Definition: ginentrypage.c:243
static BlockNumber entryGetLeftMostPage(GinBtree btree, Page page)
Definition: ginentrypage.c:446
static OffsetNumber entryFindChildPtr(GinBtree btree, Page page, BlockNumber blkno, OffsetNumber storedOff)
Definition: ginentrypage.c:405
static GinPlaceToPageRC entryBeginPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack, void *insertPayload, BlockNumber updateblkno, void **ptp_workspace, Page *newlpage, Page *newrpage)
Definition: ginentrypage.c:527
static void entryExecPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack, void *insertPayload, BlockNumber updateblkno, void *ptp_workspace)
Definition: ginentrypage.c:554
static BlockNumber entryLocateEntry(GinBtree btree, GinBtreeStack *stack)
Definition: ginentrypage.c:270
static void * entryPrepareDownlink(GinBtree btree, Buffer lbuf)
Definition: ginentrypage.c:702
BlockNumber(* findChildPage)(GinBtree, GinBtreeStack *)
Definition: gin_private.h:154
void(* execPlaceToPage)(GinBtree, Buffer, GinBtreeStack *, void *, BlockNumber, void *)
Definition: gin_private.h:162
bool(* findItem)(GinBtree, GinBtreeStack *)
Definition: gin_private.h:157
void *(* prepareDownlink)(GinBtree, Buffer)
Definition: gin_private.h:163
bool(* isMoveRight)(GinBtree, Page)
Definition: gin_private.h:156
GinPlaceToPageRC(* beginPlaceToPage)(GinBtree, Buffer, GinBtreeStack *, void *, BlockNumber, void **, Page *, Page *)
Definition: gin_private.h:161
OffsetNumber(* findChildPtr)(GinBtree, Page, BlockNumber, OffsetNumber)
Definition: gin_private.h:160
void(* fillRoot)(GinBtree, Page, BlockNumber, Page, BlockNumber, Page)
Definition: gin_private.h:164
bool isData
Definition: gin_private.h:166
BlockNumber rootBlkno
Definition: gin_private.h:169

References attnum, GinBtreeData::beginPlaceToPage, GinBtreeData::entryAttnum, entryBeginPlaceToPage(), GinBtreeData::entryCategory, entryExecPlaceToPage(), entryFindChildPtr(), entryGetLeftMostPage(), entryIsMoveRight(), GinBtreeData::entryKey, entryLocateEntry(), entryLocateLeafEntry(), entryPrepareDownlink(), GinBtreeData::execPlaceToPage, GinBtreeData::fillRoot, GinBtreeData::findChildPage, GinBtreeData::findChildPtr, GinBtreeData::findItem, GinBtreeData::fullScan, GinBtreeData::getLeftMostChild, GIN_ROOT_BLKNO, ginEntryFillRoot(), GinBtreeData::ginstate, GinState::index, GinBtreeData::index, GinBtreeData::isBuild, GinBtreeData::isData, GinBtreeData::isMoveRight, sort-test::key, GinBtreeData::prepareDownlink, and GinBtreeData::rootBlkno.

Referenced by ginEntryInsert(), and startScanEntry().

ginReadTuple()

ItemPointer ginReadTuple ( GinStateginstate,
OffsetNumber  attnum,
IndexTuple  itup,
int *  nitems 
)

Definition at line 162 of file ginentrypage.c.

164{
165 Pointer ptr = GinGetPosting(itup);
166 int nipd = GinGetNPosting(itup);
167 ItemPointer ipd;
168 int ndecoded;
169
170 if (GinItupIsCompressed(itup))
171 {
172 if (nipd > 0)
173 {
174 ipd = ginPostingListDecode((GinPostingList *) ptr, &ndecoded);
175 if (nipd != ndecoded)
176 elog(ERROR, "number of items mismatch in GIN entry tuple, %d in tuple header, %d decoded",
177 nipd, ndecoded);
178 }
179 else
180 {
181 ipd = palloc(0);
182 }
183 }
184 else
185 {
186 ipd = (ItemPointer) palloc(sizeof(ItemPointerData) * nipd);
187 memcpy(ipd, ptr, sizeof(ItemPointerData) * nipd);
188 }
189 *nitems = nipd;
190 return ipd;
191}
char * Pointer
Definition: c.h:529
#define GinItupIsCompressed(itup)
Definition: ginblock.h:239
#define GinGetNPosting(itup)
Definition: ginblock.h:228
ItemPointer ginPostingListDecode(GinPostingList *plist, int *ndecoded_out)
#define nitems(x)
Definition: indent.h:31
ItemPointerData * ItemPointer
Definition: itemptr.h:49

References elog, ERROR, GinGetNPosting, GinGetPosting, GinItupIsCompressed, ginPostingListDecode(), nitems, and palloc().

Referenced by addItemPointersToLeafTuple(), collectMatchBitmap(), and startScanEntry().

AltStyle によって変換されたページ (->オリジナル) /