PostgreSQL Source Code git master
ginutil.c File Reference
#include "postgres.h"
#include "access/gin_private.h"
#include "access/ginxlog.h"
#include "access/reloptions.h"
#include "access/xloginsert.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "commands/progress.h"
#include "commands/vacuum.h"
#include "miscadmin.h"
#include "storage/indexfsm.h"
#include "utils/builtins.h"
#include "utils/index_selfuncs.h"
#include "utils/rel.h"
#include "utils/typcache.h"
Include dependency graph for ginutil.c:

Go to the source code of this file.

Data Structures

struct  keyEntryData
 
struct  cmpEntriesArg
 

Functions

Datum ginhandler (PG_FUNCTION_ARGS)
 
void initGinState (GinState *state, Relation index)
 
OffsetNumber gintuple_get_attrnum (GinState *ginstate, IndexTuple tuple)
 
Datum gintuple_get_key (GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
 
Buffer GinNewBuffer (Relation index)
 
void GinInitPage (Page page, uint32 f, Size pageSize)
 
void GinInitBuffer (Buffer b, uint32 f)
 
void GinInitMetabuffer (Buffer b)
 
int ginCompareEntries (GinState *ginstate, OffsetNumber attnum, Datum a, GinNullCategory categorya, Datum b, GinNullCategory categoryb)
 
int ginCompareAttEntries (GinState *ginstate, OffsetNumber attnuma, Datum a, GinNullCategory categorya, OffsetNumber attnumb, Datum b, GinNullCategory categoryb)
 
static int cmpEntries (const void *a, const void *b, void *arg)
 
DatumginExtractEntries (GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries, GinNullCategory **categories)
 
byteaginoptions (Datum reloptions, bool validate)
 
void ginGetStats (Relation index, GinStatsData *stats)
 
void ginUpdateStats (Relation index, const GinStatsData *stats, bool is_build)
 
char * ginbuildphasename (int64 phasenum)
 

Function Documentation

◆ cmpEntries()

static int cmpEntries ( const void *  a,
const void *  b,
void *  arg 
)
static

Definition at line 449 of file ginutil.c.

450{
451 const keyEntryData *aa = (const keyEntryData *) a;
452 const keyEntryData *bb = (const keyEntryData *) b;
454 int res;
455
456 if (aa->isnull)
457 {
458 if (bb->isnull)
459 res = 0; /* NULL "=" NULL */
460 else
461 res = 1; /* NULL ">" not-NULL */
462 }
463 else if (bb->isnull)
464 res = -1; /* not-NULL "<" NULL */
465 else
466 res = DatumGetInt32(FunctionCall2Coll(data->cmpDatumFunc,
467 data->collation,
468 aa->datum, bb->datum));
469
470 /*
471 * Detect if we have any duplicates. If there are equal keys, qsort must
472 * compare them at some point, else it wouldn't know whether one should go
473 * before or after the other.
474 */
475 if (res == 0)
476 data->haveDups = true;
477
478 return res;
479}
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1150
int b
Definition: isn.c:74
int a
Definition: isn.c:73
void * arg
const void * data
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212
bool isnull
Definition: ginutil.c:438
Datum datum
Definition: ginutil.c:437

References a, arg, b, data, keyEntryData::datum, DatumGetInt32(), FunctionCall2Coll(), and keyEntryData::isnull.

Referenced by ginExtractEntries().

◆ ginbuildphasename()

char * ginbuildphasename ( int64  phasenum)

Definition at line 713 of file ginutil.c.

714{
715 switch (phasenum)
716 {
718 return "initializing";
720 return "scanning table";
722 return "sorting tuples (workers)";
724 return "merging tuples (workers)";
726 return "sorting tuples";
728 return "merging tuples";
729 default:
730 return NULL;
731 }
732}
#define PROGRESS_GIN_PHASE_PERFORMSORT_2
Definition: gin.h:49
#define PROGRESS_GIN_PHASE_MERGE_1
Definition: gin.h:48
#define PROGRESS_GIN_PHASE_PERFORMSORT_1
Definition: gin.h:47
#define PROGRESS_GIN_PHASE_MERGE_2
Definition: gin.h:50
#define PROGRESS_GIN_PHASE_INDEXBUILD_TABLESCAN
Definition: gin.h:46
#define PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE
Definition: progress.h:126

References PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE, PROGRESS_GIN_PHASE_INDEXBUILD_TABLESCAN, PROGRESS_GIN_PHASE_MERGE_1, PROGRESS_GIN_PHASE_MERGE_2, PROGRESS_GIN_PHASE_PERFORMSORT_1, and PROGRESS_GIN_PHASE_PERFORMSORT_2.

Referenced by ginhandler().

◆ ginCompareAttEntries()

int ginCompareAttEntries ( GinState ginstate,
OffsetNumber  attnuma,
Datum  a,
GinNullCategory  categorya,
OffsetNumber  attnumb,
Datum  b,
GinNullCategory  categoryb 
)

Definition at line 416 of file ginutil.c.

419{
420 /* attribute number is the first sort key */
421 if (attnuma != attnumb)
422 return (attnuma < attnumb) ? -1 : 1;
423
424 return ginCompareEntries(ginstate, attnuma, a, categorya, b, categoryb);
425}
int ginCompareEntries(GinState *ginstate, OffsetNumber attnum, Datum a, GinNullCategory categorya, Datum b, GinNullCategory categoryb)
Definition: ginutil.c:394

References a, b, and ginCompareEntries().

Referenced by cmpEntryAccumulator(), entryIsMoveRight(), entryLocateEntry(), entryLocateLeafEntry(), and gin_check_parent_keys_consistency().

◆ ginCompareEntries()

int ginCompareEntries ( GinState ginstate,
OffsetNumber  attnum,
Datum  a,
GinNullCategory  categorya,
Datum  b,
GinNullCategory  categoryb 
)

Definition at line 394 of file ginutil.c.

397{
398 /* if not of same null category, sort by that first */
399 if (categorya != categoryb)
400 return (categorya < categoryb) ? -1 : 1;
401
402 /* all null items in same category are equal */
403 if (categorya != GIN_CAT_NORM_KEY)
404 return 0;
405
406 /* both not null, so safe to call the compareFn */
407 return DatumGetInt32(FunctionCall2Coll(&ginstate->compareFn[attnum - 1],
408 ginstate->supportCollation[attnum - 1],
409 a, b));
410}
#define GIN_CAT_NORM_KEY
Definition: ginblock.h:208
int16 attnum
Definition: pg_attribute.h:74
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gin_private.h:89
FmgrInfo compareFn[INDEX_MAX_KEYS]
Definition: gin_private.h:80

References a, attnum, b, GinState::compareFn, DatumGetInt32(), FunctionCall2Coll(), GIN_CAT_NORM_KEY, and GinState::supportCollation.

Referenced by collectMatchBitmap(), collectMatchesForHeapRow(), ginCompareAttEntries(), and ginFillScanEntry().

◆ ginExtractEntries()

Datum * ginExtractEntries ( GinState ginstate,
OffsetNumber  attnum,
Datum  value,
bool  isNull,
int32 nentries,
GinNullCategory **  categories 
)

Definition at line 489 of file ginutil.c.

492{
493 Datum *entries;
494 bool *nullFlags;
495 int32 i;
496
497 /*
498 * We don't call the extractValueFn on a null item. Instead generate a
499 * placeholder.
500 */
501 if (isNull)
502 {
503 *nentries = 1;
504 entries = palloc_object(Datum);
505 entries[0] = (Datum) 0;
506 *categories = palloc_object(GinNullCategory);
507 (*categories)[0] = GIN_CAT_NULL_ITEM;
508 return entries;
509 }
510
511 /* OK, call the opclass's extractValueFn */
512 nullFlags = NULL; /* in case extractValue doesn't set it */
513 entries = (Datum *)
515 ginstate->supportCollation[attnum - 1],
516 value,
517 PointerGetDatum(nentries),
518 PointerGetDatum(&nullFlags)));
519
520 /*
521 * Generate a placeholder if the item contained no keys.
522 */
523 if (entries == NULL || *nentries <= 0)
524 {
525 *nentries = 1;
526 entries = palloc_object(Datum);
527 entries[0] = (Datum) 0;
528 *categories = palloc_object(GinNullCategory);
529 (*categories)[0] = GIN_CAT_EMPTY_ITEM;
530 return entries;
531 }
532
533 /*
534 * If the extractValueFn didn't create a nullFlags array, create one,
535 * assuming that everything's non-null.
536 */
537 if (nullFlags == NULL)
538 nullFlags = (bool *) palloc0(*nentries * sizeof(bool));
539
540 /*
541 * If there's more than one key, sort and unique-ify.
542 *
543 * XXX Using qsort here is notationally painful, and the overhead is
544 * pretty bad too. For small numbers of keys it'd likely be better to use
545 * a simple insertion sort.
546 */
547 if (*nentries > 1)
548 {
549 keyEntryData *keydata;
551
552 keydata = palloc_array(keyEntryData, *nentries);
553 for (i = 0; i < *nentries; i++)
554 {
555 keydata[i].datum = entries[i];
556 keydata[i].isnull = nullFlags[i];
557 }
558
559 arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
560 arg.collation = ginstate->supportCollation[attnum - 1];
561 arg.haveDups = false;
562 qsort_arg(keydata, *nentries, sizeof(keyEntryData),
563 cmpEntries, &arg);
564
565 if (arg.haveDups)
566 {
567 /* there are duplicates, must get rid of 'em */
568 int32 j;
569
570 entries[0] = keydata[0].datum;
571 nullFlags[0] = keydata[0].isnull;
572 j = 1;
573 for (i = 1; i < *nentries; i++)
574 {
575 if (cmpEntries(&keydata[i - 1], &keydata[i], &arg) != 0)
576 {
577 entries[j] = keydata[i].datum;
578 nullFlags[j] = keydata[i].isnull;
579 j++;
580 }
581 }
582 *nentries = j;
583 }
584 else
585 {
586 /* easy, no duplicates */
587 for (i = 0; i < *nentries; i++)
588 {
589 entries[i] = keydata[i].datum;
590 nullFlags[i] = keydata[i].isnull;
591 }
592 }
593
594 pfree(keydata);
595 }
596
597 /*
598 * Create GinNullCategory representation from nullFlags.
599 */
600 *categories = (GinNullCategory *) palloc0(*nentries * sizeof(GinNullCategory));
601 for (i = 0; i < *nentries; i++)
602 (*categories)[i] = (nullFlags[i] ? GIN_CAT_NULL_KEY : GIN_CAT_NORM_KEY);
603
604 return entries;
605}
int32_t int32
Definition: c.h:548
#define palloc_object(type)
Definition: fe_memutils.h:74
#define palloc_array(type, count)
Definition: fe_memutils.h:76
Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition: fmgr.c:1172
#define GIN_CAT_EMPTY_ITEM
Definition: ginblock.h:210
signed char GinNullCategory
Definition: ginblock.h:206
#define GIN_CAT_NULL_ITEM
Definition: ginblock.h:211
#define GIN_CAT_NULL_KEY
Definition: ginblock.h:209
static int cmpEntries(const void *a, const void *b, void *arg)
Definition: ginutil.c:449
static struct @171 value
int j
Definition: isn.c:78
int i
Definition: isn.c:77
void pfree(void *pointer)
Definition: mcxt.c:1616
void * palloc0(Size size)
Definition: mcxt.c:1417
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:352
uint64_t Datum
Definition: postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:342
FmgrInfo extractValueFn[INDEX_MAX_KEYS]
Definition: gin_private.h:81

