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
32
33/*
34 * GIN handler function: return IndexAmRoutine with access method parameters
35 * and callbacks.
36 */
39{
40 static const IndexAmRoutine amroutine = {
42 .amstrategies = 0,
43 .amsupport = GINNProcs,
44 .amoptsprocnum = GIN_OPTIONS_PROC,
45 .amcanorder = false,
46 .amcanorderbyop = false,
47 .amcanhash = false,
48 .amconsistentequality = false,
49 .amconsistentordering = false,
50 .amcanbackward = false,
51 .amcanunique = false,
52 .amcanmulticol = true,
53 .amoptionalkey = true,
54 .amsearcharray = false,
55 .amsearchnulls = false,
56 .amstorage = true,
57 .amclusterable = false,
58 .ampredlocks = true,
59 .amcanparallel = false,
60 .amcanbuildparallel = true,
61 .amcaninclude = false,
62 .amusemaintenanceworkmem = true,
63 .amsummarizing = false,
64 .amparallelvacuumoptions =
66 .amkeytype = InvalidOid,
67
68 .ambuild = ginbuild,
69 .ambuildempty = ginbuildempty,
70 .aminsert = gininsert,
71 .aminsertcleanup = NULL,
72 .ambulkdelete = ginbulkdelete,
73 .amvacuumcleanup = ginvacuumcleanup,
74 .amcanreturn = NULL,
75 .amcostestimate = gincostestimate,
76 .amgettreeheight = NULL,
77 .amoptions = ginoptions,
78 .amproperty = NULL,
79 .ambuildphasename = ginbuildphasename,
80 .amvalidate = ginvalidate,
81 .amadjustmembers = ginadjustmembers,
82 .ambeginscan = ginbeginscan,
83 .amrescan = ginrescan,
84 .amgettuple = NULL,
85 .amgetbitmap = gingetbitmap,
86 .amendscan = ginendscan,
87 .ammarkpos = NULL,
88 .amrestrpos = NULL,
89 .amestimateparallelscan = NULL,
90 .aminitparallelscan = NULL,
91 .amparallelrescan = NULL,
92 };
93
95}
96
97/*
98 * initGinState: fill in an empty GinState struct to describe the index
99 *
100 * Note: assorted subsidiary data is allocated in the CurrentMemoryContext.
101 */
102void
104{
105 TupleDesc origTupdesc = RelationGetDescr(index);
106 int i;
107
108 MemSet(state, 0, sizeof(GinState));
109
110 state->index = index;
111 state->oneCol = (origTupdesc->natts == 1);
112 state->origTupdesc = origTupdesc;
113
114 for (i = 0; i < origTupdesc->natts; i++)
115 {
116 Form_pg_attribute attr = TupleDescAttr(origTupdesc, i);
117
118 if (state->oneCol)
119 state->tupdesc[i] = state->origTupdesc;
120 else
121 {
122 state->tupdesc[i] = CreateTemplateTupleDesc(2);
123
124 TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 1, NULL,
125 INT2OID, -1, 0);
126 TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 2, NULL,
127 attr->atttypid,
128 attr->atttypmod,
129 attr->attndims);
131 attr->attcollation);
132 TupleDescFinalize(state->tupdesc[i]);
133 }
134
135 /*
136 * If the compare proc isn't specified in the opclass definition, look
137 * up the index key type's default btree comparator.
138 */
140 {
141 fmgr_info_copy(&(state->compareFn[i]),
144 }
145 else
146 {
147 TypeCacheEntry *typentry;
148
149 typentry = lookup_type_cache(attr->atttypid,
151 if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
154 errmsg("could not identify a comparison function for type %s",
155 format_type_be(attr->atttypid))));
156 fmgr_info_copy(&(state->compareFn[i]),
157 &(typentry->cmp_proc_finfo),
159 }
160
161 /* Opclass must always provide extract procs */
162 fmgr_info_copy(&(state->extractValueFn[i]),
165 fmgr_info_copy(&(state->extractQueryFn[i]),
168
169 /*
170 * Check opclass capability to do tri-state or binary logic consistent
171 * check.
172 */
174 {
175 fmgr_info_copy(&(state->triConsistentFn[i]),
178 }
179
181 {
182 fmgr_info_copy(&(state->consistentFn[i]),
185 }
186
187 if (state->consistentFn[i].fn_oid == InvalidOid &&
188 state->triConsistentFn[i].fn_oid == InvalidOid)
189 {
190 elog(ERROR, "missing GIN support function (%d or %d) for attribute %d of index \"%s\"",
193 }
194
195 /*
196 * Check opclass capability to do partial match.
197 */
199 {
200 fmgr_info_copy(&(state->comparePartialFn[i]),
203 state->canPartialMatch[i] = true;
204 }
205 else
206 {
207 state->canPartialMatch[i] = false;
208 }
209
210 /*
211 * If the index column has a specified collation, we should honor that
212 * while doing comparisons. However, we may have a collatable storage
213 * type for a noncollatable indexed data type (for instance, hstore
214 * uses text index entries). If there's no index collation then
215 * specify default collation in case the support functions need
216 * collation. This is harmless if the support functions don't care
217 * about collation, so we just do it unconditionally. (We could
218 * alternatively call get_typcollation, but that seems like expensive
219 * overkill --- there aren't going to be any cases where a GIN storage
220 * type has a nondefault collation.)
221 */
222 if (OidIsValid(index->rd_indcollation[i]))
223 state->supportCollation[i] = index->rd_indcollation[i];
224 else
225 state->supportCollation[i] = DEFAULT_COLLATION_OID;
226 }
227}
228
229/*
230 * Extract attribute (column) number of stored entry from GIN tuple
231 */
234{
236
237 if (ginstate->oneCol)
238 {
239 /* column number is not stored explicitly */
241 }
242 else
243 {
244 Datum res;
245 bool isnull;
246
247 /*
248 * First attribute is always int16, so we can safely use any tuple
249 * descriptor to obtain first attribute of tuple
250 */
251 res = index_getattr(tuple, FirstOffsetNumber, ginstate->tupdesc[0],
252 &isnull);
253 Assert(!isnull);
254
255 colN = DatumGetUInt16(res);
256 Assert(colN >= FirstOffsetNumber && colN <= ginstate->origTupdesc->natts);
257 }
258
259 return colN;
260}
261
262/*
263 * Extract stored datum (and possible null category) from GIN tuple
264 */
265Datum
267 GinNullCategory *category)
268{
269 Datum res;
270 bool isnull;
271
272 if (ginstate->oneCol)
273 {
274 /*
275 * Single column index doesn't store attribute numbers in tuples
276 */
277 res = index_getattr(tuple, FirstOffsetNumber, ginstate->origTupdesc,
278 &isnull);
279 }
280 else
281 {
282 /*
283 * Since the datum type depends on which index column it's from, we
284 * must be careful to use the right tuple descriptor here.
285 */
286 OffsetNumber colN = gintuple_get_attrnum(ginstate, tuple);
287
289 ginstate->tupdesc[colN - 1],
290 &isnull);
291 }
292
293 if (isnull)
294 *category = GinGetNullCategory(tuple, ginstate);
295 else
296 *category = GIN_CAT_NORM_KEY;
297
298 return res;
299}
300
301/*
302 * Allocate a new page (either by recycling, or by extending the index file)
303 * The returned buffer is already pinned and exclusive-locked
304 * Caller is responsible for initializing the page by calling GinInitBuffer
305 */
306Buffer
308{
309 Buffer buffer;
310
311 /* First, try to get a page from FSM */
312 for (;;)
313 {
315
316 if (blkno == InvalidBlockNumber)
317 break;
318
319 buffer = ReadBuffer(index, blkno);
320
321 /*
322 * We have to guard against the possibility that someone else already
323 * recycled this page; the buffer may be locked if so.
324 */
325 if (ConditionalLockBuffer(buffer))
326 {
328 return buffer; /* OK to use */
329
330 LockBuffer(buffer, GIN_UNLOCK);
331 }
332
333 /* Can't use it, so release buffer and try again */
334 ReleaseBuffer(buffer);
335 }
336
337 /* Must extend the file */
340
341 return buffer;
342}
343
344void
346{
347 GinPageOpaque opaque;
348
349 PageInit(page, pageSize, sizeof(GinPageOpaqueData));
350
351 opaque = GinPageGetOpaque(page);
352 opaque->flags = f;
354}
355
356void
361
362void
364{
365 GinMetaPageData *metadata;
366 Page page = BufferGetPage(b);
367
369
370 metadata = GinPageGetMeta(page);
371
372 metadata->head = metadata->tail = InvalidBlockNumber;
373 metadata->tailFreeSize = 0;
374 metadata->nPendingPages = 0;
375 metadata->nPendingHeapTuples = 0;
376 metadata->nTotalPages = 0;
377 metadata->nEntryPages = 0;
378 metadata->nDataPages = 0;
379 metadata->nEntries = 0;
381
382 /*
383 * Set pd_lower just past the end of the metadata. This is essential,
384 * because without doing so, metadata will be lost if xlog.c compresses
385 * the page.
386 */
387 ((PageHeader) page)->pd_lower =
388 ((char *) metadata + sizeof(GinMetaPageData)) - (char *) page;
389}
390
391/*
392 * Support for sorting key datums in ginExtractEntries
393 *
394 * Note: we only have to worry about null and not-null keys here;
395 * ginExtractEntries never generates more than one placeholder null,
396 * so it doesn't have to sort those.
397 */
398typedef struct
399{
401 bool isnull;
403
410
411static int
412cmpEntries(const void *a, const void *b, void *arg)
413{
414 const keyEntryData *aa = (const keyEntryData *) a;
415 const keyEntryData *bb = (const keyEntryData *) b;
417 int res;
418
419 if (aa->isnull)
420 {
421 if (bb->isnull)
422 res = 0; /* NULL "=" NULL */
423 else
424 res = 1; /* NULL ">" not-NULL */
425 }
426 else if (bb->isnull)
427 res = -1; /* not-NULL "<" NULL */
428 else
429 res = DatumGetInt32(FunctionCall2Coll(data->cmpDatumFunc,
430 data->collation,
431 aa->datum, bb->datum));
432
433 /*
434 * Detect if we have any duplicates. If there are equal keys, qsort must
435 * compare them at some point, else it wouldn't know whether one should go
436 * before or after the other.
437 */
438 if (res == 0)
439 data->haveDups = true;
440
441 return res;
442}
443
444
445/*
446 * Extract the index key values from an indexable item
447 *
448 * The resulting key values are sorted, and any duplicates are removed.
449 * This avoids generating redundant index entries.
450 */
451Datum *
453 Datum value, bool isNull,
454 int32 *nentries, GinNullCategory **categories)
455{
456 Datum *entries;
457 bool *nullFlags;
458 int32 i;
459
460 /*
461 * We don't call the extractValueFn on a null item. Instead generate a
462 * placeholder.
463 */
464 if (isNull)
465 {
466 *nentries = 1;
467 entries = palloc_object(Datum);
468 entries[0] = (Datum) 0;
469 *categories = palloc_object(GinNullCategory);
470 (*categories)[0] = GIN_CAT_NULL_ITEM;
471 return entries;
472 }
473
474 /* OK, call the opclass's extractValueFn */
475 nullFlags = NULL; /* in case extractValue doesn't set it */
476 entries = (Datum *)
478 ginstate->supportCollation[attnum - 1],
479 value,
480 PointerGetDatum(nentries),
482
483 /*
484 * Generate a placeholder if the item contained no keys.
485 */
486 if (entries == NULL || *nentries <= 0)
487 {
488 *nentries = 1;
489 entries = palloc_object(Datum);
490 entries[0] = (Datum) 0;
491 *categories = palloc_object(GinNullCategory);
492 (*categories)[0] = GIN_CAT_EMPTY_ITEM;
493 return entries;
494 }
495
496 /*
497 * If the extractValueFn didn't create a nullFlags array, create one,
498 * assuming that everything's non-null.
499 */
500 if (nullFlags == NULL)
501 nullFlags = (bool *) palloc0(*nentries * sizeof(bool));
502
503 /*
504 * If there's more than one key, sort and unique-ify.
505 *
506 * XXX Using qsort here is notationally painful, and the overhead is
507 * pretty bad too. For small numbers of keys it'd likely be better to use
508 * a simple insertion sort.
509 */
510 if (*nentries > 1)
511 {
514
515 keydata = palloc_array(keyEntryData, *nentries);
516 for (i = 0; i < *nentries; i++)
517 {
518 keydata[i].datum = entries[i];
519 keydata[i].isnull = nullFlags[i];
520 }
521
522 arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
523 arg.collation = ginstate->supportCollation[attnum - 1];
524 arg.haveDups = false;
525 qsort_arg(keydata, *nentries, sizeof(keyEntryData),
526 cmpEntries, &arg);
527
528 if (arg.haveDups)
529 {
530 /* there are duplicates, must get rid of 'em */
531 int32 j;
532
533 entries[0] = keydata[0].datum;
534 nullFlags[0] = keydata[0].isnull;
535 j = 1;
536 for (i = 1; i < *nentries; i++)
537 {
538 if (cmpEntries(&keydata[i - 1], &keydata[i], &arg) != 0)
539 {
540 entries[j] = keydata[i].datum;
541 nullFlags[j] = keydata[i].isnull;
542 j++;
543 }
544 }
545 *nentries = j;
546 }
547 else
548 {
549 /* easy, no duplicates */
550 for (i = 0; i < *nentries; i++)
551 {
552 entries[i] = keydata[i].datum;
553 nullFlags[i] = keydata[i].isnull;
554 }
555 }
556
557 pfree(keydata);
558 }
559
560 /*
561 * Create GinNullCategory representation from nullFlags.
562 */
563 *categories = (GinNullCategory *) palloc0(*nentries * sizeof(GinNullCategory));
564 for (i = 0; i < *nentries; i++)
565 (*categories)[i] = (nullFlags[i] ? GIN_CAT_NULL_KEY : GIN_CAT_NORM_KEY);
566
567 return entries;
568}
569
570bytea *
571ginoptions(Datum reloptions, bool validate)
572{
573 static const relopt_parse_elt tab[] = {
574 {"fastupdate", RELOPT_TYPE_BOOL, offsetof(GinOptions, useFastUpdate)},
575 {"gin_pending_list_limit", RELOPT_TYPE_INT, offsetof(GinOptions,
576 pendingListCleanupSize)}
577 };
578
579 return (bytea *) build_reloptions(reloptions, validate,
581 sizeof(GinOptions),
582 tab, lengthof(tab));
583}
584
585/*
586 * Fetch index's statistical data into *stats
587 *
588 * Note: in the result, nPendingPages can be trusted to be up-to-date,
589 * as can ginVersion; but the other fields are as of the last VACUUM.
590 */
591void
593{
596 GinMetaPageData *metadata;
597
601 metadata = GinPageGetMeta(metapage);
602
603 stats->nPendingPages = metadata->nPendingPages;
604 stats->nTotalPages = metadata->nTotalPages;
605 stats->nEntryPages = metadata->nEntryPages;
606 stats->nDataPages = metadata->nDataPages;
607 stats->nEntries = metadata->nEntries;
608 stats->ginVersion = metadata->ginVersion;
609
611}
612
613/*
614 * Write the given statistics to the index's metapage
615 *
616 * Note: nPendingPages and ginVersion are *not* copied over
617 */
618void
619ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
620{
623 GinMetaPageData *metadata;
624
628 metadata = GinPageGetMeta(metapage);
629
631
632 metadata->nTotalPages = stats->nTotalPages;
633 metadata->nEntryPages = stats->nEntryPages;
634 metadata->nDataPages = stats->nDataPages;
635 metadata->nEntries = stats->nEntries;
636
637 /*
638 * Set pd_lower just past the end of the metadata. This is essential,
639 * because without doing so, metadata will be lost if xlog.c compresses
640 * the page. (We must do this here because pre-v11 versions of PG did not
641 * set the metapage's pd_lower correctly, so a pg_upgraded index might
642 * contain the wrong value.)
643 */
644 ((PageHeader) metapage)->pd_lower =
645 ((char *) metadata + sizeof(GinMetaPageData)) - (char *) metapage;
646
648
649 if (RelationNeedsWAL(index) && !is_build)
650 {
653
654 data.locator = index->rd_locator;
655 data.ntuples = 0;
656 data.newRightlink = data.prevTail = InvalidBlockNumber;
657 memcpy(&data.metadata, metadata, sizeof(GinMetaPageData));
658
662
665 }
666
668
670}
671
672/*
673 * ginbuildphasename() -- Return name of index build phase.
674 */
675char *
677{
678 switch (phasenum)
679 {
681 return "initializing";
683 return "scanning table";
685 return "sorting tuples (workers)";
687 return "merging tuples (workers)";
689 return "sorting tuples";
691 return "merging tuples";
692 default:
693 return NULL;
694 }
695}
int16 AttrNumber
Definition attnum.h:21
static bool validate(Port *port, const char *auth)
Definition auth-oauth.c:638
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:974
bool ConditionalLockBuffer(Buffer buffer)
Definition bufmgr.c:6484
void ReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5505
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5522
void MarkBufferDirty(Buffer buffer)
Definition bufmgr.c:3063
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition bufmgr.c:874
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:470
static Size BufferGetPageSize(Buffer buffer)
Definition bufmgr.h:459
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:332
@ 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:417
PageData * Page
Definition bufpage.h:81
#define Assert(condition)
Definition c.h:945
int64_t int64
Definition c.h:615
int32_t int32
Definition c.h:614
uint32_t uint32
Definition c.h:618
#define lengthof(array)
Definition c.h:875
#define MemSet(start, val, len)
Definition c.h:1109
#define OidIsValid(objectId)
Definition c.h:860
size_t Size
Definition c.h:691
Datum arg
Definition elog.c:1322
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
#define palloc_object(type)
Definition fe_memutils.h:74
#define palloc_array(type, count)
Definition fe_memutils.h:76
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:345
bytea * ginoptions(Datum reloptions, bool validate)
Definition ginutil.c:571
Datum ginhandler(PG_FUNCTION_ARGS)
Definition ginutil.c:38
void ginGetStats(Relation index, GinStatsData *stats)
Definition ginutil.c:592
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Definition ginutil.c:233
Buffer GinNewBuffer(Relation index)
Definition ginutil.c:307
void GinInitBuffer(Buffer b, uint32 f)
Definition ginutil.c:357
Datum * ginExtractEntries(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries, GinNullCategory **categories)
Definition ginutil.c:452
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
Definition ginutil.c:266
void GinInitMetabuffer(Buffer b)
Definition ginutil.c:363
static int cmpEntries(const void *a, const void *b, void *arg)
Definition ginutil.c:412
char * ginbuildphasename(int64 phasenum)
Definition ginutil.c:676
void initGinState(GinState *state, Relation index)
Definition ginutil.c:103
void ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
Definition ginutil.c:619
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:917
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition indexam.c:883
BlockNumber GetFreeIndexPage(Relation rel)
Definition indexfsm.c:38
static struct @174 value
int b
Definition isn.c:74
int a
Definition isn.c:73
int j
Definition isn.c:78
int i
Definition isn.c:77
static Datum index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition itup.h:131
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc0(Size size)
Definition mcxt.c:1417
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define START_CRIT_SECTION()
Definition miscadmin.h:150
#define END_CRIT_SECTION()
Definition miscadmin.h:152
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
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
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:132
#define RelationGetDescr(relation)
Definition rel.h:540
#define RelationGetRelationName(relation)
Definition rel.h:548
#define RelationNeedsWAL(relation)
Definition rel.h:637
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:47
@ RELOPT_TYPE_INT
Definition reloptions.h:33
@ RELOPT_TYPE_BOOL
Definition reloptions.h:31
@ 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:8622
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:406
bool haveDups
Definition ginutil.c:408
RelFileLocator locator
Definition ginxlog.h:170
Definition type.h:96
bool isnull
Definition ginutil.c:401
Datum datum
Definition ginutil.c:400
Definition c.h:778
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:508
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition tupdesc.c:1081
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:897
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:63
#define VACUUM_OPTION_PARALLEL_BULKDEL
Definition vacuum.h:48
uint64 XLogRecPtr
Definition xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition xloginsert.c:479
void XLogRegisterData(const void *data, uint32 len)
Definition xloginsert.c:369
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