PostgreSQL Source Code  git master
gininsert.c File Reference
#include "postgres.h"
#include "access/gin_private.h"
#include "access/ginxlog.h"
#include "access/tableam.h"
#include "access/xloginsert.h"
#include "catalog/index.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/indexfsm.h"
#include "storage/predicate.h"
#include "storage/smgr.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for gininsert.c:

Go to the source code of this file.

Data Structures

struct  GinBuildState
 

Functions

static IndexTuple addItemPointersToLeafTuple (GinState *ginstate, IndexTuple old, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats, Buffer buffer)
 
static IndexTuple buildFreshLeafTuple (GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats, Buffer buffer)
 
void ginEntryInsert (GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
 
static void ginHeapTupleBulkInsert (GinBuildState *buildstate, OffsetNumber attnum, Datum value, bool isNull, ItemPointer heapptr)
 
static void ginBuildCallback (Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
 
IndexBuildResultginbuild (Relation heap, Relation index, IndexInfo *indexInfo)
 
void ginbuildempty (Relation index)
 
static void ginHeapTupleInsert (GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, ItemPointer item)
 
bool gininsert (Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, IndexInfo *indexInfo)
 

Function Documentation

◆ addItemPointersToLeafTuple()

static IndexTuple addItemPointersToLeafTuple ( GinState ginstate,
IndexTuple  old,
ItemPointerData items,
uint32  nitem,
GinStatsData buildStats,
Buffer  buffer 
)
static

Definition at line 49 of file gininsert.c.

References Assert, attnum, createPostingTree(), ginCompressPostingList(), GinFormTuple(), ginInsertItemPointers(), GinIsPostingTree, GinMaxItemSize, ginMergeItemPointers(), ginReadTuple(), GinSetPostingTree, gintuple_get_attrnum(), gintuple_get_key(), GinState::index, sort-test::key, pfree(), and SizeOfGinPostingList.

Referenced by ginEntryInsert().

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 }
GinPostingList * ginCompressPostingList(const ItemPointer ipd, int nipd, int maxsize, int *nwritten)
void ginInsertItemPointers(Relation index, BlockNumber rootBlkno, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
Definition: gindatapage.c:1902
Relation index
Definition: gin_private.h:58
BlockNumber createPostingTree(Relation index, ItemPointerData *items, uint32 nitems, GinStatsData *buildStats, Buffer entrybuffer)
Definition: gindatapage.c:1769
uint32 BlockNumber
Definition: block.h:31
ItemPointer ginMergeItemPointers(ItemPointerData *a, uint32 na, ItemPointerData *b, uint32 nb, int *nmerged)
uint16 OffsetNumber
Definition: off.h:24
#define GinSetPostingTree(itup, blkno)
Definition: ginblock.h:233
void pfree(void *pointer)
Definition: mcxt.c:1056
signed char GinNullCategory
Definition: ginblock.h:207
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Definition: ginutil.c:218
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
Definition: ginutil.c:251
uintptr_t Datum
Definition: postgres.h:367
int16 attnum
Definition: pg_attribute.h:79
#define Assert(condition)
Definition: c.h:739
IndexTuple GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, Pointer data, Size dataSize, int nipd, bool errorTooBig)
Definition: ginentrypage.c:45
ItemPointer ginReadTuple(GinState *ginstate, OffsetNumber attnum, IndexTuple itup, int *nitems)
Definition: ginentrypage.c:163
#define GinIsPostingTree(itup)
Definition: ginblock.h:232
#define SizeOfGinPostingList(plist)
Definition: ginblock.h:343
#define GinMaxItemSize
Definition: ginblock.h:249

◆ buildFreshLeafTuple()

static IndexTuple buildFreshLeafTuple ( GinState ginstate,
OffsetNumber  attnum,
Datum  key,
GinNullCategory  category,
ItemPointerData items,
uint32  nitem,
GinStatsData buildStats,
Buffer  buffer 
)
static

Definition at line 129 of file gininsert.c.

References createPostingTree(), ginCompressPostingList(), GinFormTuple(), GinMaxItemSize, GinSetPostingTree, GinState::index, pfree(), and SizeOfGinPostingList.

Referenced by ginEntryInsert().

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 }
GinPostingList * ginCompressPostingList(const ItemPointer ipd, int nipd, int maxsize, int *nwritten)
Relation index
Definition: gin_private.h:58
BlockNumber createPostingTree(Relation index, ItemPointerData *items, uint32 nitems, GinStatsData *buildStats, Buffer entrybuffer)
Definition: gindatapage.c:1769
uint32 BlockNumber
Definition: block.h:31
#define GinSetPostingTree(itup, blkno)
Definition: ginblock.h:233
void pfree(void *pointer)
Definition: mcxt.c:1056
int16 attnum
Definition: pg_attribute.h:79
IndexTuple GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, Pointer data, Size dataSize, int nipd, bool errorTooBig)
Definition: ginentrypage.c:45
#define SizeOfGinPostingList(plist)
Definition: ginblock.h:343
#define GinMaxItemSize
Definition: ginblock.h:249

