PostgreSQL Source Code  git master
gininsert.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * gininsert.c
4  * insert routines for the postgres inverted index access method.
5  *
6  *
7  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * IDENTIFICATION
11  * src/backend/access/gin/gininsert.c
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres.h"
16 
17 #include "access/gin_private.h"
18 #include "access/ginxlog.h"
19 #include "access/xloginsert.h"
20 #include "catalog/index.h"
21 #include "miscadmin.h"
22 #include "storage/bufmgr.h"
23 #include "storage/smgr.h"
24 #include "storage/indexfsm.h"
25 #include "storage/predicate.h"
26 #include "utils/memutils.h"
27 #include "utils/rel.h"
28 
29 
30 typedef struct
31 {
33  double indtuples;
39 
40 
41 /*
42  * Adds array of item pointers to tuple's posting list, or
43  * creates posting tree and tuple pointing to tree in case
44  * of not enough space. Max size of tuple is defined in
45  * GinFormTuple(). Returns a new, modified index tuple.
46  * items[] must be in sorted order with no duplicates.
47  */
48 static IndexTuple
50  IndexTuple old,
51  ItemPointerData *items, uint32 nitem,
52  GinStatsData *buildStats, Buffer buffer)
53 {
55  Datum key;
56  GinNullCategory category;
57  IndexTuple res;
58  ItemPointerData *newItems,
59  *oldItems;
60  int oldNPosting,
61  newNPosting;
62  GinPostingList *compressedList;
63 
64  Assert(!GinIsPostingTree(old));
65 
66  attnum = gintuple_get_attrnum(ginstate, old);
67  key = gintuple_get_key(ginstate, old, &category);
68 
69  /* merge the old and new posting lists */
70  oldItems = ginReadTuple(ginstate, attnum, old, &oldNPosting);
71 
72  newItems = ginMergeItemPointers(items, nitem,
73  oldItems, oldNPosting,
74  &newNPosting);
75 
76  /* Compress the posting list, and try to a build tuple with room for it */
77  res = NULL;
78  compressedList = ginCompressPostingList(newItems, newNPosting, GinMaxItemSize,
79  NULL);
80  pfree(newItems);
81  if (compressedList)
82  {
83  res = GinFormTuple(ginstate, attnum, key, category,
84  (char *) compressedList,
85  SizeOfGinPostingList(compressedList),
86  newNPosting,
87  false);
88  pfree(compressedList);
89  }
90  if (!res)
91  {
92  /* posting list would be too big, convert to posting tree */
93  BlockNumber postingRoot;
94 
95  /*
96  * Initialize posting tree with the old tuple's posting list. It's
97  * surely small enough to fit on one posting-tree page, and should
98  * already be in order with no duplicates.
99  */
100  postingRoot = createPostingTree(ginstate->index,
101  oldItems,
102  oldNPosting,
103  buildStats,
104  buffer);
105 
106  /* Now insert the TIDs-to-be-added into the posting tree */
107  ginInsertItemPointers(ginstate->index, postingRoot,
108  items, nitem,
109  buildStats);
110 
111  /* And build a new posting-tree-only result tuple */
112  res = GinFormTuple(ginstate, attnum, key, category, NULL, 0, 0, true);
113  GinSetPostingTree(res, postingRoot);
114  }
115  pfree(oldItems);
116 
117  return res;
118 }
119 
120 /*
121  * Build a fresh leaf tuple, either posting-list or posting-tree format
122  * depending on whether the given items list will fit.
123  * items[] must be in sorted order with no duplicates.
124  *
125  * This is basically the same logic as in addItemPointersToLeafTuple,
126  * but working from slightly different input.
127  */
128 static IndexTuple
130  OffsetNumber attnum, Datum key, GinNullCategory category,
131  ItemPointerData *items, uint32 nitem,
132  GinStatsData *buildStats, Buffer buffer)
133 {
134  IndexTuple res = NULL;
135  GinPostingList *compressedList;
136 
137  /* try to build a posting list tuple with all the items */
138  compressedList = ginCompressPostingList(items, nitem, GinMaxItemSize, NULL);
139  if (compressedList)
140  {
141  res = GinFormTuple(ginstate, attnum, key, category,
142  (char *) compressedList,
143  SizeOfGinPostingList(compressedList),
144  nitem, false);
145  pfree(compressedList);
146  }
147  if (!res)
148  {
149  /* posting list would be too big, build posting tree */
150  BlockNumber postingRoot;
151 
152  /*
153  * Build posting-tree-only result tuple. We do this first so as to
154  * fail quickly if the key is too big.
155  */
156  res = GinFormTuple(ginstate, attnum, key, category, NULL, 0, 0, true);
157 
158  /*
159  * Initialize a new posting tree with the TIDs.
160  */
161  postingRoot = createPostingTree(ginstate->index, items, nitem,
162  buildStats, buffer);
163 
164  /* And save the root link in the result tuple */
165  GinSetPostingTree(res, postingRoot);
166  }
167 
168  return res;
169 }
170 
171 /*
172  * Insert one or more heap TIDs associated with the given key value.
173  * This will either add a single key entry, or enlarge a pre-existing entry.
174  *
175  * During an index build, buildStats is non-null and the counters
176  * it contains should be incremented as needed.
177  */
178 void
180  OffsetNumber attnum, Datum key, GinNullCategory category,
181  ItemPointerData *items, uint32 nitem,
182  GinStatsData *buildStats)
183 {
184  GinBtreeData btree;
185  GinBtreeEntryInsertData insertdata;
186  GinBtreeStack *stack;
187  IndexTuple itup;
188  Page page;
189 
190  insertdata.isDelete = false;
191 
192  /* During index build, count the to-be-inserted entry */
193  if (buildStats)
194  buildStats->nEntries++;
195 
196  ginPrepareEntryScan(&btree, attnum, key, category, ginstate);
197 
198  stack = ginFindLeafPage(&btree, false, NULL);
199  page = BufferGetPage(stack->buffer);
200 
201  if (btree.findItem(&btree, stack))
202  {
203  /* found pre-existing entry */
204  itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, stack->off));
205 
206  if (GinIsPostingTree(itup))
207  {
208  /* add entries to existing posting tree */
209  BlockNumber rootPostingTree = GinGetPostingTree(itup);
210 
211  /* release all stack */
212  LockBuffer(stack->buffer, GIN_UNLOCK);
213  freeGinBtreeStack(stack);
214 
215  /* insert into posting tree */
216  ginInsertItemPointers(ginstate->index, rootPostingTree,
217  items, nitem,
218  buildStats);
219  return;
220  }
221 
222  GinCheckForSerializableConflictIn(btree.index, NULL, stack->buffer);
223  /* modify an existing leaf entry */
224  itup = addItemPointersToLeafTuple(ginstate, itup,
225  items, nitem, buildStats, stack->buffer);
226 
227  insertdata.isDelete = true;
228  }
229  else
230  {
231  GinCheckForSerializableConflictIn(btree.index, NULL, stack->buffer);
232  /* no match, so construct a new leaf entry */
233  itup = buildFreshLeafTuple(ginstate, attnum, key, category,
234  items, nitem, buildStats, stack->buffer);
235  }
236 
237  /* Insert the new or modified leaf tuple */
238  insertdata.entry = itup;
239  ginInsertValue(&btree, stack, &insertdata, buildStats);
240  pfree(itup);
241 }
242 
243 /*
244  * Extract index entries for a single indexable item, and add them to the
245  * BuildAccumulator's state.
246  *
247  * This function is used only during initial index creation.
248  */
249 static void
251  Datum value, bool isNull,
252  ItemPointer heapptr)
253 {
254  Datum *entries;
255  GinNullCategory *categories;
256  int32 nentries;
257  MemoryContext oldCtx;
258 
259  oldCtx = MemoryContextSwitchTo(buildstate->funcCtx);
260  entries = ginExtractEntries(buildstate->accum.ginstate, attnum,
261  value, isNull,
262  &nentries, &categories);
263  MemoryContextSwitchTo(oldCtx);
264 
265  ginInsertBAEntries(&buildstate->accum, heapptr, attnum,
266  entries, categories, nentries);
267 
268  buildstate->indtuples += nentries;
269 
270  MemoryContextReset(buildstate->funcCtx);
271 }
272 
273 static void
275  bool *isnull, bool tupleIsAlive, void *state)
276 {
277  GinBuildState *buildstate = (GinBuildState *) state;
278  MemoryContext oldCtx;
279  int i;
280 
281  oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
282 
283  for (i = 0; i < buildstate->ginstate.origTupdesc->natts; i++)
284  ginHeapTupleBulkInsert(buildstate, (OffsetNumber) (i + 1),
285  values[i], isnull[i],
286  &htup->t_self);
287 
288  /* If we've maxed out our available memory, dump everything to the index */
289  if (buildstate->accum.allocatedMemory >= (Size) maintenance_work_mem * 1024L)
290  {
292  Datum key;
293  GinNullCategory category;
294  uint32 nlist;
296 
297  ginBeginBAScan(&buildstate->accum);
298  while ((list = ginGetBAEntry(&buildstate->accum,
299  &attnum, &key, &category, &nlist)) != NULL)
300  {
301  /* there could be many entries, so be willing to abort here */
303  ginEntryInsert(&buildstate->ginstate, attnum, key, category,
304  list, nlist, &buildstate->buildStats);
305  }
306 
307  MemoryContextReset(buildstate->tmpCtx);
308  ginInitBA(&buildstate->accum);
309  }
310 
311  MemoryContextSwitchTo(oldCtx);
312 }
313 
316 {
317  IndexBuildResult *result;
318  double reltuples;
319  GinBuildState buildstate;
320  Buffer RootBuffer,
321  MetaBuffer;
323  Datum key;
324  GinNullCategory category;
325  uint32 nlist;
326  MemoryContext oldCtx;
328 
329  if (RelationGetNumberOfBlocks(index) != 0)
330  elog(ERROR, "index \"%s\" already contains data",
331  RelationGetRelationName(index));
332 
333  initGinState(&buildstate.ginstate, index);
334  buildstate.indtuples = 0;
335  memset(&buildstate.buildStats, 0, sizeof(GinStatsData));
336 
337  /* initialize the meta page */
338  MetaBuffer = GinNewBuffer(index);
339 
340  /* initialize the root page */
341  RootBuffer = GinNewBuffer(index);
342 
344  GinInitMetabuffer(MetaBuffer);
345  MarkBufferDirty(MetaBuffer);
346  GinInitBuffer(RootBuffer, GIN_LEAF);
347  MarkBufferDirty(RootBuffer);
348 
349  if (RelationNeedsWAL(index))
350  {
351  XLogRecPtr recptr;
352  Page page;
353 
354  XLogBeginInsert();
356  XLogRegisterBuffer(1, RootBuffer, REGBUF_WILL_INIT);
357 
358  recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_CREATE_INDEX);
359 
360  page = BufferGetPage(RootBuffer);
361  PageSetLSN(page, recptr);
362 
363  page = BufferGetPage(MetaBuffer);
364  PageSetLSN(page, recptr);
365  }
366 
367  UnlockReleaseBuffer(MetaBuffer);
368  UnlockReleaseBuffer(RootBuffer);
370 
371  /* count the root as first entry page */
372  buildstate.buildStats.nEntryPages++;
373 
374  /*
375  * create a temporary memory context that is used to hold data not yet
376  * dumped out to the index
377  */
379  "Gin build temporary context",
381 
382  /*
383  * create a temporary memory context that is used for calling
384  * ginExtractEntries(), and can be reset after each tuple
385  */
387  "Gin build temporary context for user-defined function",
389 
390  buildstate.accum.ginstate = &buildstate.ginstate;
391  ginInitBA(&buildstate.accum);
392 
393  /*
394  * Do the heap scan. We disallow sync scan here because dataPlaceToPage
395  * prefers to receive tuples in TID order.
396  */
397  reltuples = IndexBuildHeapScan(heap, index, indexInfo, false,
398  ginBuildCallback, (void *) &buildstate, NULL);
399 
400  /* dump remaining entries to the index */
401  oldCtx = MemoryContextSwitchTo(buildstate.tmpCtx);
402  ginBeginBAScan(&buildstate.accum);
403  while ((list = ginGetBAEntry(&buildstate.accum,
404  &attnum, &key, &category, &nlist)) != NULL)
405  {
406  /* there could be many entries, so be willing to abort here */
408  ginEntryInsert(&buildstate.ginstate, attnum, key, category,
409  list, nlist, &buildstate.buildStats);
410  }
411  MemoryContextSwitchTo(oldCtx);
412 
413  MemoryContextDelete(buildstate.funcCtx);
414  MemoryContextDelete(buildstate.tmpCtx);
415 
416  /*
417  * Update metapage stats
418  */
419  buildstate.buildStats.nTotalPages = RelationGetNumberOfBlocks(index);
420  ginUpdateStats(index, &buildstate.buildStats);
421 
422  /*
423  * Return statistics
424  */
425  result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
426 
427  result->heap_tuples = reltuples;
428  result->index_tuples = buildstate.indtuples;
429 
430  return result;
431 }
432 
433 /*
434  * ginbuildempty() -- build an empty gin index in the initialization fork
435  */
436 void
438 {
439  Buffer RootBuffer,
440  MetaBuffer;
441 
442  /* An empty GIN index has two pages. */
443  MetaBuffer =
445  LockBuffer(MetaBuffer, BUFFER_LOCK_EXCLUSIVE);
446  RootBuffer =
448  LockBuffer(RootBuffer, BUFFER_LOCK_EXCLUSIVE);
449 
450  /* Initialize and xlog metabuffer and root buffer. */
452  GinInitMetabuffer(MetaBuffer);
453  MarkBufferDirty(MetaBuffer);
454  log_newpage_buffer(MetaBuffer, true);
455  GinInitBuffer(RootBuffer, GIN_LEAF);
456  MarkBufferDirty(RootBuffer);
457  log_newpage_buffer(RootBuffer, false);
459 
460  /* Unlock and release the buffers. */
461  UnlockReleaseBuffer(MetaBuffer);
462  UnlockReleaseBuffer(RootBuffer);
463 }
464 
465 /*
466  * Insert index entries for a single indexable item during "normal"
467  * (non-fast-update) insertion
468  */
469 static void
471  Datum value, bool isNull,
472  ItemPointer item)
473 {
474  Datum *entries;
475  GinNullCategory *categories;
476  int32 i,
477  nentries;
478 
479  entries = ginExtractEntries(ginstate, attnum, value, isNull,
480  &nentries, &categories);
481 
482  for (i = 0; i < nentries; i++)
483  ginEntryInsert(ginstate, attnum, entries[i], categories[i],
484  item, 1, NULL);
485 }
486 
487 bool
489  ItemPointer ht_ctid, Relation heapRel,
490  IndexUniqueCheck checkUnique,
491  IndexInfo *indexInfo)
492 {
493  GinState *ginstate = (GinState *) indexInfo->ii_AmCache;
494  MemoryContext oldCtx;
495  MemoryContext insertCtx;
496  int i;
497 
498  /* Initialize GinState cache if first call in this statement */
499  if (ginstate == NULL)
500  {
501  oldCtx = MemoryContextSwitchTo(indexInfo->ii_Context);
502  ginstate = (GinState *) palloc(sizeof(GinState));
503  initGinState(ginstate, index);
504  indexInfo->ii_AmCache = (void *) ginstate;
505  MemoryContextSwitchTo(oldCtx);
506  }
507 
509  "Gin insert temporary context",
511 
512  oldCtx = MemoryContextSwitchTo(insertCtx);
513 
514  if (GinGetUseFastUpdate(index))
515  {
516  GinTupleCollector collector;
517 
518  memset(&collector, 0, sizeof(GinTupleCollector));
519 
520  /*
521  * With fastupdate on each scan and each insert begin with access to
522  * pending list, so it effectively lock entire index. In this case
523  * we aquire predicate lock and check for conflicts over index relation,
524  * and hope that it will reduce locking overhead.
525  *
526  * Do not use GinCheckForSerializableConflictIn() here, because
527  * it will do nothing (it does actual work only with fastupdate off).
528  * Check for conflicts for entire index.
529  */
531 
532  for (i = 0; i < ginstate->origTupdesc->natts; i++)
533  ginHeapTupleFastCollect(ginstate, &collector,
534  (OffsetNumber) (i + 1),
535  values[i], isnull[i],
536  ht_ctid);
537 
538  ginHeapTupleFastInsert(ginstate, &collector);
539  }
540  else
541  {
542  GinStatsData stats;
543 
544  /*
545  * Fastupdate is off but if pending list isn't empty then we need to
546  * check conflicts with PredicateLockRelation in scanPendingInsert().
547  */
548  ginGetStats(index, &stats);
549  if (stats.nPendingPages > 0)
551 
552  for (i = 0; i < ginstate->origTupdesc->natts; i++)
553  ginHeapTupleInsert(ginstate, (OffsetNumber) (i + 1),
554  values[i], isnull[i],
555  ht_ctid);
556  }
557 
558  MemoryContextSwitchTo(oldCtx);
559  MemoryContextDelete(insertCtx);
560 
561  return false;
562 }
#define GIN_UNLOCK
Definition: gin_private.h:43
BlockNumber nEntryPages
Definition: gin.h:45
GinPostingList * ginCompressPostingList(const ItemPointer ipd, int nipd, int maxsize, int *nwritten)
Buffer GinNewBuffer(Relation index)
Definition: ginutil.c:291
MemoryContext ii_Context
Definition: execnodes.h:171
void GinCheckForSerializableConflictIn(Relation relation, HeapTuple tuple, Buffer buffer)
Definition: ginutil.c:723
void GinInitMetabuffer(Buffer b)
Definition: ginutil.c:361
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
void ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
Definition: ginfast.c:222
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)
Definition: xloginsert.c:1009
void ginInsertItemPointers(Relation index, BlockNumber rootBlkno, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
Definition: gindatapage.c:1894
Relation index
Definition: gin_private.h:53
OffsetNumber off
Definition: gin_private.h:128
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
BlockNumber createPostingTree(Relation index, ItemPointerData *items, uint32 nitems, GinStatsData *buildStats, Buffer entrybuffer)
Definition: gindatapage.c:1762
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:640
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
GinStatsData buildStats
Definition: gininsert.c:34
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define InvalidBuffer
Definition: buf.h:25
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int64 nEntries
Definition: gin.h:47
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
uint32 BlockNumber
Definition: block.h:31
#define P_NEW
Definition: bufmgr.h:82
void ginbuildempty(Relation index)
Definition: gininsert.c:437
double indtuples
Definition: gininsert.c:33
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
ItemPointer ginMergeItemPointers(ItemPointerData *a, uint32 na, ItemPointerData *b, uint32 nb, int *nmerged)
static void ginBuildCallback(Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: gininsert.c:274
static void ginHeapTupleInsert(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, ItemPointer item)
Definition: gininsert.c:470
void CheckForSerializableConflictIn(Relation relation, HeapTuple tuple, Buffer buffer)
Definition: predicate.c:4280
int natts
Definition: tupdesc.h:82
static IndexTuple addItemPointersToLeafTuple(GinState *ginstate, IndexTuple old, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats, Buffer buffer)
Definition: gininsert.c:49
bool(* findItem)(GinBtree, GinBtreeStack *)
Definition: gin_private.h:151
signed int int32
Definition: c.h:313
uint16 OffsetNumber
Definition: off.h:24
GinState ginstate
Definition: gininsert.c:32
Definition: type.h:89
GinBtreeStack * ginFindLeafPage(GinBtree btree, bool searchMode, Snapshot snapshot)
Definition: ginbtree.c:77
IndexUniqueCheck
Definition: genam.h:111
#define GinSetPostingTree(itup, blkno)
Definition: ginblock.h:226
void pfree(void *pointer)
Definition: mcxt.c:1031
void ginEntryInsert(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
Definition: gininsert.c:179
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
IndexBuildResult * ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
Definition: gininsert.c:315
signed char GinNullCategory
Definition: ginblock.h:200
double IndexBuildHeapScan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, IndexBuildCallback callback, void *callback_state, HeapScanDesc scan)
Definition: index.c:2418
ItemPointerData t_self
Definition: htup.h:65
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void ginUpdateStats(Relation index, const GinStatsData *stats)
Definition: ginutil.c:669
bool gininsert(Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, IndexInfo *indexInfo)
Definition: gininsert.c:488
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Definition: ginutil.c:217
BuildAccumulator accum
Definition: gininsert.c:37
static void ginHeapTupleBulkInsert(GinBuildState *buildstate, OffsetNumber attnum, Datum value, bool isNull, ItemPointer heapptr)
Definition: gininsert.c:250
IndexTupleData * IndexTuple
Definition: itup.h:53
#define REGBUF_STANDARD
Definition: xloginsert.h:34
void initGinState(GinState *state, Relation index)
Definition: ginutil.c:88
static IndexTuple buildFreshLeafTuple(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats, Buffer buffer)
Definition: gininsert.c:129
#define RelationGetRelationName(relation)
Definition: rel.h:441
unsigned int uint32
Definition: c.h:325
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
GinState * ginstate
Definition: gin_private.h:409
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
Definition: ginutil.c:250
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
void ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum, Datum key, GinNullCategory category, GinState *ginstate)
Definition: ginentrypage.c:745
void * ii_AmCache
Definition: execnodes.h:170
#define XLOG_GIN_CREATE_INDEX
Definition: ginxlog.h:19
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
BlockNumber nPendingPages
Definition: gin.h:43
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
uintptr_t Datum
Definition: postgres.h:365
void ginGetStats(Relation index, GinStatsData *stats)
Definition: ginutil.c:642
void ginInsertBAEntries(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum *entries, GinNullCategory *categories, int32 nentries)
Definition: ginbulk.c:210
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
void ginInsertValue(GinBtree btree, GinBtreeStack *stack, void *insertdata, GinStatsData *buildStats)
Definition: ginbtree.c:777
Relation index
Definition: gin_private.h:162
static struct @131 value
int16 attnum
Definition: pg_attribute.h:79
int maintenance_work_mem
Definition: globals.c:123
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
Definition: regguts.h:298
IndexTuple GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, Pointer data, Size dataSize, int nipd, bool errorTooBig)
Definition: ginentrypage.c:45
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
size_t Size
Definition: c.h:433
void GinInitBuffer(Buffer b, uint32 f)
Definition: ginutil.c:355
ItemPointerData * ginGetBAEntry(BuildAccumulator *accum, OffsetNumber *attnum, Datum *key, GinNullCategory *category, uint32 *n)
Definition: ginbulk.c:268
ItemPointer ginReadTuple(GinState *ginstate, OffsetNumber attnum, IndexTuple itup, int *nitems)
Definition: ginentrypage.c:163
#define GinGetUseFastUpdate(relation)
Definition: gin_private.h:32
#define RelationNeedsWAL(relation)
Definition: rel.h:510
#define GinGetPostingTree(itup)
Definition: ginblock.h:227
void ginBeginBAScan(BuildAccumulator *accum)
Definition: ginbulk.c:257
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define GinIsPostingTree(itup)
Definition: ginblock.h:225
void * palloc(Size size)
Definition: mcxt.c:924
#define SizeOfGinPostingList(plist)
Definition: ginblock.h:336
void freeGinBtreeStack(GinBtreeStack *stack)
Definition: ginbtree.c:194
MemoryContext tmpCtx
Definition: gininsert.c:35
#define GinMaxItemSize
Definition: ginblock.h:242
int i
void ginHeapTupleFastCollect(GinState *ginstate, GinTupleCollector *collector, OffsetNumber attnum, Datum value, bool isNull, ItemPointer ht_ctid)
Definition: ginfast.c:470
TupleDesc origTupdesc
Definition: gin_private.h:67
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define elog
Definition: elog.h:219
MemoryContext funcCtx
Definition: gininsert.c:36
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
Datum * ginExtractEntries(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries, GinNullCategory **categories)
Definition: ginutil.c:488
float4 reltuples
Definition: pg_class.h:44
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
double index_tuples
Definition: genam.h:33
double heap_tuples
Definition: genam.h:32
void ginInitBA(BuildAccumulator *accum)
Definition: ginbulk.c:109
#define GIN_LEAF
Definition: ginblock.h:40