Header And Logo

PostgreSQL
| The world's most advanced open source database.

spgist_private.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * spgist_private.h
00004  *    Private declarations for SP-GiST access method.
00005  *
00006  *
00007  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00008  * Portions Copyright (c) 1994, Regents of the University of California
00009  *
00010  * src/include/access/spgist_private.h
00011  *
00012  *-------------------------------------------------------------------------
00013  */
00014 #ifndef SPGIST_PRIVATE_H
00015 #define SPGIST_PRIVATE_H
00016 
00017 #include "access/itup.h"
00018 #include "access/spgist.h"
00019 #include "nodes/tidbitmap.h"
00020 #include "storage/relfilenode.h"
00021 #include "utils/relcache.h"
00022 
00023 
00024 /* Page numbers of fixed-location pages */
00025 #define SPGIST_METAPAGE_BLKNO    (0)    /* metapage */
00026 #define SPGIST_ROOT_BLKNO        (1)    /* root for normal entries */
00027 #define SPGIST_NULL_BLKNO        (2)    /* root for null-value entries */
00028 #define SPGIST_LAST_FIXED_BLKNO  SPGIST_NULL_BLKNO
00029 
00030 #define SpGistBlockIsRoot(blkno) \
00031     ((blkno) == SPGIST_ROOT_BLKNO || (blkno) == SPGIST_NULL_BLKNO)
00032 #define SpGistBlockIsFixed(blkno) \
00033     ((BlockNumber) (blkno) <= (BlockNumber) SPGIST_LAST_FIXED_BLKNO)
00034 
00035 /*
00036  * Contents of page special space on SPGiST index pages
00037  */
00038 typedef struct SpGistPageOpaqueData
00039 {
00040     uint16      flags;          /* see bit definitions below */
00041     uint16      nRedirection;   /* number of redirection tuples on page */
00042     uint16      nPlaceholder;   /* number of placeholder tuples on page */
00043     /* note there's no count of either LIVE or DEAD tuples ... */
00044     uint16      spgist_page_id; /* for identification of SP-GiST indexes */
00045 } SpGistPageOpaqueData;
00046 
00047 typedef SpGistPageOpaqueData *SpGistPageOpaque;
00048 
00049 /* Flag bits in page special space */
00050 #define SPGIST_META         (1<<0)
00051 #define SPGIST_DELETED      (1<<1)
00052 #define SPGIST_LEAF         (1<<2)
00053 #define SPGIST_NULLS        (1<<3)
00054 
00055 #define SpGistPageGetOpaque(page) ((SpGistPageOpaque) PageGetSpecialPointer(page))
00056 #define SpGistPageIsMeta(page) (SpGistPageGetOpaque(page)->flags & SPGIST_META)
00057 #define SpGistPageIsDeleted(page) (SpGistPageGetOpaque(page)->flags & SPGIST_DELETED)
00058 #define SpGistPageSetDeleted(page) (SpGistPageGetOpaque(page)->flags |= SPGIST_DELETED)
00059 #define SpGistPageIsLeaf(page) (SpGistPageGetOpaque(page)->flags & SPGIST_LEAF)
00060 #define SpGistPageStoresNulls(page) (SpGistPageGetOpaque(page)->flags & SPGIST_NULLS)
00061 
00062 /*
00063  * The page ID is for the convenience of pg_filedump and similar utilities,
00064  * which otherwise would have a hard time telling pages of different index
00065  * types apart.  It should be the last 2 bytes on the page.  This is more or
00066  * less "free" due to alignment considerations.
00067  */
00068 #define SPGIST_PAGE_ID      0xFF82
00069 
00070 /*
00071  * Each backend keeps a cache of last-used page info in its index->rd_amcache
00072  * area.  This is initialized from, and occasionally written back to,
00073  * shared storage in the index metapage.
00074  */
00075 typedef struct SpGistLastUsedPage
00076 {
00077     BlockNumber blkno;          /* block number, or InvalidBlockNumber */
00078     int         freeSpace;      /* page's free space (could be obsolete!) */
00079 } SpGistLastUsedPage;
00080 
00081 /* Note: indexes in cachedPage[] match flag assignments for SpGistGetBuffer */
00082 #define SPGIST_CACHED_PAGES 8
00083 
00084 typedef struct SpGistLUPCache
00085 {
00086     SpGistLastUsedPage cachedPage[SPGIST_CACHED_PAGES];
00087 } SpGistLUPCache;
00088 
00089 /*
00090  * metapage
00091  */
00092 typedef struct SpGistMetaPageData
00093 {
00094     uint32      magicNumber;    /* for identity cross-check */
00095     SpGistLUPCache lastUsedPages;       /* shared storage of last-used info */
00096 } SpGistMetaPageData;
00097 
00098 #define SPGIST_MAGIC_NUMBER (0xBA0BABEE)
00099 
00100 #define SpGistPageGetMeta(p) \
00101     ((SpGistMetaPageData *) PageGetContents(p))
00102 
00103 /*
00104  * Private state of index AM.  SpGistState is common to both insert and
00105  * search code; SpGistScanOpaque is for searches only.
00106  */
00107 
00108 /* Per-datatype info needed in SpGistState */
00109 typedef struct SpGistTypeDesc
00110 {
00111     Oid         type;
00112     bool        attbyval;
00113     int16       attlen;
00114 } SpGistTypeDesc;
00115 
00116 typedef struct SpGistState
00117 {
00118     spgConfigOut config;        /* filled in by opclass config method */
00119 
00120     SpGistTypeDesc attType;     /* type of input data and leaf values */
00121     SpGistTypeDesc attPrefixType;       /* type of inner-tuple prefix values */
00122     SpGistTypeDesc attLabelType;    /* type of node label values */
00123 
00124     char       *deadTupleStorage;       /* workspace for spgFormDeadTuple */
00125 
00126     TransactionId myXid;        /* XID to use when creating a redirect tuple */
00127     bool        isBuild;        /* true if doing index build */
00128 } SpGistState;
00129 
00130 /*
00131  * Private state of an index scan
00132  */
00133 typedef struct SpGistScanOpaqueData
00134 {
00135     SpGistState state;          /* see above */
00136     MemoryContext tempCxt;      /* short-lived memory context */
00137 
00138     /* Control flags showing whether to search nulls and/or non-nulls */
00139     bool        searchNulls;    /* scan matches (all) null entries */
00140     bool        searchNonNulls; /* scan matches (some) non-null entries */
00141 
00142     /* Index quals to be passed to opclass (null-related quals removed) */
00143     int         numberOfKeys;   /* number of index qualifier conditions */
00144     ScanKey     keyData;        /* array of index qualifier descriptors */
00145 
00146     /* Stack of yet-to-be-visited pages */
00147     List       *scanStack;      /* List of ScanStackEntrys */
00148 
00149     /* These fields are only used in amgetbitmap scans: */
00150     TIDBitmap  *tbm;            /* bitmap being filled */
00151     int64       ntids;          /* number of TIDs passed to bitmap */
00152 
00153     /* These fields are only used in amgettuple scans: */
00154     bool        want_itup;      /* are we reconstructing tuples? */
00155     TupleDesc   indexTupDesc;   /* if so, tuple descriptor for them */
00156     int         nPtrs;          /* number of TIDs found on current page */
00157     int         iPtr;           /* index for scanning through same */
00158     ItemPointerData heapPtrs[MaxIndexTuplesPerPage];    /* TIDs from cur page */
00159     bool        recheck[MaxIndexTuplesPerPage]; /* their recheck flags */
00160     IndexTuple  indexTups[MaxIndexTuplesPerPage];       /* reconstructed tuples */
00161 
00162     /*
00163      * Note: using MaxIndexTuplesPerPage above is a bit hokey since
00164      * SpGistLeafTuples aren't exactly IndexTuples; however, they are larger,
00165      * so this is safe.
00166      */
00167 } SpGistScanOpaqueData;
00168 
00169 typedef SpGistScanOpaqueData *SpGistScanOpaque;
00170 
00171 /*
00172  * This struct is what we actually keep in index->rd_amcache.  It includes
00173  * static configuration information as well as the lastUsedPages cache.
00174  */
00175 typedef struct SpGistCache
00176 {
00177     spgConfigOut config;        /* filled in by opclass config method */
00178 
00179     SpGistTypeDesc attType;     /* type of input data and leaf values */
00180     SpGistTypeDesc attPrefixType;       /* type of inner-tuple prefix values */
00181     SpGistTypeDesc attLabelType;    /* type of node label values */
00182 
00183     SpGistLUPCache lastUsedPages;       /* local storage of last-used info */
00184 } SpGistCache;
00185 
00186 
00187 /*
00188  * SPGiST tuple types.  Note: inner, leaf, and dead tuple structs
00189  * must have the same tupstate field in the same position!  Real inner and
00190  * leaf tuples always have tupstate = LIVE; if the state is something else,
00191  * use the SpGistDeadTuple struct to inspect the tuple.
00192  */
00193 
00194 /* values of tupstate (see README for more info) */
00195 #define SPGIST_LIVE         0   /* normal live tuple (either inner or leaf) */
00196 #define SPGIST_REDIRECT     1   /* temporary redirection placeholder */
00197 #define SPGIST_DEAD         2   /* dead, cannot be removed because of links */
00198 #define SPGIST_PLACEHOLDER  3   /* placeholder, used to preserve offsets */
00199 
00200 /*
00201  * SPGiST inner tuple: list of "nodes" that subdivide a set of tuples
00202  *
00203  * Inner tuple layout:
00204  * header/optional prefix/array of nodes, which are SpGistNodeTuples
00205  *
00206  * size and prefixSize must be multiples of MAXALIGN
00207  */
00208 typedef struct SpGistInnerTupleData
00209 {
00210     unsigned int tupstate:2,    /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
00211                 allTheSame:1,   /* all nodes in tuple are equivalent */
00212                 nNodes:13,      /* number of nodes within inner tuple */
00213                 prefixSize:16;  /* size of prefix, or 0 if none */
00214     uint16      size;           /* total size of inner tuple */
00215     /* On most machines there will be a couple of wasted bytes here */
00216     /* prefix datum follows, then nodes */
00217 } SpGistInnerTupleData;
00218 
00219 typedef SpGistInnerTupleData *SpGistInnerTuple;
00220 
00221 /* these must match largest values that fit in bit fields declared above */
00222 #define SGITMAXNNODES       0x1FFF
00223 #define SGITMAXPREFIXSIZE   0xFFFF
00224 #define SGITMAXSIZE         0xFFFF
00225 
00226 #define SGITHDRSZ           MAXALIGN(sizeof(SpGistInnerTupleData))
00227 #define _SGITDATA(x)        (((char *) (x)) + SGITHDRSZ)
00228 #define SGITDATAPTR(x)      ((x)->prefixSize ? _SGITDATA(x) : NULL)
00229 #define SGITDATUM(x, s)     ((x)->prefixSize ? \
00230                              ((s)->attPrefixType.attbyval ? \
00231                               *(Datum *) _SGITDATA(x) : \
00232                               PointerGetDatum(_SGITDATA(x))) \
00233                              : (Datum) 0)
00234 #define SGITNODEPTR(x)      ((SpGistNodeTuple) (_SGITDATA(x) + (x)->prefixSize))
00235 
00236 /* Macro for iterating through the nodes of an inner tuple */
00237 #define SGITITERATE(x, i, nt)   \
00238     for ((i) = 0, (nt) = SGITNODEPTR(x); \
00239          (i) < (x)->nNodes; \
00240          (i)++, (nt) = (SpGistNodeTuple) (((char *) (nt)) + IndexTupleSize(nt)))
00241 
00242 /*
00243  * SPGiST node tuple: one node within an inner tuple
00244  *
00245  * Node tuples use the same header as ordinary Postgres IndexTuples, but
00246  * we do not use a null bitmap, because we know there is only one column
00247  * so the INDEX_NULL_MASK bit suffices.  Also, pass-by-value datums are
00248  * stored as a full Datum, the same convention as for inner tuple prefixes
00249  * and leaf tuple datums.
00250  */
00251 
00252 typedef IndexTupleData SpGistNodeTupleData;
00253 
00254 typedef SpGistNodeTupleData *SpGistNodeTuple;
00255 
00256 #define SGNTHDRSZ           MAXALIGN(sizeof(SpGistNodeTupleData))
00257 #define SGNTDATAPTR(x)      (((char *) (x)) + SGNTHDRSZ)
00258 #define SGNTDATUM(x, s)     ((s)->attLabelType.attbyval ? \
00259                              *(Datum *) SGNTDATAPTR(x) : \
00260                              PointerGetDatum(SGNTDATAPTR(x)))
00261 
00262 /*
00263  * SPGiST leaf tuple: carries a datum and a heap tuple TID
00264  *
00265  * In the simplest case, the datum is the same as the indexed value; but
00266  * it could also be a suffix or some other sort of delta that permits
00267  * reconstruction given knowledge of the prefix path traversed to get here.
00268  *
00269  * The size field is wider than could possibly be needed for an on-disk leaf
00270  * tuple, but this allows us to form leaf tuples even when the datum is too
00271  * wide to be stored immediately, and it costs nothing because of alignment
00272  * considerations.
00273  *
00274  * Normally, nextOffset links to the next tuple belonging to the same parent
00275  * node (which must be on the same page).  But when the root page is a leaf
00276  * page, we don't chain its tuples, so nextOffset is always 0 on the root.
00277  *
00278  * size must be a multiple of MAXALIGN; also, it must be at least SGDTSIZE
00279  * so that the tuple can be converted to REDIRECT status later.  (This
00280  * restriction only adds bytes for the null-datum case, otherwise alignment
00281  * restrictions force it anyway.)
00282  *
00283  * In a leaf tuple for a NULL indexed value, there's no useful datum value;
00284  * however, the SGDTSIZE limit ensures that's there's a Datum word there
00285  * anyway, so SGLTDATUM can be applied safely as long as you don't do
00286  * anything with the result.
00287  */
00288 typedef struct SpGistLeafTupleData
00289 {
00290     unsigned int tupstate:2,    /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
00291                 size:30;        /* large enough for any palloc'able value */
00292     OffsetNumber nextOffset;    /* next tuple in chain, or InvalidOffset */
00293     ItemPointerData heapPtr;    /* TID of represented heap tuple */
00294     /* leaf datum follows */
00295 } SpGistLeafTupleData;
00296 
00297 typedef SpGistLeafTupleData *SpGistLeafTuple;
00298 
00299 #define SGLTHDRSZ           MAXALIGN(sizeof(SpGistLeafTupleData))
00300 #define SGLTDATAPTR(x)      (((char *) (x)) + SGLTHDRSZ)
00301 #define SGLTDATUM(x, s)     ((s)->attType.attbyval ? \
00302                              *(Datum *) SGLTDATAPTR(x) : \
00303                              PointerGetDatum(SGLTDATAPTR(x)))
00304 
00305 /*
00306  * SPGiST dead tuple: declaration for examining non-live tuples
00307  *
00308  * The tupstate field of this struct must match those of regular inner and
00309  * leaf tuples, and its size field must match a leaf tuple's.
00310  * Also, the pointer field must be in the same place as a leaf tuple's heapPtr
00311  * field, to satisfy some Asserts that we make when replacing a leaf tuple
00312  * with a dead tuple.
00313  * We don't use nextOffset, but it's needed to align the pointer field.
00314  * pointer and xid are only valid when tupstate = REDIRECT.
00315  */
00316 typedef struct SpGistDeadTupleData
00317 {
00318     unsigned int tupstate:2,    /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
00319                 size:30;
00320     OffsetNumber nextOffset;    /* not used in dead tuples */
00321     ItemPointerData pointer;    /* redirection inside index */
00322     TransactionId xid;          /* ID of xact that inserted this tuple */
00323 } SpGistDeadTupleData;
00324 
00325 typedef SpGistDeadTupleData *SpGistDeadTuple;
00326 
00327 #define SGDTSIZE        MAXALIGN(sizeof(SpGistDeadTupleData))
00328 
00329 /*
00330  * Macros for doing free-space calculations.  Note that when adding up the
00331  * space needed for tuples, we always consider each tuple to need the tuple's
00332  * size plus sizeof(ItemIdData) (for the line pointer).  This works correctly
00333  * so long as tuple sizes are always maxaligned.
00334  */
00335 
00336 /* Page capacity after allowing for fixed header and special space */
00337 #define SPGIST_PAGE_CAPACITY  \
00338     MAXALIGN_DOWN(BLCKSZ - \
00339                   SizeOfPageHeaderData - \
00340                   MAXALIGN(sizeof(SpGistPageOpaqueData)))
00341 
00342 /*
00343  * Compute free space on page, assuming that up to n placeholders can be
00344  * recycled if present (n should be the number of tuples to be inserted)
00345  */
00346 #define SpGistPageGetFreeSpace(p, n) \
00347     (PageGetExactFreeSpace(p) + \
00348      Min(SpGistPageGetOpaque(p)->nPlaceholder, n) * \
00349      (SGDTSIZE + sizeof(ItemIdData)))
00350 
00351 /*
00352  * XLOG stuff
00353  *
00354  * ACCEPT_RDATA_* can only use fixed-length rdata arrays, because of lengthof
00355  */
00356 
00357 #define ACCEPT_RDATA_DATA(p, s, i)  \
00358     do { \
00359         Assert((i) < lengthof(rdata)); \
00360         rdata[i].data = (char *) (p); \
00361         rdata[i].len = (s); \
00362         rdata[i].buffer = InvalidBuffer; \
00363         rdata[i].buffer_std = true; \
00364         rdata[i].next = NULL; \
00365         if ((i) > 0) \
00366             rdata[(i) - 1].next = rdata + (i); \
00367     } while(0)
00368 
00369 #define ACCEPT_RDATA_BUFFER(b, i)  \
00370     do { \
00371         Assert((i) < lengthof(rdata)); \
00372         rdata[i].data = NULL; \
00373         rdata[i].len = 0; \
00374         rdata[i].buffer = (b); \
00375         rdata[i].buffer_std = true; \
00376         rdata[i].next = NULL; \
00377         if ((i) > 0) \
00378             rdata[(i) - 1].next = rdata + (i); \
00379     } while(0)
00380 
00381 
00382 /* XLOG record types for SPGiST */
00383 #define XLOG_SPGIST_CREATE_INDEX    0x00
00384 #define XLOG_SPGIST_ADD_LEAF        0x10
00385 #define XLOG_SPGIST_MOVE_LEAFS      0x20
00386 #define XLOG_SPGIST_ADD_NODE        0x30
00387 #define XLOG_SPGIST_SPLIT_TUPLE     0x40
00388 #define XLOG_SPGIST_PICKSPLIT       0x50
00389 #define XLOG_SPGIST_VACUUM_LEAF     0x60
00390 #define XLOG_SPGIST_VACUUM_ROOT     0x70
00391 #define XLOG_SPGIST_VACUUM_REDIRECT 0x80
00392 
00393 /*
00394  * Some redo functions need an SpGistState, although only a few of its fields
00395  * need to be valid.  spgxlogState carries the required info in xlog records.
00396  * (See fillFakeState in spgxlog.c for more comments.)
00397  */
00398 typedef struct spgxlogState
00399 {
00400     TransactionId myXid;
00401     bool        isBuild;
00402 } spgxlogState;
00403 
00404 #define STORE_STATE(s, d)  \
00405     do { \
00406         (d).myXid = (s)->myXid; \
00407         (d).isBuild = (s)->isBuild; \
00408     } while(0)
00409 
00410 
00411 typedef struct spgxlogAddLeaf
00412 {
00413     RelFileNode node;
00414 
00415     BlockNumber blknoLeaf;      /* destination page for leaf tuple */
00416     bool        newPage;        /* init dest page? */
00417     bool        storesNulls;    /* page is in the nulls tree? */
00418     OffsetNumber offnumLeaf;    /* offset where leaf tuple gets placed */
00419     OffsetNumber offnumHeadLeaf;    /* offset of head tuple in chain, if any */
00420 
00421     BlockNumber blknoParent;    /* where the parent downlink is, if any */
00422     OffsetNumber offnumParent;
00423     uint16      nodeI;
00424 
00425     /*
00426      * new leaf tuple follows, on an intalign boundary (replay only needs to
00427      * fetch its size field, so that should be enough alignment)
00428      */
00429 } spgxlogAddLeaf;
00430 
00431 typedef struct spgxlogMoveLeafs
00432 {
00433     RelFileNode node;
00434 
00435     BlockNumber blknoSrc;       /* source leaf page */
00436     BlockNumber blknoDst;       /* destination leaf page */
00437     uint16      nMoves;         /* number of tuples moved from source page */
00438     bool        newPage;        /* init dest page? */
00439     bool        replaceDead;    /* are we replacing a DEAD source tuple? */
00440     bool        storesNulls;    /* pages are in the nulls tree? */
00441 
00442     BlockNumber blknoParent;    /* where the parent downlink is */
00443     OffsetNumber offnumParent;
00444     uint16      nodeI;
00445 
00446     spgxlogState stateSrc;
00447 
00448     /*----------
00449      * data follows:
00450      *      array of deleted tuple numbers, length nMoves
00451      *      array of inserted tuple numbers, length nMoves + 1 or 1
00452      *      list of leaf tuples, length nMoves + 1 or 1 (must be maxaligned)
00453      * the tuple number arrays are padded to maxalign boundaries so that the
00454      * leaf tuples will be suitably aligned
00455      *
00456      * Note: if replaceDead is true then there is only one inserted tuple
00457      * number and only one leaf tuple in the data, because we are not copying
00458      * the dead tuple from the source
00459      *
00460      * Buffer references in the rdata array are:
00461      *      Src page
00462      *      Dest page
00463      *      Parent page
00464      *----------
00465      */
00466 } spgxlogMoveLeafs;
00467 
00468 typedef struct spgxlogAddNode
00469 {
00470     RelFileNode node;
00471 
00472     BlockNumber blkno;          /* block number of original inner tuple */
00473     OffsetNumber offnum;        /* offset of original inner tuple */
00474 
00475     BlockNumber blknoParent;    /* where parent downlink is, if updated */
00476     OffsetNumber offnumParent;
00477     uint16      nodeI;
00478 
00479     BlockNumber blknoNew;       /* where new tuple goes, if not same place */
00480     OffsetNumber offnumNew;
00481     bool        newPage;        /* init new page? */
00482 
00483     spgxlogState stateSrc;
00484 
00485     /*
00486      * updated inner tuple follows, on an intalign boundary (replay only needs
00487      * to fetch its size field, so that should be enough alignment)
00488      */
00489 } spgxlogAddNode;
00490 
00491 typedef struct spgxlogSplitTuple
00492 {
00493     RelFileNode node;
00494 
00495     BlockNumber blknoPrefix;    /* where the prefix tuple goes */
00496     OffsetNumber offnumPrefix;
00497 
00498     BlockNumber blknoPostfix;   /* where the postfix tuple goes */
00499     OffsetNumber offnumPostfix;
00500     bool        newPage;        /* need to init that page? */
00501 
00502     /*
00503      * new prefix inner tuple follows, then new postfix inner tuple, on
00504      * intalign boundaries (replay only needs to fetch size fields, so that
00505      * should be enough alignment)
00506      */
00507 } spgxlogSplitTuple;
00508 
00509 typedef struct spgxlogPickSplit
00510 {
00511     RelFileNode node;
00512 
00513     BlockNumber blknoSrc;       /* original leaf page */
00514     BlockNumber blknoDest;      /* other leaf page, if any */
00515     uint16      nDelete;        /* n to delete from Src */
00516     uint16      nInsert;        /* n to insert on Src and/or Dest */
00517     bool        initSrc;        /* re-init the Src page? */
00518     bool        initDest;       /* re-init the Dest page? */
00519 
00520     BlockNumber blknoInner;     /* where to put new inner tuple */
00521     OffsetNumber offnumInner;
00522     bool        initInner;      /* re-init the Inner page? */
00523 
00524     bool        storesNulls;    /* pages are in the nulls tree? */
00525 
00526     BlockNumber blknoParent;    /* where the parent downlink is, if any */
00527     OffsetNumber offnumParent;
00528     uint16      nodeI;
00529 
00530     spgxlogState stateSrc;
00531 
00532     /*----------
00533      * data follows:
00534      *      new inner tuple (assumed to have a maxaligned length)
00535      *      array of deleted tuple numbers, length nDelete
00536      *      array of inserted tuple numbers, length nInsert
00537      *      array of page selector bytes for inserted tuples, length nInsert
00538      *      list of leaf tuples, length nInsert (must be maxaligned)
00539      * the tuple number and page selector arrays are padded to maxalign
00540      * boundaries so that the leaf tuples will be suitably aligned
00541      *
00542      * Buffer references in the rdata array are:
00543      *      Src page (only if not root and not being init'd)
00544      *      Dest page (if used and not being init'd)
00545      *      Inner page (only if not being init'd)
00546      *      Parent page (if any; could be same as Inner)
00547      *----------
00548      */
00549 } spgxlogPickSplit;
00550 
00551 typedef struct spgxlogVacuumLeaf
00552 {
00553     RelFileNode node;
00554 
00555     BlockNumber blkno;          /* block number to clean */
00556     uint16      nDead;          /* number of tuples to become DEAD */
00557     uint16      nPlaceholder;   /* number of tuples to become PLACEHOLDER */
00558     uint16      nMove;          /* number of tuples to move */
00559     uint16      nChain;         /* number of tuples to re-chain */
00560 
00561     spgxlogState stateSrc;
00562 
00563     /*----------
00564      * data follows:
00565      *      tuple numbers to become DEAD
00566      *      tuple numbers to become PLACEHOLDER
00567      *      tuple numbers to move from (and replace with PLACEHOLDER)
00568      *      tuple numbers to move to (replacing what is there)
00569      *      tuple numbers to update nextOffset links of
00570      *      tuple numbers to insert in nextOffset links
00571      *----------
00572      */
00573 } spgxlogVacuumLeaf;
00574 
00575 typedef struct spgxlogVacuumRoot
00576 {
00577     /* vacuum a root page when it is also a leaf */
00578     RelFileNode node;
00579 
00580     BlockNumber blkno;          /* block number to clean */
00581     uint16      nDelete;        /* number of tuples to delete */
00582 
00583     spgxlogState stateSrc;
00584 
00585     /* offsets of tuples to delete follow */
00586 } spgxlogVacuumRoot;
00587 
00588 typedef struct spgxlogVacuumRedirect
00589 {
00590     RelFileNode node;
00591 
00592     BlockNumber blkno;          /* block number to clean */
00593     uint16      nToPlaceholder; /* number of redirects to make placeholders */
00594     OffsetNumber firstPlaceholder;      /* first placeholder tuple to remove */
00595     TransactionId newestRedirectXid;    /* newest XID of removed redirects */
00596 
00597     /* offsets of redirect tuples to make placeholders follow */
00598 } spgxlogVacuumRedirect;
00599 
00600 /*
00601  * The "flags" argument for SpGistGetBuffer should be either GBUF_LEAF to
00602  * get a leaf page, or GBUF_INNER_PARITY(blockNumber) to get an inner
00603  * page in the same triple-parity group as the specified block number.
00604  * (Typically, this should be GBUF_INNER_PARITY(parentBlockNumber + 1)
00605  * to follow the rule described in spgist/README.)
00606  * In addition, GBUF_NULLS can be OR'd in to get a page for storage of
00607  * null-valued tuples.
00608  *
00609  * Note: these flag values are used as indexes into lastUsedPages.
00610  */
00611 #define GBUF_LEAF               0x03
00612 #define GBUF_INNER_PARITY(x)    ((x) % 3)
00613 #define GBUF_NULLS              0x04
00614 
00615 #define GBUF_PARITY_MASK        0x03
00616 #define GBUF_REQ_LEAF(flags)    (((flags) & GBUF_PARITY_MASK) == GBUF_LEAF)
00617 #define GBUF_REQ_NULLS(flags)   ((flags) & GBUF_NULLS)
00618 
00619 /* spgutils.c */
00620 extern SpGistCache *spgGetCache(Relation index);
00621 extern void initSpGistState(SpGistState *state, Relation index);
00622 extern Buffer SpGistNewBuffer(Relation index);
00623 extern void SpGistUpdateMetaPage(Relation index);
00624 extern Buffer SpGistGetBuffer(Relation index, int flags,
00625                 int needSpace, bool *isNew);
00626 extern void SpGistSetLastUsedPage(Relation index, Buffer buffer);
00627 extern void SpGistInitPage(Page page, uint16 f);
00628 extern void SpGistInitBuffer(Buffer b, uint16 f);
00629 extern void SpGistInitMetapage(Page page);
00630 extern unsigned int SpGistGetTypeSize(SpGistTypeDesc *att, Datum datum);
00631 extern SpGistLeafTuple spgFormLeafTuple(SpGistState *state,
00632                  ItemPointer heapPtr,
00633                  Datum datum, bool isnull);
00634 extern SpGistNodeTuple spgFormNodeTuple(SpGistState *state,
00635                  Datum label, bool isnull);
00636 extern SpGistInnerTuple spgFormInnerTuple(SpGistState *state,
00637                   bool hasPrefix, Datum prefix,
00638                   int nNodes, SpGistNodeTuple *nodes);
00639 extern SpGistDeadTuple spgFormDeadTuple(SpGistState *state, int tupstate,
00640                  BlockNumber blkno, OffsetNumber offnum);
00641 extern Datum *spgExtractNodeLabels(SpGistState *state,
00642                      SpGistInnerTuple innerTuple);
00643 extern OffsetNumber SpGistPageAddNewItem(SpGistState *state, Page page,
00644                      Item item, Size size,
00645                      OffsetNumber *startOffset,
00646                      bool errorOK);
00647 
00648 /* spgdoinsert.c */
00649 extern void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN,
00650                   BlockNumber blkno, OffsetNumber offset);
00651 extern void spgPageIndexMultiDelete(SpGistState *state, Page page,
00652                         OffsetNumber *itemnos, int nitems,
00653                         int firststate, int reststate,
00654                         BlockNumber blkno, OffsetNumber offnum);
00655 extern void spgdoinsert(Relation index, SpGistState *state,
00656             ItemPointer heapPtr, Datum datum, bool isnull);
00657 
00658 #endif   /* SPGIST_PRIVATE_H */