spgist_private.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /*-------------------------------------------------------------------------
  2. *
  3. * spgist_private.h
  4. * Private declarations for SP-GiST access method.
  5. *
  6. *
  7. * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
  8. * Portions Copyright (c) 1994, Regents of the University of California
  9. *
  10. * src/include/access/spgist_private.h
  11. *
  12. *-------------------------------------------------------------------------
  13. */
  14. #ifndef SPGIST_PRIVATE_H
  15. #define SPGIST_PRIVATE_H
  16. #include "access/itup.h"
  17. #include "access/spgist.h"
  18. #include "nodes/tidbitmap.h"
  19. #include "storage/buf.h"
  20. #include "utils/relcache.h"
  21. /* Page numbers of fixed-location pages */
  22. #define SPGIST_METAPAGE_BLKNO (0) /* metapage */
  23. #define SPGIST_ROOT_BLKNO (1) /* root for normal entries */
  24. #define SPGIST_NULL_BLKNO (2) /* root for null-value entries */
  25. #define SPGIST_LAST_FIXED_BLKNO SPGIST_NULL_BLKNO
  26. #define SpGistBlockIsRoot(blkno) \
  27. ((blkno) == SPGIST_ROOT_BLKNO || (blkno) == SPGIST_NULL_BLKNO)
  28. #define SpGistBlockIsFixed(blkno) \
  29. ((BlockNumber) (blkno) <= (BlockNumber) SPGIST_LAST_FIXED_BLKNO)
  30. /*
  31. * Contents of page special space on SPGiST index pages
  32. */
  33. typedef struct SpGistPageOpaqueData
  34. {
  35. uint16 flags; /* see bit definitions below */
  36. uint16 nRedirection; /* number of redirection tuples on page */
  37. uint16 nPlaceholder; /* number of placeholder tuples on page */
  38. /* note there's no count of either LIVE or DEAD tuples ... */
  39. uint16 spgist_page_id; /* for identification of SP-GiST indexes */
  40. } SpGistPageOpaqueData;
  41. typedef SpGistPageOpaqueData *SpGistPageOpaque;
  42. /* Flag bits in page special space */
  43. #define SPGIST_META (1<<0)
  44. #define SPGIST_DELETED (1<<1) /* never set, but keep for backwards
  45. * compatibility */
  46. #define SPGIST_LEAF (1<<2)
  47. #define SPGIST_NULLS (1<<3)
  48. #define SpGistPageGetOpaque(page) ((SpGistPageOpaque) PageGetSpecialPointer(page))
  49. #define SpGistPageIsMeta(page) (SpGistPageGetOpaque(page)->flags & SPGIST_META)
  50. #define SpGistPageIsDeleted(page) (SpGistPageGetOpaque(page)->flags & SPGIST_DELETED)
  51. #define SpGistPageIsLeaf(page) (SpGistPageGetOpaque(page)->flags & SPGIST_LEAF)
  52. #define SpGistPageStoresNulls(page) (SpGistPageGetOpaque(page)->flags & SPGIST_NULLS)
  53. /*
  54. * The page ID is for the convenience of pg_filedump and similar utilities,
  55. * which otherwise would have a hard time telling pages of different index
  56. * types apart. It should be the last 2 bytes on the page. This is more or
  57. * less "free" due to alignment considerations.
  58. *
  59. * See comments above GinPageOpaqueData.
  60. */
  61. #define SPGIST_PAGE_ID 0xFF82
  62. /*
  63. * Each backend keeps a cache of last-used page info in its index->rd_amcache
  64. * area. This is initialized from, and occasionally written back to,
  65. * shared storage in the index metapage.
  66. */
  67. typedef struct SpGistLastUsedPage
  68. {
  69. BlockNumber blkno; /* block number, or InvalidBlockNumber */
  70. int freeSpace; /* page's free space (could be obsolete!) */
  71. } SpGistLastUsedPage;
  72. /* Note: indexes in cachedPage[] match flag assignments for SpGistGetBuffer */
  73. #define SPGIST_CACHED_PAGES 8
  74. typedef struct SpGistLUPCache
  75. {
  76. SpGistLastUsedPage cachedPage[SPGIST_CACHED_PAGES];
  77. } SpGistLUPCache;
  78. /*
  79. * metapage
  80. */
  81. typedef struct SpGistMetaPageData
  82. {
  83. uint32 magicNumber; /* for identity cross-check */
  84. SpGistLUPCache lastUsedPages; /* shared storage of last-used info */
  85. } SpGistMetaPageData;
  86. #define SPGIST_MAGIC_NUMBER (0xBA0BABEE)
  87. #define SpGistPageGetMeta(p) \
  88. ((SpGistMetaPageData *) PageGetContents(p))
  89. /*
  90. * Private state of index AM. SpGistState is common to both insert and
  91. * search code; SpGistScanOpaque is for searches only.
  92. */
  93. /* Per-datatype info needed in SpGistState */
  94. typedef struct SpGistTypeDesc
  95. {
  96. Oid type;
  97. bool attbyval;
  98. int16 attlen;
  99. } SpGistTypeDesc;
  100. typedef struct SpGistState
  101. {
  102. spgConfigOut config; /* filled in by opclass config method */
  103. SpGistTypeDesc attType; /* type of input data and leaf values */
  104. SpGistTypeDesc attPrefixType; /* type of inner-tuple prefix values */
  105. SpGistTypeDesc attLabelType; /* type of node label values */
  106. char *deadTupleStorage; /* workspace for spgFormDeadTuple */
  107. TransactionId myXid; /* XID to use when creating a redirect tuple */
  108. bool isBuild; /* true if doing index build */
  109. } SpGistState;
  110. /*
  111. * Private state of an index scan
  112. */
  113. typedef struct SpGistScanOpaqueData
  114. {
  115. SpGistState state; /* see above */
  116. MemoryContext tempCxt; /* short-lived memory context */
  117. /* Control flags showing whether to search nulls and/or non-nulls */
  118. bool searchNulls; /* scan matches (all) null entries */
  119. bool searchNonNulls; /* scan matches (some) non-null entries */
  120. /* Index quals to be passed to opclass (null-related quals removed) */
  121. int numberOfKeys; /* number of index qualifier conditions */
  122. ScanKey keyData; /* array of index qualifier descriptors */
  123. /* Stack of yet-to-be-visited pages */
  124. List *scanStack; /* List of ScanStackEntrys */
  125. /* These fields are only used in amgetbitmap scans: */
  126. TIDBitmap *tbm; /* bitmap being filled */
  127. int64 ntids; /* number of TIDs passed to bitmap */
  128. /* These fields are only used in amgettuple scans: */
  129. bool want_itup; /* are we reconstructing tuples? */
  130. TupleDesc indexTupDesc; /* if so, tuple descriptor for them */
  131. int nPtrs; /* number of TIDs found on current page */
  132. int iPtr; /* index for scanning through same */
  133. ItemPointerData heapPtrs[MaxIndexTuplesPerPage]; /* TIDs from cur page */
  134. bool recheck[MaxIndexTuplesPerPage]; /* their recheck flags */
  135. IndexTuple indexTups[MaxIndexTuplesPerPage]; /* reconstructed tuples */
  136. /*
  137. * Note: using MaxIndexTuplesPerPage above is a bit hokey since
  138. * SpGistLeafTuples aren't exactly IndexTuples; however, they are larger,
  139. * so this is safe.
  140. */
  141. } SpGistScanOpaqueData;
  142. typedef SpGistScanOpaqueData *SpGistScanOpaque;
  143. /*
  144. * This struct is what we actually keep in index->rd_amcache. It includes
  145. * static configuration information as well as the lastUsedPages cache.
  146. */
  147. typedef struct SpGistCache
  148. {
  149. spgConfigOut config; /* filled in by opclass config method */
  150. SpGistTypeDesc attType; /* type of input data and leaf values */
  151. SpGistTypeDesc attPrefixType; /* type of inner-tuple prefix values */
  152. SpGistTypeDesc attLabelType; /* type of node label values */
  153. SpGistLUPCache lastUsedPages; /* local storage of last-used info */
  154. } SpGistCache;
  155. /*
  156. * SPGiST tuple types. Note: inner, leaf, and dead tuple structs
  157. * must have the same tupstate field in the same position! Real inner and
  158. * leaf tuples always have tupstate = LIVE; if the state is something else,
  159. * use the SpGistDeadTuple struct to inspect the tuple.
  160. */
  161. /* values of tupstate (see README for more info) */
  162. #define SPGIST_LIVE 0 /* normal live tuple (either inner or leaf) */
  163. #define SPGIST_REDIRECT 1 /* temporary redirection placeholder */
  164. #define SPGIST_DEAD 2 /* dead, cannot be removed because of links */
  165. #define SPGIST_PLACEHOLDER 3 /* placeholder, used to preserve offsets */
  166. /*
  167. * SPGiST inner tuple: list of "nodes" that subdivide a set of tuples
  168. *
  169. * Inner tuple layout:
  170. * header/optional prefix/array of nodes, which are SpGistNodeTuples
  171. *
  172. * size and prefixSize must be multiples of MAXALIGN
  173. */
  174. typedef struct SpGistInnerTupleData
  175. {
  176. unsigned int tupstate:2, /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
  177. allTheSame:1, /* all nodes in tuple are equivalent */
  178. nNodes:13, /* number of nodes within inner tuple */
  179. prefixSize:16; /* size of prefix, or 0 if none */
  180. uint16 size; /* total size of inner tuple */
  181. /* On most machines there will be a couple of wasted bytes here */
  182. /* prefix datum follows, then nodes */
  183. } SpGistInnerTupleData;
  184. typedef SpGistInnerTupleData *SpGistInnerTuple;
  185. /* these must match largest values that fit in bit fields declared above */
  186. #define SGITMAXNNODES 0x1FFF
  187. #define SGITMAXPREFIXSIZE 0xFFFF
  188. #define SGITMAXSIZE 0xFFFF
  189. #define SGITHDRSZ MAXALIGN(sizeof(SpGistInnerTupleData))
  190. #define _SGITDATA(x) (((char *) (x)) + SGITHDRSZ)
  191. #define SGITDATAPTR(x) ((x)->prefixSize ? _SGITDATA(x) : NULL)
  192. #define SGITDATUM(x, s) ((x)->prefixSize ? \
  193. ((s)->attPrefixType.attbyval ? \
  194. *(Datum *) _SGITDATA(x) : \
  195. PointerGetDatum(_SGITDATA(x))) \
  196. : (Datum) 0)
  197. #define SGITNODEPTR(x) ((SpGistNodeTuple) (_SGITDATA(x) + (x)->prefixSize))
  198. /* Macro for iterating through the nodes of an inner tuple */
  199. #define SGITITERATE(x, i, nt) \
  200. for ((i) = 0, (nt) = SGITNODEPTR(x); \
  201. (i) < (x)->nNodes; \
  202. (i)++, (nt) = (SpGistNodeTuple) (((char *) (nt)) + IndexTupleSize(nt)))
  203. /*
  204. * SPGiST node tuple: one node within an inner tuple
  205. *
  206. * Node tuples use the same header as ordinary Postgres IndexTuples, but
  207. * we do not use a null bitmap, because we know there is only one column
  208. * so the INDEX_NULL_MASK bit suffices. Also, pass-by-value datums are
  209. * stored as a full Datum, the same convention as for inner tuple prefixes
  210. * and leaf tuple datums.
  211. */
  212. typedef IndexTupleData SpGistNodeTupleData;
  213. typedef SpGistNodeTupleData *SpGistNodeTuple;
  214. #define SGNTHDRSZ MAXALIGN(sizeof(SpGistNodeTupleData))
  215. #define SGNTDATAPTR(x) (((char *) (x)) + SGNTHDRSZ)
  216. #define SGNTDATUM(x, s) ((s)->attLabelType.attbyval ? \
  217. *(Datum *) SGNTDATAPTR(x) : \
  218. PointerGetDatum(SGNTDATAPTR(x)))
  219. /*
  220. * SPGiST leaf tuple: carries a datum and a heap tuple TID
  221. *
  222. * In the simplest case, the datum is the same as the indexed value; but
  223. * it could also be a suffix or some other sort of delta that permits
  224. * reconstruction given knowledge of the prefix path traversed to get here.
  225. *
  226. * The size field is wider than could possibly be needed for an on-disk leaf
  227. * tuple, but this allows us to form leaf tuples even when the datum is too
  228. * wide to be stored immediately, and it costs nothing because of alignment
  229. * considerations.
  230. *
  231. * Normally, nextOffset links to the next tuple belonging to the same parent
  232. * node (which must be on the same page). But when the root page is a leaf
  233. * page, we don't chain its tuples, so nextOffset is always 0 on the root.
  234. *
  235. * size must be a multiple of MAXALIGN; also, it must be at least SGDTSIZE
  236. * so that the tuple can be converted to REDIRECT status later. (This
  237. * restriction only adds bytes for the null-datum case, otherwise alignment
  238. * restrictions force it anyway.)
  239. *
  240. * In a leaf tuple for a NULL indexed value, there's no useful datum value;
  241. * however, the SGDTSIZE limit ensures that's there's a Datum word there
  242. * anyway, so SGLTDATUM can be applied safely as long as you don't do
  243. * anything with the result.
  244. */
  245. typedef struct SpGistLeafTupleData
  246. {
  247. unsigned int tupstate:2, /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
  248. size:30; /* large enough for any palloc'able value */
  249. OffsetNumber nextOffset; /* next tuple in chain, or InvalidOffset */
  250. ItemPointerData heapPtr; /* TID of represented heap tuple */
  251. /* leaf datum follows */
  252. } SpGistLeafTupleData;
  253. typedef SpGistLeafTupleData *SpGistLeafTuple;
  254. #define SGLTHDRSZ MAXALIGN(sizeof(SpGistLeafTupleData))
  255. #define SGLTDATAPTR(x) (((char *) (x)) + SGLTHDRSZ)
  256. #define SGLTDATUM(x, s) ((s)->attType.attbyval ? \
  257. *(Datum *) SGLTDATAPTR(x) : \
  258. PointerGetDatum(SGLTDATAPTR(x)))
  259. /*
  260. * SPGiST dead tuple: declaration for examining non-live tuples
  261. *
  262. * The tupstate field of this struct must match those of regular inner and
  263. * leaf tuples, and its size field must match a leaf tuple's.
  264. * Also, the pointer field must be in the same place as a leaf tuple's heapPtr
  265. * field, to satisfy some Asserts that we make when replacing a leaf tuple
  266. * with a dead tuple.
  267. * We don't use nextOffset, but it's needed to align the pointer field.
  268. * pointer and xid are only valid when tupstate = REDIRECT.
  269. */
  270. typedef struct SpGistDeadTupleData
  271. {
  272. unsigned int tupstate:2, /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
  273. size:30;
  274. OffsetNumber nextOffset; /* not used in dead tuples */
  275. ItemPointerData pointer; /* redirection inside index */
  276. TransactionId xid; /* ID of xact that inserted this tuple */
  277. } SpGistDeadTupleData;
  278. typedef SpGistDeadTupleData *SpGistDeadTuple;
  279. #define SGDTSIZE MAXALIGN(sizeof(SpGistDeadTupleData))
  280. /*
  281. * Macros for doing free-space calculations. Note that when adding up the
  282. * space needed for tuples, we always consider each tuple to need the tuple's
  283. * size plus sizeof(ItemIdData) (for the line pointer). This works correctly
  284. * so long as tuple sizes are always maxaligned.
  285. */
  286. /* Page capacity after allowing for fixed header and special space */
  287. #define SPGIST_PAGE_CAPACITY \
  288. MAXALIGN_DOWN(BLCKSZ - \
  289. SizeOfPageHeaderData - \
  290. MAXALIGN(sizeof(SpGistPageOpaqueData)))
  291. /*
  292. * Compute free space on page, assuming that up to n placeholders can be
  293. * recycled if present (n should be the number of tuples to be inserted)
  294. */
  295. #define SpGistPageGetFreeSpace(p, n) \
  296. (PageGetExactFreeSpace(p) + \
  297. Min(SpGistPageGetOpaque(p)->nPlaceholder, n) * \
  298. (SGDTSIZE + sizeof(ItemIdData)))
  299. /*
  300. * XLOG stuff
  301. */
  302. /* XLOG record types for SPGiST */
  303. #define XLOG_SPGIST_CREATE_INDEX 0x00
  304. #define XLOG_SPGIST_ADD_LEAF 0x10
  305. #define XLOG_SPGIST_MOVE_LEAFS 0x20
  306. #define XLOG_SPGIST_ADD_NODE 0x30
  307. #define XLOG_SPGIST_SPLIT_TUPLE 0x40
  308. #define XLOG_SPGIST_PICKSPLIT 0x50
  309. #define XLOG_SPGIST_VACUUM_LEAF 0x60
  310. #define XLOG_SPGIST_VACUUM_ROOT 0x70
  311. #define XLOG_SPGIST_VACUUM_REDIRECT 0x80
  312. /*
  313. * Some redo functions need an SpGistState, although only a few of its fields
  314. * need to be valid. spgxlogState carries the required info in xlog records.
  315. * (See fillFakeState in spgxlog.c for more comments.)
  316. */
  317. typedef struct spgxlogState
  318. {
  319. TransactionId myXid;
  320. bool isBuild;
  321. } spgxlogState;
  322. #define STORE_STATE(s, d) \
  323. do { \
  324. (d).myXid = (s)->myXid; \
  325. (d).isBuild = (s)->isBuild; \
  326. } while(0)
  327. /*
  328. * Backup Blk 0: destination page for leaf tuple
  329. * Backup Blk 1: parent page (if any)
  330. */
  331. typedef struct spgxlogAddLeaf
  332. {
  333. bool newPage; /* init dest page? */
  334. bool storesNulls; /* page is in the nulls tree? */
  335. OffsetNumber offnumLeaf; /* offset where leaf tuple gets placed */
  336. OffsetNumber offnumHeadLeaf; /* offset of head tuple in chain, if any */
  337. OffsetNumber offnumParent; /* where the parent downlink is, if any */
  338. uint16 nodeI;
  339. /* new leaf tuple follows (unaligned!) */
  340. } spgxlogAddLeaf;
  341. /*
  342. * Backup Blk 0: source leaf page
  343. * Backup Blk 1: destination leaf page
  344. * Backup Blk 2: parent page
  345. */
  346. typedef struct spgxlogMoveLeafs
  347. {
  348. uint16 nMoves; /* number of tuples moved from source page */
  349. bool newPage; /* init dest page? */
  350. bool replaceDead; /* are we replacing a DEAD source tuple? */
  351. bool storesNulls; /* pages are in the nulls tree? */
  352. /* where the parent downlink is */
  353. OffsetNumber offnumParent;
  354. uint16 nodeI;
  355. spgxlogState stateSrc;
  356. /*----------
  357. * data follows:
  358. * array of deleted tuple numbers, length nMoves
  359. * array of inserted tuple numbers, length nMoves + 1 or 1
  360. * list of leaf tuples, length nMoves + 1 or 1 (unaligned!)
  361. *
  362. * Note: if replaceDead is true then there is only one inserted tuple
  363. * number and only one leaf tuple in the data, because we are not copying
  364. * the dead tuple from the source
  365. *----------
  366. */
  367. OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
  368. } spgxlogMoveLeafs;
  369. #define SizeOfSpgxlogMoveLeafs offsetof(spgxlogMoveLeafs, offsets)
  370. /*
  371. * Backup Blk 0: original page
  372. * Backup Blk 1: where new tuple goes, if not same place
  373. * Backup Blk 2: where parent downlink is, if updated and different from
  374. * the old and new
  375. */
  376. typedef struct spgxlogAddNode
  377. {
  378. /*
  379. * Offset of the original inner tuple, in the original page (on backup
  380. * block 0).
  381. */
  382. OffsetNumber offnum;
  383. /*
  384. * Offset of the new tuple, on the new page (on backup block 1). Invalid,
  385. * if we overwrote the old tuple in the original page).
  386. */
  387. OffsetNumber offnumNew;
  388. bool newPage; /* init new page? */
  389. /*----
  390. * Where is the parent downlink? parentBlk indicates which page it's on,
  391. * and offnumParent is the offset within the page. The possible values for
  392. * parentBlk are:
  393. *
  394. * 0: parent == original page
  395. * 1: parent == new page
  396. * 2: parent == different page (blk ref 2)
  397. * -1: parent not updated
  398. *----
  399. */
  400. int8 parentBlk;
  401. OffsetNumber offnumParent; /* offset within the parent page */
  402. uint16 nodeI;
  403. spgxlogState stateSrc;
  404. /*
  405. * updated inner tuple follows (unaligned!)
  406. */
  407. } spgxlogAddNode;
  408. /*
  409. * Backup Blk 0: where the prefix tuple goes
  410. * Backup Blk 1: where the postfix tuple goes (if different page)
  411. */
  412. typedef struct spgxlogSplitTuple
  413. {
  414. /* where the prefix tuple goes */
  415. OffsetNumber offnumPrefix;
  416. /* where the postfix tuple goes */
  417. OffsetNumber offnumPostfix;
  418. bool newPage; /* need to init that page? */
  419. bool postfixBlkSame; /* was postfix tuple put on same page as
  420. * prefix? */
  421. /*
  422. * new prefix inner tuple follows, then new postfix inner tuple (both are
  423. * unaligned!)
  424. */
  425. } spgxlogSplitTuple;
  426. /*
  427. * Buffer references in the rdata array are:
  428. * Backup Blk 0: Src page (only if not root)
  429. * Backup Blk 1: Dest page (if used)
  430. * Backup Blk 2: Inner page
  431. * Backup Blk 3: Parent page (if any, and different from Inner)
  432. */
  433. typedef struct spgxlogPickSplit
  434. {
  435. bool isRootSplit;
  436. uint16 nDelete; /* n to delete from Src */
  437. uint16 nInsert; /* n to insert on Src and/or Dest */
  438. bool initSrc; /* re-init the Src page? */
  439. bool initDest; /* re-init the Dest page? */
  440. /* where to put new inner tuple */
  441. OffsetNumber offnumInner;
  442. bool initInner; /* re-init the Inner page? */
  443. bool storesNulls; /* pages are in the nulls tree? */
  444. /* where the parent downlink is, if any */
  445. bool innerIsParent; /* is parent the same as inner page? */
  446. OffsetNumber offnumParent;
  447. uint16 nodeI;
  448. spgxlogState stateSrc;
  449. /*----------
  450. * data follows:
  451. * array of deleted tuple numbers, length nDelete
  452. * array of inserted tuple numbers, length nInsert
  453. * array of page selector bytes for inserted tuples, length nInsert
  454. * new inner tuple (unaligned!)
  455. * list of leaf tuples, length nInsert (unaligned!)
  456. *----------
  457. */
  458. OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
  459. } spgxlogPickSplit;
  460. #define SizeOfSpgxlogPickSplit offsetof(spgxlogPickSplit, offsets)
  461. typedef struct spgxlogVacuumLeaf
  462. {
  463. uint16 nDead; /* number of tuples to become DEAD */
  464. uint16 nPlaceholder; /* number of tuples to become PLACEHOLDER */
  465. uint16 nMove; /* number of tuples to move */
  466. uint16 nChain; /* number of tuples to re-chain */
  467. spgxlogState stateSrc;
  468. /*----------
  469. * data follows:
  470. * tuple numbers to become DEAD
  471. * tuple numbers to become PLACEHOLDER
  472. * tuple numbers to move from (and replace with PLACEHOLDER)
  473. * tuple numbers to move to (replacing what is there)
  474. * tuple numbers to update nextOffset links of
  475. * tuple numbers to insert in nextOffset links
  476. *----------
  477. */
  478. OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
  479. } spgxlogVacuumLeaf;
  480. #define SizeOfSpgxlogVacuumLeaf offsetof(spgxlogVacuumLeaf, offsets)
  481. typedef struct spgxlogVacuumRoot
  482. {
  483. /* vacuum a root page when it is also a leaf */
  484. uint16 nDelete; /* number of tuples to delete */
  485. spgxlogState stateSrc;
  486. /* offsets of tuples to delete follow */
  487. OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
  488. } spgxlogVacuumRoot;
  489. #define SizeOfSpgxlogVacuumRoot offsetof(spgxlogVacuumRoot, offsets)
  490. typedef struct spgxlogVacuumRedirect
  491. {
  492. uint16 nToPlaceholder; /* number of redirects to make placeholders */
  493. OffsetNumber firstPlaceholder; /* first placeholder tuple to remove */
  494. TransactionId newestRedirectXid; /* newest XID of removed redirects */
  495. /* offsets of redirect tuples to make placeholders follow */
  496. OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
  497. } spgxlogVacuumRedirect;
  498. #define SizeOfSpgxlogVacuumRedirect offsetof(spgxlogVacuumRedirect, offsets)
  499. /*
  500. * The "flags" argument for SpGistGetBuffer should be either GBUF_LEAF to
  501. * get a leaf page, or GBUF_INNER_PARITY(blockNumber) to get an inner
  502. * page in the same triple-parity group as the specified block number.
  503. * (Typically, this should be GBUF_INNER_PARITY(parentBlockNumber + 1)
  504. * to follow the rule described in spgist/README.)
  505. * In addition, GBUF_NULLS can be OR'd in to get a page for storage of
  506. * null-valued tuples.
  507. *
  508. * Note: these flag values are used as indexes into lastUsedPages.
  509. */
  510. #define GBUF_LEAF 0x03
  511. #define GBUF_INNER_PARITY(x) ((x) % 3)
  512. #define GBUF_NULLS 0x04
  513. #define GBUF_PARITY_MASK 0x03
  514. #define GBUF_REQ_LEAF(flags) (((flags) & GBUF_PARITY_MASK) == GBUF_LEAF)
  515. #define GBUF_REQ_NULLS(flags) ((flags) & GBUF_NULLS)
  516. /* spgutils.c */
  517. extern SpGistCache *spgGetCache(Relation index);
  518. extern void initSpGistState(SpGistState *state, Relation index);
  519. extern Buffer SpGistNewBuffer(Relation index);
  520. extern void SpGistUpdateMetaPage(Relation index);
  521. extern Buffer SpGistGetBuffer(Relation index, int flags,
  522. int needSpace, bool *isNew);
  523. extern void SpGistSetLastUsedPage(Relation index, Buffer buffer);
  524. extern void SpGistInitPage(Page page, uint16 f);
  525. extern void SpGistInitBuffer(Buffer b, uint16 f);
  526. extern void SpGistInitMetapage(Page page);
  527. extern unsigned int SpGistGetTypeSize(SpGistTypeDesc *att, Datum datum);
  528. extern SpGistLeafTuple spgFormLeafTuple(SpGistState *state,
  529. ItemPointer heapPtr,
  530. Datum datum, bool isnull);
  531. extern SpGistNodeTuple spgFormNodeTuple(SpGistState *state,
  532. Datum label, bool isnull);
  533. extern SpGistInnerTuple spgFormInnerTuple(SpGistState *state,
  534. bool hasPrefix, Datum prefix,
  535. int nNodes, SpGistNodeTuple *nodes);
  536. extern SpGistDeadTuple spgFormDeadTuple(SpGistState *state, int tupstate,
  537. BlockNumber blkno, OffsetNumber offnum);
  538. extern Datum *spgExtractNodeLabels(SpGistState *state,
  539. SpGistInnerTuple innerTuple);
  540. extern OffsetNumber SpGistPageAddNewItem(SpGistState *state, Page page,
  541. Item item, Size size,
  542. OffsetNumber *startOffset,
  543. bool errorOK);
  544. /* spgdoinsert.c */
  545. extern void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN,
  546. BlockNumber blkno, OffsetNumber offset);
  547. extern void spgPageIndexMultiDelete(SpGistState *state, Page page,
  548. OffsetNumber *itemnos, int nitems,
  549. int firststate, int reststate,
  550. BlockNumber blkno, OffsetNumber offnum);
  551. extern bool spgdoinsert(Relation index, SpGistState *state,
  552. ItemPointer heapPtr, Datum datum, bool isnull);
  553. #endif /* SPGIST_PRIVATE_H */