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/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)
 

Function Documentation

◆ cmpEntries()

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

Definition at line 443 of file ginutil.c.

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

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

Referenced by ginExtractEntries().

◆ ginCompareAttEntries()

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

Definition at line 410 of file ginutil.c.

413 {
414  /* attribute number is the first sort key */
415  if (attnuma != attnumb)
416  return (attnuma < attnumb) ? -1 : 1;
417 
418  return ginCompareEntries(ginstate, attnuma, a, categorya, b, categoryb);
419 }
int ginCompareEntries(GinState *ginstate, OffsetNumber attnum, Datum a, GinNullCategory categorya, Datum b, GinNullCategory categoryb)
Definition: ginutil.c:388

References a, b, and ginCompareEntries().

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

◆ ginCompareEntries()

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

Definition at line 388 of file ginutil.c.

391 {
392  /* if not of same null category, sort by that first */
393  if (categorya != categoryb)
394  return (categorya < categoryb) ? -1 : 1;
395 
396  /* all null items in same category are equal */
397  if (categorya != GIN_CAT_NORM_KEY)
398  return 0;
399 
400  /* both not null, so safe to call the compareFn */
401  return DatumGetInt32(FunctionCall2Coll(&ginstate->compareFn[attnum - 1],
402  ginstate->supportCollation[attnum - 1],
403  a, b));
404 }
#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:88
FmgrInfo compareFn[INDEX_MAX_KEYS]
Definition: gin_private.h:79

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 483 of file ginutil.c.

486 {
487  Datum *entries;
488  bool *nullFlags;
489  int32 i;
490 
491  /*
492  * We don't call the extractValueFn on a null item. Instead generate a
493  * placeholder.
494  */
495  if (isNull)
496  {
497  *nentries = 1;
498  entries = (Datum *) palloc(sizeof(Datum));
499  entries[0] = (Datum) 0;
500  *categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
501  (*categories)[0] = GIN_CAT_NULL_ITEM;
502  return entries;
503  }
504 
505  /* OK, call the opclass's extractValueFn */
506  nullFlags = NULL; /* in case extractValue doesn't set it */
507  entries = (Datum *)
509  ginstate->supportCollation[attnum - 1],
510  value,
511  PointerGetDatum(nentries),
512  PointerGetDatum(&nullFlags)));
513 
514  /*
515  * Generate a placeholder if the item contained no keys.
516  */
517  if (entries == NULL || *nentries <= 0)
518  {
519  *nentries = 1;
520  entries = (Datum *) palloc(sizeof(Datum));
521  entries[0] = (Datum) 0;
522  *categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
523  (*categories)[0] = GIN_CAT_EMPTY_ITEM;
524  return entries;
525  }
526 
527  /*
528  * If the extractValueFn didn't create a nullFlags array, create one,
529  * assuming that everything's non-null.
530  */
531  if (nullFlags == NULL)
532  nullFlags = (bool *) palloc0(*nentries * sizeof(bool));
533 
534  /*
535  * If there's more than one key, sort and unique-ify.
536  *
537  * XXX Using qsort here is notationally painful, and the overhead is
538  * pretty bad too. For small numbers of keys it'd likely be better to use
539  * a simple insertion sort.
540  */
541  if (*nentries > 1)
542  {
543  keyEntryData *keydata;
545 
546  keydata = (keyEntryData *) palloc(*nentries * sizeof(keyEntryData));
547  for (i = 0; i < *nentries; i++)
548  {
549  keydata[i].datum = entries[i];
550  keydata[i].isnull = nullFlags[i];
551  }
552 
553  arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
554  arg.collation = ginstate->supportCollation[attnum - 1];
555  arg.haveDups = false;
556  qsort_arg(keydata, *nentries, sizeof(keyEntryData),
557  cmpEntries, &arg);
558 
559  if (arg.haveDups)
560  {
561  /* there are duplicates, must get rid of 'em */
562  int32 j;
563 
564  entries[0] = keydata[0].datum;
565  nullFlags[0] = keydata[0].isnull;
566  j = 1;
567  for (i = 1; i < *nentries; i++)
568  {
569  if (cmpEntries(&keydata[i - 1], &keydata[i], &arg) != 0)
570  {
571  entries[j] = keydata[i].datum;
572  nullFlags[j] = keydata[i].isnull;
573  j++;
574  }
575  }
576  *nentries = j;
577  }
578  else
579  {
580  /* easy, no duplicates */
581  for (i = 0; i < *nentries; i++)
582  {
583  entries[i] = keydata[i].datum;
584  nullFlags[i] = keydata[i].isnull;
585  }
586  }
587 
588  pfree(keydata);
589  }
590 
591  /*
592  * Create GinNullCategory representation from nullFlags.
593  */
594  *categories = (GinNullCategory *) palloc0(*nentries * sizeof(GinNullCategory));
595  for (i = 0; i < *nentries; i++)
596  (*categories)[i] = (nullFlags[i] ? GIN_CAT_NULL_KEY : GIN_CAT_NORM_KEY);
597 
598  return entries;
599 }
signed int int32
Definition: c.h:481
Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition: fmgr.c:1171
#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:443
static struct @150 value
int j
Definition: isn.c:74
int i
Definition: isn.c:73
void pfree(void *pointer)
Definition: mcxt.c:1508
void * palloc0(Size size)
Definition: mcxt.c:1334
void * palloc(Size size)
Definition: mcxt.c:1304
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:322
uintptr_t Datum
Definition: postgres.h:64
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
FmgrInfo extractValueFn[INDEX_MAX_KEYS]
Definition: gin_private.h:80

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, palloc(), palloc0(), pfree(), PointerGetDatum(), qsort_arg(), GinState::supportCollation, and value.

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

