PostgreSQL Source Code git master
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-2025, 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{
41
42 amroutine->amstrategies = 0;
43 amroutine->amsupport = GINNProcs;
45 amroutine->amcanorder = false;
46 amroutine->amcanorderbyop = false;
47 amroutine->amcanhash = false;
48 amroutine->amconsistentequality = false;
49 amroutine->amconsistentordering = false;
50 amroutine->amcanbackward = false;
51 amroutine->amcanunique = false;
52 amroutine->amcanmulticol = true;
53 amroutine->amoptionalkey = true;
54 amroutine->amsearcharray = false;
55 amroutine->amsearchnulls = false;
56 amroutine->amstorage = true;
57 amroutine->amclusterable = false;
58 amroutine->ampredlocks = true;
59 amroutine->amcanparallel = false;
60 amroutine->amcanbuildparallel = true;
61 amroutine->amcaninclude = false;
62 amroutine->amusemaintenanceworkmem = true;
63 amroutine->amsummarizing = false;
64 amroutine->amparallelvacuumoptions =
66 amroutine->amkeytype = InvalidOid;
67
68 amroutine->ambuild = ginbuild;
69 amroutine->ambuildempty = ginbuildempty;
70 amroutine->aminsert = gininsert;
71 amroutine->aminsertcleanup = NULL;
72 amroutine->ambulkdelete = ginbulkdelete;
74 amroutine->amcanreturn = NULL;
76 amroutine->amgettreeheight = NULL;
77 amroutine->amoptions = ginoptions;
78 amroutine->amproperty = NULL;
80 amroutine->amvalidate = ginvalidate;
82 amroutine->ambeginscan = ginbeginscan;
83 amroutine->amrescan = ginrescan;
84 amroutine->amgettuple = NULL;
85 amroutine->amgetbitmap = gingetbitmap;
86 amroutine->amendscan = ginendscan;
87 amroutine->ammarkpos = NULL;
88 amroutine->amrestrpos = NULL;
89 amroutine->amestimateparallelscan = NULL;
90 amroutine->aminitparallelscan = NULL;
91 amroutine->amparallelrescan = NULL;
92
93 PG_RETURN_POINTER(amroutine);
94}
95
96/*
97 * initGinState: fill in an empty GinState struct to describe the index
98 *
99 * Note: assorted subsidiary data is allocated in the CurrentMemoryContext.
100 */
101void
103{
104 TupleDesc origTupdesc = RelationGetDescr(index);
105 int i;
106
107 MemSet(state, 0, sizeof(GinState));
108
109 state->index = index;
110 state->oneCol = (origTupdesc->natts == 1);
111 state->origTupdesc = origTupdesc;
112
113 for (i = 0; i < origTupdesc->natts; i++)
114 {
115 Form_pg_attribute attr = TupleDescAttr(origTupdesc, i);
116
117 if (state->oneCol)
118 state->tupdesc[i] = state->origTupdesc;
119 else
120 {
121 state->tupdesc[i] = CreateTemplateTupleDesc(2);
122
123 TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 1, NULL,
124 INT2OID, -1, 0);
125 TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 2, NULL,
126 attr->atttypid,
127 attr->atttypmod,
128 attr->attndims);
130 attr->attcollation);
131 }
132
133 /*
134 * If the compare proc isn't specified in the opclass definition, look
135 * up the index key type's default btree comparator.
136 */
138 {
139 fmgr_info_copy(&(state->compareFn[i]),
142 }
143 else
144 {
145 TypeCacheEntry *typentry;
146
147 typentry = lookup_type_cache(attr->atttypid,
149 if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
151 (errcode(ERRCODE_UNDEFINED_FUNCTION),
152 errmsg("could not identify a comparison function for type %s",
153 format_type_be(attr->atttypid))));
154 fmgr_info_copy(&(state->compareFn[i]),
155 &(typentry->cmp_proc_finfo),
157 }
158
159 /* Opclass must always provide extract procs */
160 fmgr_info_copy(&(state->extractValueFn[i]),
163 fmgr_info_copy(&(state->extractQueryFn[i]),
166
167 /*
168 * Check opclass capability to do tri-state or binary logic consistent
169 * check.
170 */
172 {
173 fmgr_info_copy(&(state->triConsistentFn[i]),
176 }
177
179 {
180 fmgr_info_copy(&(state->consistentFn[i]),
183 }
184
185 if (state->consistentFn[i].fn_oid == InvalidOid &&
186 state->triConsistentFn[i].fn_oid == InvalidOid)
187 {
188 elog(ERROR, "missing GIN support function (%d or %d) for attribute %d of index \"%s\"",
191 }
192
193 /*
194 * Check opclass capability to do partial match.
195 */
197 {
198 fmgr_info_copy(&(state->comparePartialFn[i]),
201 state->canPartialMatch[i] = true;
202 }
203 else
204 {
205 state->canPartialMatch[i] = false;
206 }
207
208 /*
209 * If the index column has a specified collation, we should honor that
210 * while doing comparisons. However, we may have a collatable storage
211 * type for a noncollatable indexed data type (for instance, hstore
212 * uses text index entries). If there's no index collation then
213 * specify default collation in case the support functions need
214 * collation. This is harmless if the support functions don't care
215 * about collation, so we just do it unconditionally. (We could
216 * alternatively call get_typcollation, but that seems like expensive
217 * overkill --- there aren't going to be any cases where a GIN storage
218 * type has a nondefault collation.)
219 */
220 if (OidIsValid(index->rd_indcollation[i]))
221 state->supportCollation[i] = index->rd_indcollation[i];
222 else
223 state->supportCollation[i] = DEFAULT_COLLATION_OID;
224 }
225}
226
227/*
228 * Extract attribute (column) number of stored entry from GIN tuple
229 */
232{
233 OffsetNumber colN;
234
235 if (ginstate->oneCol)
236 {
237 /* column number is not stored explicitly */
238 colN = FirstOffsetNumber;
239 }
240 else
241 {
242 Datum res;
243 bool isnull;
244
245 /*
246 * First attribute is always int16, so we can safely use any tuple
247 * descriptor to obtain first attribute of tuple
248 */
249 res = index_getattr(tuple, FirstOffsetNumber, ginstate->tupdesc[0],
250 &isnull);
251 Assert(!isnull);
252
253 colN = DatumGetUInt16(res);
254 Assert(colN >= FirstOffsetNumber && colN <= ginstate->origTupdesc->natts);
255 }
256
257 return colN;
258}
259
260/*
261 * Extract stored datum (and possible null category) from GIN tuple
262 */
263Datum
265 GinNullCategory *category)
266{
267 Datum res;
268 bool isnull;
269
270 if (ginstate->oneCol)
271 {
272 /*
273 * Single column index doesn't store attribute numbers in tuples
274 */
275 res = index_getattr(tuple, FirstOffsetNumber, ginstate->origTupdesc,
276 &isnull);
277 }
278 else
279 {
280 /*
281 * Since the datum type depends on which index column it's from, we
282 * must be careful to use the right tuple descriptor here.
283 */
284 OffsetNumber colN = gintuple_get_attrnum(ginstate, tuple);
285
287 ginstate->tupdesc[colN - 1],
288 &isnull);
289 }
290
291 if (isnull)
292 *category = GinGetNullCategory(tuple, ginstate);
293 else
294 *category = GIN_CAT_NORM_KEY;
295
296 return res;
297}
298
299/*
300 * Allocate a new page (either by recycling, or by extending the index file)
301 * The returned buffer is already pinned and exclusive-locked
302 * Caller is responsible for initializing the page by calling GinInitBuffer
303 */
304Buffer
306{
307 Buffer buffer;
308
309 /* First, try to get a page from FSM */
310 for (;;)
311 {
313
314 if (blkno == InvalidBlockNumber)
315 break;
316
317 buffer = ReadBuffer(index, blkno);
318
319 /*
320 * We have to guard against the possibility that someone else already
321 * recycled this page; the buffer may be locked if so.
322 */
323 if (ConditionalLockBuffer(buffer))
324 {
326 return buffer; /* OK to use */
327
328 LockBuffer(buffer, GIN_UNLOCK);
329 }
330
331 /* Can't use it, so release buffer and try again */
332 ReleaseBuffer(buffer);
333 }
334
335 /* Must extend the file */
338
339 return buffer;
340}
341
342void
343GinInitPage(Page page, uint32 f, Size pageSize)
344{
345 GinPageOpaque opaque;
346
347 PageInit(page, pageSize, sizeof(GinPageOpaqueData));
348
349 opaque = GinPageGetOpaque(page);
350 opaque->flags = f;
352}
353
354void
356{
358}
359
360void
362{
363 GinMetaPageData *metadata;
364 Page page = BufferGetPage(b);
365
367
368 metadata = GinPageGetMeta(page);
369
370 metadata->head = metadata->tail = InvalidBlockNumber;
371 metadata->tailFreeSize = 0;
372 metadata->nPendingPages = 0;
373 metadata->nPendingHeapTuples = 0;
374 metadata->nTotalPages = 0;
375 metadata->nEntryPages = 0;
376 metadata->nDataPages = 0;
377 metadata->nEntries = 0;
379
380 /*
381 * Set pd_lower just past the end of the metadata. This is essential,
382 * because without doing so, metadata will be lost if xlog.c compresses
383 * the page.
384 */
385 ((PageHeader) page)->pd_lower =
386 ((char *) metadata + sizeof(GinMetaPageData)) - (char *) page;
387}
388
389/*
390 * Compare two keys of the same index column
391 */
392int
394 Datum a, GinNullCategory categorya,
395 Datum b, GinNullCategory categoryb)
396{
397 /* if not of same null category, sort by that first */
398 if (categorya != categoryb)
399 return (categorya < categoryb) ? -1 : 1;
400
401 /* all null items in same category are equal */
402 if (categorya != GIN_CAT_NORM_KEY)
403 return 0;
404
405 /* both not null, so safe to call the compareFn */
406 return DatumGetInt32(FunctionCall2Coll(&ginstate->compareFn[attnum - 1],
407 ginstate->supportCollation[attnum - 1],
408 a, b));
409}
410
411/*
412 * Compare two keys of possibly different index columns
413 */
414int
416 OffsetNumber attnuma, Datum a, GinNullCategory categorya,
417 OffsetNumber attnumb, Datum b, GinNullCategory categoryb)
418{
419 /* attribute number is the first sort key */
420 if (attnuma != attnumb)
421 return (attnuma < attnumb) ? -1 : 1;
422
423 return ginCompareEntries(ginstate, attnuma, a, categorya, b, categoryb);
424}
425
426
427/*
428 * Support for sorting key datums in ginExtractEntries
429 *
430 * Note: we only have to worry about null and not-null keys here;
431 * ginExtractEntries never generates more than one placeholder null,
432 * so it doesn't have to sort those.
433 */
434typedef struct
435{
437 bool isnull;
439
440typedef struct
441{
446
447static int
448cmpEntries(const void *a, const void *b, void *arg)
449{
450 const keyEntryData *aa = (const keyEntryData *) a;
451 const keyEntryData *bb = (const keyEntryData *) b;
453 int res;
454
455 if (aa->isnull)
456 {
457 if (bb->isnull)
458 res = 0; /* NULL "=" NULL */
459 else
460 res = 1; /* NULL ">" not-NULL */
461 }
462 else if (bb->isnull)
463 res = -1; /* not-NULL "<" NULL */
464 else
465 res = DatumGetInt32(FunctionCall2Coll(data->cmpDatumFunc,
466 data->collation,
467 aa->datum, bb->datum));
468
469 /*
470 * Detect if we have any duplicates. If there are equal keys, qsort must
471 * compare them at some point, else it wouldn't know whether one should go
472 * before or after the other.
473 */
474 if (res == 0)
475 data->haveDups = true;
476
477 return res;
478}
479
480
481/*
482 * Extract the index key values from an indexable item
483 *
484 * The resulting key values are sorted, and any duplicates are removed.
485 * This avoids generating redundant index entries.
486 */
487Datum *
489 Datum value, bool isNull,
490 int32 *nentries, GinNullCategory **categories)
491{
492 Datum *entries;
493 bool *nullFlags;
494 int32 i;
495
496 /*
497 * We don't call the extractValueFn on a null item. Instead generate a
498 * placeholder.
499 */
500 if (isNull)
501 {
502 *nentries = 1;
503 entries = (Datum *) palloc(sizeof(Datum));
504 entries[0] = (Datum) 0;
505 *categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
506 (*categories)[0] = GIN_CAT_NULL_ITEM;
507 return entries;
508 }
509
510 /* OK, call the opclass's extractValueFn */
511 nullFlags = NULL; /* in case extractValue doesn't set it */
512 entries = (Datum *)
514 ginstate->supportCollation[attnum - 1],
515 value,
516 PointerGetDatum(nentries),
517 PointerGetDatum(&nullFlags)));
518
519 /*
520 * Generate a placeholder if the item contained no keys.
521 */
522 if (entries == NULL || *nentries <= 0)
523 {
524 *nentries = 1;
525 entries = (Datum *) palloc(sizeof(Datum));
526 entries[0] = (Datum) 0;
527 *categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
528 (*categories)[0] = GIN_CAT_EMPTY_ITEM;
529 return entries;
530 }
531
532 /*
533 * If the extractValueFn didn't create a nullFlags array, create one,
534 * assuming that everything's non-null.
535 */
536 if (nullFlags == NULL)
537 nullFlags = (bool *) palloc0(*nentries * sizeof(bool));
538
539 /*
540 * If there's more than one key, sort and unique-ify.
541 *
542 * XXX Using qsort here is notationally painful, and the overhead is
543 * pretty bad too. For small numbers of keys it'd likely be better to use
544 * a simple insertion sort.
545 */
546 if (*nentries > 1)
547 {
548 keyEntryData *keydata;
550
551 keydata = (keyEntryData *) palloc(*nentries * sizeof(keyEntryData));
552 for (i = 0; i < *nentries; i++)
553 {
554 keydata[i].datum = entries[i];
555 keydata[i].isnull = nullFlags[i];
556 }
557
558 arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
559 arg.collation = ginstate->supportCollation[attnum - 1];
560 arg.haveDups = false;
561 qsort_arg(keydata, *nentries, sizeof(keyEntryData),
562 cmpEntries, &arg);
563
564 if (arg.haveDups)
565 {
566 /* there are duplicates, must get rid of 'em */
567 int32 j;
568
569 entries[0] = keydata[0].datum;
570 nullFlags[0] = keydata[0].isnull;
571 j = 1;
572 for (i = 1; i < *nentries; i++)
573 {
574 if (cmpEntries(&keydata[i - 1], &keydata[i], &arg) != 0)
575 {
576 entries[j] = keydata[i].datum;
577 nullFlags[j] = keydata[i].isnull;
578 j++;
579 }
580 }
581 *nentries = j;
582 }
583 else
584 {
585 /* easy, no duplicates */
586 for (i = 0; i < *nentries; i++)
587 {
588 entries[i] = keydata[i].datum;
589 nullFlags[i] = keydata[i].isnull;
590 }
591 }
592
593 pfree(keydata);
594 }
595
596 /*
597 * Create GinNullCategory representation from nullFlags.
598 */
599 *categories = (GinNullCategory *) palloc0(*nentries * sizeof(GinNullCategory));
600 for (i = 0; i < *nentries; i++)
601 (*categories)[i] = (nullFlags[i] ? GIN_CAT_NULL_KEY : GIN_CAT_NORM_KEY);
602
603 return entries;
604}
605
606bytea *
607ginoptions(Datum reloptions, bool validate)
608{
609 static const relopt_parse_elt tab[] = {
610 {"fastupdate", RELOPT_TYPE_BOOL, offsetof(GinOptions, useFastUpdate)},
611 {"gin_pending_list_limit", RELOPT_TYPE_INT, offsetof(GinOptions,
612 pendingListCleanupSize)}
613 };
614
615 return (bytea *) build_reloptions(reloptions, validate,
617 sizeof(GinOptions),
618 tab, lengthof(tab));
619}
620
621/*
622 * Fetch index's statistical data into *stats
623 *
624 * Note: in the result, nPendingPages can be trusted to be up-to-date,
625 * as can ginVersion; but the other fields are as of the last VACUUM.
626 */
627void
629{
630 Buffer metabuffer;
631 Page metapage;
632 GinMetaPageData *metadata;
633
634 metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO);
635 LockBuffer(metabuffer, GIN_SHARE);
636 metapage = BufferGetPage(metabuffer);
637 metadata = GinPageGetMeta(metapage);
638
639 stats->nPendingPages = metadata->nPendingPages;
640 stats->nTotalPages = metadata->nTotalPages;
641 stats->nEntryPages = metadata->nEntryPages;
642 stats->nDataPages = metadata->nDataPages;
643 stats->nEntries = metadata->nEntries;
644 stats->ginVersion = metadata->ginVersion;
645
646 UnlockReleaseBuffer(metabuffer);
647}
648
649/*
650 * Write the given statistics to the index's metapage
651 *
652 * Note: nPendingPages and ginVersion are *not* copied over
653 */
654void
655ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
656{
657 Buffer metabuffer;
658 Page metapage;
659 GinMetaPageData *metadata;
660
661 metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO);
662 LockBuffer(metabuffer, GIN_EXCLUSIVE);
663 metapage = BufferGetPage(metabuffer);
664 metadata = GinPageGetMeta(metapage);
665
667
668 metadata->nTotalPages = stats->nTotalPages;
669 metadata->nEntryPages = stats->nEntryPages;
670 metadata->nDataPages = stats->nDataPages;
671 metadata->nEntries = stats->nEntries;
672
673 /*
674 * Set pd_lower just past the end of the metadata. This is essential,
675 * because without doing so, metadata will be lost if xlog.c compresses
676 * the page. (We must do this here because pre-v11 versions of PG did not
677 * set the metapage's pd_lower correctly, so a pg_upgraded index might
678 * contain the wrong value.)
679 */
680 ((PageHeader) metapage)->pd_lower =
681 ((char *) metadata + sizeof(GinMetaPageData)) - (char *) metapage;
682
683 MarkBufferDirty(metabuffer);
684
685 if (RelationNeedsWAL(index) && !is_build)
686 {
687 XLogRecPtr recptr;
689
690 data.locator = index->rd_locator;
691 data.ntuples = 0;
692 data.newRightlink = data.prevTail = InvalidBlockNumber;
693 memcpy(&data.metadata, metadata, sizeof(GinMetaPageData));
694
698
699 recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_UPDATE_META_PAGE);
700 PageSetLSN(metapage, recptr);
701 }
702
703 UnlockReleaseBuffer(metabuffer);
704
706}
707
708/*
709 * ginbuildphasename() -- Return name of index build phase.
710 */
711char *
713{
714 switch (phasenum)
715 {
717 return "initializing";
719 return "scanning table";
721 return "sorting tuples (workers)";
723 return "merging tuples (workers)";
725 return "sorting tuples";
727 return "merging tuples";
728 default:
729 return NULL;
730 }
731}
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:851
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:5177
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4917
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4934
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2596
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5151
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:751
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:401
static Size BufferGetPageSize(Buffer buffer)
Definition: bufmgr.h:390
@ EB_LOCK_FIRST
Definition: bufmgr.h:86
#define BMR_REL(p_rel)
Definition: bufmgr.h:107
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:42
PageHeaderData * PageHeader
Definition: bufpage.h:174
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:391
PageData * Page
Definition: bufpage.h:82
int64_t int64
Definition: c.h:499
int32_t int32
Definition: c.h:498
uint32_t uint32
Definition: c.h:502
#define lengthof(array)
Definition: c.h:759
#define MemSet(start, val, len)
Definition: c.h:991
#define OidIsValid(objectId)
Definition: c.h:746
size_t Size
Definition: c.h:576
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1149
Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition: fmgr.c:1171
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:580
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#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:49
#define GIN_EXCLUSIVE
Definition: gin_private.h:51
#define GIN_SHARE
Definition: gin_private.h:50
#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:1929
IndexBuildResult * ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
Definition: gininsert.c:581
void ginbuildempty(Relation index)
Definition: gininsert.c:775
bool gininsert(Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
Definition: gininsert.c:824
IndexScanDesc ginbeginscan(Relation rel, int nkeys, int norderbys)
Definition: ginscan.c:25
void ginendscan(IndexScanDesc scan)
Definition: ginscan.c:463
void ginrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
Definition: ginscan.c:450
void GinInitPage(Page page, uint32 f, Size pageSize)
Definition: ginutil.c:343
bytea * ginoptions(Datum reloptions, bool validate)
Definition: ginutil.c:607
Datum ginhandler(PG_FUNCTION_ARGS)
Definition: ginutil.c:38
void ginGetStats(Relation index, GinStatsData *stats)
Definition: ginutil.c:628
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Definition: ginutil.c:231
Buffer GinNewBuffer(Relation index)
Definition: ginutil.c:305
void GinInitBuffer(Buffer b, uint32 f)
Definition: ginutil.c:355
Datum * ginExtractEntries(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries, GinNullCategory **categories)
Definition: ginutil.c:488
int ginCompareAttEntries(GinState *ginstate, OffsetNumber attnuma, Datum a, GinNullCategory categorya, OffsetNumber attnumb, Datum b, GinNullCategory categoryb)
Definition: ginutil.c:415
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
Definition: ginutil.c:264
void GinInitMetabuffer(Buffer b)
Definition: ginutil.c:361
static int cmpEntries(const void *a, const void *b, void *arg)
Definition: ginutil.c:448
char * ginbuildphasename(int64 phasenum)
Definition: ginutil.c:712
void initGinState(GinState *state, Relation index)
Definition: ginutil.c:102
int ginCompareEntries(GinState *ginstate, OffsetNumber attnum, Datum a, GinNullCategory categorya, Datum b, GinNullCategory categoryb)
Definition: ginutil.c:393
void ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
Definition: ginutil.c:655
bool GinPageIsRecyclable(Page page)
Definition: ginvacuum.c:801
IndexBulkDeleteResult * ginbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
Definition: ginvacuum.c:564
IndexBulkDeleteResult * ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
Definition: ginvacuum.c:687
bool ginvalidate(Oid opclassoid)
Definition: ginvalidate.c:31
void ginadjustmembers(Oid opfamilyoid, Oid opclassoid, List *operators, List *functions)
Definition: ginvalidate.c:269
#define XLOG_GIN_UPDATE_META_PAGE
Definition: ginxlog.h:162
Assert(PointerIsAligned(start, uint64))
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:906
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:872
BlockNumber GetFreeIndexPage(Relation rel)
Definition: indexfsm.c:38
static struct @165 value
int b
Definition: isn.c:71
int a
Definition: isn.c:70
int j
Definition: isn.c:75
int i
Definition: isn.c:74
static Datum index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: itup.h:131
void pfree(void *pointer)
Definition: mcxt.c:1524
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
#define makeNode(_type_)
Definition: nodes.h:157
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
void * arg
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:327
uintptr_t Datum
Definition: postgres.h:69
static uint16 DatumGetUInt16(Datum X)
Definition: postgres.h:187
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:207
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE
Definition: progress.h:109
#define RelationGetDescr(relation)
Definition: rel.h:539
#define RelationGetRelationName(relation)
Definition: rel.h:547
#define RelationNeedsWAL(relation)
Definition: rel.h:636
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
Definition: reloptions.c:1942
@ RELOPT_KIND_GIN
Definition: reloptions.h:46
@ RELOPT_TYPE_INT
Definition: reloptions.h:32
@ 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:7801
Definition: fmgr.h:57
Oid fn_oid
Definition: fmgr.h:59
int64 nEntries
Definition: ginblock.h:82
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:60
TupleDesc tupdesc[INDEX_MAX_KEYS]
Definition: gin_private.h:74
TupleDesc origTupdesc
Definition: gin_private.h:73
FmgrInfo extractValueFn[INDEX_MAX_KEYS]
Definition: gin_private.h:80
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gin_private.h:88
FmgrInfo compareFn[INDEX_MAX_KEYS]
Definition: gin_private.h:79
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
ambuildphasename_function ambuildphasename
Definition: amapi.h:303
ambuildempty_function ambuildempty
Definition: amapi.h:293
amvacuumcleanup_function amvacuumcleanup
Definition: amapi.h:297
bool amclusterable
Definition: amapi.h:267
amoptions_function amoptions
Definition: amapi.h:301
amestimateparallelscan_function amestimateparallelscan
Definition: amapi.h:315
amrestrpos_function amrestrpos
Definition: amapi.h:312
aminsert_function aminsert
Definition: amapi.h:294
amendscan_function amendscan
Definition: amapi.h:310
uint16 amoptsprocnum
Definition: amapi.h:241
amparallelrescan_function amparallelrescan
Definition: amapi.h:317
Oid amkeytype
Definition: amapi.h:283
bool amconsistentordering
Definition: amapi.h:251
bool ampredlocks
Definition: amapi.h:269
uint16 amsupport
Definition: amapi.h:239
amcostestimate_function amcostestimate
Definition: amapi.h:299
bool amcanorderbyop
Definition: amapi.h:245
amadjustmembers_function amadjustmembers
Definition: amapi.h:305
ambuild_function ambuild
Definition: amapi.h:292
bool amstorage
Definition: amapi.h:265
uint16 amstrategies
Definition: amapi.h:237
bool amoptionalkey
Definition: amapi.h:259
amgettuple_function amgettuple
Definition: amapi.h:308
amcanreturn_function amcanreturn
Definition: amapi.h:298
bool amcanunique
Definition: amapi.h:255
amgetbitmap_function amgetbitmap
Definition: amapi.h:309
amproperty_function amproperty
Definition: amapi.h:302
ambulkdelete_function ambulkdelete
Definition: amapi.h:296
bool amsearcharray
Definition: amapi.h:261
bool amsummarizing
Definition: amapi.h:279
amvalidate_function amvalidate
Definition: amapi.h:304
ammarkpos_function ammarkpos
Definition: amapi.h:311
bool amcanmulticol
Definition: amapi.h:257
bool amusemaintenanceworkmem
Definition: amapi.h:277
ambeginscan_function ambeginscan
Definition: amapi.h:306
bool amcanparallel
Definition: amapi.h:271
amrescan_function amrescan
Definition: amapi.h:307
bool amcanorder
Definition: amapi.h:243
bool amcanbuildparallel
Definition: amapi.h:273
aminitparallelscan_function aminitparallelscan
Definition: amapi.h:316
uint8 amparallelvacuumoptions
Definition: amapi.h:281
aminsertcleanup_function aminsertcleanup
Definition: amapi.h:295
bool amcanbackward
Definition: amapi.h:253
amgettreeheight_function amgettreeheight
Definition: amapi.h:300
bool amcaninclude
Definition: amapi.h:275
bool amsearchnulls
Definition: amapi.h:263
bool amconsistentequality
Definition: amapi.h:249
bool amcanhash
Definition: amapi.h:247
FmgrInfo cmp_proc_finfo
Definition: typcache.h:76
FmgrInfo * cmpDatumFunc
Definition: ginutil.c:442
Oid collation
Definition: ginutil.c:443
bool haveDups
Definition: ginutil.c:444
Definition: type.h:96
bool isnull
Definition: ginutil.c:437
Datum datum
Definition: ginutil.c:436
Definition: regguts.h:323
Definition: c.h:658
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:164
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:985
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:801
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:154
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:143
#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:474
void XLogRegisterData(const void *data, uint32 len)
Definition: xloginsert.c:364
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:242
void XLogBeginInsert(void)
Definition: xloginsert.c:149
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define REGBUF_WILL_INIT
Definition: xloginsert.h:34