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-2025, 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/tableam.h"
19#include "access/xloginsert.h"
20#include "miscadmin.h"
21#include "nodes/execnodes.h"
22#include "storage/bufmgr.h"
23#include "storage/predicate.h"
24#include "utils/memutils.h"
25#include "utils/rel.h"
26
27typedef struct
28{
30 double indtuples;
36
37
38/*
39 * Adds array of item pointers to tuple's posting list, or
40 * creates posting tree and tuple pointing to tree in case
41 * of not enough space. Max size of tuple is defined in
42 * GinFormTuple(). Returns a new, modified index tuple.
43 * items[] must be in sorted order with no duplicates.
44 */
45static IndexTuple
47 IndexTuple old,
49 GinStatsData *buildStats, Buffer buffer)
50{
52 Datum key;
53 GinNullCategory category;
55 ItemPointerData *newItems,
56 *oldItems;
57 int oldNPosting,
58 newNPosting;
59 GinPostingList *compressedList;
60
62
63 attnum = gintuple_get_attrnum(ginstate, old);
64 key = gintuple_get_key(ginstate, old, &category);
65
66 /* merge the old and new posting lists */
67 oldItems = ginReadTuple(ginstate, attnum, old, &oldNPosting);
68
69 newItems = ginMergeItemPointers(items, nitem,
70 oldItems, oldNPosting,
71 &newNPosting);
72
73 /* Compress the posting list, and try to a build tuple with room for it */
74 res = NULL;
75 compressedList = ginCompressPostingList(newItems, newNPosting, GinMaxItemSize,
76 NULL);
77 pfree(newItems);
78 if (compressedList)
79 {
80 res = GinFormTuple(ginstate, attnum, key, category,
81 (char *) compressedList,
82 SizeOfGinPostingList(compressedList),
83 newNPosting,
84 false);
85 pfree(compressedList);
86 }
87 if (!res)
88 {
89 /* posting list would be too big, convert to posting tree */
90 BlockNumber postingRoot;
91
92 /*
93 * Initialize posting tree with the old tuple's posting list. It's
94 * surely small enough to fit on one posting-tree page, and should
95 * already be in order with no duplicates.
96 */
97 postingRoot = createPostingTree(ginstate->index,
98 oldItems,
99 oldNPosting,
100 buildStats,
101 buffer);
102
103 /* Now insert the TIDs-to-be-added into the posting tree */
104 ginInsertItemPointers(ginstate->index, postingRoot,
105 items, nitem,
106 buildStats);
107
108 /* And build a new posting-tree-only result tuple */
109 res = GinFormTuple(ginstate, attnum, key, category, NULL, 0, 0, true);
110 GinSetPostingTree(res, postingRoot);
111 }
112 pfree(oldItems);
113
114 return res;
115}
116
117/*
118 * Build a fresh leaf tuple, either posting-list or posting-tree format
119 * depending on whether the given items list will fit.
120 * items[] must be in sorted order with no duplicates.
121 *
122 * This is basically the same logic as in addItemPointersToLeafTuple,
123 * but working from slightly different input.
124 */
125static IndexTuple
129 GinStatsData *buildStats, Buffer buffer)
130{
131 IndexTuple res = NULL;
132 GinPostingList *compressedList;
133
134 /* try to build a posting list tuple with all the items */
135 compressedList = ginCompressPostingList(items, nitem, GinMaxItemSize, NULL);
136 if (compressedList)
137 {
138 res = GinFormTuple(ginstate, attnum, key, category,
139 (char *) compressedList,
140 SizeOfGinPostingList(compressedList),
141 nitem, false);
142 pfree(compressedList);
143 }
144 if (!res)
145 {
146 /* posting list would be too big, build posting tree */
147 BlockNumber postingRoot;
148
149 /*
150 * Build posting-tree-only result tuple. We do this first so as to
151 * fail quickly if the key is too big.
152 */
153 res = GinFormTuple(ginstate, attnum, key, category, NULL, 0, 0, true);
154
155 /*
156 * Initialize a new posting tree with the TIDs.
157 */
158 postingRoot = createPostingTree(ginstate->index, items, nitem,
159 buildStats, buffer);
160
161 /* And save the root link in the result tuple */
162 GinSetPostingTree(res, postingRoot);
163 }
164
165 return res;
166}
167
168/*
169 * Insert one or more heap TIDs associated with the given key value.
170 * This will either add a single key entry, or enlarge a pre-existing entry.
171 *
172 * During an index build, buildStats is non-null and the counters
173 * it contains should be incremented as needed.
174 */
175void
179 GinStatsData *buildStats)
180{
181 GinBtreeData btree;
182 GinBtreeEntryInsertData insertdata;
183 GinBtreeStack *stack;
184 IndexTuple itup;
185 Page page;
186
187 insertdata.isDelete = false;
188
189 ginPrepareEntryScan(&btree, attnum, key, category, ginstate);
190 btree.isBuild = (buildStats != NULL);
191
192 stack = ginFindLeafPage(&btree, false, false);
193 page = BufferGetPage(stack->buffer);
194
195 if (btree.findItem(&btree, stack))
196 {
197 /* found pre-existing entry */
198 itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, stack->off));
199
200 if (GinIsPostingTree(itup))
201 {
202 /* add entries to existing posting tree */
203 BlockNumber rootPostingTree = GinGetPostingTree(itup);
204
205 /* release all stack */
207 freeGinBtreeStack(stack);
208
209 /* insert into posting tree */
210 ginInsertItemPointers(ginstate->index, rootPostingTree,
211 items, nitem,
212 buildStats);
213 return;
214 }
215
218 /* modify an existing leaf entry */
219 itup = addItemPointersToLeafTuple(ginstate, itup,
220 items, nitem, buildStats, stack->buffer);
221
222 insertdata.isDelete = true;
223 }
224 else
225 {
228 /* no match, so construct a new leaf entry */
229 itup = buildFreshLeafTuple(ginstate, attnum, key, category,
230 items, nitem, buildStats, stack->buffer);
231
232 /*
233 * nEntries counts leaf tuples, so increment it only when we make a
234 * new one.
235 */
236 if (buildStats)
237 buildStats->nEntries++;
238 }
239
240 /* Insert the new or modified leaf tuple */
241 insertdata.entry = itup;
242 ginInsertValue(&btree, stack, &insertdata, buildStats);
243 pfree(itup);
244}
245
246/*
247 * Extract index entries for a single indexable item, and add them to the
248 * BuildAccumulator's state.
249 *
250 * This function is used only during initial index creation.
251 */
252static void
254 Datum value, bool isNull,
255 ItemPointer heapptr)
256{
257 Datum *entries;
258 GinNullCategory *categories;
259 int32 nentries;
260 MemoryContext oldCtx;
261
262 oldCtx = MemoryContextSwitchTo(buildstate->funcCtx);
263 entries = ginExtractEntries(buildstate->accum.ginstate, attnum,
264 value, isNull,
265 &nentries, &categories);
266 MemoryContextSwitchTo(oldCtx);
267
268 ginInsertBAEntries(&buildstate->accum, heapptr, attnum,
269 entries, categories, nentries);
270
271 buildstate->indtuples += nentries;
272
273 MemoryContextReset(buildstate->funcCtx);
274}
275
276static void
278 bool *isnull, bool tupleIsAlive, void *state)
279{
280 GinBuildState *buildstate = (GinBuildState *) state;
281 MemoryContext oldCtx;
282 int i;
283
284 oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
285
286 for (i = 0; i < buildstate->ginstate.origTupdesc->natts; i++)
287 ginHeapTupleBulkInsert(buildstate, (OffsetNumber) (i + 1),
288 values[i], isnull[i], tid);
289
290 /* If we've maxed out our available memory, dump everything to the index */
291 if (buildstate->accum.allocatedMemory >= maintenance_work_mem * (Size) 1024)
292 {
294 Datum key;
295 GinNullCategory category;
296 uint32 nlist;
298
299 ginBeginBAScan(&buildstate->accum);
300 while ((list = ginGetBAEntry(&buildstate->accum,
301 &attnum, &key, &category, &nlist)) != NULL)
302 {
303 /* there could be many entries, so be willing to abort here */
305 ginEntryInsert(&buildstate->ginstate, attnum, key, category,
306 list, nlist, &buildstate->buildStats);
307 }
308
309 MemoryContextReset(buildstate->tmpCtx);
310 ginInitBA(&buildstate->accum);
311 }
312
313 MemoryContextSwitchTo(oldCtx);
314}
315
318{
319 IndexBuildResult *result;
320 double reltuples;
321 GinBuildState buildstate;
322 Buffer RootBuffer,
323 MetaBuffer;
325 Datum key;
326 GinNullCategory category;
327 uint32 nlist;
328 MemoryContext oldCtx;
330
332 elog(ERROR, "index \"%s\" already contains data",
334
335 initGinState(&buildstate.ginstate, index);
336 buildstate.indtuples = 0;
337 memset(&buildstate.buildStats, 0, sizeof(GinStatsData));
338
339 /* initialize the meta page */
340 MetaBuffer = GinNewBuffer(index);
341
342 /* initialize the root page */
343 RootBuffer = GinNewBuffer(index);
344
346 GinInitMetabuffer(MetaBuffer);
347 MarkBufferDirty(MetaBuffer);
348 GinInitBuffer(RootBuffer, GIN_LEAF);
349 MarkBufferDirty(RootBuffer);
350
351
352 UnlockReleaseBuffer(MetaBuffer);
353 UnlockReleaseBuffer(RootBuffer);
355
356 /* count the root as first entry page */
357 buildstate.buildStats.nEntryPages++;
358
359 /*
360 * create a temporary memory context that is used to hold data not yet
361 * dumped out to the index
362 */
364 "Gin build temporary context",
366
367 /*
368 * create a temporary memory context that is used for calling
369 * ginExtractEntries(), and can be reset after each tuple
370 */
372 "Gin build temporary context for user-defined function",
374
375 buildstate.accum.ginstate = &buildstate.ginstate;
376 ginInitBA(&buildstate.accum);
377
378 /*
379 * Do the heap scan. We disallow sync scan here because dataPlaceToPage
380 * prefers to receive tuples in TID order.
381 */
382 reltuples = table_index_build_scan(heap, index, indexInfo, false, true,
383 ginBuildCallback, &buildstate, NULL);
384
385 /* dump remaining entries to the index */
386 oldCtx = MemoryContextSwitchTo(buildstate.tmpCtx);
387 ginBeginBAScan(&buildstate.accum);
388 while ((list = ginGetBAEntry(&buildstate.accum,
389 &attnum, &key, &category, &nlist)) != NULL)
390 {
391 /* there could be many entries, so be willing to abort here */
393 ginEntryInsert(&buildstate.ginstate, attnum, key, category,
394 list, nlist, &buildstate.buildStats);
395 }
396 MemoryContextSwitchTo(oldCtx);
397
398 MemoryContextDelete(buildstate.funcCtx);
399 MemoryContextDelete(buildstate.tmpCtx);
400
401 /*
402 * Update metapage stats
403 */
405 ginUpdateStats(index, &buildstate.buildStats, true);
406
407 /*
408 * We didn't write WAL records as we built the index, so if WAL-logging is
409 * required, write all pages to the WAL now.
410 */
412 {
415 true);
416 }
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 */
432void
434{
435 Buffer RootBuffer,
436 MetaBuffer;
437
438 /* An empty GIN index has two pages. */
439 MetaBuffer = ExtendBufferedRel(BMR_REL(index), INIT_FORKNUM, NULL,
441 RootBuffer = ExtendBufferedRel(BMR_REL(index), INIT_FORKNUM, NULL,
443
444 /* Initialize and xlog metabuffer and root buffer. */
446 GinInitMetabuffer(MetaBuffer);
447 MarkBufferDirty(MetaBuffer);
448 log_newpage_buffer(MetaBuffer, true);
449 GinInitBuffer(RootBuffer, GIN_LEAF);
450 MarkBufferDirty(RootBuffer);
451 log_newpage_buffer(RootBuffer, false);
453
454 /* Unlock and release the buffers. */
455 UnlockReleaseBuffer(MetaBuffer);
456 UnlockReleaseBuffer(RootBuffer);
457}
458
459/*
460 * Insert index entries for a single indexable item during "normal"
461 * (non-fast-update) insertion
462 */
463static void
465 Datum value, bool isNull,
466 ItemPointer item)
467{
468 Datum *entries;
469 GinNullCategory *categories;
470 int32 i,
471 nentries;
472
473 entries = ginExtractEntries(ginstate, attnum, value, isNull,
474 &nentries, &categories);
475
476 for (i = 0; i < nentries; i++)
477 ginEntryInsert(ginstate, attnum, entries[i], categories[i],
478 item, 1, NULL);
479}
480
481bool
483 ItemPointer ht_ctid, Relation heapRel,
484 IndexUniqueCheck checkUnique,
485 bool indexUnchanged,
486 IndexInfo *indexInfo)
487{
488 GinState *ginstate = (GinState *) indexInfo->ii_AmCache;
489 MemoryContext oldCtx;
490 MemoryContext insertCtx;
491 int i;
492
493 /* Initialize GinState cache if first call in this statement */
494 if (ginstate == NULL)
495 {
496 oldCtx = MemoryContextSwitchTo(indexInfo->ii_Context);
497 ginstate = (GinState *) palloc(sizeof(GinState));
498 initGinState(ginstate, index);
499 indexInfo->ii_AmCache = ginstate;
500 MemoryContextSwitchTo(oldCtx);
501 }
502
504 "Gin insert temporary context",
506
507 oldCtx = MemoryContextSwitchTo(insertCtx);
508
510 {
511 GinTupleCollector collector;
512
513 memset(&collector, 0, sizeof(GinTupleCollector));
514
515 for (i = 0; i < ginstate->origTupdesc->natts; i++)
516 ginHeapTupleFastCollect(ginstate, &collector,
517 (OffsetNumber) (i + 1),
518 values[i], isnull[i],
519 ht_ctid);
520
521 ginHeapTupleFastInsert(ginstate, &collector);
522 }
523 else
524 {
525 for (i = 0; i < ginstate->origTupdesc->natts; i++)
526 ginHeapTupleInsert(ginstate, (OffsetNumber) (i + 1),
527 values[i], isnull[i],
528 ht_ctid);
529 }
530
531 MemoryContextSwitchTo(oldCtx);
532 MemoryContextDelete(insertCtx);
533
534 return false;
535}
uint32 BlockNumber
Definition: block.h:31
static Datum values[MAXATTR]
Definition: bootstrap.c:151
int Buffer
Definition: buf.h:23
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3724
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
Definition: bufmgr.c:846
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4883
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2532
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5100
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:273
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:396
@ EB_SKIP_EXTENSION_LOCK
Definition: bufmgr.h:74
@ EB_LOCK_FIRST
Definition: bufmgr.h:86
#define BMR_REL(p_rel)
Definition: bufmgr.h:107
static Item PageGetItem(const PageData *page, const ItemIdData *itemId)
Definition: bufpage.h:354
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:244
PageData * Page
Definition: bufpage.h:82
#define Assert(condition)
Definition: c.h:815
int32_t int32
Definition: c.h:484
uint32_t uint32
Definition: c.h:488
size_t Size
Definition: c.h:562
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
IndexUniqueCheck
Definition: genam.h:118
#define GIN_UNLOCK
Definition: gin_private.h:49
#define GinGetUseFastUpdate(relation)
Definition: gin_private.h:34
#define GinIsPostingTree(itup)
Definition: ginblock.h:231
#define SizeOfGinPostingList(plist)
Definition: ginblock.h:342
#define GIN_LEAF
Definition: ginblock.h:42
#define GinGetPostingTree(itup)
Definition: ginblock.h:233
signed char GinNullCategory
Definition: ginblock.h:206
#define GinSetPostingTree(itup, blkno)
Definition: ginblock.h:232
#define GinMaxItemSize
Definition: ginblock.h:248
void freeGinBtreeStack(GinBtreeStack *stack)
Definition: ginbtree.c:198
void ginInsertValue(GinBtree btree, GinBtreeStack *stack, void *insertdata, GinStatsData *buildStats)
Definition: ginbtree.c:816
GinBtreeStack * ginFindLeafPage(GinBtree btree, bool searchMode, bool rootConflictCheck)
Definition: ginbtree.c:83
void ginBeginBAScan(BuildAccumulator *accum)
Definition: ginbulk.c:257
ItemPointerData * ginGetBAEntry(BuildAccumulator *accum, OffsetNumber *attnum, Datum *key, GinNullCategory *category, uint32 *n)
Definition: ginbulk.c:268
void ginInsertBAEntries(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum *entries, GinNullCategory *categories, int32 nentries)
Definition: ginbulk.c:210
void ginInitBA(BuildAccumulator *accum)
Definition: ginbulk.c:109
BlockNumber createPostingTree(Relation index, ItemPointerData *items, uint32 nitems, GinStatsData *buildStats, Buffer entrybuffer)
Definition: gindatapage.c:1775
void ginInsertItemPointers(Relation index, BlockNumber rootBlkno, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
Definition: gindatapage.c:1908
ItemPointer ginReadTuple(GinState *ginstate, OffsetNumber attnum, IndexTuple itup, int *nitems)
Definition: ginentrypage.c:162
IndexTuple GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, Pointer data, Size dataSize, int nipd, bool errorTooBig)
Definition: ginentrypage.c:44
void ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum, Datum key, GinNullCategory category, GinState *ginstate)
Definition: ginentrypage.c:747
void ginHeapTupleFastCollect(GinState *ginstate, GinTupleCollector *collector, OffsetNumber attnum, Datum value, bool isNull, ItemPointer ht_ctid)
Definition: ginfast.c:483
void ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
Definition: ginfast.c:219
static IndexTuple addItemPointersToLeafTuple(GinState *ginstate, IndexTuple old, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats, Buffer buffer)
Definition: gininsert.c:46
IndexBuildResult * ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
Definition: gininsert.c:317
static IndexTuple buildFreshLeafTuple(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats, Buffer buffer)
Definition: gininsert.c:126
static void ginHeapTupleBulkInsert(GinBuildState *buildstate, OffsetNumber attnum, Datum value, bool isNull, ItemPointer heapptr)
Definition: gininsert.c:253
void ginEntryInsert(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
Definition: gininsert.c:176
static void ginHeapTupleInsert(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, ItemPointer item)
Definition: gininsert.c:464
void ginbuildempty(Relation index)
Definition: gininsert.c:433
bool gininsert(Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
Definition: gininsert.c:482
static void ginBuildCallback(Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: gininsert.c:277
GinPostingList * ginCompressPostingList(const ItemPointer ipd, int nipd, int maxsize, int *nwritten)
ItemPointer ginMergeItemPointers(ItemPointerData *a, uint32 na, ItemPointerData *b, uint32 nb, int *nmerged)
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Definition: ginutil.c:227
Buffer GinNewBuffer(Relation index)
Definition: ginutil.c:301
void GinInitBuffer(Buffer b, uint32 f)
Definition: ginutil.c:351
Datum * ginExtractEntries(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries, GinNullCategory **categories)
Definition: ginutil.c:484
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
Definition: ginutil.c:260
void GinInitMetabuffer(Buffer b)
Definition: ginutil.c:357
void initGinState(GinState *state, Relation index)
Definition: ginutil.c:98
void ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
Definition: ginutil.c:651
int maintenance_work_mem
Definition: globals.c:132
static struct @162 value
int i
Definition: isn.c:72
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
IndexTupleData * IndexTuple
Definition: itup.h:53
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
uint16 OffsetNumber
Definition: off.h:24
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
int16 attnum
Definition: pg_attribute.h:74
uintptr_t Datum
Definition: postgres.h:69
void CheckForSerializableConflictIn(Relation relation, ItemPointer tid, BlockNumber blkno)
Definition: predicate.c:4326
#define RelationGetRelationName(relation)
Definition: rel.h:540
#define RelationNeedsWAL(relation)
Definition: rel.h:629
@ MAIN_FORKNUM
Definition: relpath.h:58
@ INIT_FORKNUM
Definition: relpath.h:61
GinState * ginstate
Definition: gin_private.h:433
bool(* findItem)(GinBtree, GinBtreeStack *)
Definition: gin_private.h:156
OffsetNumber off
Definition: gin_private.h:133
double indtuples
Definition: gininsert.c:30
GinState ginstate
Definition: gininsert.c:29
MemoryContext tmpCtx
Definition: gininsert.c:32
GinStatsData buildStats
Definition: gininsert.c:31
MemoryContext funcCtx
Definition: gininsert.c:33
BuildAccumulator accum
Definition: gininsert.c:34
TupleDesc origTupdesc
Definition: gin_private.h:73
Relation index
Definition: gin_private.h:59
BlockNumber nEntryPages
Definition: gin.h:46
int64 nEntries
Definition: gin.h:48
BlockNumber nTotalPages
Definition: gin.h:45
double heap_tuples
Definition: genam.h:34
double index_tuples
Definition: genam.h:35
void * ii_AmCache
Definition: execnodes.h:219
MemoryContext ii_Context
Definition: execnodes.h:220
Definition: type.h:96
Definition: regguts.h:323
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:1781
static ItemArray items
Definition: test_tidstore.c:48
void log_newpage_range(Relation rel, ForkNumber forknum, BlockNumber startblk, BlockNumber endblk, bool page_std)
Definition: xloginsert.c:1270
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)
Definition: xloginsert.c:1237