◆ ginGetStats()

void ginGetStats ( Relation  index,
GinStatsData stats 
)

Definition at line 623 of file ginutil.c.

624 {
625  Buffer metabuffer;
626  Page metapage;
627  GinMetaPageData *metadata;
628 
629  metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO);
630  LockBuffer(metabuffer, GIN_SHARE);
631  metapage = BufferGetPage(metabuffer);
632  metadata = GinPageGetMeta(metapage);
633 
634  stats->nPendingPages = metadata->nPendingPages;
635  stats->nTotalPages = metadata->nTotalPages;
636  stats->nEntryPages = metadata->nEntryPages;
637  stats->nDataPages = metadata->nDataPages;
638  stats->nEntries = metadata->nEntries;
639  stats->ginVersion = metadata->ginVersion;
640 
641  UnlockReleaseBuffer(metabuffer);
642 }
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4577
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4795
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:734
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:350
Pointer Page
Definition: bufpage.h:78
#define GIN_SHARE
Definition: gin_private.h:50
#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:47
BlockNumber nPendingPages
Definition: gin.h:44
BlockNumber nEntryPages
Definition: gin.h:46
int64 nEntries
Definition: gin.h:48
BlockNumber nTotalPages
Definition: gin.h:45
int32 ginVersion
Definition: gin.h:49
Definition: type.h:95

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 37 of file ginutil.c.