References arg, attnum, cmpEntries(), GinState::compareFn, keyEntryData::datum, DatumGetPointer(), GinState::extractValueFn, FunctionCall3Coll(), GIN_CAT_EMPTY_ITEM, GIN_CAT_NORM_KEY, GIN_CAT_NULL_ITEM, GIN_CAT_NULL_KEY, i, keyEntryData::isnull, j, palloc0(), palloc_array, palloc_object, pfree(), PointerGetDatum(), qsort_arg(), GinState::supportCollation, and value.

Referenced by ginHeapTupleBulkInsert(), ginHeapTupleFastCollect(), and ginHeapTupleInsert().

◆ ginGetStats()

void ginGetStats ( Relation  index,
GinStatsData stats 
)

Definition at line 629 of file ginutil.c.

630{
631 Buffer metabuffer;
632 Page metapage;
633 GinMetaPageData *metadata;
634
635 metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO);
636 LockBuffer(metabuffer, GIN_SHARE);
637 metapage = BufferGetPage(metabuffer);
638 metadata = GinPageGetMeta(metapage);
639
640 stats->nPendingPages = metadata->nPendingPages;
641 stats->nTotalPages = metadata->nTotalPages;
642 stats->nEntryPages = metadata->nEntryPages;
643 stats->nDataPages = metadata->nDataPages;
644 stats->nEntries = metadata->nEntries;
645 stats->ginVersion = metadata->ginVersion;
646
647 UnlockReleaseBuffer(metabuffer);
648}
int Buffer
Definition: buf.h:23
void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition: bufmgr.c:5699
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5478
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:839
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:436
PageData * Page
Definition: bufpage.h:81
#define GIN_SHARE
Definition: gin_private.h:51
#define GIN_METAPAGE_BLKNO
Definition: ginblock.h:51
#define GinPageGetMeta(p)
Definition: ginblock.h:104
int64 nEntries
Definition: ginblock.h:82
int32 ginVersion
Definition: ginblock.h:99
BlockNumber nEntryPages
Definition: ginblock.h:80
BlockNumber nPendingPages
Definition: ginblock.h:73
BlockNumber nTotalPages
Definition: ginblock.h:79
BlockNumber nDataPages
Definition: ginblock.h:81
BlockNumber nDataPages
Definition: gin.h:60
BlockNumber nPendingPages
Definition: gin.h:57
BlockNumber nEntryPages
Definition: gin.h:59
int64 nEntries
Definition: gin.h:61
BlockNumber nTotalPages
Definition: gin.h:58
int32 ginVersion
Definition: gin.h:62
Definition: type.h:96

