PostgreSQL Source Code git master
Loading...
Searching...
No Matches
verify_gin.c File Reference
#include "postgres.h"
#include "access/gin_private.h"
#include "access/nbtree.h"
#include "catalog/pg_am.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "verify_common.h"
#include "string.h"
Include dependency graph for verify_gin.c:

Go to the source code of this file.

Data Structures

struct  GinScanItem
 
struct  GinPostingTreeScanItem
 

Typedefs

typedef struct GinScanItem GinScanItem
 
typedef struct GinPostingTreeScanItem GinPostingTreeScanItem
 

Functions

 PG_FUNCTION_INFO_V1 (gin_index_check)
 
static void gin_check_parent_keys_consistency (Relation rel, Relation heaprel, void *callback_state, bool readonly)
 
static void check_index_page (Relation rel, Buffer buffer, BlockNumber blockNo)
 
static IndexTuple gin_refind_parent (Relation rel, BlockNumber parentblkno, BlockNumber childblkno, BufferAccessStrategy strategy)
 
static ItemId PageGetItemIdCareful (Relation rel, BlockNumber block, Page page, OffsetNumber offset)
 
Datum gin_index_check (PG_FUNCTION_ARGS)
 
static ItemPointer ginReadTupleWithoutState (IndexTuple itup, int *nitems)
 
static void gin_check_posting_tree_parent_keys_consistency (Relation rel, BlockNumber posting_tree_root)
 

Typedef Documentation

◆ GinPostingTreeScanItem

◆ GinScanItem

Function Documentation

◆ check_index_page()

static void check_index_page ( Relation  rel,
Buffer  buffer,
BlockNumber  blockNo 
)
static

Definition at line 662 of file verify_gin.c.