◆ ginbuild()

IndexBuildResult* ginbuild ( Relation  heap,
Relation  index,
IndexInfo indexInfo 
)

Definition at line 318 of file gininsert.c.

References GinBuildState::accum, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, attnum, GinBuildState::buildStats, CHECK_FOR_INTERRUPTS, CurrentMemoryContext, elog, END_CRIT_SECTION, ERROR, GinBuildState::funcCtx, GIN_LEAF, ginBeginBAScan(), ginBuildCallback(), ginEntryInsert(), ginGetBAEntry(), ginInitBA(), GinInitBuffer(), GinInitMetabuffer(), GinNewBuffer(), GinBuildState::ginstate, BuildAccumulator::ginstate, ginUpdateStats(), IndexBuildResult::heap_tuples, IndexBuildResult::index_tuples, GinBuildState::indtuples, initGinState(), sort-test::key, sort-test::list, log_newpage_range(), MAIN_FORKNUM, MarkBufferDirty(), MemoryContextDelete(), MemoryContextSwitchTo(), GinStatsData::nEntryPages, palloc(), RelationGetNumberOfBlocks, RelationGetRelationName, RelationNeedsWAL, reltuples, START_CRIT_SECTION, table_index_build_scan(), GinBuildState::tmpCtx, and UnlockReleaseBuffer().

Referenced by ginhandler().

