123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- /*--------------------------------------------------------------------------
- * gin_private.h
- * header file for postgres inverted index access method implementation.
- *
- * Copyright (c) 2006-2022, PostgreSQL Global Development Group
- *
- * src/include/access/gin_private.h
- *--------------------------------------------------------------------------
- */
- #ifndef GIN_PRIVATE_H
- #define GIN_PRIVATE_H
- #include "access/amapi.h"
- #include "access/gin.h"
- #include "access/ginblock.h"
- #include "access/itup.h"
- #include "catalog/pg_am_d.h"
- #include "fmgr.h"
- #include "lib/rbtree.h"
- #include "storage/bufmgr.h"
- /*
- * Storage type for GIN's reloptions
- */
- typedef struct GinOptions
- {
- int32 vl_len_; /* varlena header (do not touch directly!) */
- bool useFastUpdate; /* use fast updates? */
- int pendingListCleanupSize; /* maximum size of pending list */
- } GinOptions;
- #define GIN_DEFAULT_USE_FASTUPDATE true
- #define GinGetUseFastUpdate(relation) \
- (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
- relation->rd_rel->relam == GIN_AM_OID), \
- (relation)->rd_options ? \
- ((GinOptions *) (relation)->rd_options)->useFastUpdate : GIN_DEFAULT_USE_FASTUPDATE)
- #define GinGetPendingListCleanupSize(relation) \
- (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
- relation->rd_rel->relam == GIN_AM_OID), \
- (relation)->rd_options && \
- ((GinOptions *) (relation)->rd_options)->pendingListCleanupSize != -1 ? \
- ((GinOptions *) (relation)->rd_options)->pendingListCleanupSize : \
- gin_pending_list_limit)
- /* Macros for buffer lock/unlock operations */
- #define GIN_UNLOCK BUFFER_LOCK_UNLOCK
- #define GIN_SHARE BUFFER_LOCK_SHARE
- #define GIN_EXCLUSIVE BUFFER_LOCK_EXCLUSIVE
- /*
- * GinState: working data structure describing the index being worked on
- */
- typedef struct GinState
- {
- Relation index;
- bool oneCol; /* true if single-column index */
- /*
- * origTupdesc is the nominal tuple descriptor of the index, ie, the i'th
- * attribute shows the key type (not the input data type!) of the i'th
- * index column. In a single-column index this describes the actual leaf
- * index tuples. In a multi-column index, the actual leaf tuples contain
- * a smallint column number followed by a key datum of the appropriate
- * type for that column. We set up tupdesc[i] to describe the actual
- * rowtype of the index tuples for the i'th column, ie, (int2, keytype).
- * Note that in any case, leaf tuples contain more data than is known to
- * the TupleDesc; see access/gin/README for details.
- */
- TupleDesc origTupdesc;
- TupleDesc tupdesc[INDEX_MAX_KEYS];
- /*
- * Per-index-column opclass support functions
- */
- FmgrInfo compareFn[INDEX_MAX_KEYS];
- FmgrInfo extractValueFn[INDEX_MAX_KEYS];
- FmgrInfo extractQueryFn[INDEX_MAX_KEYS];
- FmgrInfo consistentFn[INDEX_MAX_KEYS];
- FmgrInfo triConsistentFn[INDEX_MAX_KEYS];
- FmgrInfo comparePartialFn[INDEX_MAX_KEYS]; /* optional method */
- /* canPartialMatch[i] is true if comparePartialFn[i] is valid */
- bool canPartialMatch[INDEX_MAX_KEYS];
- /* Collations to pass to the support functions */
- Oid supportCollation[INDEX_MAX_KEYS];
- } GinState;
- /* ginutil.c */
- extern bytea *ginoptions(Datum reloptions, bool validate);
- extern void initGinState(GinState *state, Relation index);
- extern Buffer GinNewBuffer(Relation index);
- extern void GinInitBuffer(Buffer b, uint32 f);
- extern void GinInitPage(Page page, uint32 f, Size pageSize);
- extern void GinInitMetabuffer(Buffer b);
- extern int ginCompareEntries(GinState *ginstate, OffsetNumber attnum,
- Datum a, GinNullCategory categorya,
- Datum b, GinNullCategory categoryb);
- extern int ginCompareAttEntries(GinState *ginstate,
- OffsetNumber attnuma, Datum a, GinNullCategory categorya,
- OffsetNumber attnumb, Datum b, GinNullCategory categoryb);
- extern Datum *ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
- Datum value, bool isNull,
- int32 *nentries, GinNullCategory **categories);
- extern OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple);
- extern Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple,
- GinNullCategory *category);
- /* gininsert.c */
- extern IndexBuildResult *ginbuild(Relation heap, Relation index,
- struct IndexInfo *indexInfo);
- extern void ginbuildempty(Relation index);
- extern bool gininsert(Relation index, Datum *values, bool *isnull,
- ItemPointer ht_ctid, Relation heapRel,
- IndexUniqueCheck checkUnique,
- bool indexUnchanged,
- struct IndexInfo *indexInfo);
- extern void ginEntryInsert(GinState *ginstate,
- OffsetNumber attnum, Datum key, GinNullCategory category,
- ItemPointerData *items, uint32 nitem,
- GinStatsData *buildStats);
- /* ginbtree.c */
- typedef struct GinBtreeStack
- {
- BlockNumber blkno;
- Buffer buffer;
- OffsetNumber off;
- ItemPointerData iptr;
- /* predictNumber contains predicted number of pages on current level */
- uint32 predictNumber;
- struct GinBtreeStack *parent;
- } GinBtreeStack;
- typedef struct GinBtreeData *GinBtree;
- /* Return codes for GinBtreeData.beginPlaceToPage method */
- typedef enum
- {
- GPTP_NO_WORK,
- GPTP_INSERT,
- GPTP_SPLIT
- } GinPlaceToPageRC;
- typedef struct GinBtreeData
- {
- /* search methods */
- BlockNumber (*findChildPage) (GinBtree, GinBtreeStack *);
- BlockNumber (*getLeftMostChild) (GinBtree, Page);
- bool (*isMoveRight) (GinBtree, Page);
- bool (*findItem) (GinBtree, GinBtreeStack *);
- /* insert methods */
- OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber);
- GinPlaceToPageRC (*beginPlaceToPage) (GinBtree, Buffer, GinBtreeStack *, void *, BlockNumber, void **, Page *, Page *);
- void (*execPlaceToPage) (GinBtree, Buffer, GinBtreeStack *, void *, BlockNumber, void *);
- void *(*prepareDownlink) (GinBtree, Buffer);
- void (*fillRoot) (GinBtree, Page, BlockNumber, Page, BlockNumber, Page);
- bool isData;
- Relation index;
- BlockNumber rootBlkno;
- GinState *ginstate; /* not valid in a data scan */
- bool fullScan;
- bool isBuild;
- /* Search key for Entry tree */
- OffsetNumber entryAttnum;
- Datum entryKey;
- GinNullCategory entryCategory;
- /* Search key for data tree (posting tree) */
- ItemPointerData itemptr;
- } GinBtreeData;
- /* This represents a tuple to be inserted to entry tree. */
- typedef struct
- {
- IndexTuple entry; /* tuple to insert */
- bool isDelete; /* delete old tuple at same offset? */
- } GinBtreeEntryInsertData;
- /*
- * This represents an itempointer, or many itempointers, to be inserted to
- * a data (posting tree) leaf page
- */
- typedef struct
- {
- ItemPointerData *items;
- uint32 nitem;
- uint32 curitem;
- } GinBtreeDataLeafInsertData;
- /*
- * For internal data (posting tree) pages, the insertion payload is a
- * PostingItem
- */
- extern GinBtreeStack *ginFindLeafPage(GinBtree btree, bool searchMode,
- bool rootConflictCheck, Snapshot snapshot);
- extern Buffer ginStepRight(Buffer buffer, Relation index, int lockmode);
- extern void freeGinBtreeStack(GinBtreeStack *stack);
- extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack,
- void *insertdata, GinStatsData *buildStats);
- /* ginentrypage.c */
- extern IndexTuple GinFormTuple(GinState *ginstate,
- OffsetNumber attnum, Datum key, GinNullCategory category,
- Pointer data, Size dataSize, int nipd, bool errorTooBig);
- extern void ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum,
- Datum key, GinNullCategory category,
- GinState *ginstate);
- extern void ginEntryFillRoot(GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage);
- extern ItemPointer ginReadTuple(GinState *ginstate, OffsetNumber attnum,
- IndexTuple itup, int *nitems);
- /* gindatapage.c */
- extern ItemPointer GinDataLeafPageGetItems(Page page, int *nitems, ItemPointerData advancePast);
- extern int GinDataLeafPageGetItemsToTbm(Page page, TIDBitmap *tbm);
- extern BlockNumber createPostingTree(Relation index,
- ItemPointerData *items, uint32 nitems,
- GinStatsData *buildStats, Buffer entrybuffer);
- extern void GinDataPageAddPostingItem(Page page, PostingItem *data, OffsetNumber offset);
- extern void GinPageDeletePostingItem(Page page, OffsetNumber offset);
- extern void ginInsertItemPointers(Relation index, BlockNumber rootBlkno,
- ItemPointerData *items, uint32 nitem,
- GinStatsData *buildStats);
- extern GinBtreeStack *ginScanBeginPostingTree(GinBtree btree, Relation index, BlockNumber rootBlkno, Snapshot snapshot);
- extern void ginDataFillRoot(GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage);
- /*
- * This is declared in ginvacuum.c, but is passed between ginVacuumItemPointers
- * and ginVacuumPostingTreeLeaf and as an opaque struct, so we need a forward
- * declaration for it.
- */
- typedef struct GinVacuumState GinVacuumState;
- extern void ginVacuumPostingTreeLeaf(Relation rel, Buffer buf, GinVacuumState *gvs);
- /* ginscan.c */
- /*
- * GinScanKeyData describes a single GIN index qualifier expression.
- *
- * From each qual expression, we extract one or more specific index search
- * conditions, which are represented by GinScanEntryData. It's quite
- * possible for identical search conditions to be requested by more than
- * one qual expression, in which case we merge such conditions to have just
- * one unique GinScanEntry --- this is particularly important for efficiency
- * when dealing with full-index-scan entries. So there can be multiple
- * GinScanKeyData.scanEntry pointers to the same GinScanEntryData.
- *
- * In each GinScanKeyData, nentries is the true number of entries, while
- * nuserentries is the number that extractQueryFn returned (which is what
- * we report to consistentFn). The "user" entries must come first.
- */
- typedef struct GinScanKeyData *GinScanKey;
- typedef struct GinScanEntryData *GinScanEntry;
- typedef struct GinScanKeyData
- {
- /* Real number of entries in scanEntry[] (always > 0) */
- uint32 nentries;
- /* Number of entries that extractQueryFn and consistentFn know about */
- uint32 nuserentries;
- /* array of GinScanEntry pointers, one per extracted search condition */
- GinScanEntry *scanEntry;
- /*
- * At least one of the entries in requiredEntries must be present for a
- * tuple to match the overall qual.
- *
- * additionalEntries contains entries that are needed by the consistent
- * function to decide if an item matches, but are not sufficient to
- * satisfy the qual without entries from requiredEntries.
- */
- GinScanEntry *requiredEntries;
- int nrequired;
- GinScanEntry *additionalEntries;
- int nadditional;
- /* array of check flags, reported to consistentFn */
- GinTernaryValue *entryRes;
- bool (*boolConsistentFn) (GinScanKey key);
- GinTernaryValue (*triConsistentFn) (GinScanKey key);
- FmgrInfo *consistentFmgrInfo;
- FmgrInfo *triConsistentFmgrInfo;
- Oid collation;
- /* other data needed for calling consistentFn */
- Datum query;
- /* NB: these three arrays have only nuserentries elements! */
- Datum *queryValues;
- GinNullCategory *queryCategories;
- Pointer *extra_data;
- StrategyNumber strategy;
- int32 searchMode;
- OffsetNumber attnum;
- /*
- * An excludeOnly scan key is not able to enumerate all matching tuples.
- * That is, to be semantically correct on its own, it would need to have a
- * GIN_CAT_EMPTY_QUERY scanEntry, but it doesn't. Such a key can still be
- * used to filter tuples returned by other scan keys, so we will get the
- * right answers as long as there's at least one non-excludeOnly scan key
- * for each index attribute considered by the search. For efficiency
- * reasons we don't want to have unnecessary GIN_CAT_EMPTY_QUERY entries,
- * so we will convert an excludeOnly scan key to non-excludeOnly (by
- * adding a GIN_CAT_EMPTY_QUERY scanEntry) only if there are no other
- * non-excludeOnly scan keys.
- */
- bool excludeOnly;
- /*
- * Match status data. curItem is the TID most recently tested (could be a
- * lossy-page pointer). curItemMatches is true if it passes the
- * consistentFn test; if so, recheckCurItem is the recheck flag.
- * isFinished means that all the input entry streams are finished, so this
- * key cannot succeed for any later TIDs.
- */
- ItemPointerData curItem;
- bool curItemMatches;
- bool recheckCurItem;
- bool isFinished;
- } GinScanKeyData;
- typedef struct GinScanEntryData
- {
- /* query key and other information from extractQueryFn */
- Datum queryKey;
- GinNullCategory queryCategory;
- bool isPartialMatch;
- Pointer extra_data;
- StrategyNumber strategy;
- int32 searchMode;
- OffsetNumber attnum;
- /* Current page in posting tree */
- Buffer buffer;
- /* current ItemPointer to heap */
- ItemPointerData curItem;
- /* for a partial-match or full-scan query, we accumulate all TIDs here */
- TIDBitmap *matchBitmap;
- TBMIterator *matchIterator;
- TBMIterateResult *matchResult;
- /* used for Posting list and one page in Posting tree */
- ItemPointerData *list;
- int nlist;
- OffsetNumber offset;
- bool isFinished;
- bool reduceResult;
- uint32 predictNumberResult;
- GinBtreeData btree;
- } GinScanEntryData;
- typedef struct GinScanOpaqueData
- {
- MemoryContext tempCtx;
- GinState ginstate;
- GinScanKey keys; /* one per scan qualifier expr */
- uint32 nkeys;
- GinScanEntry *entries; /* one per index search condition */
- uint32 totalentries;
- uint32 allocentries; /* allocated length of entries[] */
- MemoryContext keyCtx; /* used to hold key and entry data */
- bool isVoidRes; /* true if query is unsatisfiable */
- } GinScanOpaqueData;
- typedef GinScanOpaqueData *GinScanOpaque;
- extern IndexScanDesc ginbeginscan(Relation rel, int nkeys, int norderbys);
- extern void ginendscan(IndexScanDesc scan);
- extern void ginrescan(IndexScanDesc scan, ScanKey key, int nscankeys,
- ScanKey orderbys, int norderbys);
- extern void ginNewScanKey(IndexScanDesc scan);
- extern void ginFreeScanKeys(GinScanOpaque so);
- /* ginget.c */
- extern int64 gingetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
- /* ginlogic.c */
- extern void ginInitConsistentFunction(GinState *ginstate, GinScanKey key);
- /* ginvacuum.c */
- extern IndexBulkDeleteResult *ginbulkdelete(IndexVacuumInfo *info,
- IndexBulkDeleteResult *stats,
- IndexBulkDeleteCallback callback,
- void *callback_state);
- extern IndexBulkDeleteResult *ginvacuumcleanup(IndexVacuumInfo *info,
- IndexBulkDeleteResult *stats);
- extern ItemPointer ginVacuumItemPointers(GinVacuumState *gvs,
- ItemPointerData *items, int nitem, int *nremaining);
- /* ginvalidate.c */
- extern bool ginvalidate(Oid opclassoid);
- extern void ginadjustmembers(Oid opfamilyoid,
- Oid opclassoid,
- List *operators,
- List *functions);
- /* ginbulk.c */
- typedef struct GinEntryAccumulator
- {
- RBTNode rbtnode;
- Datum key;
- GinNullCategory category;
- OffsetNumber attnum;
- bool shouldSort;
- ItemPointerData *list;
- uint32 maxcount; /* allocated size of list[] */
- uint32 count; /* current number of list[] entries */
- } GinEntryAccumulator;
- typedef struct
- {
- GinState *ginstate;
- Size allocatedMemory;
- GinEntryAccumulator *entryallocator;
- uint32 eas_used;
- RBTree *tree;
- RBTreeIterator tree_walk;
- } BuildAccumulator;
- extern void ginInitBA(BuildAccumulator *accum);
- extern void ginInsertBAEntries(BuildAccumulator *accum,
- ItemPointer heapptr, OffsetNumber attnum,
- Datum *entries, GinNullCategory *categories,
- int32 nentries);
- extern void ginBeginBAScan(BuildAccumulator *accum);
- extern ItemPointerData *ginGetBAEntry(BuildAccumulator *accum,
- OffsetNumber *attnum, Datum *key, GinNullCategory *category,
- uint32 *n);
- /* ginfast.c */
- typedef struct GinTupleCollector
- {
- IndexTuple *tuples;
- uint32 ntuples;
- uint32 lentuples;
- uint32 sumsize;
- } GinTupleCollector;
- extern void ginHeapTupleFastInsert(GinState *ginstate,
- GinTupleCollector *collector);
- extern void ginHeapTupleFastCollect(GinState *ginstate,
- GinTupleCollector *collector,
- OffsetNumber attnum, Datum value, bool isNull,
- ItemPointer ht_ctid);
- extern void ginInsertCleanup(GinState *ginstate, bool full_clean,
- bool fill_fsm, bool forceCleanup, IndexBulkDeleteResult *stats);
- /* ginpostinglist.c */
- extern GinPostingList *ginCompressPostingList(const ItemPointer ipd, int nipd,
- int maxsize, int *nwritten);
- extern int ginPostingListDecodeAllSegmentsToTbm(GinPostingList *ptr, int totalsize, TIDBitmap *tbm);
- extern ItemPointer ginPostingListDecodeAllSegments(GinPostingList *ptr, int len, int *ndecoded);
- extern ItemPointer ginPostingListDecode(GinPostingList *ptr, int *ndecoded);
- extern ItemPointer ginMergeItemPointers(ItemPointerData *a, uint32 na,
- ItemPointerData *b, uint32 nb,
- int *nmerged);
- /*
- * Merging the results of several gin scans compares item pointers a lot,
- * so we want this to be inlined.
- */
- static inline int
- ginCompareItemPointers(ItemPointer a, ItemPointer b)
- {
- uint64 ia = (uint64) GinItemPointerGetBlockNumber(a) << 32 | GinItemPointerGetOffsetNumber(a);
- uint64 ib = (uint64) GinItemPointerGetBlockNumber(b) << 32 | GinItemPointerGetOffsetNumber(b);
- if (ia == ib)
- return 0;
- else if (ia > ib)
- return 1;
- else
- return -1;
- }
- extern int ginTraverseLock(Buffer buffer, bool searchMode);
- #endif /* GIN_PRIVATE_H */
|