663{
664 Page page = BufferGetPage(buffer);
665
666 /*
667 * ReadBuffer verifies that every newly-read page passes
668 * PageHeaderIsValid, which means it either contains a reasonably sane
669 * page header or is all-zero. We have to defend against the all-zero
670 * case, however.
671 */
672 if (PageIsNew(page))
675 errmsg("index \"%s\" contains unexpected zero page at block %u",
677 BufferGetBlockNumber(buffer)),
678 errhint("Please REINDEX it.")));
679
680 /*
681 * Additionally check that the special area looks sane.
682 */
683 if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GinPageOpaqueData)))
686 errmsg("index \"%s\" contains corrupted page at block %u",
688 BufferGetBlockNumber(buffer)),
689 errhint("Please REINDEX it.")));
690
691 if (GinPageIsDeleted(page))
692 {
693 if (!GinPageIsLeaf(page))
696 errmsg("index \"%s\" has deleted internal page %u",
701 errmsg("index \"%s\" has deleted page %u with tuples",
703 }
707 errmsg("index \"%s\" has page %u with exceeding count of tuples",
709}
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition bufmgr.c:4446
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:468
static uint16 PageGetSpecialSize(const PageData *page)
Definition bufpage.h:341
static bool PageIsNew(const PageData *page)
Definition bufpage.h:258
PageData * Page
Definition bufpage.h:81
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition bufpage.h:396
#define MAXALIGN(LEN)
Definition c.h:896
int errcode(int sqlerrcode)
Definition elog.c:874
int errhint(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
#define GinPageIsDeleted(page)
Definition ginblock.h:124
#define GinPageIsLeaf(page)
Definition ginblock.h:112
#define MaxIndexTuplesPerPage
Definition itup.h:181
static char * errmsg
#define InvalidOffsetNumber
Definition off.h:26
static int fb(int x)
#define RelationGetRelationName(relation)
Definition rel.h:550

References BufferGetBlockNumber(), BufferGetPage(), ereport, errcode(), errhint(), errmsg, ERROR, fb(), GinPageIsDeleted, GinPageIsLeaf, InvalidOffsetNumber, MAXALIGN, MaxIndexTuplesPerPage, PageGetMaxOffsetNumber(), PageGetSpecialSize(), PageIsNew(), and RelationGetRelationName.

Referenced by gin_check_parent_keys_consistency().

◆ gin_check_parent_keys_consistency()

static void gin_check_parent_keys_consistency ( Relation  rel,
Relation  heaprel,
void callback_state,
bool  readonly 
)
static

Definition at line 389 of file verify_gin.c.

393{
395 GinScanItem *stack;
397 MemoryContext oldcontext;
399 int leafdepth;
400
402 "amcheck consistency check context",
404 oldcontext = MemoryContextSwitchTo(mctx);
405 initGinState(&state, rel);
406
407 /*
408 * We don't know the height of the tree yet, but as soon as we encounter a
409 * leaf page, we will set 'leafdepth' to its depth.
410 */
411 leafdepth = -1;
412
413 /* Start the scan at the root page */
415 stack->depth = 0;
416 stack->parenttup = NULL;
418 stack->blkno = GIN_ROOT_BLKNO;
419
420 while (stack)
421 {
423 Buffer buffer;
424 Page page;
426 maxoff,
429 BlockNumber rightlink;
430
432
433 buffer = ReadBufferExtended(rel, MAIN_FORKNUM, stack->blkno,
434 RBM_NORMAL, strategy);
435 LockBuffer(buffer, GIN_SHARE);
436 page = BufferGetPage(buffer);
437 maxoff = PageGetMaxOffsetNumber(page);
438 rightlink = GinPageGetOpaque(page)->rightlink;
439
440 /* Do basic sanity checks on the page headers */
441 check_index_page(rel, buffer, stack->blkno);
442
443 elog(DEBUG3, "processing entry tree page at blk %u, maxoff: %u", stack->blkno, maxoff);
444
445 /*
446 * It's possible that the page was split since we looked at the
447 * parent, so that we didn't missed the downlink of the right sibling
448 * when we scanned the parent. If so, add the right sibling to the
449 * stack now.
450 */
451 if (stack->parenttup != NULL)
452 {
455 stack->parenttup,
458 ItemId iid = PageGetItemIdCareful(rel, stack->blkno,
459 page, maxoff);
464
465 if (rightlink != InvalidBlockNumber &&
469 {
470 /* split page detected, install right link to the stack */
471 GinScanItem *ptr;
472
473 elog(DEBUG3, "split detected for blk: %u, parent blk: %u", stack->blkno, stack->parentblk);
474
476 ptr->depth = stack->depth;
477 ptr->parenttup = CopyIndexTuple(stack->parenttup);
478 ptr->parentblk = stack->parentblk;
479 ptr->blkno = rightlink;
480 ptr->next = stack->next;
481 stack->next = ptr;
482 }
483 }
484
485 /* Check that the tree has the same height in all branches */
486 if (GinPageIsLeaf(page))
487 {
488 if (leafdepth == -1)
489 leafdepth = stack->depth;
490 else if (stack->depth != leafdepth)
493 errmsg("index \"%s\": internal pages traversal encountered leaf page unexpectedly on block %u",
494 RelationGetRelationName(rel), stack->blkno)));
495 }
496
497 /*
498 * Check that tuples in each page are properly ordered and consistent
499 * with parent high key
500 */
503 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
504 {
505 ItemId iid = PageGetItemIdCareful(rel, stack->blkno, page, i);
510
514 errmsg("index \"%s\" has inconsistent tuple sizes, block %u, offset %u",
515 RelationGetRelationName(rel), stack->blkno, i)));
516
518
519 /*
520 * Compare the entry to the preceding one.
521 *
522 * Don't check for high key on the rightmost inner page, as this
523 * key is not really stored explicitly.
524 *
525 * The entries may be for different attributes, so make sure to
526 * use ginCompareAttEntries for comparison.
527 */
528 if ((i != FirstOffsetNumber) &&
529 !(i == maxoff && rightlink == InvalidBlockNumber && !GinPageIsLeaf(page)))
530 {
533
540 errmsg("index \"%s\" has wrong tuple order on entry tree page, block %u, offset %u, rightlink %u",
541 RelationGetRelationName(rel), stack->blkno, i, rightlink)));
542 }
543
544 /*
545 * Check if this tuple is consistent with the downlink in the
546 * parent.
547 */
548 if (stack->parenttup &&
549 i == maxoff)
550 {
554 stack->parenttup,
556
560 {
561 /*
562 * There was a discrepancy between parent and child
563 * tuples. We need to verify it is not a result of
564 * concurrent call of gistplacetopage(). So, lock parent
565 * and try to find downlink for current page. It may be
566 * missing due to concurrent page split, this is OK.
567 */
568 pfree(stack->parenttup);
569 stack->parenttup = gin_refind_parent(rel, stack->parentblk,
570 stack->blkno, strategy);
571
572 /* We found it - make a final check before failing */
573 if (!stack->parenttup)
574 elog(NOTICE, "Unable to find parent tuple for block %u on block %u due to concurrent split",
575 stack->blkno, stack->parentblk);
576 else
577 {
580 stack->parenttup,
582
583 /*
584 * Check if it is properly adjusted. If succeed,
585 * proceed to the next key.
586 */
592 errmsg("index \"%s\" has inconsistent records on page %u offset %u",
593 RelationGetRelationName(rel), stack->blkno, i)));
594 }
595 }
596 }
597
598 /* If this is an internal page, recurse into the child */
599 if (!GinPageIsLeaf(page))
600 {
601 GinScanItem *ptr;
602
604 ptr->depth = stack->depth + 1;
605 /* last tuple in layer has no high key */
606 if (i == maxoff && rightlink == InvalidBlockNumber)
607 ptr->parenttup = NULL;
608 else
610 ptr->parentblk = stack->blkno;
612 ptr->next = stack->next;
613 stack->next = ptr;
614 }
615 /* If this item is a pointer to a posting tree, recurse into it */
616 else if (GinIsPostingTree(idxtuple))
617 {
619
621 }
622 else
623 {
625 int nipd;
626
628
629 for (int j = 0; j < nipd; j++)
630 {
634 errmsg("index \"%s\": posting list contains invalid heap pointer on block %u",
635 RelationGetRelationName(rel), stack->blkno)));
636 }
637 pfree(ipd);
638 }
639
642 }
643
644 UnlockReleaseBuffer(buffer);
645
646 /* Step to next item in the queue */
647 stack_next = stack->next;
648 if (stack->parenttup)
649 pfree(stack->parenttup);
650 pfree(stack);
651 stack = stack_next;
652 }
653
654 MemoryContextSwitchTo(oldcontext);
656}
#define InvalidAttrNumber
Definition attnum.h:23
uint32 BlockNumber
Definition block.h:31
#define InvalidBlockNumber
Definition block.h:33
int Buffer
Definition buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5603
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition bufmgr.c:926
@ BAS_BULKREAD
Definition bufmgr.h:37
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:334
@ RBM_NORMAL
Definition bufmgr.h:46
static void * PageGetItem(PageData *page, const ItemIdData *itemId)
Definition bufpage.h:378
#define DEBUG3
Definition elog.h:29
#define elog(elevel,...)
Definition elog.h:228
#define NOTICE
Definition elog.h:36
#define palloc_object(type)
Definition fe_memutils.h:74
#define palloc0_object(type)
Definition fe_memutils.h:75
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition freelist.c:426
static int ginCompareAttEntries(GinState *ginstate, OffsetNumber attnuma, Datum a, GinNullCategory categorya, OffsetNumber attnumb, Datum b, GinNullCategory categoryb)
#define GIN_SHARE
Definition gin_private.h:52
#define GinIsPostingTree(itup)
Definition ginblock.h:231
#define GinPageGetOpaque(page)
Definition ginblock.h:110
#define GIN_ROOT_BLKNO
Definition ginblock.h:52
#define GinGetDownlink(itup)
Definition ginblock.h:257
#define GinGetPostingTree(itup)
Definition ginblock.h:233
signed char GinNullCategory
Definition ginblock.h:206
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Definition ginutil.c:234
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
Definition ginutil.c:267
void initGinState(GinState *state, Relation index)
Definition ginutil.c:104
IndexTuple CopyIndexTuple(IndexTuple source)
Definition indextuple.c:479
int j
Definition isn.c:78
int i
Definition isn.c:77
#define ItemIdGetLength(itemId)
Definition itemid.h:59
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition itemptr.h:124
IndexTupleData * IndexTuple
Definition itup.h:53
static Size IndexTupleSize(const IndexTupleData *itup)
Definition itup.h:71
void pfree(void *pointer)
Definition mcxt.c:1616
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
#define OffsetNumberIsValid(offsetNumber)
Definition off.h:39
#define OffsetNumberNext(offsetNumber)
Definition off.h:52
uint16 OffsetNumber
Definition off.h:24
#define FirstOffsetNumber
Definition off.h:27
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
uint64_t Datum
Definition postgres.h:70
@ MAIN_FORKNUM
Definition relpath.h:58
IndexTuple parenttup
Definition verify_gin.c:39
BlockNumber parentblk
Definition verify_gin.c:40
BlockNumber blkno
Definition verify_gin.c:41
struct GinScanItem * next
Definition verify_gin.c:42
static IndexTuple gin_refind_parent(Relation rel, BlockNumber parentblkno, BlockNumber childblkno, BufferAccessStrategy strategy)
Definition verify_gin.c:718
static ItemPointer ginReadTupleWithoutState(IndexTuple itup, int *nitems)
Definition verify_gin.c:99
static void gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting_tree_root)
Definition verify_gin.c:134
static void check_index_page(Relation rel, Buffer buffer, BlockNumber blockNo)
Definition verify_gin.c:662
static ItemId PageGetItemIdCareful(Relation rel, BlockNumber block, Page page, OffsetNumber offset)
Definition verify_gin.c:759

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, BAS_BULKREAD, GinScanItem::blkno, BufferGetPage(), CHECK_FOR_INTERRUPTS, check_index_page(), CopyIndexTuple(), CurrentMemoryContext, DEBUG3, GinScanItem::depth, elog, ereport, errcode(), errmsg, ERROR, fb(), FirstOffsetNumber, GetAccessStrategy(), gin_check_posting_tree_parent_keys_consistency(), gin_refind_parent(), GIN_ROOT_BLKNO, GIN_SHARE, ginCompareAttEntries(), GinGetDownlink, GinGetPostingTree, GinIsPostingTree, GinPageGetOpaque, GinPageIsLeaf, ginReadTupleWithoutState(), gintuple_get_attrnum(), gintuple_get_key(), i, IndexTupleSize(), initGinState(), InvalidAttrNumber, InvalidBlockNumber, ItemIdGetLength, ItemPointerGetOffsetNumber(), j, LockBuffer(), MAIN_FORKNUM, MAXALIGN, MemoryContextDelete(), MemoryContextSwitchTo(), GinScanItem::next, NOTICE, OffsetNumberIsValid, OffsetNumberNext, PageGetItem(), PageGetItemIdCareful(), PageGetMaxOffsetNumber(), palloc0_object, palloc_object, GinScanItem::parentblk, GinScanItem::parenttup, pfree(), RBM_NORMAL, ReadBufferExtended(), RelationGetRelationName, and UnlockReleaseBuffer().