38 {
40 
41  amroutine->amstrategies = 0;
42  amroutine->amsupport = GINNProcs;
43  amroutine->amoptsprocnum = GIN_OPTIONS_PROC;
44  amroutine->amcanorder = false;
45  amroutine->amcanorderbyop = false;
46  amroutine->amcanbackward = false;
47  amroutine->amcanunique = false;
48  amroutine->amcanmulticol = true;
49  amroutine->amoptionalkey = true;
50  amroutine->amsearcharray = false;
51  amroutine->amsearchnulls = false;
52  amroutine->amstorage = true;
53  amroutine->amclusterable = false;
54  amroutine->ampredlocks = true;
55  amroutine->amcanparallel = false;
56  amroutine->amcanbuildparallel = false;
57  amroutine->amcaninclude = false;
58  amroutine->amusemaintenanceworkmem = true;
59  amroutine->amsummarizing = false;
60  amroutine->amparallelvacuumoptions =
62  amroutine->amkeytype = InvalidOid;
63 
64  amroutine->ambuild = ginbuild;
65  amroutine->ambuildempty = ginbuildempty;
66  amroutine->aminsert = gininsert;
67  amroutine->aminsertcleanup = NULL;
68  amroutine->ambulkdelete = ginbulkdelete;
69  amroutine->amvacuumcleanup = ginvacuumcleanup;
70  amroutine->amcanreturn = NULL;
71  amroutine->amcostestimate = gincostestimate;
72  amroutine->amoptions = ginoptions;
73  amroutine->amproperty = NULL;
74  amroutine->ambuildphasename = NULL;
75  amroutine->amvalidate = ginvalidate;
76  amroutine->amadjustmembers = ginadjustmembers;
77  amroutine->ambeginscan = ginbeginscan;
78  amroutine->amrescan = ginrescan;
79  amroutine->amgettuple = NULL;
80  amroutine->amgetbitmap = gingetbitmap;
81  amroutine->amendscan = ginendscan;
82  amroutine->ammarkpos = NULL;
83  amroutine->amrestrpos = NULL;
84  amroutine->amestimateparallelscan = NULL;
85  amroutine->aminitparallelscan = NULL;
86  amroutine->amparallelrescan = NULL;
87 
88  PG_RETURN_POINTER(amroutine);
89 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define GINNProcs
Definition: gin.h:29
#define GIN_OPTIONS_PROC
Definition: gin.h:28
int64 gingetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
Definition: ginget.c:1914
IndexBuildResult * ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
Definition: gininsert.c:317
void ginbuildempty(Relation index)
Definition: gininsert.c:434
bool gininsert(Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
Definition: gininsert.c:483
IndexScanDesc ginbeginscan(Relation rel, int nkeys, int norderbys)
Definition: ginscan.c:25
void ginendscan(IndexScanDesc scan)
Definition: ginscan.c:458
void ginrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
Definition: ginscan.c:442
bytea * ginoptions(Datum reloptions, bool validate)
Definition: ginutil.c:602
IndexBulkDeleteResult * ginbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
Definition: ginvacuum.c:565
IndexBulkDeleteResult * ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
Definition: ginvacuum.c:688
bool ginvalidate(Oid opclassoid)
Definition: ginvalidate.c:31
void ginadjustmembers(Oid opfamilyoid, Oid opclassoid, List *operators, List *functions)
Definition: ginvalidate.c:277
#define makeNode(_type_)
Definition: nodes.h:155
#define InvalidOid
Definition: postgres_ext.h:36
void gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
Definition: selfuncs.c:7538
ambuildphasename_function ambuildphasename
Definition: amapi.h:276
ambuildempty_function ambuildempty
Definition: amapi.h:267
amvacuumcleanup_function amvacuumcleanup
Definition: amapi.h:271
bool amclusterable
Definition: amapi.h:241
amoptions_function amoptions
Definition: amapi.h:274
amestimateparallelscan_function amestimateparallelscan
Definition: amapi.h:288
amrestrpos_function amrestrpos
Definition: amapi.h:285
aminsert_function aminsert
Definition: amapi.h:268
amendscan_function amendscan
Definition: amapi.h:283
uint16 amoptsprocnum
Definition: amapi.h:221
amparallelrescan_function amparallelrescan
Definition: amapi.h:290
Oid amkeytype
Definition: amapi.h:257
bool ampredlocks
Definition: amapi.h:243
uint16 amsupport
Definition: amapi.h:219
amcostestimate_function amcostestimate
Definition: amapi.h:273
bool amcanorderbyop
Definition: amapi.h:225
amadjustmembers_function amadjustmembers
Definition: amapi.h:278
ambuild_function ambuild
Definition: amapi.h:266
bool amstorage
Definition: amapi.h:239
uint16 amstrategies
Definition: amapi.h:217
bool amoptionalkey
Definition: amapi.h:233
amgettuple_function amgettuple
Definition: amapi.h:281
amcanreturn_function amcanreturn
Definition: amapi.h:272
bool amcanunique
Definition: amapi.h:229
amgetbitmap_function amgetbitmap
Definition: amapi.h:282
amproperty_function amproperty
Definition: amapi.h:275
ambulkdelete_function ambulkdelete
Definition: amapi.h:270
bool amsearcharray
Definition: amapi.h:235
bool amsummarizing
Definition: amapi.h:253
amvalidate_function amvalidate
Definition: amapi.h:277
ammarkpos_function ammarkpos
Definition: amapi.h:284
bool amcanmulticol
Definition: amapi.h:231
bool amusemaintenanceworkmem
Definition: amapi.h:251
ambeginscan_function ambeginscan
Definition: amapi.h:279
bool amcanparallel
Definition: amapi.h:245
amrescan_function amrescan
Definition: amapi.h:280
bool amcanorder
Definition: amapi.h:223
bool amcanbuildparallel
Definition: amapi.h:247
aminitparallelscan_function aminitparallelscan
Definition: amapi.h:289
uint8 amparallelvacuumoptions
Definition: amapi.h:255
aminsertcleanup_function aminsertcleanup
Definition: amapi.h:269
bool amcanbackward
Definition: amapi.h:227
bool amcaninclude
Definition: amapi.h:249
bool amsearchnulls
Definition: amapi.h:237
#define VACUUM_OPTION_PARALLEL_CLEANUP
Definition: vacuum.h:62
#define VACUUM_OPTION_PARALLEL_BULKDEL
Definition: vacuum.h:47

References IndexAmRoutine::amadjustmembers, IndexAmRoutine::ambeginscan, IndexAmRoutine::ambuild, IndexAmRoutine::ambuildempty, IndexAmRoutine::ambuildphasename, IndexAmRoutine::ambulkdelete, IndexAmRoutine::amcanbackward, IndexAmRoutine::amcanbuildparallel, IndexAmRoutine::amcaninclude, IndexAmRoutine::amcanmulticol, IndexAmRoutine::amcanorder, IndexAmRoutine::amcanorderbyop, IndexAmRoutine::amcanparallel, IndexAmRoutine::amcanreturn, IndexAmRoutine::amcanunique, IndexAmRoutine::amclusterable, IndexAmRoutine::amcostestimate, IndexAmRoutine::amendscan, IndexAmRoutine::amestimateparallelscan, IndexAmRoutine::amgetbitmap, IndexAmRoutine::amgettuple, IndexAmRoutine::aminitparallelscan, IndexAmRoutine::aminsert, IndexAmRoutine::aminsertcleanup, IndexAmRoutine::amkeytype, IndexAmRoutine::ammarkpos, IndexAmRoutine::amoptionalkey, IndexAmRoutine::amoptions, IndexAmRoutine::amoptsprocnum, IndexAmRoutine::amparallelrescan, IndexAmRoutine::amparallelvacuumoptions, IndexAmRoutine::ampredlocks, IndexAmRoutine::amproperty, IndexAmRoutine::amrescan, IndexAmRoutine::amrestrpos, IndexAmRoutine::amsearcharray, IndexAmRoutine::amsearchnulls, IndexAmRoutine::amstorage, IndexAmRoutine::amstrategies, IndexAmRoutine::amsummarizing, IndexAmRoutine::amsupport, IndexAmRoutine::amusemaintenanceworkmem, IndexAmRoutine::amvacuumcleanup, IndexAmRoutine::amvalidate, GIN_OPTIONS_PROC, ginadjustmembers(), ginbeginscan(), ginbuild(), ginbuildempty(), ginbulkdelete(), gincostestimate(), ginendscan(), gingetbitmap(), gininsert(), GINNProcs, ginoptions(), ginrescan(), ginvacuumcleanup(), ginvalidate(), InvalidOid, makeNode, PG_RETURN_POINTER, VACUUM_OPTION_PARALLEL_BULKDEL, and VACUUM_OPTION_PARALLEL_CLEANUP.

◆ GinInitBuffer()

void GinInitBuffer ( Buffer  b,
uint32  f 
)

Definition at line 350 of file ginutil.c.

351 {
353 }
static Size BufferGetPageSize(Buffer buffer)
Definition: bufmgr.h:339
void GinInitPage(Page page, uint32 f, Size pageSize)
Definition: ginutil.c:338

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

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

◆ GinInitMetabuffer()

void GinInitMetabuffer ( Buffer  b)

Definition at line 356 of file ginutil.c.

357 {
358  GinMetaPageData *metadata;
359  Page page = BufferGetPage(b);
360 
362 
363  metadata = GinPageGetMeta(page);
364 
365  metadata->head = metadata->tail = InvalidBlockNumber;
366  metadata->tailFreeSize = 0;
367  metadata->nPendingPages = 0;
368  metadata->nPendingHeapTuples = 0;
369  metadata->nTotalPages = 0;
370  metadata->nEntryPages = 0;
371  metadata->nDataPages = 0;
372  metadata->nEntries = 0;
373  metadata->ginVersion = GIN_CURRENT_VERSION;
374 
375  /*
376  * Set pd_lower just past the end of the metadata. This is essential,
377  * because without doing so, metadata will be lost if xlog.c compresses
378  * the page.
379  */
380  ((PageHeader) page)->pd_lower =
381  ((char *) metadata + sizeof(GinMetaPageData)) - (char *) page;
382 }
#define InvalidBlockNumber
Definition: block.h:33
PageHeaderData * PageHeader
Definition: bufpage.h:170
#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 338 of file ginutil.c.

339 {
340  GinPageOpaque opaque;
341 
342  PageInit(page, pageSize, sizeof(GinPageOpaqueData));
343 
344  opaque = GinPageGetOpaque(page);
345  opaque->flags = f;
346  opaque->rightlink = InvalidBlockNumber;
347 }
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 300 of file ginutil.c.

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

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 602 of file ginutil.c.

603 {
604  static const relopt_parse_elt tab[] = {
605  {"fastupdate", RELOPT_TYPE_BOOL, offsetof(GinOptions, useFastUpdate)},
606  {"gin_pending_list_limit", RELOPT_TYPE_INT, offsetof(GinOptions,
607  pendingListCleanupSize)}
608  };
609 
610  return (bytea *) build_reloptions(reloptions, validate,
612  sizeof(GinOptions),
613  tab, lengthof(tab));
614 }
#define lengthof(array)
Definition: c.h:775
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:1908
@ RELOPT_KIND_GIN
Definition: reloptions.h:46
@ RELOPT_TYPE_INT
Definition: reloptions.h:32
@ RELOPT_TYPE_BOOL
Definition: reloptions.h:31
Definition: c.h:674

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

Referenced by ginhandler().

◆ gintuple_get_attrnum()

OffsetNumber gintuple_get_attrnum ( GinState ginstate,
IndexTuple  tuple 
)

Definition at line 226 of file ginutil.c.

227 {
228  OffsetNumber colN;
229 
230  if (ginstate->oneCol)
231  {
232  /* column number is not stored explicitly */
233  colN = FirstOffsetNumber;
234  }
235  else
236  {
237  Datum res;
238  bool isnull;
239 
240  /*
241  * First attribute is always int16, so we can safely use any tuple
242  * descriptor to obtain first attribute of tuple
243  */
244  res = index_getattr(tuple, FirstOffsetNumber, ginstate->tupdesc[0],
245  &isnull);
246  Assert(!isnull);
247 
248  colN = DatumGetUInt16(res);
249  Assert(colN >= FirstOffsetNumber && colN <= ginstate->origTupdesc->natts);
250  }
251 
252  return colN;
253 }
static Datum index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: itup.h:117
Assert(fmt[strlen(fmt) - 1] !='\n')
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
static uint16 DatumGetUInt16(Datum X)
Definition: postgres.h:182
bool oneCol
Definition: gin_private.h:60
TupleDesc tupdesc[INDEX_MAX_KEYS]
Definition: gin_private.h:74

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

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

◆ gintuple_get_key()

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

Definition at line 259 of file ginutil.c.

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

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

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

◆ ginUpdateStats()

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

Definition at line 650 of file ginutil.c.

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

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 97 of file ginutil.c.

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

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_clean_pending_list(), ginbeginscan(), ginbuild(), ginbulkdelete(), gininsert(), and ginvacuumcleanup().