References BufferGetPage(), GIN_METAPAGE_BLKNO, GIN_SHARE, GinPageGetMeta, GinStatsData::ginVersion, GinMetaPageData::ginVersion, LockBuffer(), GinStatsData::nDataPages, GinMetaPageData::nDataPages, GinStatsData::nEntries, GinMetaPageData::nEntries, GinStatsData::nEntryPages, GinMetaPageData::nEntryPages, GinStatsData::nPendingPages, GinMetaPageData::nPendingPages, GinStatsData::nTotalPages, GinMetaPageData::nTotalPages, ReadBuffer(), and UnlockReleaseBuffer().

Referenced by gincostestimate().

◆ ginhandler()

Datum ginhandler ( PG_FUNCTION_ARGS  )

Definition at line 38 of file ginutil.c.

39{
40 static const IndexAmRoutine amroutine = {
41 .type = T_IndexAmRoutine,
42 .amstrategies = 0,
43 .amsupport = GINNProcs,
44 .amoptsprocnum = GIN_OPTIONS_PROC,
45 .amcanorder = false,
46 .amcanorderbyop = false,
47 .amcanhash = false,
48 .amconsistentequality = false,
49 .amconsistentordering = false,
50 .amcanbackward = false,
51 .amcanunique = false,
52 .amcanmulticol = true,
53 .amoptionalkey = true,
54 .amsearcharray = false,
55 .amsearchnulls = false,
56 .amstorage = true,
57 .amclusterable = false,
58 .ampredlocks = true,
59 .amcanparallel = false,
60 .amcanbuildparallel = true,
61 .amcaninclude = false,
62 .amusemaintenanceworkmem = true,
63 .amsummarizing = false,
64 .amparallelvacuumoptions =
66 .amkeytype = InvalidOid,
67
68 .ambuild = ginbuild,
69 .ambuildempty = ginbuildempty,
70 .aminsert = gininsert,
71 .aminsertcleanup = NULL,
72 .ambulkdelete = ginbulkdelete,
73 .amvacuumcleanup = ginvacuumcleanup,
74 .amcanreturn = NULL,
75 .amcostestimate = gincostestimate,
76 .amgettreeheight = NULL,
77 .amoptions = ginoptions,
78 .amproperty = NULL,
79 .ambuildphasename = ginbuildphasename,
80 .amvalidate = ginvalidate,
81 .amadjustmembers = ginadjustmembers,
82 .ambeginscan = ginbeginscan,
83 .amrescan = ginrescan,
84 .amgettuple = NULL,
85 .amgetbitmap = gingetbitmap,
86 .amendscan = ginendscan,
87 .ammarkpos = NULL,
88 .amrestrpos = NULL,
89 .amestimateparallelscan = NULL,
90 .aminitparallelscan = NULL,
91 .amparallelrescan = NULL,
92 };
93
94 PG_RETURN_POINTER(&amroutine);
95}
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:363
#define GINNProcs
Definition: gin.h:31
#define GIN_OPTIONS_PROC
Definition: gin.h:30
int64 gingetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
Definition: ginget.c:1931
IndexBuildResult * ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
Definition: gininsert.c:612
void ginbuildempty(Relation index)
Definition: gininsert.c:806
bool gininsert(Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
Definition: gininsert.c:855
IndexScanDesc ginbeginscan(Relation rel, int nkeys, int norderbys)
Definition: ginscan.c:25
void ginendscan(IndexScanDesc scan)
Definition: ginscan.c:503
void ginrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
Definition: ginscan.c:490
bytea * ginoptions(Datum reloptions, bool validate)
Definition: ginutil.c:608
char * ginbuildphasename(int64 phasenum)
Definition: ginutil.c:713
IndexBulkDeleteResult * ginbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
Definition: ginvacuum.c:564
IndexBulkDeleteResult * ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
Definition: ginvacuum.c:687
bool ginvalidate(Oid opclassoid)
Definition: ginvalidate.c:31
void ginadjustmembers(Oid opfamilyoid, Oid opclassoid, List *operators, List *functions)
Definition: ginvalidate.c:269
#define InvalidOid
Definition: postgres_ext.h:37
void gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
Definition: selfuncs.c:8601
NodeTag type
Definition: amapi.h:234
#define VACUUM_OPTION_PARALLEL_CLEANUP
Definition: vacuum.h:63
#define VACUUM_OPTION_PARALLEL_BULKDEL
Definition: vacuum.h:48

References GIN_OPTIONS_PROC, ginadjustmembers(), ginbeginscan(), ginbuild(), ginbuildempty(), ginbuildphasename(), ginbulkdelete(), gincostestimate(), ginendscan(), gingetbitmap(), gininsert(), GINNProcs, ginoptions(), ginrescan(), ginvacuumcleanup(), ginvalidate(), InvalidOid, PG_RETURN_POINTER, IndexAmRoutine::type, VACUUM_OPTION_PARALLEL_BULKDEL, and VACUUM_OPTION_PARALLEL_CLEANUP.

◆ GinInitBuffer()

void GinInitBuffer ( Buffer  b,
uint32  f 
)

Definition at line 356 of file ginutil.c.

357{
359}
static Size BufferGetPageSize(Buffer buffer)
Definition: bufmgr.h:425
void GinInitPage(Page page, uint32 f, Size pageSize)
Definition: ginutil.c:344

References b, BufferGetPage(), BufferGetPageSize(), and GinInitPage().

Referenced by ginbuild(), ginbuildempty(), ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoInsertListPage(), and writeListPage().

◆ GinInitMetabuffer()

void GinInitMetabuffer ( Buffer  b)

Definition at line 362 of file ginutil.c.

363{
364 GinMetaPageData *metadata;
365 Page page = BufferGetPage(b);
366
368
369 metadata = GinPageGetMeta(page);
370
371 metadata->head = metadata->tail = InvalidBlockNumber;
372 metadata->tailFreeSize = 0;
373 metadata->nPendingPages = 0;
374 metadata->nPendingHeapTuples = 0;
375 metadata->nTotalPages = 0;
376 metadata->nEntryPages = 0;
377 metadata->nDataPages = 0;
378 metadata->nEntries = 0;
380
381 /*
382 * Set pd_lower just past the end of the metadata. This is essential,
383 * because without doing so, metadata will be lost if xlog.c compresses
384 * the page.
385 */
386 ((PageHeader) page)->pd_lower =
387 ((char *) metadata + sizeof(GinMetaPageData)) - (char *) page;
388}
#define InvalidBlockNumber
Definition: block.h:33
PageHeaderData * PageHeader
Definition: bufpage.h:173
#define GIN_CURRENT_VERSION
Definition: ginblock.h:102
#define GIN_META
Definition: ginblock.h:44
BlockNumber tail
Definition: ginblock.h:62
uint32 tailFreeSize
Definition: ginblock.h:67
int64 nPendingHeapTuples
Definition: ginblock.h:74
BlockNumber head
Definition: ginblock.h:61

References b, BufferGetPage(), BufferGetPageSize(), GIN_CURRENT_VERSION, GIN_META, GinInitPage(), GinPageGetMeta, GinMetaPageData::ginVersion, GinMetaPageData::head, InvalidBlockNumber, GinMetaPageData::nDataPages, GinMetaPageData::nEntries, GinMetaPageData::nEntryPages, GinMetaPageData::nPendingHeapTuples, GinMetaPageData::nPendingPages, GinMetaPageData::nTotalPages, GinMetaPageData::tail, and GinMetaPageData::tailFreeSize.

Referenced by ginbuild(), ginbuildempty(), ginRedoDeleteListPages(), and ginRedoUpdateMetapage().

◆ GinInitPage()

void GinInitPage ( Page  page,
uint32  f,
Size  pageSize 
)

Definition at line 344 of file ginutil.c.

345{
346 GinPageOpaque opaque;
347
348 PageInit(page, pageSize, sizeof(GinPageOpaqueData));
349
350 opaque = GinPageGetOpaque(page);
351 opaque->flags = f;
353}
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:42
#define GinPageGetOpaque(page)
Definition: ginblock.h:110
BlockNumber rightlink
Definition: ginblock.h:32

References GinPageOpaqueData::flags, GinPageGetOpaque, InvalidBlockNumber, PageInit(), and GinPageOpaqueData::rightlink.

Referenced by createPostingTree(), dataPlaceToPageLeafSplit(), dataSplitPageInternal(), entrySplitPage(), GinInitBuffer(), GinInitMetabuffer(), and ginPlaceToPage().

◆ GinNewBuffer()

Buffer GinNewBuffer ( Relation  index)

Definition at line 306 of file ginutil.c.

307{
308 Buffer buffer;
309
310 /* First, try to get a page from FSM */
311 for (;;)
312 {
314
315 if (blkno == InvalidBlockNumber)
316 break;
317
318 buffer = ReadBuffer(index, blkno);
319
320 /*
321 * We have to guard against the possibility that someone else already
322 * recycled this page; the buffer may be locked if so.
323 */
324 if (ConditionalLockBuffer(buffer))
325 {
327 return buffer; /* OK to use */
328
329 LockBuffer(buffer, GIN_UNLOCK);
330 }
331
332 /* Can't use it, so release buffer and try again */
333 ReleaseBuffer(buffer);
334 }
335
336 /* Must extend the file */
339
340 return buffer;
341}
uint32 BlockNumber
Definition: block.h:31
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
Definition: bufmgr.c:939
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:5725
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5461
@ EB_LOCK_FIRST
Definition: bufmgr.h:87
#define BMR_REL(p_rel)
Definition: bufmgr.h:114
#define GIN_UNLOCK
Definition: gin_private.h:50
bool GinPageIsRecyclable(Page page)
Definition: ginvacuum.c:801
BlockNumber GetFreeIndexPage(Relation rel)
Definition: indexfsm.c:38
@ MAIN_FORKNUM
Definition: relpath.h:58

References BMR_REL, BufferGetPage(), ConditionalLockBuffer(), EB_LOCK_FIRST, ExtendBufferedRel(), GetFreeIndexPage(), GIN_UNLOCK, GinPageIsRecyclable(), InvalidBlockNumber, LockBuffer(), MAIN_FORKNUM, ReadBuffer(), and ReleaseBuffer().

Referenced by createPostingTree(), ginbuild(), ginPlaceToPage(), and makeSublist().

◆ ginoptions()

bytea * ginoptions ( Datum  reloptions,
bool  validate 
)

Definition at line 608 of file ginutil.c.

609{
610 static const relopt_parse_elt tab[] = {
611 {"fastupdate", RELOPT_TYPE_BOOL, offsetof(GinOptions, useFastUpdate)},
612 {"gin_pending_list_limit", RELOPT_TYPE_INT, offsetof(GinOptions,
613 pendingListCleanupSize)}
614 };
615
616 return (bytea *) build_reloptions(reloptions, validate,
618 sizeof(GinOptions),
619 tab, lengthof(tab));
620}
static bool validate(Port *port, const char *auth)
Definition: auth-oauth.c:638
#define lengthof(array)
Definition: c.h:809
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
Definition: reloptions.c:1954
@ RELOPT_KIND_GIN
Definition: reloptions.h:46
@ RELOPT_TYPE_INT
Definition: reloptions.h:32
@ RELOPT_TYPE_BOOL
Definition: reloptions.h:31
Definition: c.h:712

References build_reloptions(), lengthof, RELOPT_KIND_GIN, RELOPT_TYPE_BOOL, RELOPT_TYPE_INT, and validate().

Referenced by ginhandler().

◆ gintuple_get_attrnum()

OffsetNumber gintuple_get_attrnum ( GinState ginstate,
IndexTuple  tuple 
)

Definition at line 232 of file ginutil.c.

233{
234 OffsetNumber colN;
235
236 if (ginstate->oneCol)
237 {
238 /* column number is not stored explicitly */
239 colN = FirstOffsetNumber;
240 }
241 else
242 {
243 Datum res;
244 bool isnull;
245
246 /*
247 * First attribute is always int16, so we can safely use any tuple
248 * descriptor to obtain first attribute of tuple
249 */
250 res = index_getattr(tuple, FirstOffsetNumber, ginstate->tupdesc[0],
251 &isnull);
252 Assert(!isnull);
253
254 colN = DatumGetUInt16(res);
255 Assert(colN >= FirstOffsetNumber && colN <= ginstate->origTupdesc->natts);
256 }
257
258 return colN;
259}
Assert(PointerIsAligned(start, uint64))
static Datum index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: itup.h:131
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
static uint16 DatumGetUInt16(Datum X)
Definition: postgres.h:192
bool oneCol
Definition: gin_private.h:61
TupleDesc tupdesc[INDEX_MAX_KEYS]
Definition: gin_private.h:75

References Assert(), DatumGetUInt16(), FirstOffsetNumber, index_getattr(), GinState::oneCol, and GinState::tupdesc.

Referenced by addItemPointersToLeafTuple(), collectMatchBitmap(), collectMatchesForHeapRow(), entryIsMoveRight(), entryLocateEntry(), entryLocateLeafEntry(), gin_check_parent_keys_consistency(), gintuple_get_key(), ginVacuumEntryPage(), matchPartialInPendingList(), and processPendingPage().

◆ gintuple_get_key()

Datum gintuple_get_key ( GinState ginstate,
IndexTuple  tuple,
GinNullCategory category 
)

Definition at line 265 of file ginutil.c.

267{
268 Datum res;
269 bool isnull;
270
271 if (ginstate->oneCol)
272 {
273 /*
274 * Single column index doesn't store attribute numbers in tuples
275 */
276 res = index_getattr(tuple, FirstOffsetNumber, ginstate->origTupdesc,
277 &isnull);
278 }
279 else
280 {
281 /*
282 * Since the datum type depends on which index column it's from, we
283 * must be careful to use the right tuple descriptor here.
284 */
285 OffsetNumber colN = gintuple_get_attrnum(ginstate, tuple);
286
288 ginstate->tupdesc[colN - 1],
289 &isnull);
290 }
291
292 if (isnull)
293 *category = GinGetNullCategory(tuple, ginstate);
294 else
295 *category = GIN_CAT_NORM_KEY;
296
297 return res;
298}
#define GinGetNullCategory(itup, ginstate)
Definition: ginblock.h:220
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Definition: ginutil.c:232
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
TupleDesc origTupdesc
Definition: gin_private.h:74