Referenced by gin_index_check().

◆ gin_check_posting_tree_parent_keys_consistency()

static void gin_check_posting_tree_parent_keys_consistency ( Relation  rel,
BlockNumber  posting_tree_root 
)
static

Definition at line 134 of file verify_gin.c.

135{
139 MemoryContext oldcontext;
140
141 int leafdepth;
142
144 "posting tree check context",
146 oldcontext = MemoryContextSwitchTo(mctx);
147
148 /*
149 * We don't know the height of the tree yet, but as soon as we encounter a
150 * leaf page, we will set 'leafdepth' to its depth.
151 */
152 leafdepth = -1;
153
154 /* Start the scan at the root page */
156 stack->depth = 0;
159 stack->blkno = posting_tree_root;
160
161 elog(DEBUG3, "processing posting tree at blk %u", posting_tree_root);
162
163 while (stack)
164 {
166 Buffer buffer;
167 Page page;
169 maxoff;
170 BlockNumber rightlink;
171
173
174 buffer = ReadBufferExtended(rel, MAIN_FORKNUM, stack->blkno,
175 RBM_NORMAL, strategy);
176 LockBuffer(buffer, GIN_SHARE);
177 page = BufferGetPage(buffer);
178
179 Assert(GinPageIsData(page));
180
181 /* Check that the tree has the same height in all branches */
182 if (GinPageIsLeaf(page))
183 {
185 int nlist;
188
190
191 elog(DEBUG1, "page blk: %u, type leaf", stack->blkno);
192
193 if (leafdepth == -1)
194 leafdepth = stack->depth;
195 else if (stack->depth != leafdepth)
198 errmsg("index \"%s\": internal pages traversal encountered leaf page unexpectedly on block %u",
199 RelationGetRelationName(rel), stack->blkno)));
200 list = GinDataLeafPageGetItems(page, &nlist, minItem);
201
202 if (nlist > 0)
204 "%d tids (%u, %u) - (%u, %u)",
205 nlist,
208 ItemPointerGetBlockNumberNoCheck(&list[nlist - 1]),
209 ItemPointerGetOffsetNumberNoCheck(&list[nlist - 1]));
210 else
211 snprintf(tidrange_buf, sizeof(tidrange_buf), "0 tids");
212
213 if (stack->parentblk != InvalidBlockNumber)
214 elog(DEBUG3, "blk %u: parent %u highkey (%u, %u), %s",
215 stack->blkno,
216 stack->parentblk,
220 else
221 elog(DEBUG3, "blk %u: root leaf, %s",
222 stack->blkno,
224
225 if (stack->parentblk != InvalidBlockNumber &&
227 nlist > 0 && ItemPointerCompare(&stack->parentkey, &list[nlist - 1]) < 0)
230 errmsg("index \"%s\": tid exceeds parent's high key in postingTree leaf on block %u",
231 RelationGetRelationName(rel), stack->blkno)));
232 }
233 else
234 {
235 LocationIndex pd_lower;
236 ItemPointerData bound;
237 int lowersize;
238
239 /*
240 * Check that tuples in each page are properly ordered and
241 * consistent with parent high key
242 */
243 maxoff = GinPageGetOpaque(page)->maxoff;
244 rightlink = GinPageGetOpaque(page)->rightlink;
245
246 elog(DEBUG1, "page blk: %u, type data, maxoff %d", stack->blkno, maxoff);
247
248 if (stack->parentblk != InvalidBlockNumber)
249 elog(DEBUG3, "blk %u: internal posting tree page with %u items, parent %u highkey (%u, %u)",
250 stack->blkno, maxoff, stack->parentblk,
253 else
254 elog(DEBUG3, "blk %u: root internal posting tree page with %u items",
255 stack->blkno, maxoff);
256
257 /*
258 * A GIN posting tree internal page stores PostingItems in the
259 * 'lower' part of the page. The 'upper' part is unused. The
260 * number of elements is stored in the opaque area (maxoff). Make
261 * sure the size of the 'lower' part agrees with 'maxoff'
262 *
263 * We didn't set pd_lower until PostgreSQL version 9.4, so if this
264 * check fails, it could also be because the index was
265 * binary-upgraded from an earlier version. That was a long time
266 * ago, though, so let's warn if it doesn't match.
267 */
268 pd_lower = ((PageHeader) page)->pd_lower;
270 if ((lowersize - MAXALIGN(sizeof(ItemPointerData))) / sizeof(PostingItem) != maxoff)
273 errmsg("index \"%s\" has unexpected pd_lower %u in posting tree block %u with maxoff %u)",
274 RelationGetRelationName(rel), pd_lower, stack->blkno, maxoff)));
275
276 /*
277 * Before the PostingItems, there's one ItemPointerData in the
278 * 'lower' part that stores the page's high key.
279 */
280 bound = *GinDataPageGetRightBound(page);
281
282 /*
283 * Gin page right bound has a sane value only when not a highkey
284 * on the rightmost page (at a given level). For the rightmost
285 * page does not store the highkey explicitly, and the value is
286 * infinity.
287 */
288 if (ItemPointerIsValid(&stack->parentkey) &&
289 rightlink != InvalidBlockNumber &&
290 !ItemPointerEquals(&stack->parentkey, &bound))
293 errmsg("index \"%s\": posting tree page's high key (%u, %u) doesn't match the downlink on block %u (parent blk %u, key (%u, %u))",
297 stack->blkno, stack->parentblk,
300
301 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
302 {
305
306 /* ItemPointerGetOffsetNumber expects a valid pointer */
307 if (!(i == maxoff &&
308 rightlink == InvalidBlockNumber))
309 elog(DEBUG3, "key (%u, %u) -> %u",
312 BlockIdGetBlockNumber(&posting_item->child_blkno));
313 else
314 elog(DEBUG3, "key (%u, %u) -> %u",
315 0, 0, BlockIdGetBlockNumber(&posting_item->child_blkno));
316
317 if (i == maxoff && rightlink == InvalidBlockNumber)
318 {
319 /*
320 * The rightmost item in the tree level has (0, 0) as the
321 * key
322 */
327 errmsg("index \"%s\": rightmost posting tree page (blk %u) has unexpected last key (%u, %u)",
329 stack->blkno,
332 }
333 else if (i != FirstOffsetNumber)
334 {
336
340 errmsg("index \"%s\" has wrong tuple order in posting tree, block %u, offset %u",
341 RelationGetRelationName(rel), stack->blkno, i)));
342 }
343
344 /*
345 * Check if this tuple is consistent with the downlink in the
346 * parent.
347 */
348 if (i == maxoff && ItemPointerIsValid(&stack->parentkey) &&
349 ItemPointerCompare(&stack->parentkey, &posting_item->key) < 0)
352 errmsg("index \"%s\": posting item exceeds parent's high key in postingTree internal page on block %u offset %u",
354 stack->blkno, i)));
355
356 /* This is an internal page, recurse into the child. */
358 ptr->depth = stack->depth + 1;
359
360 /*
361 * The rightmost parent key is always invalid item pointer.
362 * Its value is 'Infinity' and not explicitly stored.
363 */
364 ptr->parentkey = posting_item->key;
365 ptr->parentblk = stack->blkno;
366 ptr->blkno = BlockIdGetBlockNumber(&posting_item->child_blkno);
367 ptr->next = stack->next;
368 stack->next = ptr;
369 }
370 }
371 UnlockReleaseBuffer(buffer);
372
373 /* Step to next item in the queue */
374 stack_next = stack->next;
375 pfree(stack);
376 stack = stack_next;
377 }
378
379 MemoryContextSwitchTo(oldcontext);
381}
static BlockNumber BlockIdGetBlockNumber(const BlockIdData *blockId)
Definition block.h:103
PageHeaderData * PageHeader
Definition bufpage.h:199
#define SizeOfPageHeaderData
Definition bufpage.h:241
uint16 LocationIndex
Definition bufpage.h:90
#define Assert(condition)
Definition c.h:943
#define DEBUG1
Definition elog.h:31
#define GinDataPageGetRightBound(page)
Definition ginblock.h:288
#define GinPageIsData(page)
Definition ginblock.h:115
#define ItemPointerSetMin(p)
Definition ginblock.h:166
#define GinDataPageGetPostingItem(page, i)
Definition ginblock.h:298
ItemPointer GinDataLeafPageGetItems(Page page, int *nitems, ItemPointerData advancePast)
int32 ItemPointerCompare(const ItemPointerData *arg1, const ItemPointerData *arg2)
Definition itemptr.c:51
bool ItemPointerEquals(const ItemPointerData *pointer1, const ItemPointerData *pointer2)
Definition itemptr.c:35
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition itemptr.h:184
static OffsetNumber ItemPointerGetOffsetNumberNoCheck(const ItemPointerData *pointer)
Definition itemptr.h:114
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition itemptr.h:103
static BlockNumber ItemPointerGetBlockNumberNoCheck(const ItemPointerData *pointer)
Definition itemptr.h:93
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Definition itemptr.h:83
#define MAXPGPATH
#define snprintf
Definition port.h:260
BlockNumber parentblk
Definition verify_gin.c:52
ItemPointerData parentkey
Definition verify_gin.c:51
struct GinPostingTreeScanItem * next
Definition verify_gin.c:54

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BAS_BULKREAD, GinPostingTreeScanItem::blkno, BlockIdGetBlockNumber(), BufferGetPage(), CHECK_FOR_INTERRUPTS, CurrentMemoryContext, DEBUG1, DEBUG3, GinPostingTreeScanItem::depth, elog, ereport, errcode(), errmsg, ERROR, fb(), FirstOffsetNumber, GetAccessStrategy(), GIN_SHARE, GinDataLeafPageGetItems(), GinDataPageGetPostingItem, GinDataPageGetRightBound, GinPageGetOpaque, GinPageIsData, GinPageIsLeaf, i, InvalidBlockNumber, InvalidOffsetNumber, ItemPointerCompare(), ItemPointerEquals(), ItemPointerGetBlockNumber(), ItemPointerGetBlockNumberNoCheck(), ItemPointerGetOffsetNumber(), ItemPointerGetOffsetNumberNoCheck(), ItemPointerIsValid(), ItemPointerSetInvalid(), ItemPointerSetMin, LockBuffer(), MAIN_FORKNUM, MAXALIGN, MAXPGPATH, MemoryContextDelete(), MemoryContextSwitchTo(), GinPostingTreeScanItem::next, OffsetNumberNext, palloc0_object, palloc_object, GinPostingTreeScanItem::parentblk, GinPostingTreeScanItem::parentkey, pfree(), RBM_NORMAL, ReadBufferExtended(), RelationGetRelationName, SizeOfPageHeaderData, snprintf, and UnlockReleaseBuffer().

