gooderp18绿色标准版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
7.9KB

  1. /*-------------------------------------------------------------------------
  2. *
  3. * gist.h
  4. * The public API for GiST indexes. This API is exposed to
  5. * individuals implementing GiST indexes, so backward-incompatible
  6. * changes should be made with care.
  7. *
  8. *
  9. * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
  10. * Portions Copyright (c) 1994, Regents of the University of California
  11. *
  12. * src/include/access/gist.h
  13. *
  14. *-------------------------------------------------------------------------
  15. */
  16. #ifndef GIST_H
  17. #define GIST_H
  18. #include "access/transam.h"
  19. #include "access/xlog.h"
  20. #include "access/xlogdefs.h"
  21. #include "storage/block.h"
  22. #include "storage/bufpage.h"
  23. #include "utils/relcache.h"
  24. /*
  25. * amproc indexes for GiST indexes.
  26. */
  27. #define GIST_CONSISTENT_PROC 1
  28. #define GIST_UNION_PROC 2
  29. #define GIST_COMPRESS_PROC 3
  30. #define GIST_DECOMPRESS_PROC 4
  31. #define GIST_PENALTY_PROC 5
  32. #define GIST_PICKSPLIT_PROC 6
  33. #define GIST_EQUAL_PROC 7
  34. #define GIST_DISTANCE_PROC 8
  35. #define GIST_FETCH_PROC 9
  36. #define GISTNProcs 9
  37. /*
  38. * Page opaque data in a GiST index page.
  39. */
  40. #define F_LEAF (1 << 0) /* leaf page */
  41. #define F_DELETED (1 << 1) /* the page has been deleted */
  42. #define F_TUPLES_DELETED (1 << 2) /* some tuples on the page were
  43. * deleted */
  44. #define F_FOLLOW_RIGHT (1 << 3) /* page to the right has no downlink */
  45. #define F_HAS_GARBAGE (1 << 4) /* some tuples on the page are dead,
  46. * but not deleted yet */
  47. typedef XLogRecPtr GistNSN;
  48. /*
  49. * A bogus LSN / NSN value used during index build. Must be smaller than any
  50. * real or fake unlogged LSN, so that after an index build finishes, all the
  51. * splits are considered completed.
  52. */
  53. #define GistBuildLSN ((XLogRecPtr) 1)
  54. /*
  55. * For on-disk compatibility with pre-9.3 servers, NSN is stored as two
  56. * 32-bit fields on disk, same as LSNs.
  57. */
  58. typedef PageXLogRecPtr PageGistNSN;
  59. typedef struct GISTPageOpaqueData
  60. {
  61. PageGistNSN nsn; /* this value must change on page split */
  62. BlockNumber rightlink; /* next page if any */
  63. uint16 flags; /* see bit definitions above */
  64. uint16 gist_page_id; /* for identification of GiST indexes */
  65. } GISTPageOpaqueData;
  66. typedef GISTPageOpaqueData *GISTPageOpaque;
  67. /*
  68. * The page ID is for the convenience of pg_filedump and similar utilities,
  69. * which otherwise would have a hard time telling pages of different index
  70. * types apart. It should be the last 2 bytes on the page. This is more or
  71. * less "free" due to alignment considerations.
  72. */
  73. #define GIST_PAGE_ID 0xFF81
  74. /*
  75. * This is the Split Vector to be returned by the PickSplit method.
  76. * PickSplit should fill the indexes of tuples to go to the left side into
  77. * spl_left[], and those to go to the right into spl_right[] (note the method
  78. * is responsible for palloc'ing both of these arrays!). The tuple counts
  79. * go into spl_nleft/spl_nright, and spl_ldatum/spl_rdatum must be set to
  80. * the union keys for each side.
  81. *
  82. * If spl_ldatum_exists and spl_rdatum_exists are true, then we are performing
  83. * a "secondary split" using a non-first index column. In this case some
  84. * decisions have already been made about a page split, and the set of tuples
  85. * being passed to PickSplit is just the tuples about which we are undecided.
  86. * spl_ldatum/spl_rdatum then contain the union keys for the tuples already
  87. * chosen to go left or right. Ideally the PickSplit method should take those
  88. * keys into account while deciding what to do with the remaining tuples, ie
  89. * it should try to "build out" from those unions so as to minimally expand
  90. * them. If it does so, it should union the given tuples' keys into the
  91. * existing spl_ldatum/spl_rdatum values rather than just setting those values
  92. * from scratch, and then set spl_ldatum_exists/spl_rdatum_exists to false to
  93. * show it has done this.
  94. *
  95. * If the PickSplit method fails to clear spl_ldatum_exists/spl_rdatum_exists,
  96. * the core GiST code will make its own decision about how to merge the
  97. * secondary-split results with the previously-chosen tuples, and will then
  98. * recompute the union keys from scratch. This is a workable though often not
  99. * optimal approach.
  100. */
  101. typedef struct GIST_SPLITVEC
  102. {
  103. OffsetNumber *spl_left; /* array of entries that go left */
  104. int spl_nleft; /* size of this array */
  105. Datum spl_ldatum; /* Union of keys in spl_left */
  106. bool spl_ldatum_exists; /* true, if spl_ldatum already exists. */
  107. OffsetNumber *spl_right; /* array of entries that go right */
  108. int spl_nright; /* size of the array */
  109. Datum spl_rdatum; /* Union of keys in spl_right */
  110. bool spl_rdatum_exists; /* true, if spl_rdatum already exists. */
  111. } GIST_SPLITVEC;
  112. /*
  113. * An entry on a GiST node. Contains the key, as well as its own
  114. * location (rel,page,offset) which can supply the matching pointer.
  115. * leafkey is a flag to tell us if the entry is in a leaf node.
  116. */
  117. typedef struct GISTENTRY
  118. {
  119. Datum key;
  120. Relation rel;
  121. Page page;
  122. OffsetNumber offset;
  123. bool leafkey;
  124. } GISTENTRY;
  125. #define GistPageGetOpaque(page) ( (GISTPageOpaque) PageGetSpecialPointer(page) )
  126. #define GistPageIsLeaf(page) ( GistPageGetOpaque(page)->flags & F_LEAF)
  127. #define GIST_LEAF(entry) (GistPageIsLeaf((entry)->page))
  128. #define GistPageIsDeleted(page) ( GistPageGetOpaque(page)->flags & F_DELETED)
  129. #define GistTuplesDeleted(page) ( GistPageGetOpaque(page)->flags & F_TUPLES_DELETED)
  130. #define GistMarkTuplesDeleted(page) ( GistPageGetOpaque(page)->flags |= F_TUPLES_DELETED)
  131. #define GistClearTuplesDeleted(page) ( GistPageGetOpaque(page)->flags &= ~F_TUPLES_DELETED)
  132. #define GistPageHasGarbage(page) ( GistPageGetOpaque(page)->flags & F_HAS_GARBAGE)
  133. #define GistMarkPageHasGarbage(page) ( GistPageGetOpaque(page)->flags |= F_HAS_GARBAGE)
  134. #define GistClearPageHasGarbage(page) ( GistPageGetOpaque(page)->flags &= ~F_HAS_GARBAGE)
  135. #define GistFollowRight(page) ( GistPageGetOpaque(page)->flags & F_FOLLOW_RIGHT)
  136. #define GistMarkFollowRight(page) ( GistPageGetOpaque(page)->flags |= F_FOLLOW_RIGHT)
  137. #define GistClearFollowRight(page) ( GistPageGetOpaque(page)->flags &= ~F_FOLLOW_RIGHT)
  138. #define GistPageGetNSN(page) ( PageXLogRecPtrGet(GistPageGetOpaque(page)->nsn))
  139. #define GistPageSetNSN(page, val) ( PageXLogRecPtrSet(GistPageGetOpaque(page)->nsn, val))
  140. /*
  141. * On a deleted page, we store this struct. A deleted page doesn't contain any
  142. * tuples, so we don't use the normal page layout with line pointers. Instead,
  143. * this struct is stored right after the standard page header. pd_lower points
  144. * to the end of this struct. If we add fields to this struct in the future, we
  145. * can distinguish the old and new formats by pd_lower.
  146. */
  147. typedef struct GISTDeletedPageContents
  148. {
  149. /* last xid which could see the page in a scan */
  150. FullTransactionId deleteXid;
  151. } GISTDeletedPageContents;
  152. static inline void
  153. GistPageSetDeleted(Page page, FullTransactionId deletexid)
  154. {
  155. Assert(PageIsEmpty(page));
  156. GistPageGetOpaque(page)->flags |= F_DELETED;
  157. ((PageHeader) page)->pd_lower = MAXALIGN(SizeOfPageHeaderData) + sizeof(GISTDeletedPageContents);
  158. ((GISTDeletedPageContents *) PageGetContents(page))->deleteXid = deletexid;
  159. }
  160. static inline FullTransactionId
  161. GistPageGetDeleteXid(Page page)
  162. {
  163. Assert(GistPageIsDeleted(page));
  164. /* Is the deleteXid field present? */
  165. if (((PageHeader) page)->pd_lower >= MAXALIGN(SizeOfPageHeaderData) +
  166. offsetof(GISTDeletedPageContents, deleteXid) + sizeof(FullTransactionId))
  167. {
  168. return ((GISTDeletedPageContents *) PageGetContents(page))->deleteXid;
  169. }
  170. else
  171. return FullTransactionIdFromEpochAndXid(0, FirstNormalTransactionId);
  172. }
  173. /*
  174. * Vector of GISTENTRY structs; user-defined methods union and picksplit
  175. * take it as one of their arguments
  176. */
  177. typedef struct
  178. {
  179. int32 n; /* number of elements */
  180. GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER];
  181. } GistEntryVector;
  182. #define GEVHDRSZ (offsetof(GistEntryVector, vector))
  183. /*
  184. * macro to initialize a GISTENTRY
  185. */
  186. #define gistentryinit(e, k, r, pg, o, l) \
  187. do { (e).key = (k); (e).rel = (r); (e).page = (pg); \
  188. (e).offset = (o); (e).leafkey = (l); } while (0)
  189. #endif /* GIST_H */
上海开阖软件有限公司 沪ICP备12045867号-1