PostgreSQL Source Code git master
Loading...
Searching...
No Matches
ginutil.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * ginutil.c
4 * Utility routines for the Postgres inverted index access method.
5 *
6 *
7 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 * IDENTIFICATION
11 * src/backend/access/gin/ginutil.c
12 *-------------------------------------------------------------------------
13 */
14
15#include "postgres.h"
16
17#include "access/gin_private.h"
18#include "access/ginxlog.h"
19#include "access/reloptions.h"
20#include "access/xloginsert.h"
22#include "catalog/pg_type.h"
23#include "commands/progress.h"
24#include "commands/vacuum.h"
25#include "miscadmin.h"
26#include "storage/indexfsm.h"
27#include "utils/builtins.h"
29#include "utils/rel.h"
30#include "utils/typcache.h"
31#include "lib/qunique.h"
32
33
34/*
35 * GIN handler function: return IndexAmRoutine with access method parameters
36 * and callbacks.
37 */
40{
41 static const IndexAmRoutine amroutine = {
43 .amstrategies = 0,
44 .amsupport = GINNProcs,
45 .amoptsprocnum = GIN_OPTIONS_PROC,
46 .amcanorder = false,
47 .amcanorderbyop = false,
48 .amcanhash = false,
49 .amconsistentequality = false,
50 .amconsistentordering = false,
51 .amcanbackward = false,
52 .amcanunique = false,
53 .amcanmulticol = true,
54 .amoptionalkey = true,
55 .amsearcharray = false,
56 .amsearchnulls = false,
57 .amstorage = true,
58 .amclusterable = false,
59 .ampredlocks = true,
60 .amcanparallel = false,
61 .amcanbuildparallel = true,
62 .amcaninclude = false,
63 .amusemaintenanceworkmem = true,
64 .amsummarizing = false,
65 .amparallelvacuumoptions =
67 .amkeytype = InvalidOid,
68
69 .ambuild = ginbuild,
70 .ambuildempty = ginbuildempty,
71 .aminsert = gininsert,
72 .aminsertcleanup = NULL,
73 .ambulkdelete = ginbulkdelete,
74 .amvacuumcleanup = ginvacuumcleanup,
75 .amcanreturn = NULL,
76 .amcostestimate = gincostestimate,
77 .amgettreeheight = NULL,
78 .amoptions = ginoptions,
79 .amproperty = NULL,
80 .ambuildphasename = ginbuildphasename,
81 .amvalidate = ginvalidate,
82 .amadjustmembers = ginadjustmembers,
83 .ambeginscan = ginbeginscan,
84 .amrescan = ginrescan,
85 .amgettuple = NULL,
86 .amgetbitmap = gingetbitmap,
87 .amendscan = ginendscan,
88 .ammarkpos = NULL,
89 .amrestrpos = NULL,
90 .amestimateparallelscan = NULL,
91 .aminitparallelscan = NULL,
92 .amparallelrescan = NULL,
93 };
94
96}
97
98/*
99 * initGinState: fill in an empty GinState struct to describe the index
100 *
101 * Note: assorted subsidiary data is allocated in the CurrentMemoryContext.
102 */
103void
105{
106 TupleDesc origTupdesc = RelationGetDescr(index);
107 int i;
108
109 MemSet(state, 0, sizeof(GinState));
110
111 state->index = index;
112 state->oneCol = (origTupdesc->natts == 1);
113 state->origTupdesc = origTupdesc;
114
115 for (i = 0; i < origTupdesc->natts; i++)
116 {
117 Form_pg_attribute attr = TupleDescAttr(origTupdesc, i);
118
119 if (state->oneCol)
120 state->tupdesc[i] = state->origTupdesc;
121 else
122 {
123 state->tupdesc[i] = CreateTemplateTupleDesc(2);
124
125 TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 1, NULL,
126 INT2OID, -1, 0);
127 TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 2, NULL,
128 attr->atttypid,
129 attr->atttypmod,
130 attr->attndims);
132 attr->attcollation);
133 TupleDescFinalize(state->tupdesc[i]);
134 }
135
136 /*
137 * If the compare proc isn't specified in the opclass definition, look
138 * up the index key type's default btree comparator.
139 */
141 {
142 fmgr_info_copy(&(state->compareFn[i]),
145 }
146 else
147 {
148 TypeCacheEntry *typentry;
149
150 typentry = lookup_type_cache(attr->atttypid,
152 if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
155 errmsg("could not identify a comparison function for type %s",
156 format_type_be(attr->atttypid))));
157 fmgr_info_copy(&(state->compareFn[i]),
158 &(typentry->cmp_proc_finfo),
160 }
161
162 /* Opclass must always provide extract procs */
163 fmgr_info_copy(&(state->extractValueFn[i]),
166 fmgr_info_copy(&(state->extractQueryFn[i]),
169
170 /*
171 * Check opclass capability to do tri-state or binary logic consistent
172 * check.
173 */
175 {
176 fmgr_info_copy(&(state->triConsistentFn[i]),
179 }
180
182 {
183 fmgr_info_copy(&(state->consistentFn[i]),
186 }
187
188 if (state->consistentFn[i].fn_oid == InvalidOid &&
189 state->triConsistentFn[i].fn_oid == InvalidOid)
190 {
191 elog(ERROR, "missing GIN support function (%d or %d) for attribute %d of index \"%s\"",
194 }
195
196 /*
197 * Check opclass capability to do partial match.
198 */
200 {
201 fmgr_info_copy(&(state->comparePartialFn[i]),
204 state->canPartialMatch[i] = true;
205 }
206 else
207 {
208 state->canPartialMatch[i] = false;
209 }
210
211 /*
212 * If the index column has a specified collation, we should honor that
213 * while doing comparisons. However, we may have a collatable storage
214 * type for a noncollatable indexed data type (for instance, hstore
215 * uses text index entries). If there's no index collation then
216 * specify default collation in case the support functions need
217 * collation. This is harmless if the support functions don't care
218 * about collation, so we just do it unconditionally. (We could
219 * alternatively call get_typcollation, but that seems like expensive
220 * overkill --- there aren't going to be any cases where a GIN storage
221 * type has a nondefault collation.)
222 */
223 if (OidIsValid(index->rd_indcollation[i]))
224 state->supportCollation[i] = index->rd_indcollation[i];
225 else
226 state->supportCollation[i] = DEFAULT_COLLATION_OID;
227 }
228}
229
230/*
231 * Extract attribute (column) number of stored entry from GIN tuple
232 */
235{
237
238 if (ginstate->oneCol)
239 {
240 /* column number is not stored explicitly */
242 }
243 else
244 {
245 Datum res;
246 bool isnull;
247
248 /*
249 * First attribute is always int16, so we can safely use any tuple
250 * descriptor to obtain first attribute of tuple
251 */
252 res = index_getattr(tuple, FirstOffsetNumber, ginstate->tupdesc[0],
253 &isnull);
254 Assert(!isnull);
255
256 colN = DatumGetUInt16(res);
257 Assert(colN >= FirstOffsetNumber && colN <= ginstate->origTupdesc->natts);
258 }
259
260 return colN;
261}
262
263/*
264 * Extract stored datum (and possible null category) from GIN tuple
265 */
266Datum
268 GinNullCategory *category)
269{
270 Datum res;
271 bool isnull;
272
273 if (ginstate->oneCol)
274 {
275 /*
276 * Single column index doesn't store attribute numbers in tuples
277 */
278 res = index_getattr(tuple, FirstOffsetNumber, ginstate->origTupdesc,
279 &isnull);
280 }
281 else
282 {
283 /*
284 * Since the datum type depends on which index column it's from, we
285 * must be careful to use the right tuple descriptor here.
286 */
287 OffsetNumber colN = gintuple_get_attrnum(ginstate, tuple);
288
290 ginstate->tupdesc[colN - 1],
291 &isnull);
292 }
293
294 if (isnull)
295 *category = GinGetNullCategory(tuple, ginstate);
296 else
297 *category = GIN_CAT_NORM_KEY;
298
299 return res;
300}
301
302/*
303 * Allocate a new page (either by recycling, or by extending the index file)
304 * The returned buffer is already pinned and exclusive-locked
305 * Caller is responsible for initializing the page by calling GinInitBuffer
306 */
307Buffer
309{
310 Buffer buffer;
311
312 /* First, try to get a page from FSM */
313 for (;;)
314 {
316
317 if (blkno == InvalidBlockNumber)
318 break;
319
320 buffer = ReadBuffer(index, blkno);
321
322 /*
323 * We have to guard against the possibility that someone else already
324 * recycled this page; the buffer may be locked if so.
325 */
326 if (ConditionalLockBuffer(buffer))
327 {
329 return buffer; /* OK to use */
330
331 LockBuffer(buffer, GIN_UNLOCK);
332 }
333
334 /* Can't use it, so release buffer and try again */
335 ReleaseBuffer(buffer);
336 }
337
338 /* Must extend the file */
341
342 return buffer;
343}
344
345void
347{
348 GinPageOpaque opaque;
349
350 PageInit(page, pageSize, sizeof(GinPageOpaqueData));
351
352 opaque = GinPageGetOpaque(page);
353 opaque->flags = f;
355}
356
357void
362
363void
365{
366 GinMetaPageData *metadata;
367 Page page = BufferGetPage(b);
368
370
371 metadata = GinPageGetMeta(page);
372
373 metadata->head = metadata->tail = InvalidBlockNumber;
374 metadata->tailFreeSize = 0;
375 metadata->nPendingPages = 0;
376 metadata->nPendingHeapTuples = 0;
377 metadata->nTotalPages = 0;
378 metadata->nEntryPages = 0;
379 metadata->nDataPages = 0;
380 metadata->nEntries = 0;
382
383 /*
384 * Set pd_lower just past the end of the metadata. This is essential,
385 * because without doing so, metadata will be lost if xlog.c compresses
386 * the page.
387 */
388 ((PageHeader) page)->pd_lower =
389 ((char *) metadata + sizeof(GinMetaPageData)) - (char *) page;
390}
391
392/*
393 * Support for sorting key datums and detecting duplicates in
394 * ginExtractEntries
395 */
402
403static int
404cmpEntries(const void *a, const void *b, void *arg)
405{
406 const Datum *aa = (const Datum *) a;
407 const Datum *bb = (const Datum *) b;
409 int res;
410
411 res = DatumGetInt32(FunctionCall2Coll(data->cmpDatumFunc,
412 data->collation,
413 *aa, *bb));
414
415 /*
416 * Detect if we have any duplicates. If there are equal keys, qsort must
417 * compare them at some point, else it wouldn't know whether one should go
418 * before or after the other.
419 */
420 if (res == 0)
421 data->haveDups = true;
422
423 return res;
424}
425
426#define ST_SORT qsort_arg_entries
427#define ST_ELEMENT_TYPE Datum
428#define ST_COMPARE_ARG_TYPE cmpEntriesArg
429#define ST_COMPARE(a, b, arg) cmpEntries(a, b, arg)
430#define ST_SCOPE static
431#define ST_DEFINE
432#define ST_DECLARE
433#include "lib/sort_template.h"
434
435/*
436 * Extract the index key values from an indexable item
437 *
438 * The resulting key values are sorted, and any duplicates are removed.
439 * This avoids generating redundant index entries.
440 */
441Datum *
443 Datum value, bool isNull,
445{
446 Datum *entries;
447 bool *nullFlags;
448 GinNullCategory *categories;
449 bool hasNull;
450 int32 nentries;
451
452 /*
453 * We don't call the extractValueFn on a null item. Instead generate a
454 * placeholder.
455 */
456 if (isNull)
457 {
458 *nentries_p = 1;
459 entries = palloc_object(Datum);
460 entries[0] = (Datum) 0;
462 (*categories_p)[0] = GIN_CAT_NULL_ITEM;
463 return entries;
464 }
465
466 /* OK, call the opclass's extractValueFn */
467 nullFlags = NULL; /* in case extractValue doesn't set it */
468 nentries = 0;
469 entries = (Datum *)
471 ginstate->supportCollation[attnum - 1],
472 value,
473 PointerGetDatum(&nentries),
475
476 /*
477 * Generate a placeholder if the item contained no keys.
478 */
479 if (entries == NULL || nentries <= 0)
480 {
481 *nentries_p = 1;
482 entries = palloc_object(Datum);
483 entries[0] = (Datum) 0;
485 (*categories_p)[0] = GIN_CAT_EMPTY_ITEM;
486 return entries;
487 }
488
489 /*
490 * Scan the items for any NULLs. All NULLs are considered equal, so we
491 * just need to check and remember if there are any. We remove them from
492 * the array here, and after deduplication, put back one NULL entry to
493 * represent them all.
494 */
495 hasNull = false;
496 if (nullFlags)
497 {
498 int32 numNonNulls = 0;
499
500 for (int32 i = 0; i < nentries; i++)
501 {
502 if (nullFlags[i])
503 hasNull = true;
504 else
505 {
506 entries[numNonNulls] = entries[i];
507 numNonNulls++;
508 }
509 }
510 nentries = numNonNulls;
511 }
512
513 /*
514 * If there's more than one key, sort and unique-ify.
515 *
516 * XXX Using qsort here is notationally painful, and the overhead is
517 * pretty bad too. For small numbers of keys it'd likely be better to use
518 * a simple insertion sort.
519 */
520 if (nentries > 1)
521 {
523
524 arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
525 arg.collation = ginstate->supportCollation[attnum - 1];
526 arg.haveDups = false;
527
528 qsort_arg_entries(entries, nentries, &arg);
529
530 if (arg.haveDups)
531 nentries = qunique_arg(entries, nentries, sizeof(Datum), cmpEntries, &arg);
532 }
533
534 /*
535 * Create GinNullCategory representation.
536 */
537 StaticAssertStmt(GIN_CAT_NORM_KEY == 0, "Assuming GIN_CAT_NORM_KEY=0");
538 categories = palloc0_array(GinNullCategory, nentries + (hasNull ? 1 : 0));
539
540 /* Put back a NULL entry, if there were any */
541 if (hasNull)
542 {
543 entries[nentries] = (Datum) 0;
544 categories[nentries] = GIN_CAT_NULL_KEY;
545 nentries++;
546 }
547
548 *nentries_p = nentries;
549 *categories_p = categories;
550 return entries;
551}
552
553bytea *
554ginoptions(Datum reloptions, bool validate)
555{
556 static const relopt_parse_elt tab[] = {
557 {"fastupdate", RELOPT_TYPE_BOOL, offsetof(GinOptions, useFastUpdate)},
558 {"gin_pending_list_limit", RELOPT_TYPE_INT, offsetof(GinOptions,
559 pendingListCleanupSize)}
560 };
561
562 return (bytea *) build_reloptions(reloptions, validate,
564 sizeof(GinOptions),
565 tab, lengthof(tab));
566}
567
568/*
569 * Fetch index's statistical data into *stats
570 *
571 * Note: in the result, nPendingPages can be trusted to be up-to-date,
572 * as can ginVersion; but the other fields are as of the last VACUUM.
573 */
574void
576{
579 GinMetaPageData *metadata;
580
584 metadata = GinPageGetMeta(metapage);
585
586 stats->nPendingPages = metadata->nPendingPages;
587 stats->nTotalPages = metadata->nTotalPages;
588 stats->nEntryPages = metadata->nEntryPages;
589 stats->nDataPages = metadata->nDataPages;
590 stats->nEntries = metadata->nEntries;
591 stats->ginVersion = metadata->ginVersion;
592
594}
595
596/*
597 * Write the given statistics to the index's metapage
598 *
599 * Note: nPendingPages and ginVersion are *not* copied over
600 */
601void
602ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
603{
606 GinMetaPageData *metadata;
607
611 metadata = GinPageGetMeta(metapage);
612
614
615 metadata->nTotalPages = stats->nTotalPages;
616 metadata->nEntryPages = stats->nEntryPages;
617 metadata->nDataPages = stats->nDataPages;
618 metadata->nEntries = stats->nEntries;
619
620 /*
621 * Set pd_lower just past the end of the metadata. This is essential,
622 * because without doing so, metadata will be lost if xlog.c compresses
623 * the page. (We must do this here because pre-v11 versions of PG did not
624 * set the metapage's pd_lower correctly, so a pg_upgraded index might
625 * contain the wrong value.)
626 */
627 ((PageHeader) metapage)->pd_lower =
628 ((char *) metadata + sizeof(GinMetaPageData)) - (char *) metapage;
629
631
632 if (RelationNeedsWAL(index) && !is_build)
633 {
636
637 data.locator = index->rd_locator;
638 data.ntuples = 0;
639 data.newRightlink = data.prevTail = InvalidBlockNumber;
640 memcpy(&data.metadata, metadata, sizeof(GinMetaPageData));
641
645
648 }
649
651
653}
654
655/*
656 * ginbuildphasename() -- Return name of index build phase.
657 */
658char *
660{
661 switch (phasenum)
662 {
664 return "initializing";
666 return "scanning table";
668 return "sorting tuples (workers)";
670 return "merging tuples (workers)";
672 return "sorting tuples";
674 return "merging tuples";
675 default:
676 return NULL;
677 }
678}
int16 AttrNumber
Definition attnum.h:21
static bool validate(Port *port, const char *auth, const char **logdetail)
Definition auth-oauth.c:672
uint32 BlockNumber
Definition block.h:31
#define InvalidBlockNumber
Definition block.h:33
int Buffer
Definition buf.h:23
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
Definition bufmgr.c:979
bool ConditionalLockBuffer(Buffer buffer)
Definition bufmgr.c:6617
void ReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5586
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5603
void MarkBufferDirty(Buffer buffer)
Definition bufmgr.c:3147
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition bufmgr.c:879
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:468
static Size BufferGetPageSize(Buffer buffer)
Definition bufmgr.h:457
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:334
@ EB_LOCK_FIRST
Definition bufmgr.h:87
#define BMR_REL(p_rel)
Definition bufmgr.h:114
void PageInit(Page page, Size pageSize, Size specialSize)
Definition bufpage.c:42
PageHeaderData * PageHeader
Definition bufpage.h:199
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition bufpage.h:416
PageData * Page
Definition bufpage.h:81
#define Assert(condition)
Definition c.h:943
int64_t int64
Definition c.h:621
int32_t int32
Definition c.h:620
uint32_t uint32
Definition c.h:624
#define lengthof(array)
Definition c.h:873
#define MemSet(start, val, len)
Definition c.h:1107
#define StaticAssertStmt(condition, errmessage)
Definition c.h:1015
#define OidIsValid(objectId)
Definition c.h:858
size_t Size
Definition c.h:689
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
Datum arg
Definition elog.c:1322
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
#define palloc_object(type)
Definition fe_memutils.h:74
#define palloc0_array(type, count)
Definition fe_memutils.h:77
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition fmgr.c:1151
Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition fmgr.c:1173
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition fmgr.c:582
#define PG_RETURN_POINTER(x)
Definition fmgr.h:363
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
char * format_type_be(Oid type_oid)
#define GIN_COMPARE_PROC
Definition gin.h:24
#define GIN_CONSISTENT_PROC
Definition gin.h:27
#define PROGRESS_GIN_PHASE_PERFORMSORT_2
Definition gin.h:49
#define PROGRESS_GIN_PHASE_MERGE_1
Definition gin.h:48
#define PROGRESS_GIN_PHASE_PERFORMSORT_1
Definition gin.h:47
#define GIN_EXTRACTQUERY_PROC
Definition gin.h:26
#define GIN_EXTRACTVALUE_PROC
Definition gin.h:25
#define GINNProcs
Definition gin.h:31
#define PROGRESS_GIN_PHASE_MERGE_2
Definition gin.h:50
#define GIN_TRICONSISTENT_PROC
Definition gin.h:29
#define GIN_COMPARE_PARTIAL_PROC
Definition gin.h:28
#define GIN_OPTIONS_PROC
Definition gin.h:30
#define PROGRESS_GIN_PHASE_INDEXBUILD_TABLESCAN
Definition gin.h:46
#define GIN_UNLOCK
Definition gin_private.h:51
#define GIN_EXCLUSIVE
Definition gin_private.h:53
#define GIN_SHARE
Definition gin_private.h:52
#define GIN_CURRENT_VERSION
Definition ginblock.h:102
#define GIN_METAPAGE_BLKNO
Definition ginblock.h:51
#define GinGetNullCategory(itup, ginstate)
Definition ginblock.h:220
#define GinPageGetOpaque(page)
Definition ginblock.h:110
#define GIN_CAT_NORM_KEY
Definition ginblock.h:208
#define GIN_CAT_EMPTY_ITEM
Definition ginblock.h:210
#define GIN_META
Definition ginblock.h:44
signed char GinNullCategory
Definition ginblock.h:206
#define GIN_CAT_NULL_ITEM
Definition ginblock.h:211
#define GIN_CAT_NULL_KEY
Definition ginblock.h:209
#define GinPageGetMeta(p)
Definition ginblock.h:104
int64 gingetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
Definition ginget.c:1931
IndexBuildResult * ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
Definition gininsert.c:618
void ginbuildempty(Relation index)
Definition gininsert.c:812
bool gininsert(Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
Definition gininsert.c:865
IndexScanDesc ginbeginscan(Relation rel, int nkeys, int norderbys)
Definition ginscan.c:26
void ginendscan(IndexScanDesc scan)
Definition ginscan.c:504
void ginrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
Definition ginscan.c:491
void GinInitPage(Page page, uint32 f, Size pageSize)
Definition ginutil.c:346
bytea * ginoptions(Datum reloptions, bool validate)
Definition ginutil.c:554
Datum ginhandler(PG_FUNCTION_ARGS)
Definition ginutil.c:39
void ginGetStats(Relation index, GinStatsData *stats)
Definition ginutil.c:575
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Definition ginutil.c:234
Buffer GinNewBuffer(Relation index)
Definition ginutil.c:308
void GinInitBuffer(Buffer b, uint32 f)
Definition ginutil.c:358
Datum * ginExtractEntries(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries_p, GinNullCategory **categories_p)
Definition ginutil.c:442
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
Definition ginutil.c:267
void GinInitMetabuffer(Buffer b)
Definition ginutil.c:364
static int cmpEntries(const void *a, const void *b, void *arg)
Definition ginutil.c:404
char * ginbuildphasename(int64 phasenum)
Definition ginutil.c:659
void initGinState(GinState *state, Relation index)
Definition ginutil.c:104
void ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
Definition ginutil.c:602
bool GinPageIsRecyclable(Page page)
Definition ginvacuum.c:862
IndexBulkDeleteResult * ginbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
Definition ginvacuum.c:602
IndexBulkDeleteResult * ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
Definition ginvacuum.c:725
bool ginvalidate(Oid opclassoid)
Definition ginvalidate.c:31
void ginadjustmembers(Oid opfamilyoid, Oid opclassoid, List *operators, List *functions)
#define XLOG_GIN_UPDATE_META_PAGE
Definition ginxlog.h:162
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition indexam.c:885
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition indexam.c:851
BlockNumber GetFreeIndexPage(Relation rel)
Definition indexfsm.c:38
static struct @177 value
int b
Definition isn.c:74
int a
Definition isn.c:73
int i
Definition isn.c:77
static Datum index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition itup.h:131
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define START_CRIT_SECTION()
Definition miscadmin.h:152
#define END_CRIT_SECTION()
Definition miscadmin.h:154
static char * errmsg
#define OffsetNumberNext(offsetNumber)
Definition off.h:52
uint16 OffsetNumber
Definition off.h:24
#define FirstOffsetNumber
Definition off.h:27
int16 attnum
FormData_pg_attribute * Form_pg_attribute
const void * data
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static uint16 DatumGetUInt16(Datum X)
Definition postgres.h:182
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static int32 DatumGetInt32(Datum X)
Definition postgres.h:202
#define InvalidOid
unsigned int Oid
static int fb(int x)
#define PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE
Definition progress.h:135
static size_t qunique_arg(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *, void *), void *arg)
Definition qunique.h:46
#define RelationGetDescr(relation)
Definition rel.h:542
#define RelationGetRelationName(relation)
Definition rel.h:550
#define RelationNeedsWAL(relation)
Definition rel.h:639
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
@ RELOPT_KIND_GIN
Definition reloptions.h:46
@ RELOPT_TYPE_INT
Definition reloptions.h:32
@ RELOPT_TYPE_BOOL
Definition reloptions.h:30
@ MAIN_FORKNUM
Definition relpath.h:58
void gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
Definition selfuncs.c:8623
Oid fn_oid
Definition fmgr.h:59
int32 ginVersion
Definition ginblock.h:99
BlockNumber tail
Definition ginblock.h:62
BlockNumber nEntryPages
Definition ginblock.h:80
uint32 tailFreeSize
Definition ginblock.h:67
BlockNumber nPendingPages
Definition ginblock.h:73
int64 nPendingHeapTuples
Definition ginblock.h:74
BlockNumber nTotalPages
Definition ginblock.h:79
BlockNumber nDataPages
Definition ginblock.h:81
BlockNumber head
Definition ginblock.h:61
BlockNumber rightlink
Definition ginblock.h:32
bool oneCol
Definition gin_private.h:62
TupleDesc tupdesc[INDEX_MAX_KEYS]
Definition gin_private.h:76
TupleDesc origTupdesc
Definition gin_private.h:75
FmgrInfo extractValueFn[INDEX_MAX_KEYS]
Definition gin_private.h:82
Oid supportCollation[INDEX_MAX_KEYS]
Definition gin_private.h:90
FmgrInfo compareFn[INDEX_MAX_KEYS]
Definition gin_private.h:81
BlockNumber nDataPages
Definition gin.h:60
BlockNumber nPendingPages
Definition gin.h:57
BlockNumber nEntryPages
Definition gin.h:59
int64 nEntries
Definition gin.h:61
BlockNumber nTotalPages
Definition gin.h:58
int32 ginVersion
Definition gin.h:62
NodeTag type
Definition amapi.h:234
FmgrInfo cmp_proc_finfo
Definition typcache.h:77
FmgrInfo * cmpDatumFunc
Definition ginutil.c:398
bool haveDups
Definition ginutil.c:400
RelFileLocator locator
Definition ginxlog.h:170
Definition type.h:96
Definition c.h:776
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition tupdesc.c:1084
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:900
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_CMP_PROC_FINFO
Definition typcache.h:144
#define VACUUM_OPTION_PARALLEL_CLEANUP
Definition vacuum.h:62
#define VACUUM_OPTION_PARALLEL_BULKDEL
Definition vacuum.h:47
uint64 XLogRecPtr
Definition xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition xloginsert.c:482
void XLogRegisterData(const void *data, uint32 len)
Definition xloginsert.c:372
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition xloginsert.c:246
void XLogBeginInsert(void)
Definition xloginsert.c:153
#define REGBUF_STANDARD
Definition xloginsert.h:35
#define REGBUF_WILL_INIT
Definition xloginsert.h:34