Referenced by gin_check_parent_keys_consistency().

◆ gin_index_check()

Datum gin_index_check ( PG_FUNCTION_ARGS  )

Definition at line 79 of file verify_gin.c.

80{
82
87 NULL);
88
90}
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define AccessShareLock
Definition lockdefs.h:36
unsigned int Oid
void amcheck_lock_relation_and_check(Oid indrelid, Oid am_id, IndexDoCheckCallback check, LOCKMODE lockmode, void *state)
static void gin_check_parent_keys_consistency(Relation rel, Relation heaprel, void *callback_state, bool readonly)
Definition verify_gin.c:389

References AccessShareLock, amcheck_lock_relation_and_check(), gin_check_parent_keys_consistency(), PG_GETARG_OID, and PG_RETURN_VOID.

◆ gin_refind_parent()

static IndexTuple gin_refind_parent ( Relation  rel,
BlockNumber  parentblkno,
BlockNumber  childblkno,
BufferAccessStrategy  strategy 
)
static

◆ ginReadTupleWithoutState()

static ItemPointer ginReadTupleWithoutState ( IndexTuple  itup,
int nitems 
)
static

Definition at line 99 of file verify_gin.c.

100{
101 Pointer ptr = GinGetPosting(itup);
102 int nipd = GinGetNPosting(itup);
104 int ndecoded;
105
106 if (GinItupIsCompressed(itup))
107 {
108 if (nipd > 0)
109 {
111 if (nipd != ndecoded)
112 elog(ERROR, "number of items mismatch in GIN entry tuple, %d in tuple header, %d decoded",
113 nipd, ndecoded);
114 }
115 else
116 ipd = palloc(0);
117 }
118 else
119 {
121 memcpy(ipd, ptr, sizeof(ItemPointerData) * nipd);
122 }
123 *nitems = nipd;
124 return ipd;
125}
void * Pointer
Definition c.h:615
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define GinGetPosting(itup)
Definition ginblock.h:238
#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
void * palloc(Size size)
Definition mcxt.c:1387

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

