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