gin_private.h 17 KB

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