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