319 {
320  IndexBuildResult *result;
321  double reltuples;
322  GinBuildState buildstate;
323  Buffer RootBuffer,
324  MetaBuffer;
326  Datum key;
327  GinNullCategory category;
328  uint32 nlist;
329  MemoryContext oldCtx;
331 
332  if (RelationGetNumberOfBlocks(index) != 0)
333  elog(ERROR, "index \"%s\" already contains data",
334  RelationGetRelationName(index));
335 
336  initGinState(&buildstate.ginstate, index);
337  buildstate.indtuples = 0;
338  memset(&buildstate.buildStats, 0, sizeof(GinStatsData));
339 
340  /* initialize the meta page */
341  MetaBuffer = GinNewBuffer(index);
342 
343  /* initialize the root page */
344  RootBuffer = GinNewBuffer(index);
345 
347  GinInitMetabuffer(MetaBuffer);
348  MarkBufferDirty(MetaBuffer);
349  GinInitBuffer(RootBuffer, GIN_LEAF);
350  MarkBufferDirty(RootBuffer);
351 
352 
353  UnlockReleaseBuffer(MetaBuffer);
354  UnlockReleaseBuffer(RootBuffer);
356 
357  /* count the root as first entry page */
358  buildstate.buildStats.nEntryPages++;
359 
360  /*
361  * create a temporary memory context that is used to hold data not yet
362  * dumped out to the index
363  */
365  "Gin build temporary context",
367 
368  /*
369  * create a temporary memory context that is used for calling
370  * ginExtractEntries(), and can be reset after each tuple
371  */
373  "Gin build temporary context for user-defined function",
375 
376  buildstate.accum.ginstate = &buildstate.ginstate;
377  ginInitBA(&buildstate.accum);
378 
379  /*
380  * Do the heap scan. We disallow sync scan here because dataPlaceToPage
381  * prefers to receive tuples in TID order.
382  */
383  reltuples = table_index_build_scan(heap, index, indexInfo, false, true,
384  ginBuildCallback, (void *) &buildstate,
385  NULL);
386 
387  /* dump remaining entries to the index */
388  oldCtx = MemoryContextSwitchTo(buildstate.tmpCtx);
389  ginBeginBAScan(&buildstate.accum);
390  while ((list = ginGetBAEntry(&buildstate.accum,
391  &attnum, &key, &category, &nlist)) != NULL)
392  {
393  /* there could be many entries, so be willing to abort here */
395  ginEntryInsert(&buildstate.ginstate, attnum, key, category,
396  list, nlist, &buildstate.buildStats);
397  }
398  MemoryContextSwitchTo(oldCtx);
399 
400  MemoryContextDelete(buildstate.funcCtx);
401  MemoryContextDelete(buildstate.tmpCtx);
402 
403  /*
404  * Update metapage stats
405  */
407  ginUpdateStats(index, &buildstate.buildStats, true);
408 
409  /*
410  * We didn't write WAL records as we built the index, so if WAL-logging is
411  * required, write all pages to the WAL now.
412  */
413  if (RelationNeedsWAL(index))
414  {
416  0, RelationGetNumberOfBlocks(index),
417  true);
418  }
419 
420  /*
421  * Return statistics
422  */
423  result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
424 
425  result->heap_tuples = reltuples;
426  result->index_tuples = buildstate.indtuples;
427 
428  return result;
429 }
BlockNumber nEntryPages
Definition: gin.h:45
Buffer GinNewBuffer(Relation index)
Definition: ginutil.c:292
void GinInitMetabuffer(Buffer b)
Definition: ginutil.c:357
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
GinStatsData buildStats
Definition: gininsert.c:34
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
static void ginBuildCallback(Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: gininsert.c:278
double indtuples
Definition: gininsert.c:33
uint16 OffsetNumber
Definition: off.h:24
GinState ginstate
Definition: gininsert.c:32
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:3388
#define ERROR
Definition: elog.h:43
signed char GinNullCategory
Definition: ginblock.h:207
static double table_index_build_scan(Relation table_rel, Relation index_rel, struct IndexInfo *index_info, bool allow_sync, bool progress, IndexBuildCallback callback, void *callback_state, TableScanDesc scan)
Definition: tableam.h:1499
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
BuildAccumulator accum
Definition: gininsert.c:37
void initGinState(GinState *state, Relation index)
Definition: ginutil.c:89
#define RelationGetRelationName(relation)
Definition: rel.h:456
unsigned int uint32
Definition: c.h:359
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
GinState * ginstate
Definition: gin_private.h:412
uintptr_t Datum
Definition: postgres.h:367
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:198
int16 attnum
Definition: pg_attribute.h:79
void GinInitBuffer(Buffer b, uint32 f)
Definition: ginutil.c:351
BlockNumber nTotalPages
Definition: gin.h:44
ItemPointerData * ginGetBAEntry(BuildAccumulator *accum, OffsetNumber *attnum, Datum *key, GinNullCategory *category, uint32 *n)
Definition: ginbulk.c:268
#define RelationNeedsWAL(relation)
Definition: rel.h:524
void ginBeginBAScan(BuildAccumulator *accum)
Definition: ginbulk.c:257
void log_newpage_range(Relation rel, ForkNumber forkNum, BlockNumber startblk, BlockNumber endblk, bool page_std)
Definition: xloginsert.c:1042
void ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
Definition: ginutil.c:651
void * palloc(Size size)
Definition: mcxt.c:949
MemoryContext tmpCtx
Definition: gininsert.c:35
#define elog(elevel,...)
Definition: elog.h:228
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
MemoryContext funcCtx
Definition: gininsert.c:36
int Buffer
Definition: buf.h:23
float4 reltuples
Definition: pg_class.h:63
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:41

◆ ginBuildCallback()

static void ginBuildCallback ( Relation  index,
ItemPointer  tid,
Datum values,
bool isnull,
bool  tupleIsAlive,
void *  state 
)
static

Definition at line 278 of file gininsert.c.

References GinBuildState::accum, BuildAccumulator::allocatedMemory, attnum, GinBuildState::buildStats, CHECK_FOR_INTERRUPTS, ginBeginBAScan(), ginEntryInsert(), ginGetBAEntry(), ginHeapTupleBulkInsert(), ginInitBA(), GinBuildState::ginstate, i, sort-test::key, sort-test::list, maintenance_work_mem, MemoryContextReset(), MemoryContextSwitchTo(), TupleDescData::natts, GinState::origTupdesc, and GinBuildState::tmpCtx.

Referenced by ginbuild().

280 {
281  GinBuildState *buildstate = (GinBuildState *) state;
282  MemoryContext oldCtx;
283  int i;
284 
285  oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
286 
287  for (i = 0; i < buildstate->ginstate.origTupdesc->natts; i++)
288  ginHeapTupleBulkInsert(buildstate, (OffsetNumber) (i + 1),
289  values[i], isnull[i], tid);
290 
291  /* If we've maxed out our available memory, dump everything to the index */
292  if (buildstate->accum.allocatedMemory >= (Size) maintenance_work_mem * 1024L)
293  {
295  Datum key;
296  GinNullCategory category;
297  uint32 nlist;
299 
300  ginBeginBAScan(&buildstate->accum);
301  while ((list = ginGetBAEntry(&buildstate->accum,
302  &attnum, &key, &category, &nlist)) != NULL)
303  {
304  /* there could be many entries, so be willing to abort here */
306  ginEntryInsert(&buildstate->ginstate, attnum, key, category,
307  list, nlist, &buildstate->buildStats);
308  }
309 
310  MemoryContextReset(buildstate->tmpCtx);
311  ginInitBA(&buildstate->accum);
312  }
313 
314  MemoryContextSwitchTo(oldCtx);
315 }
GinStatsData buildStats
Definition: gininsert.c:34
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
uint16 OffsetNumber
Definition: off.h:24
GinState ginstate
Definition: gininsert.c:32
void ginEntryInsert(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
Definition: gininsert.c:179
signed char GinNullCategory
Definition: ginblock.h:207
BuildAccumulator accum
Definition: gininsert.c:37
static void ginHeapTupleBulkInsert(GinBuildState *buildstate, OffsetNumber attnum, Datum value, bool isNull, ItemPointer heapptr)
Definition: gininsert.c:254
unsigned int uint32
Definition: c.h:359
uintptr_t Datum
Definition: postgres.h:367
int16 attnum
Definition: pg_attribute.h:79
int maintenance_work_mem
Definition: globals.c:122
Definition: regguts.h:298
size_t Size
Definition: c.h:467
ItemPointerData * ginGetBAEntry(BuildAccumulator *accum, OffsetNumber *attnum, Datum *key, GinNullCategory *category, uint32 *n)
Definition: ginbulk.c:268
void ginBeginBAScan(BuildAccumulator *accum)
Definition: ginbulk.c:257
static Datum values[MAXATTR]
Definition: bootstrap.c:167
MemoryContext tmpCtx
Definition: gininsert.c:35
int i
TupleDesc origTupdesc
Definition: gin_private.h:72
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
void ginInitBA(BuildAccumulator *accum)
Definition: ginbulk.c:109

◆ ginbuildempty()

void ginbuildempty ( Relation  index)

Definition at line 435 of file gininsert.c.

References BUFFER_LOCK_EXCLUSIVE, END_CRIT_SECTION, GIN_LEAF, GinInitBuffer(), GinInitMetabuffer(), INIT_FORKNUM, LockBuffer(), log_newpage_buffer(), MarkBufferDirty(), P_NEW, RBM_NORMAL, ReadBufferExtended(), START_CRIT_SECTION, and UnlockReleaseBuffer().

Referenced by ginhandler().

436 {
437  Buffer RootBuffer,
438  MetaBuffer;
439 
440  /* An empty GIN index has two pages. */
441  MetaBuffer =
443  LockBuffer(MetaBuffer, BUFFER_LOCK_EXCLUSIVE);
444  RootBuffer =
446  LockBuffer(RootBuffer, BUFFER_LOCK_EXCLUSIVE);
447 
448  /* Initialize and xlog metabuffer and root buffer. */
450  GinInitMetabuffer(MetaBuffer);
451  MarkBufferDirty(MetaBuffer);
452  log_newpage_buffer(MetaBuffer, true);
453  GinInitBuffer(RootBuffer, GIN_LEAF);
454  MarkBufferDirty(RootBuffer);
455  log_newpage_buffer(RootBuffer, false);
457 
458  /* Unlock and release the buffers. */
459  UnlockReleaseBuffer(MetaBuffer);
460  UnlockReleaseBuffer(RootBuffer);
461 }
void GinInitMetabuffer(Buffer b)
Definition: ginutil.c:357
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)
Definition: xloginsert.c:1009
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:642
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
#define P_NEW
Definition: bufmgr.h:81
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:88
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3388
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3602
void GinInitBuffer(Buffer b, uint32 f)
Definition: ginutil.c:351
int Buffer
Definition: buf.h:23
#define GIN_LEAF
Definition: ginblock.h:41

◆ ginEntryInsert()

void ginEntryInsert ( GinState ginstate,
OffsetNumber  attnum,
Datum  key,
GinNullCategory  category,
ItemPointerData items,
uint32  nitem,
GinStatsData buildStats 
)

Definition at line 179 of file gininsert.c.

References addItemPointersToLeafTuple(), GinBtreeStack::buffer, BufferGetPage, buildFreshLeafTuple(), CheckForSerializableConflictIn(), GinBtreeEntryInsertData::entry, GinBtreeData::findItem, freeGinBtreeStack(), GIN_UNLOCK, ginFindLeafPage(), GinGetPostingTree, ginInsertItemPointers(), ginInsertValue(), GinIsPostingTree, ginPrepareEntryScan(), GinState::index, GinBtreeData::isBuild, GinBtreeEntryInsertData::isDelete, LockBuffer(), GinStatsData::nEntries, GinBtreeStack::off, PageGetItem, PageGetItemId, and pfree().

Referenced by ginbuild(), ginBuildCallback(), ginHeapTupleInsert(), and ginInsertCleanup().

183 {
184  GinBtreeData btree;
185  GinBtreeEntryInsertData insertdata;
186  GinBtreeStack *stack;
187  IndexTuple itup;
188  Page page;
189 
190  insertdata.isDelete = false;
191 
192  ginPrepareEntryScan(&btree, attnum, key, category, ginstate);
193  btree.isBuild = (buildStats != NULL);
194 
195  stack = ginFindLeafPage(&btree, false, false, NULL);
196  page = BufferGetPage(stack->buffer);
197 
198  if (btree.findItem(&btree, stack))
199  {
200  /* found pre-existing entry */
201  itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, stack->off));
202 
203  if (GinIsPostingTree(itup))
204  {
205  /* add entries to existing posting tree */
206  BlockNumber rootPostingTree = GinGetPostingTree(itup);
207 
208  /* release all stack */
209  LockBuffer(stack->buffer, GIN_UNLOCK);
210  freeGinBtreeStack(stack);
211 
212  /* insert into posting tree */
213  ginInsertItemPointers(ginstate->index, rootPostingTree,
214  items, nitem,
215  buildStats);
216  return;
217  }
218 
219  CheckForSerializableConflictIn(ginstate->index, NULL, stack->buffer);
220  /* modify an existing leaf entry */
221  itup = addItemPointersToLeafTuple(ginstate, itup,
222  items, nitem, buildStats, stack->buffer);
223 
224  insertdata.isDelete = true;
225  }
226  else
227  {
228  CheckForSerializableConflictIn(ginstate->index, NULL, stack->buffer);
229  /* no match, so construct a new leaf entry */
230  itup = buildFreshLeafTuple(ginstate, attnum, key, category,
231  items, nitem, buildStats, stack->buffer);
232 
233  /*
234  * nEntries counts leaf tuples, so increment it only when we make a
235  * new one.
236  */
237  if (buildStats)
238  buildStats->nEntries++;
239  }
240 
241  /* Insert the new or modified leaf tuple */
242  insertdata.entry = itup;
243  ginInsertValue(&btree, stack, &insertdata, buildStats);
244  pfree(itup);
245 }
#define GIN_UNLOCK
Definition: gin_private.h:48
void ginInsertItemPointers(Relation index, BlockNumber rootBlkno, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
Definition: gindatapage.c:1902
Relation index
Definition: gin_private.h:58
OffsetNumber off
Definition: gin_private.h:131
GinBtreeStack * ginFindLeafPage(GinBtree btree, bool searchMode, bool rootConflictCheck, Snapshot snapshot)
Definition: ginbtree.c:80
int64 nEntries
Definition: gin.h:47
uint32 BlockNumber
Definition: block.h:31
void CheckForSerializableConflictIn(Relation relation, HeapTuple tuple, Buffer buffer)
Definition: predicate.c:4426
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:154
void pfree(void *pointer)
Definition: mcxt.c:1056
IndexTupleData * IndexTuple
Definition: itup.h:53
static IndexTuple buildFreshLeafTuple(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats, Buffer buffer)
Definition: gininsert.c:129
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
void ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum, Datum key, GinNullCategory category, GinState *ginstate)
Definition: ginentrypage.c:745
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3602
void ginInsertValue(GinBtree btree, GinBtreeStack *stack, void *insertdata, GinStatsData *buildStats)
Definition: ginbtree.c:777
int16 attnum
Definition: pg_attribute.h:79
#define GinGetPostingTree(itup)
Definition: ginblock.h:234
#define GinIsPostingTree(itup)
Definition: ginblock.h:232
void freeGinBtreeStack(GinBtreeStack *stack)
Definition: ginbtree.c:194
#define PageGetItem(page, itemId)
Definition: bufpage.h:340
Pointer Page
Definition: bufpage.h:78

