1 /*--------------------------------------------------------------------------
3 * header file for postgres inverted index access method implementation.
5 * Copyright (c) 2006, PostgreSQL Global Development Group
6 * $PostgreSQL: pgsql/src/include/access/gin.h,v 1.10 2007/01/31 15:09:45 teodor Exp $
7 *--------------------------------------------------------------------------
14 #include "access/relscan.h"
15 #include "access/skey.h"
16 #include "access/xlog.h"
17 #include "access/xlogdefs.h"
18 #include "storage/bufpage.h"
19 #include "storage/off.h"
20 #include "utils/rel.h"
21 #include "access/itup.h"
26 * amproc indexes for inverted indexes.
28 #define GIN_COMPARE_PROC 1
29 #define GIN_EXTRACTVALUE_PROC 2
30 #define GIN_EXTRACTQUERY_PROC 3
31 #define GIN_CONSISTENT_PROC 4
34 typedef XLogRecPtr GinNSN;
37 * Page opaque data in a inverted index page.
39 typedef struct GinPageOpaqueData
42 OffsetNumber maxoff; /* number entries on GIN_DATA page: number of
43 * heap ItemPointer on GIN_DATA|GIN_LEAF page
44 * and number of records on GIN_DATA &
46 BlockNumber rightlink;
49 typedef GinPageOpaqueData *GinPageOpaque;
51 #define GIN_ROOT_BLKNO (0)
55 BlockIdData child_blkno; /* use it instead of BlockNumber to save space
60 #define PostingItemGetBlockNumber(pointer) \
61 BlockIdGetBlockNumber(&(pointer)->child_blkno)
63 #define PostingItemSetBlockNumber(pointer, blockNumber) \
64 BlockIdSet(&((pointer)->child_blkno), (blockNumber))
67 * Page opaque data in a inverted index page.
69 #define GIN_DATA (1 << 0)
70 #define GIN_LEAF (1 << 1)
71 #define GIN_DELETED (1 << 2)
76 #define GinPageGetOpaque(page) ( (GinPageOpaque) PageGetSpecialPointer(page) )
78 #define GinPageIsLeaf(page) ( GinPageGetOpaque(page)->flags & GIN_LEAF )
79 #define GinPageSetLeaf(page) ( GinPageGetOpaque(page)->flags |= GIN_LEAF )
80 #define GinPageSetNonLeaf(page) ( GinPageGetOpaque(page)->flags &= ~GIN_LEAF )
81 #define GinPageIsData(page) ( GinPageGetOpaque(page)->flags & GIN_DATA )
82 #define GinPageSetData(page) ( GinPageGetOpaque(page)->flags |= GIN_DATA )
84 #define GinPageIsDeleted(page) ( GinPageGetOpaque(page)->flags & GIN_DELETED)
85 #define GinPageSetDeleted(page) ( GinPageGetOpaque(page)->flags |= GIN_DELETED)
86 #define GinPageSetNonDeleted(page) ( GinPageGetOpaque(page)->flags &= ~GIN_DELETED)
88 #define GinPageRightMost(page) ( GinPageGetOpaque(page)->rightlink == InvalidBlockNumber)
91 * Define our ItemPointerGet(BlockNumber|GetOffsetNumber)
95 #define GinItemPointerGetBlockNumber(pointer) \
96 BlockIdGetBlockNumber(&(pointer)->ip_blkid)
98 #define GinItemPointerGetOffsetNumber(pointer) \
102 * Support work on IndexTuuple on leaf pages
104 #define GinGetNPosting(itup) GinItemPointerGetOffsetNumber(&(itup)->t_tid)
105 #define GinSetNPosting(itup,n) ItemPointerSetOffsetNumber(&(itup)->t_tid,(n))
106 #define GIN_TREE_POSTING ((OffsetNumber)0xffff)
107 #define GinIsPostingTree(itup) ( GinGetNPosting(itup)==GIN_TREE_POSTING )
108 #define GinSetPostingTree(itup, blkno) ( GinSetNPosting((itup),GIN_TREE_POSTING ), ItemPointerSetBlockNumber(&(itup)->t_tid, blkno) )
109 #define GinGetPostingTree(itup) GinItemPointerGetBlockNumber(&(itup)->t_tid)
111 #define GinGetOrigSizePosting(itup) GinItemPointerGetBlockNumber(&(itup)->t_tid)
112 #define GinSetOrigSizePosting(itup,n) ItemPointerSetBlockNumber(&(itup)->t_tid,(n))
113 #define GinGetPosting(itup) ( (ItemPointer)(( ((char*)(itup)) + SHORTALIGN(GinGetOrigSizePosting(itup)) )) )
115 #define GinMaxItemSize \
116 ((BLCKSZ - SizeOfPageHeaderData - \
117 MAXALIGN(sizeof(GinPageOpaqueData))) / 3 - sizeof(ItemIdData))
121 * Data (posting tree) pages
123 #define GinDataPageGetData(page) \
124 (PageGetContents(page)+MAXALIGN(sizeof(ItemPointerData)))
125 #define GinDataPageGetRightBound(page) ((ItemPointer)PageGetContents(page))
126 #define GinSizeOfItem(page) ( (GinPageIsLeaf(page)) ? sizeof(ItemPointerData) : sizeof(PostingItem) )
127 #define GinDataPageGetItem(page,i) ( GinDataPageGetData(page) + ((i)-1) * GinSizeOfItem(page) )
129 #define GinDataPageGetFreeSpace(page) \
130 ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GinPageOpaqueData)) - \
131 GinPageGetOpaque(page)->maxoff * GinSizeOfItem(page) - \
132 MAXALIGN(sizeof(ItemPointerData)))
136 #define GIN_UNLOCK BUFFER_LOCK_UNLOCK
137 #define GIN_SHARE BUFFER_LOCK_SHARE
138 #define GIN_EXCLUSIVE BUFFER_LOCK_EXCLUSIVE
140 typedef struct GinState
143 FmgrInfo extractValueFn;
144 FmgrInfo extractQueryFn;
145 FmgrInfo consistentFn;
152 #define XLOG_GIN_CREATE_INDEX 0x00
154 #define XLOG_GIN_CREATE_PTREE 0x10
156 typedef struct ginxlogCreatePostingTree
161 /* follows list of heap's ItemPointer */
162 } ginxlogCreatePostingTree;
164 #define XLOG_GIN_INSERT 0x20
166 typedef struct ginxlogInsert
170 BlockNumber updateBlkno;
178 * follows: tuples or ItemPointerData or PostingItem or list of
183 #define XLOG_GIN_SPLIT 0x30
185 typedef struct ginxlogSplit
189 BlockNumber rootBlkno;
192 OffsetNumber separator;
199 BlockNumber leftChildBlkno;
200 BlockNumber updateBlkno;
202 ItemPointerData rightbound; /* used only in posting tree */
203 /* follows: list of tuple or ItemPointerData or PostingItem */
206 #define XLOG_GIN_VACUUM_PAGE 0x40
208 typedef struct ginxlogVacuumPage
213 /* follows content of page */
216 #define XLOG_GIN_DELETE_PAGE 0x50
218 typedef struct ginxlogDeletePage
222 BlockNumber parentBlkno;
223 OffsetNumber parentOffset;
224 BlockNumber leftBlkno;
225 BlockNumber rightLink;
229 extern Datum ginoptions(PG_FUNCTION_ARGS);
230 extern void initGinState(GinState *state, Relation index);
231 extern Buffer GinNewBuffer(Relation index);
232 extern void GinInitBuffer(Buffer b, uint32 f);
233 extern void GinInitPage(Page page, uint32 f, Size pageSize);
234 extern int compareEntries(GinState *ginstate, Datum a, Datum b);
235 extern Datum *extractEntriesS(GinState *ginstate, Datum value,
236 int32 *nentries, bool *needUnique);
237 extern Datum *extractEntriesSU(GinState *ginstate, Datum value, int32 *nentries);
238 extern Page GinPageGetCopyPage(Page page);
241 extern Datum ginbuild(PG_FUNCTION_ARGS);
242 extern Datum gininsert(PG_FUNCTION_ARGS);
245 extern void gin_redo(XLogRecPtr lsn, XLogRecord *record);
246 extern void gin_desc(StringInfo buf, uint8 xl_info, char *rec);
247 extern void gin_xlog_startup(void);
248 extern void gin_xlog_cleanup(void);
249 extern bool gin_safe_restartpoint(void);
253 typedef struct GinBtreeStack
258 /* predictNumber contains prediction number of pages on current level */
259 uint32 predictNumber;
260 struct GinBtreeStack *parent;
263 typedef struct GinBtreeData *GinBtree;
265 typedef struct GinBtreeData
268 BlockNumber (*findChildPage) (GinBtree, GinBtreeStack *);
269 bool (*isMoveRight) (GinBtree, Page);
270 bool (*findItem) (GinBtree, GinBtreeStack *);
273 OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber);
274 BlockNumber (*getLeftMostPage) (GinBtree, Page);
275 bool (*isEnoughSpace) (GinBtree, Buffer, OffsetNumber);
276 void (*placeToPage) (GinBtree, Buffer, OffsetNumber, XLogRecData **);
277 Page (*splitPage) (GinBtree, Buffer, Buffer, OffsetNumber, XLogRecData **);
278 void (*fillRoot) (GinBtree, Buffer, Buffer, Buffer);
287 BlockNumber rightblkno;
294 /* Data (posting tree) option */
295 ItemPointerData *items;
302 extern GinBtreeStack *ginPrepareFindLeafPage(GinBtree btree, BlockNumber blkno);
303 extern GinBtreeStack *ginFindLeafPage(GinBtree btree, GinBtreeStack *stack);
304 extern void freeGinBtreeStack(GinBtreeStack *stack);
305 extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack);
306 extern void findParents(GinBtree btree, GinBtreeStack *stack, BlockNumber rootBlkno);
309 extern IndexTuple GinFormTuple(GinState *ginstate, Datum key, ItemPointerData *ipd, uint32 nipd);
310 extern Datum ginGetHighKey(GinState *ginstate, Page page);
311 extern void prepareEntryScan(GinBtree btree, Relation index, Datum value, GinState *ginstate);
312 extern void entryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf);
313 extern IndexTuple ginPageGetLinkItup(Buffer buf);
316 extern int compareItemPointers(ItemPointer a, ItemPointer b);
319 ItemPointerData *dst,
320 ItemPointerData *a, uint32 na,
321 ItemPointerData *b, uint32 nb
324 extern void GinDataPageAddItem(Page page, void *data, OffsetNumber offset);
325 extern void PageDeletePostingItem(Page page, OffsetNumber offset);
330 GinBtreeStack *stack;
331 } GinPostingTreeScan;
333 extern GinPostingTreeScan *prepareScanPostingTree(Relation index,
334 BlockNumber rootBlkno, bool searchMode);
335 extern void insertItemPointer(GinPostingTreeScan *gdi,
336 ItemPointerData *items, uint32 nitem);
337 extern Buffer scanBeginPostingTree(GinPostingTreeScan *gdi);
338 extern void dataFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf);
339 extern void prepareDataScan(GinBtree btree, Relation index);
343 typedef struct GinScanEntryData *GinScanEntry;
345 typedef struct GinScanEntryData
347 /* link to the equals entry in current scan key */
351 * link to values reported to consistentFn, points to
352 * GinScanKey->entryRes[i]
356 /* entry, got from extractQueryFn */
359 /* current ItemPointer to heap, its offset in buffer and buffer */
360 ItemPointerData curItem;
364 /* in case of Posing list */
365 ItemPointerData *list;
370 uint32 predictNumberResult;
373 typedef struct GinScanKeyData
375 /* Number of entries in query (got by extractQueryFn) */
378 /* array of ItemPointer result, reported to consistentFn */
381 /* array of scans per entry */
382 GinScanEntry scanEntry;
384 /* for calling consistentFn(GinScanKey->entryRes, strategy, query) */
385 StrategyNumber strategy;
388 ItemPointerData curItem;
393 typedef GinScanKeyData *GinScanKey;
395 typedef struct GinScanOpaqueData
397 MemoryContext tempCtx;
402 bool isVoidRes; /* true if ginstate.extractQueryFn
403 guarantees that nothing will be found */
408 typedef GinScanOpaqueData *GinScanOpaque;
410 extern Datum ginbeginscan(PG_FUNCTION_ARGS);
411 extern Datum ginendscan(PG_FUNCTION_ARGS);
412 extern Datum ginrescan(PG_FUNCTION_ARGS);
413 extern Datum ginmarkpos(PG_FUNCTION_ARGS);
414 extern Datum ginrestrpos(PG_FUNCTION_ARGS);
415 extern void newScanKey(IndexScanDesc scan);
418 extern DLLIMPORT int GinFuzzySearchLimit;
420 #define ItemPointerSetMax(p) ItemPointerSet( (p), (BlockNumber)0xffffffff, (OffsetNumber)0xffff )
421 #define ItemPointerIsMax(p) ( ItemPointerGetBlockNumber(p) == (BlockNumber)0xffffffff && ItemPointerGetOffsetNumber(p) == (OffsetNumber)0xffff )
422 #define ItemPointerSetMin(p) ItemPointerSet( (p), (BlockNumber)0, (OffsetNumber)0)
423 #define ItemPointerIsMin(p) ( ItemPointerGetBlockNumber(p) == (BlockNumber)0 && ItemPointerGetOffsetNumber(p) == (OffsetNumber)0 )
425 extern Datum gingetmulti(PG_FUNCTION_ARGS);
426 extern Datum gingettuple(PG_FUNCTION_ARGS);
429 extern Datum ginbulkdelete(PG_FUNCTION_ARGS);
430 extern Datum ginvacuumcleanup(PG_FUNCTION_ARGS);
433 extern Datum ginarrayextract(PG_FUNCTION_ARGS);
434 extern Datum ginarrayconsistent(PG_FUNCTION_ARGS);
437 typedef struct EntryAccumulator
442 ItemPointerData *list;
444 struct EntryAccumulator *left;
445 struct EntryAccumulator *right;
451 EntryAccumulator *entries;
453 EntryAccumulator **stack;
455 uint32 allocatedMemory;
458 EntryAccumulator *entryallocator;
461 extern void ginInitBA(BuildAccumulator *accum);
462 extern void ginInsertRecordBA(BuildAccumulator *accum,
463 ItemPointer heapptr, Datum *entries, int32 nentry);
464 extern ItemPointerData *ginGetEntry(BuildAccumulator *accum, Datum *entry, uint32 *n);