References FirstOffsetNumber, GIN_CAT_NORM_KEY, GinGetNullCategory, gintuple_get_attrnum(), index_getattr(), OffsetNumberNext, GinState::oneCol, GinState::origTupdesc, and GinState::tupdesc.

Referenced by addItemPointersToLeafTuple(), collectMatchBitmap(), collectMatchesForHeapRow(), entryIsMoveRight(), entryLocateEntry(), entryLocateLeafEntry(), gin_check_parent_keys_consistency(), ginVacuumEntryPage(), matchPartialInPendingList(), and processPendingPage().

◆ ginUpdateStats()

void ginUpdateStats ( Relation  index,
const GinStatsData stats,
bool  is_build 
)

Definition at line 656 of file ginutil.c.

657{
658 Buffer metabuffer;
659 Page metapage;
660 GinMetaPageData *metadata;
661
662 metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO);
663 LockBuffer(metabuffer, GIN_EXCLUSIVE);
664 metapage = BufferGetPage(metabuffer);
665 metadata = GinPageGetMeta(metapage);
666
668
669 metadata->nTotalPages = stats->nTotalPages;
670 metadata->nEntryPages = stats->nEntryPages;
671 metadata->nDataPages = stats->nDataPages;
672 metadata->nEntries = stats->nEntries;
673
674 /*
675 * Set pd_lower just past the end of the metadata. This is essential,
676 * because without doing so, metadata will be lost if xlog.c compresses
677 * the page. (We must do this here because pre-v11 versions of PG did not
678 * set the metapage's pd_lower correctly, so a pg_upgraded index might
679 * contain the wrong value.)
680 */
681 ((PageHeader) metapage)->pd_lower =
682 ((char *) metadata + sizeof(GinMetaPageData)) - (char *) metapage;
683
684 MarkBufferDirty(metabuffer);
685
686 if (RelationNeedsWAL(index) && !is_build)
687 {
688 XLogRecPtr recptr;
690
691 data.locator = index->rd_locator;
692 data.ntuples = 0;
693 data.newRightlink = data.prevTail = InvalidBlockNumber;
694 memcpy(&data.metadata, metadata, sizeof(GinMetaPageData));
695
699
700 recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_UPDATE_META_PAGE);
701 PageSetLSN(metapage, recptr);
702 }
703
704 UnlockReleaseBuffer(metabuffer);
705
707}
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:3037
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:390
#define GIN_EXCLUSIVE
Definition: gin_private.h:52
#define XLOG_GIN_UPDATE_META_PAGE
Definition: ginxlog.h:162
#define START_CRIT_SECTION()
Definition: miscadmin.h:150
#define END_CRIT_SECTION()
Definition: miscadmin.h:152
#define RelationNeedsWAL(relation)
Definition: rel.h:638
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:478
void XLogRegisterData(const void *data, uint32 len)
Definition: xloginsert.c:368
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:245
void XLogBeginInsert(void)
Definition: xloginsert.c:152
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define REGBUF_WILL_INIT
Definition: xloginsert.h:34