Referenced by gin_check_parent_keys_consistency().

◆ PageGetItemIdCareful()

static ItemId PageGetItemIdCareful ( Relation  rel,
BlockNumber  block,
Page  page,
OffsetNumber  offset 
)
static

Definition at line 759 of file verify_gin.c.

761{
762 ItemId itemid = PageGetItemId(page, offset);
763
764 if (ItemIdGetOffset(itemid) + ItemIdGetLength(itemid) >
768 errmsg("line pointer points past end of tuple space in index \"%s\"",
770 errdetail_internal("Index tid=(%u,%u) lp_off=%u, lp_len=%u lp_flags=%u.",
771 block, offset, ItemIdGetOffset(itemid),
772 ItemIdGetLength(itemid),
773 ItemIdGetFlags(itemid))));
774
775 /*
776 * Verify that line pointer isn't LP_REDIRECT or LP_UNUSED or LP_DEAD,
777 * since GIN never uses all three. Verify that line pointer has storage,
778 * too.
779 */
780 if (ItemIdIsRedirected(itemid) || !ItemIdIsUsed(itemid) ||
781 ItemIdIsDead(itemid) || ItemIdGetLength(itemid) == 0)
784 errmsg("invalid line pointer storage in index \"%s\"",
786 errdetail_internal("Index tid=(%u,%u) lp_off=%u, lp_len=%u lp_flags=%u.",
787 block, offset, ItemIdGetOffset(itemid),
788 ItemIdGetLength(itemid),
789 ItemIdGetFlags(itemid))));
790
791 return itemid;
792}
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition bufpage.h:268
int int errdetail_internal(const char *fmt,...) pg_attribute_printf(1
#define ItemIdGetOffset(itemId)
Definition itemid.h:65
#define ItemIdIsDead(itemId)
Definition itemid.h:113
#define ItemIdIsUsed(itemId)
Definition itemid.h:92
#define ItemIdIsRedirected(itemId)
Definition itemid.h:106
#define ItemIdGetFlags(itemId)
Definition itemid.h:71

References ereport, errcode(), errdetail_internal(), errmsg, ERROR, fb(), ItemIdGetFlags, ItemIdGetLength, ItemIdGetOffset, ItemIdIsDead, ItemIdIsRedirected, ItemIdIsUsed, MAXALIGN, PageGetItemId(), and RelationGetRelationName.

Referenced by gin_check_parent_keys_consistency(), and gin_refind_parent().

◆ PG_FUNCTION_INFO_V1()

PG_FUNCTION_INFO_V1 ( gin_index_check  )