◆ ginHeapTupleBulkInsert()

static void ginHeapTupleBulkInsert ( GinBuildState buildstate,
OffsetNumber  attnum,
Datum  value,
bool  isNull,
ItemPointer  heapptr 
)
static

Definition at line 254 of file gininsert.c.

References GinBuildState::accum, GinBuildState::funcCtx, ginExtractEntries(), ginInsertBAEntries(), BuildAccumulator::ginstate, GinBuildState::indtuples, MemoryContextReset(), and MemoryContextSwitchTo().

Referenced by ginBuildCallback().

257 {
258  Datum *entries;
259  GinNullCategory *categories;
260  int32 nentries;
261  MemoryContext oldCtx;
262 
263  oldCtx = MemoryContextSwitchTo(buildstate->funcCtx);
264  entries = ginExtractEntries(buildstate->accum.ginstate, attnum,
265  value, isNull,
266  &nentries, &categories);
267  MemoryContextSwitchTo(oldCtx);
268 
269  ginInsertBAEntries(&buildstate->accum, heapptr, attnum,
270  entries, categories, nentries);
271 
272  buildstate->indtuples += nentries;
273 
274  MemoryContextReset(buildstate->funcCtx);
275 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static struct @145 value
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
double indtuples
Definition: gininsert.c:33
signed int int32
Definition: c.h:347
signed char GinNullCategory
Definition: ginblock.h:207
BuildAccumulator accum
Definition: gininsert.c:37
GinState * ginstate
Definition: gin_private.h:412
uintptr_t Datum
Definition: postgres.h:367
void ginInsertBAEntries(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum *entries, GinNullCategory *categories, int32 nentries)
Definition: ginbulk.c:210
int16 attnum
Definition: pg_attribute.h:79
MemoryContext funcCtx
Definition: gininsert.c:36
Datum * ginExtractEntries(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries, GinNullCategory **categories)
Definition: ginutil.c:484

◆ ginHeapTupleInsert()

static void ginHeapTupleInsert ( GinState ginstate,
OffsetNumber  attnum,
Datum  value,
bool  isNull,
ItemPointer  item 
)
static

Definition at line 468 of file gininsert.c.

References ginEntryInsert(), ginExtractEntries(), and i.

Referenced by gininsert().

471 {
472  Datum *entries;
473  GinNullCategory *categories;
474  int32 i,
475  nentries;
476 
477  entries = ginExtractEntries(ginstate, attnum, value, isNull,
478  &nentries, &categories);
479 
480  for (i = 0; i < nentries; i++)
481  ginEntryInsert(ginstate, attnum, entries[i], categories[i],
482  item, 1, NULL);
483 }
static struct @145 value
signed int int32
Definition: c.h:347
void ginEntryInsert(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
Definition: gininsert.c:179
signed char GinNullCategory
Definition: ginblock.h:207
uintptr_t Datum
Definition: postgres.h:367
int16 attnum
Definition: pg_attribute.h:79
int i
Datum * ginExtractEntries(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries, GinNullCategory **categories)
Definition: ginutil.c:484

◆ gininsert()

bool gininsert ( Relation  index,
Datum values,
bool isnull,
ItemPointer  ht_ctid,
Relation  heapRel,
IndexUniqueCheck  checkUnique,
IndexInfo indexInfo 
)

Definition at line 486 of file gininsert.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, GinGetUseFastUpdate, ginHeapTupleFastCollect(), ginHeapTupleFastInsert(), ginHeapTupleInsert(), i, IndexInfo::ii_AmCache, IndexInfo::ii_Context, initGinState(), MemoryContextDelete(), MemoryContextSwitchTo(), TupleDescData::natts, GinState::origTupdesc, and palloc().

Referenced by ginhandler().

490 {
491  GinState *ginstate = (GinState *) indexInfo->ii_AmCache;
492  MemoryContext oldCtx;
493  MemoryContext insertCtx;
494  int i;
495 
496  /* Initialize GinState cache if first call in this statement */
497  if (ginstate == NULL)
498  {
499  oldCtx = MemoryContextSwitchTo(indexInfo->ii_Context);
500  ginstate = (GinState *) palloc(sizeof(GinState));
501  initGinState(ginstate, index);
502  indexInfo->ii_AmCache = (void *) ginstate;
503  MemoryContextSwitchTo(oldCtx);
504  }
505 
507  "Gin insert temporary context",
509 
510  oldCtx = MemoryContextSwitchTo(insertCtx);
511 
512  if (GinGetUseFastUpdate(index))
513  {
514  GinTupleCollector collector;
515 
516  memset(&collector, 0, sizeof(GinTupleCollector));
517 
518  for (i = 0; i < ginstate->origTupdesc->natts; i++)
519  ginHeapTupleFastCollect(ginstate, &collector,
520  (OffsetNumber) (i + 1),
521  values[i], isnull[i],
522  ht_ctid);
523 
524  ginHeapTupleFastInsert(ginstate, &collector);
525  }
526  else
527  {
528  for (i = 0; i < ginstate->origTupdesc->natts; i++)
529  ginHeapTupleInsert(ginstate, (OffsetNumber) (i + 1),
530  values[i], isnull[i],
531  ht_ctid);
532  }
533 
534  MemoryContextSwitchTo(oldCtx);
535  MemoryContextDelete(insertCtx);
536 
537  return false;
538 }
MemoryContext ii_Context
Definition: execnodes.h:176
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
void ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
Definition: ginfast.c:218
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void ginHeapTupleInsert(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, ItemPointer item)
Definition: gininsert.c:468
uint16 OffsetNumber
Definition: off.h:24
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void initGinState(GinState *state, Relation index)
Definition: ginutil.c:89
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void * ii_AmCache
Definition: execnodes.h:175
#define GinGetUseFastUpdate(relation)
Definition: gin_private.h:33
static Datum values[MAXATTR]
Definition: bootstrap.c:167
void * palloc(Size size)
Definition: mcxt.c:949
int i
void ginHeapTupleFastCollect(GinState *ginstate, GinTupleCollector *collector, OffsetNumber attnum, Datum value, bool isNull, ItemPointer ht_ctid)
Definition: ginfast.c:473
TupleDesc origTupdesc
Definition: gin_private.h:72