References BufferGetPage(), data, END_CRIT_SECTION, GIN_EXCLUSIVE, GIN_METAPAGE_BLKNO, GinPageGetMeta, InvalidBlockNumber, LockBuffer(), MarkBufferDirty(), GinStatsData::nDataPages, GinMetaPageData::nDataPages, GinStatsData::nEntries, GinMetaPageData::nEntries, GinStatsData::nEntryPages, GinMetaPageData::nEntryPages, GinStatsData::nTotalPages, GinMetaPageData::nTotalPages, PageSetLSN(), ReadBuffer(), REGBUF_STANDARD, REGBUF_WILL_INIT, RelationNeedsWAL, START_CRIT_SECTION, UnlockReleaseBuffer(), XLOG_GIN_UPDATE_META_PAGE, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by ginbuild(), and ginvacuumcleanup().

◆ initGinState()

void initGinState ( GinState state,
Relation  index 
)

Definition at line 103 of file ginutil.c.

104{
105 TupleDesc origTupdesc = RelationGetDescr(index);
106 int i;
107
108 MemSet(state, 0, sizeof(GinState));
109
110 state->index = index;
111 state->oneCol = (origTupdesc->natts == 1);
112 state->origTupdesc = origTupdesc;
113
114 for (i = 0; i < origTupdesc->natts; i++)
115 {
116 Form_pg_attribute attr = TupleDescAttr(origTupdesc, i);
117
118 if (state->oneCol)
119 state->tupdesc[i] = state->origTupdesc;
120 else
121 {
122 state->tupdesc[i] = CreateTemplateTupleDesc(2);
123
124 TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 1, NULL,
125 INT2OID, -1, 0);
126 TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 2, NULL,
127 attr->atttypid,
128 attr->atttypmod,
129 attr->attndims);
131 attr->attcollation);
132 }
133
134 /*
135 * If the compare proc isn't specified in the opclass definition, look
136 * up the index key type's default btree comparator.
137 */
139 {
140 fmgr_info_copy(&(state->compareFn[i]),
143 }
144 else
145 {
146 TypeCacheEntry *typentry;
147
148 typentry = lookup_type_cache(attr->atttypid,
150 if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
152 (errcode(ERRCODE_UNDEFINED_FUNCTION),
153 errmsg("could not identify a comparison function for type %s",
154 format_type_be(attr->atttypid))));
155 fmgr_info_copy(&(state->compareFn[i]),
156 &(typentry->cmp_proc_finfo),
158 }
159
160 /* Opclass must always provide extract procs */
161 fmgr_info_copy(&(state->extractValueFn[i]),
164 fmgr_info_copy(&(state->extractQueryFn[i]),
167
168 /*
169 * Check opclass capability to do tri-state or binary logic consistent
170 * check.
171 */
173 {
174 fmgr_info_copy(&(state->triConsistentFn[i]),
177 }
178
180 {
181 fmgr_info_copy(&(state->consistentFn[i]),
184 }
185
186 if (state->consistentFn[i].fn_oid == InvalidOid &&
187 state->triConsistentFn[i].fn_oid == InvalidOid)
188 {
189 elog(ERROR, "missing GIN support function (%d or %d) for attribute %d of index \"%s\"",
192 }
193
194 /*
195 * Check opclass capability to do partial match.
196 */
198 {
199 fmgr_info_copy(&(state->comparePartialFn[i]),
202 state->canPartialMatch[i] = true;
203 }
204 else
205 {
206 state->canPartialMatch[i] = false;
207 }
208
209 /*
210 * If the index column has a specified collation, we should honor that
211 * while doing comparisons. However, we may have a collatable storage
212 * type for a noncollatable indexed data type (for instance, hstore
213 * uses text index entries). If there's no index collation then
214 * specify default collation in case the support functions need
215 * collation. This is harmless if the support functions don't care
216 * about collation, so we just do it unconditionally. (We could
217 * alternatively call get_typcollation, but that seems like expensive
218 * overkill --- there aren't going to be any cases where a GIN storage
219 * type has a nondefault collation.)
220 */
221 if (OidIsValid(index->rd_indcollation[i]))
222 state->supportCollation[i] = index->rd_indcollation[i];
223 else
224 state->supportCollation[i] = DEFAULT_COLLATION_OID;
225 }
226}
int16 AttrNumber
Definition: attnum.h:21
#define MemSet(start, val, len)
Definition: c.h:1019
#define OidIsValid(objectId)
Definition: c.h:794
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:581
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define GIN_COMPARE_PROC
Definition: gin.h:24
#define GIN_CONSISTENT_PROC
Definition: gin.h:27
#define GIN_EXTRACTQUERY_PROC
Definition: gin.h:26
#define GIN_EXTRACTVALUE_PROC
Definition: gin.h:25
#define GIN_TRICONSISTENT_PROC
Definition: gin.h:29
#define GIN_COMPARE_PARTIAL_PROC
Definition: gin.h:28
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:917
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:883
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
#define RelationGetDescr(relation)
Definition: rel.h:541
#define RelationGetRelationName(relation)
Definition: rel.h:549
Oid fn_oid
Definition: fmgr.h:59
FmgrInfo cmp_proc_finfo
Definition: typcache.h:77
Definition: regguts.h:323
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:182
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:1026
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:842
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:144

References TypeCacheEntry::cmp_proc_finfo, CreateTemplateTupleDesc(), CurrentMemoryContext, elog, ereport, errcode(), errmsg(), ERROR, fmgr_info_copy(), FmgrInfo::fn_oid, format_type_be(), GIN_COMPARE_PARTIAL_PROC, GIN_COMPARE_PROC, GIN_CONSISTENT_PROC, GIN_EXTRACTQUERY_PROC, GIN_EXTRACTVALUE_PROC, GIN_TRICONSISTENT_PROC, i, index_getprocid(), index_getprocinfo(), InvalidOid, lookup_type_cache(), MemSet, TupleDescData::natts, OidIsValid, RelationGetDescr, RelationGetRelationName, TupleDescAttr(), TupleDescInitEntry(), TupleDescInitEntryCollation(), and TYPECACHE_CMP_PROC_FINFO.

Referenced by _gin_parallel_build_main(), gin_check_parent_keys_consistency(), gin_clean_pending_list(), ginbeginscan(), ginbuild(), ginbulkdelete(), gininsert(), and ginvacuumcleanup().