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.

473 lines
17KB

  1. /*-------------------------------------------------------------------------
  2. *
  3. * spgist_private.h
  4. * Private declarations for SP-GiST access method.
  5. *
  6. *
  7. * Portions Copyright (c) 1996-2019, 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/geo_decls.h"
  21. #include "utils/relcache.h"
  22. /* Page numbers of fixed-location pages */
  23. #define SPGIST_METAPAGE_BLKNO (0) /* metapage */
  24. #define SPGIST_ROOT_BLKNO (1) /* root for normal entries */
  25. #define SPGIST_NULL_BLKNO (2) /* root for null-value entries */
  26. #define SPGIST_LAST_FIXED_BLKNO SPGIST_NULL_BLKNO
  27. #define SpGistBlockIsRoot(blkno) \
  28. ((blkno) == SPGIST_ROOT_BLKNO || (blkno) == SPGIST_NULL_BLKNO)
  29. #define SpGistBlockIsFixed(blkno) \
  30. ((BlockNumber) (blkno) <= (BlockNumber) SPGIST_LAST_FIXED_BLKNO)
  31. /*
  32. * Contents of page special space on SPGiST index pages
  33. */
  34. typedef struct SpGistPageOpaqueData
  35. {
  36. uint16 flags; /* see bit definitions below */
  37. uint16 nRedirection; /* number of redirection tuples on page */
  38. uint16 nPlaceholder; /* number of placeholder tuples on page */
  39. /* note there's no count of either LIVE or DEAD tuples ... */
  40. uint16 spgist_page_id; /* for identification of SP-GiST indexes */
  41. } SpGistPageOpaqueData;
  42. typedef SpGistPageOpaqueData *SpGistPageOpaque;
  43. /* Flag bits in page special space */
  44. #define SPGIST_META (1<<0)
  45. #define SPGIST_DELETED (1<<1) /* never set, but keep for backwards
  46. * compatibility */
  47. #define SPGIST_LEAF (1<<2)
  48. #define SPGIST_NULLS (1<<3)
  49. #define SpGistPageGetOpaque(page) ((SpGistPageOpaque) PageGetSpecialPointer(page))
  50. #define SpGistPageIsMeta(page) (SpGistPageGetOpaque(page)->flags & SPGIST_META)
  51. #define SpGistPageIsDeleted(page) (SpGistPageGetOpaque(page)->flags & SPGIST_DELETED)
  52. #define SpGistPageIsLeaf(page) (SpGistPageGetOpaque(page)->flags & SPGIST_LEAF)
  53. #define SpGistPageStoresNulls(page) (SpGistPageGetOpaque(page)->flags & SPGIST_NULLS)
  54. /*
  55. * The page ID is for the convenience of pg_filedump and similar utilities,
  56. * which otherwise would have a hard time telling pages of different index
  57. * types apart. It should be the last 2 bytes on the page. This is more or
  58. * less "free" due to alignment considerations.
  59. *
  60. * See comments above GinPageOpaqueData.
  61. */
  62. #define SPGIST_PAGE_ID 0xFF82
  63. /*
  64. * Each backend keeps a cache of last-used page info in its index->rd_amcache
  65. * area. This is initialized from, and occasionally written back to,
  66. * shared storage in the index metapage.
  67. */
  68. typedef struct SpGistLastUsedPage
  69. {
  70. BlockNumber blkno; /* block number, or InvalidBlockNumber */
  71. int freeSpace; /* page's free space (could be obsolete!) */
  72. } SpGistLastUsedPage;
  73. /* Note: indexes in cachedPage[] match flag assignments for SpGistGetBuffer */
  74. #define SPGIST_CACHED_PAGES 8
  75. typedef struct SpGistLUPCache
  76. {
  77. SpGistLastUsedPage cachedPage[SPGIST_CACHED_PAGES];
  78. } SpGistLUPCache;
  79. /*
  80. * metapage
  81. */
  82. typedef struct SpGistMetaPageData
  83. {
  84. uint32 magicNumber; /* for identity cross-check */
  85. SpGistLUPCache lastUsedPages; /* shared storage of last-used info */
  86. } SpGistMetaPageData;
  87. #define SPGIST_MAGIC_NUMBER (0xBA0BABEE)
  88. #define SpGistPageGetMeta(p) \
  89. ((SpGistMetaPageData *) PageGetContents(p))
  90. /*
  91. * Private state of index AM. SpGistState is common to both insert and
  92. * search code; SpGistScanOpaque is for searches only.
  93. */
  94. /* Per-datatype info needed in SpGistState */
  95. typedef struct SpGistTypeDesc
  96. {
  97. Oid type;
  98. bool attbyval;
  99. int16 attlen;
  100. } SpGistTypeDesc;
  101. typedef struct SpGistState
  102. {
  103. spgConfigOut config; /* filled in by opclass config method */
  104. SpGistTypeDesc attType; /* type of values to be indexed/restored */
  105. SpGistTypeDesc attLeafType; /* type of leaf-tuple values */
  106. SpGistTypeDesc attPrefixType; /* type of inner-tuple prefix values */
  107. SpGistTypeDesc attLabelType; /* type of node label values */
  108. char *deadTupleStorage; /* workspace for spgFormDeadTuple */
  109. TransactionId myXid; /* XID to use when creating a redirect tuple */
  110. bool isBuild; /* true if doing index build */
  111. } SpGistState;
  112. typedef struct SpGistSearchItem
  113. {
  114. pairingheap_node phNode; /* pairing heap node */
  115. Datum value; /* value reconstructed from parent or
  116. * leafValue if heaptuple */
  117. void *traversalValue; /* opclass-specific traverse value */
  118. int level; /* level of items on this page */
  119. ItemPointerData heapPtr; /* heap info, if heap tuple */
  120. bool isNull; /* SearchItem is NULL item */
  121. bool isLeaf; /* SearchItem is heap item */
  122. bool recheck; /* qual recheck is needed */
  123. bool recheckDistances; /* distance recheck is needed */
  124. /* array with numberOfOrderBys entries */
  125. double distances[FLEXIBLE_ARRAY_MEMBER];
  126. } SpGistSearchItem;
  127. #define SizeOfSpGistSearchItem(n_distances) \
  128. (offsetof(SpGistSearchItem, distances) + sizeof(double) * (n_distances))
  129. /*
  130. * Private state of an index scan
  131. */
  132. typedef struct SpGistScanOpaqueData
  133. {
  134. SpGistState state; /* see above */
  135. pairingheap *scanQueue; /* queue of to be visited items */
  136. MemoryContext tempCxt; /* short-lived memory context */
  137. MemoryContext traversalCxt; /* single scan lifetime memory context */
  138. /* Control flags showing whether to search nulls and/or non-nulls */
  139. bool searchNulls; /* scan matches (all) null entries */
  140. bool searchNonNulls; /* scan matches (some) non-null entries */
  141. /* Index quals to be passed to opclass (null-related quals removed) */
  142. int numberOfKeys; /* number of index qualifier conditions */
  143. ScanKey keyData; /* array of index qualifier descriptors */
  144. int numberOfOrderBys; /* number of ordering operators */
  145. int numberOfNonNullOrderBys; /* number of ordering operators
  146. * with non-NULL arguments */
  147. ScanKey orderByData; /* array of ordering op descriptors */
  148. Oid *orderByTypes; /* array of ordering op return types */
  149. int *nonNullOrderByOffsets; /* array of offset of non-NULL
  150. * ordering keys in the original array */
  151. Oid indexCollation; /* collation of index column */
  152. /* Opclass defined functions: */
  153. FmgrInfo innerConsistentFn;
  154. FmgrInfo leafConsistentFn;
  155. /* Pre-allocated workspace arrays: */
  156. double *zeroDistances;
  157. double *infDistances;
  158. /* These fields are only used in amgetbitmap scans: */
  159. TIDBitmap *tbm; /* bitmap being filled */
  160. int64 ntids; /* number of TIDs passed to bitmap */
  161. /* These fields are only used in amgettuple scans: */
  162. bool want_itup; /* are we reconstructing tuples? */
  163. TupleDesc indexTupDesc; /* if so, tuple descriptor for them */
  164. int nPtrs; /* number of TIDs found on current page */
  165. int iPtr; /* index for scanning through same */
  166. ItemPointerData heapPtrs[MaxIndexTuplesPerPage]; /* TIDs from cur page */
  167. bool recheck[MaxIndexTuplesPerPage]; /* their recheck flags */
  168. bool recheckDistances[MaxIndexTuplesPerPage]; /* distance recheck
  169. * flags */
  170. HeapTuple reconTups[MaxIndexTuplesPerPage]; /* reconstructed tuples */
  171. /* distances (for recheck) */
  172. IndexOrderByDistance *distances[MaxIndexTuplesPerPage];
  173. /*
  174. * Note: using MaxIndexTuplesPerPage above is a bit hokey since
  175. * SpGistLeafTuples aren't exactly IndexTuples; however, they are larger,
  176. * so this is safe.
  177. */
  178. } SpGistScanOpaqueData;
  179. typedef SpGistScanOpaqueData *SpGistScanOpaque;
  180. /*
  181. * This struct is what we actually keep in index->rd_amcache. It includes
  182. * static configuration information as well as the lastUsedPages cache.
  183. */
  184. typedef struct SpGistCache
  185. {
  186. spgConfigOut config; /* filled in by opclass config method */
  187. SpGistTypeDesc attType; /* type of values to be indexed/restored */
  188. SpGistTypeDesc attLeafType; /* type of leaf-tuple values */
  189. SpGistTypeDesc attPrefixType; /* type of inner-tuple prefix values */
  190. SpGistTypeDesc attLabelType; /* type of node label values */
  191. SpGistLUPCache lastUsedPages; /* local storage of last-used info */
  192. } SpGistCache;
  193. /*
  194. * SPGiST tuple types. Note: inner, leaf, and dead tuple structs
  195. * must have the same tupstate field in the same position! Real inner and
  196. * leaf tuples always have tupstate = LIVE; if the state is something else,
  197. * use the SpGistDeadTuple struct to inspect the tuple.
  198. */
  199. /* values of tupstate (see README for more info) */
  200. #define SPGIST_LIVE 0 /* normal live tuple (either inner or leaf) */
  201. #define SPGIST_REDIRECT 1 /* temporary redirection placeholder */
  202. #define SPGIST_DEAD 2 /* dead, cannot be removed because of links */
  203. #define SPGIST_PLACEHOLDER 3 /* placeholder, used to preserve offsets */
  204. /*
  205. * SPGiST inner tuple: list of "nodes" that subdivide a set of tuples
  206. *
  207. * Inner tuple layout:
  208. * header/optional prefix/array of nodes, which are SpGistNodeTuples
  209. *
  210. * size and prefixSize must be multiples of MAXALIGN
  211. */
  212. typedef struct SpGistInnerTupleData
  213. {
  214. unsigned int tupstate:2, /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
  215. allTheSame:1, /* all nodes in tuple are equivalent */
  216. nNodes:13, /* number of nodes within inner tuple */
  217. prefixSize:16; /* size of prefix, or 0 if none */
  218. uint16 size; /* total size of inner tuple */
  219. /* On most machines there will be a couple of wasted bytes here */
  220. /* prefix datum follows, then nodes */
  221. } SpGistInnerTupleData;
  222. typedef SpGistInnerTupleData *SpGistInnerTuple;
  223. /* these must match largest values that fit in bit fields declared above */
  224. #define SGITMAXNNODES 0x1FFF
  225. #define SGITMAXPREFIXSIZE 0xFFFF
  226. #define SGITMAXSIZE 0xFFFF
  227. #define SGITHDRSZ MAXALIGN(sizeof(SpGistInnerTupleData))
  228. #define _SGITDATA(x) (((char *) (x)) + SGITHDRSZ)
  229. #define SGITDATAPTR(x) ((x)->prefixSize ? _SGITDATA(x) : NULL)
  230. #define SGITDATUM(x, s) ((x)->prefixSize ? \
  231. ((s)->attPrefixType.attbyval ? \
  232. *(Datum *) _SGITDATA(x) : \
  233. PointerGetDatum(_SGITDATA(x))) \
  234. : (Datum) 0)
  235. #define SGITNODEPTR(x) ((SpGistNodeTuple) (_SGITDATA(x) + (x)->prefixSize))
  236. /* Macro for iterating through the nodes of an inner tuple */
  237. #define SGITITERATE(x, i, nt) \
  238. for ((i) = 0, (nt) = SGITNODEPTR(x); \
  239. (i) < (x)->nNodes; \
  240. (i)++, (nt) = (SpGistNodeTuple) (((char *) (nt)) + IndexTupleSize(nt)))
  241. /*
  242. * SPGiST node tuple: one node within an inner tuple
  243. *
  244. * Node tuples use the same header as ordinary Postgres IndexTuples, but
  245. * we do not use a null bitmap, because we know there is only one column
  246. * so the INDEX_NULL_MASK bit suffices. Also, pass-by-value datums are
  247. * stored as a full Datum, the same convention as for inner tuple prefixes
  248. * and leaf tuple datums.
  249. */
  250. typedef IndexTupleData SpGistNodeTupleData;
  251. typedef SpGistNodeTupleData *SpGistNodeTuple;
  252. #define SGNTHDRSZ MAXALIGN(sizeof(SpGistNodeTupleData))
  253. #define SGNTDATAPTR(x) (((char *) (x)) + SGNTHDRSZ)
  254. #define SGNTDATUM(x, s) ((s)->attLabelType.attbyval ? \
  255. *(Datum *) SGNTDATAPTR(x) : \
  256. PointerGetDatum(SGNTDATAPTR(x)))
  257. /*
  258. * SPGiST leaf tuple: carries a datum and a heap tuple TID
  259. *
  260. * In the simplest case, the datum is the same as the indexed value; but
  261. * it could also be a suffix or some other sort of delta that permits
  262. * reconstruction given knowledge of the prefix path traversed to get here.
  263. *
  264. * The size field is wider than could possibly be needed for an on-disk leaf
  265. * tuple, but this allows us to form leaf tuples even when the datum is too
  266. * wide to be stored immediately, and it costs nothing because of alignment
  267. * considerations.
  268. *
  269. * Normally, nextOffset links to the next tuple belonging to the same parent
  270. * node (which must be on the same page). But when the root page is a leaf
  271. * page, we don't chain its tuples, so nextOffset is always 0 on the root.
  272. *
  273. * size must be a multiple of MAXALIGN; also, it must be at least SGDTSIZE
  274. * so that the tuple can be converted to REDIRECT status later. (This
  275. * restriction only adds bytes for the null-datum case, otherwise alignment
  276. * restrictions force it anyway.)
  277. *
  278. * In a leaf tuple for a NULL indexed value, there's no useful datum value;
  279. * however, the SGDTSIZE limit ensures that's there's a Datum word there
  280. * anyway, so SGLTDATUM can be applied safely as long as you don't do
  281. * anything with the result.
  282. */
  283. typedef struct SpGistLeafTupleData
  284. {
  285. unsigned int tupstate:2, /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
  286. size:30; /* large enough for any palloc'able value */
  287. OffsetNumber nextOffset; /* next tuple in chain, or InvalidOffset */
  288. ItemPointerData heapPtr; /* TID of represented heap tuple */
  289. /* leaf datum follows */
  290. } SpGistLeafTupleData;
  291. typedef SpGistLeafTupleData *SpGistLeafTuple;
  292. #define SGLTHDRSZ MAXALIGN(sizeof(SpGistLeafTupleData))
  293. #define SGLTDATAPTR(x) (((char *) (x)) + SGLTHDRSZ)
  294. #define SGLTDATUM(x, s) ((s)->attLeafType.attbyval ? \
  295. *(Datum *) SGLTDATAPTR(x) : \
  296. PointerGetDatum(SGLTDATAPTR(x)))
  297. /*
  298. * SPGiST dead tuple: declaration for examining non-live tuples
  299. *
  300. * The tupstate field of this struct must match those of regular inner and
  301. * leaf tuples, and its size field must match a leaf tuple's.
  302. * Also, the pointer field must be in the same place as a leaf tuple's heapPtr
  303. * field, to satisfy some Asserts that we make when replacing a leaf tuple
  304. * with a dead tuple.
  305. * We don't use nextOffset, but it's needed to align the pointer field.
  306. * pointer and xid are only valid when tupstate = REDIRECT.
  307. */
  308. typedef struct SpGistDeadTupleData
  309. {
  310. unsigned int tupstate:2, /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
  311. size:30;
  312. OffsetNumber nextOffset; /* not used in dead tuples */
  313. ItemPointerData pointer; /* redirection inside index */
  314. TransactionId xid; /* ID of xact that inserted this tuple */
  315. } SpGistDeadTupleData;
  316. typedef SpGistDeadTupleData *SpGistDeadTuple;
  317. #define SGDTSIZE MAXALIGN(sizeof(SpGistDeadTupleData))
  318. /*
  319. * Macros for doing free-space calculations. Note that when adding up the
  320. * space needed for tuples, we always consider each tuple to need the tuple's
  321. * size plus sizeof(ItemIdData) (for the line pointer). This works correctly
  322. * so long as tuple sizes are always maxaligned.
  323. */
  324. /* Page capacity after allowing for fixed header and special space */
  325. #define SPGIST_PAGE_CAPACITY \
  326. MAXALIGN_DOWN(BLCKSZ - \
  327. SizeOfPageHeaderData - \
  328. MAXALIGN(sizeof(SpGistPageOpaqueData)))
  329. /*
  330. * Compute free space on page, assuming that up to n placeholders can be
  331. * recycled if present (n should be the number of tuples to be inserted)
  332. */
  333. #define SpGistPageGetFreeSpace(p, n) \
  334. (PageGetExactFreeSpace(p) + \
  335. Min(SpGistPageGetOpaque(p)->nPlaceholder, n) * \
  336. (SGDTSIZE + sizeof(ItemIdData)))
  337. /*
  338. * XLOG stuff
  339. */
  340. #define STORE_STATE(s, d) \
  341. do { \
  342. (d).myXid = (s)->myXid; \
  343. (d).isBuild = (s)->isBuild; \
  344. } while(0)
  345. /*
  346. * The "flags" argument for SpGistGetBuffer should be either GBUF_LEAF to
  347. * get a leaf page, or GBUF_INNER_PARITY(blockNumber) to get an inner
  348. * page in the same triple-parity group as the specified block number.
  349. * (Typically, this should be GBUF_INNER_PARITY(parentBlockNumber + 1)
  350. * to follow the rule described in spgist/README.)
  351. * In addition, GBUF_NULLS can be OR'd in to get a page for storage of
  352. * null-valued tuples.
  353. *
  354. * Note: these flag values are used as indexes into lastUsedPages.
  355. */
  356. #define GBUF_LEAF 0x03
  357. #define GBUF_INNER_PARITY(x) ((x) % 3)
  358. #define GBUF_NULLS 0x04
  359. #define GBUF_PARITY_MASK 0x03
  360. #define GBUF_REQ_LEAF(flags) (((flags) & GBUF_PARITY_MASK) == GBUF_LEAF)
  361. #define GBUF_REQ_NULLS(flags) ((flags) & GBUF_NULLS)
  362. /* spgutils.c */
  363. extern SpGistCache *spgGetCache(Relation index);
  364. extern void initSpGistState(SpGistState *state, Relation index);
  365. extern Buffer SpGistNewBuffer(Relation index);
  366. extern void SpGistUpdateMetaPage(Relation index);
  367. extern Buffer SpGistGetBuffer(Relation index, int flags,
  368. int needSpace, bool *isNew);
  369. extern void SpGistSetLastUsedPage(Relation index, Buffer buffer);
  370. extern void SpGistInitPage(Page page, uint16 f);
  371. extern void SpGistInitBuffer(Buffer b, uint16 f);
  372. extern void SpGistInitMetapage(Page page);
  373. extern unsigned int SpGistGetTypeSize(SpGistTypeDesc *att, Datum datum);
  374. extern SpGistLeafTuple spgFormLeafTuple(SpGistState *state,
  375. ItemPointer heapPtr,
  376. Datum datum, bool isnull);
  377. extern SpGistNodeTuple spgFormNodeTuple(SpGistState *state,
  378. Datum label, bool isnull);
  379. extern SpGistInnerTuple spgFormInnerTuple(SpGistState *state,
  380. bool hasPrefix, Datum prefix,
  381. int nNodes, SpGistNodeTuple *nodes);
  382. extern SpGistDeadTuple spgFormDeadTuple(SpGistState *state, int tupstate,
  383. BlockNumber blkno, OffsetNumber offnum);
  384. extern Datum *spgExtractNodeLabels(SpGistState *state,
  385. SpGistInnerTuple innerTuple);
  386. extern OffsetNumber SpGistPageAddNewItem(SpGistState *state, Page page,
  387. Item item, Size size,
  388. OffsetNumber *startOffset,
  389. bool errorOK);
  390. extern bool spgproperty(Oid index_oid, int attno,
  391. IndexAMProperty prop, const char *propname,
  392. bool *res, bool *isnull);
  393. /* spgdoinsert.c */
  394. extern void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN,
  395. BlockNumber blkno, OffsetNumber offset);
  396. extern void spgPageIndexMultiDelete(SpGistState *state, Page page,
  397. OffsetNumber *itemnos, int nitems,
  398. int firststate, int reststate,
  399. BlockNumber blkno, OffsetNumber offnum);
  400. extern bool spgdoinsert(Relation index, SpGistState *state,
  401. ItemPointer heapPtr, Datum datum, bool isnull);
  402. /* spgproc.c */
  403. extern double *spg_key_orderbys_distances(Datum key, bool isLeaf,
  404. ScanKey orderbys, int norderbys);
  405. extern BOX *box_copy(BOX *orig);
  406. #endif /* SPGIST_PRIVATE_H */
上海开阖软件有限公司 沪ICP备12045867号-1