Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
gin_private.h503 linesDownload Raw Back to access
1/*--------------------------------------------------------------------------2 * gin_private.h3 *	  header file for postgres inverted index access method implementation.4 *5 *	Copyright (c) 2006-2023, PostgreSQL Global Development Group6 *7 *	src/include/access/gin_private.h8 *--------------------------------------------------------------------------9 */10#ifndef GIN_PRIVATE_H11#define GIN_PRIVATE_H12 13#include "access/amapi.h"14#include "access/gin.h"15#include "access/ginblock.h"16#include "access/itup.h"17#include "catalog/pg_am_d.h"18#include "fmgr.h"19#include "lib/rbtree.h"20#include "storage/bufmgr.h"21 22/*23 * Storage type for GIN's reloptions24 */25typedef struct GinOptions26{27	int32		vl_len_;		/* varlena header (do not touch directly!) */28	bool		useFastUpdate;	/* use fast updates? */29	int			pendingListCleanupSize; /* maximum size of pending list */30} GinOptions;31 32#define GIN_DEFAULT_USE_FASTUPDATE	true33#define GinGetUseFastUpdate(relation) \34	(AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \35				 relation->rd_rel->relam == GIN_AM_OID), \36	 (relation)->rd_options ? \37	 ((GinOptions *) (relation)->rd_options)->useFastUpdate : GIN_DEFAULT_USE_FASTUPDATE)38#define GinGetPendingListCleanupSize(relation) \39	(AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \40				 relation->rd_rel->relam == GIN_AM_OID), \41	 (relation)->rd_options && \42	 ((GinOptions *) (relation)->rd_options)->pendingListCleanupSize != -1 ? \43	 ((GinOptions *) (relation)->rd_options)->pendingListCleanupSize : \44	 gin_pending_list_limit)45 46 47/* Macros for buffer lock/unlock operations */48#define GIN_UNLOCK	BUFFER_LOCK_UNLOCK49#define GIN_SHARE	BUFFER_LOCK_SHARE50#define GIN_EXCLUSIVE  BUFFER_LOCK_EXCLUSIVE51 52 53/*54 * GinState: working data structure describing the index being worked on55 */56typedef struct GinState57{58	Relation	index;59	bool		oneCol;			/* true if single-column index */60 61	/*62	 * origTupdesc is the nominal tuple descriptor of the index, ie, the i'th63	 * attribute shows the key type (not the input data type!) of the i'th64	 * index column.  In a single-column index this describes the actual leaf65	 * index tuples.  In a multi-column index, the actual leaf tuples contain66	 * a smallint column number followed by a key datum of the appropriate67	 * type for that column.  We set up tupdesc[i] to describe the actual68	 * rowtype of the index tuples for the i'th column, ie, (int2, keytype).69	 * Note that in any case, leaf tuples contain more data than is known to70	 * the TupleDesc; see access/gin/README for details.71	 */72	TupleDesc	origTupdesc;73	TupleDesc	tupdesc[INDEX_MAX_KEYS];74 75	/*76	 * Per-index-column opclass support functions77	 */78	FmgrInfo	compareFn[INDEX_MAX_KEYS];79	FmgrInfo	extractValueFn[INDEX_MAX_KEYS];80	FmgrInfo	extractQueryFn[INDEX_MAX_KEYS];81	FmgrInfo	consistentFn[INDEX_MAX_KEYS];82	FmgrInfo	triConsistentFn[INDEX_MAX_KEYS];83	FmgrInfo	comparePartialFn[INDEX_MAX_KEYS];	/* optional method */84	/* canPartialMatch[i] is true if comparePartialFn[i] is valid */85	bool		canPartialMatch[INDEX_MAX_KEYS];86	/* Collations to pass to the support functions */87	Oid			supportCollation[INDEX_MAX_KEYS];88} GinState;89 90 91/* ginutil.c */92extern bytea *ginoptions(Datum reloptions, bool validate);93extern void initGinState(GinState *state, Relation index);94extern Buffer GinNewBuffer(Relation index);95extern void GinInitBuffer(Buffer b, uint32 f);96extern void GinInitPage(Page page, uint32 f, Size pageSize);97extern void GinInitMetabuffer(Buffer b);98extern int	ginCompareEntries(GinState *ginstate, OffsetNumber attnum,99							  Datum a, GinNullCategory categorya,100							  Datum b, GinNullCategory categoryb);101extern int	ginCompareAttEntries(GinState *ginstate,102								 OffsetNumber attnuma, Datum a, GinNullCategory categorya,103								 OffsetNumber attnumb, Datum b, GinNullCategory categoryb);104extern Datum *ginExtractEntries(GinState *ginstate, OffsetNumber attnum,105								Datum value, bool isNull,106								int32 *nentries, GinNullCategory **categories);107 108extern OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple);109extern Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple,110							  GinNullCategory *category);111 112/* gininsert.c */113extern IndexBuildResult *ginbuild(Relation heap, Relation index,114								  struct IndexInfo *indexInfo);115extern void ginbuildempty(Relation index);116extern bool gininsert(Relation index, Datum *values, bool *isnull,117					  ItemPointer ht_ctid, Relation heapRel,118					  IndexUniqueCheck checkUnique,119					  bool indexUnchanged,120					  struct IndexInfo *indexInfo);121extern void ginEntryInsert(GinState *ginstate,122						   OffsetNumber attnum, Datum key, GinNullCategory category,123						   ItemPointerData *items, uint32 nitem,124						   GinStatsData *buildStats);125 126/* ginbtree.c */127 128typedef struct GinBtreeStack129{130	BlockNumber blkno;131	Buffer		buffer;132	OffsetNumber off;133	ItemPointerData iptr;134	/* predictNumber contains predicted number of pages on current level */135	uint32		predictNumber;136	struct GinBtreeStack *parent;137} GinBtreeStack;138 139typedef struct GinBtreeData *GinBtree;140 141/* Return codes for GinBtreeData.beginPlaceToPage method */142typedef enum143{144	GPTP_NO_WORK,145	GPTP_INSERT,146	GPTP_SPLIT147} GinPlaceToPageRC;148 149typedef struct GinBtreeData150{151	/* search methods */152	BlockNumber (*findChildPage) (GinBtree, GinBtreeStack *);153	BlockNumber (*getLeftMostChild) (GinBtree, Page);154	bool		(*isMoveRight) (GinBtree, Page);155	bool		(*findItem) (GinBtree, GinBtreeStack *);156 157	/* insert methods */158	OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber);159	GinPlaceToPageRC (*beginPlaceToPage) (GinBtree, Buffer, GinBtreeStack *, void *, BlockNumber, void **, Page *, Page *);160	void		(*execPlaceToPage) (GinBtree, Buffer, GinBtreeStack *, void *, BlockNumber, void *);161	void	   *(*prepareDownlink) (GinBtree, Buffer);162	void		(*fillRoot) (GinBtree, Page, BlockNumber, Page, BlockNumber, Page);163 164	bool		isData;165 166	Relation	index;167	BlockNumber rootBlkno;168	GinState   *ginstate;		/* not valid in a data scan */169	bool		fullScan;170	bool		isBuild;171 172	/* Search key for Entry tree */173	OffsetNumber entryAttnum;174	Datum		entryKey;175	GinNullCategory entryCategory;176 177	/* Search key for data tree (posting tree) */178	ItemPointerData itemptr;179} GinBtreeData;180 181/* This represents a tuple to be inserted to entry tree. */182typedef struct183{184	IndexTuple	entry;			/* tuple to insert */185	bool		isDelete;		/* delete old tuple at same offset? */186} GinBtreeEntryInsertData;187 188/*189 * This represents an itempointer, or many itempointers, to be inserted to190 * a data (posting tree) leaf page191 */192typedef struct193{194	ItemPointerData *items;195	uint32		nitem;196	uint32		curitem;197} GinBtreeDataLeafInsertData;198 199/*200 * For internal data (posting tree) pages, the insertion payload is a201 * PostingItem202 */203 204extern GinBtreeStack *ginFindLeafPage(GinBtree btree, bool searchMode,205									  bool rootConflictCheck, Snapshot snapshot);206extern Buffer ginStepRight(Buffer buffer, Relation index, int lockmode);207extern void freeGinBtreeStack(GinBtreeStack *stack);208extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack,209						   void *insertdata, GinStatsData *buildStats);210 211/* ginentrypage.c */212extern IndexTuple GinFormTuple(GinState *ginstate,213							   OffsetNumber attnum, Datum key, GinNullCategory category,214							   Pointer data, Size dataSize, int nipd, bool errorTooBig);215extern void ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum,216								Datum key, GinNullCategory category,217								GinState *ginstate);218extern void ginEntryFillRoot(GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage);219extern ItemPointer ginReadTuple(GinState *ginstate, OffsetNumber attnum,220								IndexTuple itup, int *nitems);221 222/* gindatapage.c */223extern ItemPointer GinDataLeafPageGetItems(Page page, int *nitems, ItemPointerData advancePast);224extern int	GinDataLeafPageGetItemsToTbm(Page page, TIDBitmap *tbm);225extern BlockNumber createPostingTree(Relation index,226									 ItemPointerData *items, uint32 nitems,227									 GinStatsData *buildStats, Buffer entrybuffer);228extern void GinDataPageAddPostingItem(Page page, PostingItem *data, OffsetNumber offset);229extern void GinPageDeletePostingItem(Page page, OffsetNumber offset);230extern void ginInsertItemPointers(Relation index, BlockNumber rootBlkno,231								  ItemPointerData *items, uint32 nitem,232								  GinStatsData *buildStats);233extern GinBtreeStack *ginScanBeginPostingTree(GinBtree btree, Relation index, BlockNumber rootBlkno, Snapshot snapshot);234extern void ginDataFillRoot(GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage);235 236/*237 * This is declared in ginvacuum.c, but is passed between ginVacuumItemPointers238 * and ginVacuumPostingTreeLeaf and as an opaque struct, so we need a forward239 * declaration for it.240 */241typedef struct GinVacuumState GinVacuumState;242 243extern void ginVacuumPostingTreeLeaf(Relation indexrel, Buffer buffer,244									 GinVacuumState *gvs);245 246/* ginscan.c */247 248/*249 * GinScanKeyData describes a single GIN index qualifier expression.250 *251 * From each qual expression, we extract one or more specific index search252 * conditions, which are represented by GinScanEntryData.  It's quite253 * possible for identical search conditions to be requested by more than254 * one qual expression, in which case we merge such conditions to have just255 * one unique GinScanEntry --- this is particularly important for efficiency256 * when dealing with full-index-scan entries.  So there can be multiple257 * GinScanKeyData.scanEntry pointers to the same GinScanEntryData.258 *259 * In each GinScanKeyData, nentries is the true number of entries, while260 * nuserentries is the number that extractQueryFn returned (which is what261 * we report to consistentFn).  The "user" entries must come first.262 */263typedef struct GinScanKeyData *GinScanKey;264 265typedef struct GinScanEntryData *GinScanEntry;266 267typedef struct GinScanKeyData268{269	/* Real number of entries in scanEntry[] (always > 0) */270	uint32		nentries;271	/* Number of entries that extractQueryFn and consistentFn know about */272	uint32		nuserentries;273 274	/* array of GinScanEntry pointers, one per extracted search condition */275	GinScanEntry *scanEntry;276 277	/*278	 * At least one of the entries in requiredEntries must be present for a279	 * tuple to match the overall qual.280	 *281	 * additionalEntries contains entries that are needed by the consistent282	 * function to decide if an item matches, but are not sufficient to283	 * satisfy the qual without entries from requiredEntries.284	 */285	GinScanEntry *requiredEntries;286	int			nrequired;287	GinScanEntry *additionalEntries;288	int			nadditional;289 290	/* array of check flags, reported to consistentFn */291	GinTernaryValue *entryRes;292	bool		(*boolConsistentFn) (GinScanKey key);293	GinTernaryValue (*triConsistentFn) (GinScanKey key);294	FmgrInfo   *consistentFmgrInfo;295	FmgrInfo   *triConsistentFmgrInfo;296	Oid			collation;297 298	/* other data needed for calling consistentFn */299	Datum		query;300	/* NB: these three arrays have only nuserentries elements! */301	Datum	   *queryValues;302	GinNullCategory *queryCategories;303	Pointer    *extra_data;304	StrategyNumber strategy;305	int32		searchMode;306	OffsetNumber attnum;307 308	/*309	 * An excludeOnly scan key is not able to enumerate all matching tuples.310	 * That is, to be semantically correct on its own, it would need to have a311	 * GIN_CAT_EMPTY_QUERY scanEntry, but it doesn't.  Such a key can still be312	 * used to filter tuples returned by other scan keys, so we will get the313	 * right answers as long as there's at least one non-excludeOnly scan key314	 * for each index attribute considered by the search.  For efficiency315	 * reasons we don't want to have unnecessary GIN_CAT_EMPTY_QUERY entries,316	 * so we will convert an excludeOnly scan key to non-excludeOnly (by317	 * adding a GIN_CAT_EMPTY_QUERY scanEntry) only if there are no other318	 * non-excludeOnly scan keys.319	 */320	bool		excludeOnly;321 322	/*323	 * Match status data.  curItem is the TID most recently tested (could be a324	 * lossy-page pointer).  curItemMatches is true if it passes the325	 * consistentFn test; if so, recheckCurItem is the recheck flag.326	 * isFinished means that all the input entry streams are finished, so this327	 * key cannot succeed for any later TIDs.328	 */329	ItemPointerData curItem;330	bool		curItemMatches;331	bool		recheckCurItem;332	bool		isFinished;333}			GinScanKeyData;334 335typedef struct GinScanEntryData336{337	/* query key and other information from extractQueryFn */338	Datum		queryKey;339	GinNullCategory queryCategory;340	bool		isPartialMatch;341	Pointer		extra_data;342	StrategyNumber strategy;343	int32		searchMode;344	OffsetNumber attnum;345 346	/* Current page in posting tree */347	Buffer		buffer;348 349	/* current ItemPointer to heap */350	ItemPointerData curItem;351 352	/* for a partial-match or full-scan query, we accumulate all TIDs here */353	TIDBitmap  *matchBitmap;354	TBMIterator *matchIterator;355	TBMIterateResult *matchResult;356 357	/* used for Posting list and one page in Posting tree */358	ItemPointerData *list;359	int			nlist;360	OffsetNumber offset;361 362	bool		isFinished;363	bool		reduceResult;364	uint32		predictNumberResult;365	GinBtreeData btree;366}			GinScanEntryData;367 368typedef struct GinScanOpaqueData369{370	MemoryContext tempCtx;371	GinState	ginstate;372 373	GinScanKey	keys;			/* one per scan qualifier expr */374	uint32		nkeys;375 376	GinScanEntry *entries;		/* one per index search condition */377	uint32		totalentries;378	uint32		allocentries;	/* allocated length of entries[] */379 380	MemoryContext keyCtx;		/* used to hold key and entry data */381 382	bool		isVoidRes;		/* true if query is unsatisfiable */383} GinScanOpaqueData;384 385typedef GinScanOpaqueData *GinScanOpaque;386 387extern IndexScanDesc ginbeginscan(Relation rel, int nkeys, int norderbys);388extern void ginendscan(IndexScanDesc scan);389extern void ginrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,390					  ScanKey orderbys, int norderbys);391extern void ginNewScanKey(IndexScanDesc scan);392extern void ginFreeScanKeys(GinScanOpaque so);393 394/* ginget.c */395extern int64 gingetbitmap(IndexScanDesc scan, TIDBitmap *tbm);396 397/* ginlogic.c */398extern void ginInitConsistentFunction(GinState *ginstate, GinScanKey key);399 400/* ginvacuum.c */401extern IndexBulkDeleteResult *ginbulkdelete(IndexVacuumInfo *info,402											IndexBulkDeleteResult *stats,403											IndexBulkDeleteCallback callback,404											void *callback_state);405extern IndexBulkDeleteResult *ginvacuumcleanup(IndexVacuumInfo *info,406											   IndexBulkDeleteResult *stats);407extern ItemPointer ginVacuumItemPointers(GinVacuumState *gvs,408										 ItemPointerData *items, int nitem, int *nremaining);409 410/* ginvalidate.c */411extern bool ginvalidate(Oid opclassoid);412extern void ginadjustmembers(Oid opfamilyoid,413							 Oid opclassoid,414							 List *operators,415							 List *functions);416 417/* ginbulk.c */418typedef struct GinEntryAccumulator419{420	RBTNode		rbtnode;421	Datum		key;422	GinNullCategory category;423	OffsetNumber attnum;424	bool		shouldSort;425	ItemPointerData *list;426	uint32		maxcount;		/* allocated size of list[] */427	uint32		count;			/* current number of list[] entries */428} GinEntryAccumulator;429 430typedef struct431{432	GinState   *ginstate;433	Size		allocatedMemory;434	GinEntryAccumulator *entryallocator;435	uint32		eas_used;436	RBTree	   *tree;437	RBTreeIterator tree_walk;438} BuildAccumulator;439 440extern void ginInitBA(BuildAccumulator *accum);441extern void ginInsertBAEntries(BuildAccumulator *accum,442							   ItemPointer heapptr, OffsetNumber attnum,443							   Datum *entries, GinNullCategory *categories,444							   int32 nentries);445extern void ginBeginBAScan(BuildAccumulator *accum);446extern ItemPointerData *ginGetBAEntry(BuildAccumulator *accum,447									  OffsetNumber *attnum, Datum *key, GinNullCategory *category,448									  uint32 *n);449 450/* ginfast.c */451 452typedef struct GinTupleCollector453{454	IndexTuple *tuples;455	uint32		ntuples;456	uint32		lentuples;457	uint32		sumsize;458} GinTupleCollector;459 460extern void ginHeapTupleFastInsert(GinState *ginstate,461								   GinTupleCollector *collector);462extern void ginHeapTupleFastCollect(GinState *ginstate,463									GinTupleCollector *collector,464									OffsetNumber attnum, Datum value, bool isNull,465									ItemPointer ht_ctid);466extern void ginInsertCleanup(GinState *ginstate, bool full_clean,467							 bool fill_fsm, bool forceCleanup, IndexBulkDeleteResult *stats);468 469/* ginpostinglist.c */470 471extern GinPostingList *ginCompressPostingList(const ItemPointer ipd, int nipd,472											  int maxsize, int *nwritten);473extern int	ginPostingListDecodeAllSegmentsToTbm(GinPostingList *ptr, int len, TIDBitmap *tbm);474 475extern ItemPointer ginPostingListDecodeAllSegments(GinPostingList *segment, int len,476												   int *ndecoded_out);477extern ItemPointer ginPostingListDecode(GinPostingList *plist, int *ndecoded_out);478extern ItemPointer ginMergeItemPointers(ItemPointerData *a, uint32 na,479										ItemPointerData *b, uint32 nb,480										int *nmerged);481 482/*483 * Merging the results of several gin scans compares item pointers a lot,484 * so we want this to be inlined.485 */486static inline int487ginCompareItemPointers(ItemPointer a, ItemPointer b)488{489	uint64		ia = (uint64) GinItemPointerGetBlockNumber(a) << 32 | GinItemPointerGetOffsetNumber(a);490	uint64		ib = (uint64) GinItemPointerGetBlockNumber(b) << 32 | GinItemPointerGetOffsetNumber(b);491 492	if (ia == ib)493		return 0;494	else if (ia > ib)495		return 1;496	else497		return -1;498}499 500extern int	ginTraverseLock(Buffer buffer, bool searchMode);501 502#endif							/* GIN_PRIVATE_H */503 
codekingpro/portable-devtools · Team Ai