/*------------------------------------------------------------------------- * * spgxlog.h * xlog declarations for SP-GiST access method. * * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/spgxlog.h * *------------------------------------------------------------------------- */ #ifndef SPGXLOG_H #define SPGXLOG_H #include "access/xlogreader.h" #include "lib/stringinfo.h" #include "storage/off.h" /* XLOG record types for SPGiST */ /* #define XLOG_SPGIST_CREATE_INDEX 0x00 */ /* not used anymore */ #define XLOG_SPGIST_ADD_LEAF 0x10 #define XLOG_SPGIST_MOVE_LEAFS 0x20 #define XLOG_SPGIST_ADD_NODE 0x30 #define XLOG_SPGIST_SPLIT_TUPLE 0x40 #define XLOG_SPGIST_PICKSPLIT 0x50 #define XLOG_SPGIST_VACUUM_LEAF 0x60 #define XLOG_SPGIST_VACUUM_ROOT 0x70 #define XLOG_SPGIST_VACUUM_REDIRECT 0x80 /* * Some redo functions need an SpGistState, although only a few of its fields * need to be valid. spgxlogState carries the required info in xlog records. * (See fillFakeState in spgxlog.c for more comments.) */ typedef struct spgxlogState { TransactionId myXid; bool isBuild; } spgxlogState; /* * Backup Blk 0: destination page for leaf tuple * Backup Blk 1: parent page (if any) */ typedef struct spgxlogAddLeaf { bool newPage; /* init dest page? */ bool storesNulls; /* page is in the nulls tree? */ OffsetNumber offnumLeaf; /* offset where leaf tuple gets placed */ OffsetNumber offnumHeadLeaf; /* offset of head tuple in chain, if any */ OffsetNumber offnumParent; /* where the parent downlink is, if any */ uint16 nodeI; /* new leaf tuple follows (unaligned!) */ } spgxlogAddLeaf; /* * Backup Blk 0: source leaf page * Backup Blk 1: destination leaf page * Backup Blk 2: parent page */ typedef struct spgxlogMoveLeafs { uint16 nMoves; /* number of tuples moved from source page */ bool newPage; /* init dest page? */ bool replaceDead; /* are we replacing a DEAD source tuple? */ bool storesNulls; /* pages are in the nulls tree? */ /* where the parent downlink is */ OffsetNumber offnumParent; uint16 nodeI; spgxlogState stateSrc; /*---------- * data follows: * array of deleted tuple numbers, length nMoves * array of inserted tuple numbers, length nMoves + 1 or 1 * list of leaf tuples, length nMoves + 1 or 1 (unaligned!) * * Note: if replaceDead is true then there is only one inserted tuple * number and only one leaf tuple in the data, because we are not copying * the dead tuple from the source *---------- */ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogMoveLeafs; #define SizeOfSpgxlogMoveLeafs offsetof(spgxlogMoveLeafs, offsets) /* * Backup Blk 0: original page * Backup Blk 1: where new tuple goes, if not same place * Backup Blk 2: where parent downlink is, if updated and different from * the old and new */ typedef struct spgxlogAddNode { /* * Offset of the original inner tuple, in the original page (on backup * block 0). */ OffsetNumber offnum; /* * Offset of the new tuple, on the new page (on backup block 1). Invalid, * if we overwrote the old tuple in the original page). */ OffsetNumber offnumNew; bool newPage; /* init new page? */ /*---- * Where is the parent downlink? parentBlk indicates which page it's on, * and offnumParent is the offset within the page. The possible values for * parentBlk are: * * 0: parent == original page * 1: parent == new page * 2: parent == different page (blk ref 2) * -1: parent not updated *---- */ int8 parentBlk; OffsetNumber offnumParent; /* offset within the parent page */ uint16 nodeI; spgxlogState stateSrc; /* * updated inner tuple follows (unaligned!) */ } spgxlogAddNode; /* * Backup Blk 0: where the prefix tuple goes * Backup Blk 1: where the postfix tuple goes (if different page) */ typedef struct spgxlogSplitTuple { /* where the prefix tuple goes */ OffsetNumber offnumPrefix; /* where the postfix tuple goes */ OffsetNumber offnumPostfix; bool newPage; /* need to init that page? */ bool postfixBlkSame; /* was postfix tuple put on same page as * prefix? */ /* * new prefix inner tuple follows, then new postfix inner tuple (both are * unaligned!) */ } spgxlogSplitTuple; /* * Buffer references in the rdata array are: * Backup Blk 0: Src page (only if not root) * Backup Blk 1: Dest page (if used) * Backup Blk 2: Inner page * Backup Blk 3: Parent page (if any, and different from Inner) */ typedef struct spgxlogPickSplit { bool isRootSplit; uint16 nDelete; /* n to delete from Src */ uint16 nInsert; /* n to insert on Src and/or Dest */ bool initSrc; /* re-init the Src page? */ bool initDest; /* re-init the Dest page? */ /* where to put new inner tuple */ OffsetNumber offnumInner; bool initInner; /* re-init the Inner page? */ bool storesNulls; /* pages are in the nulls tree? */ /* where the parent downlink is, if any */ bool innerIsParent; /* is parent the same as inner page? */ OffsetNumber offnumParent; uint16 nodeI; spgxlogState stateSrc; /*---------- * data follows: * array of deleted tuple numbers, length nDelete * array of inserted tuple numbers, length nInsert * array of page selector bytes for inserted tuples, length nInsert * new inner tuple (unaligned!) * list of leaf tuples, length nInsert (unaligned!) *---------- */ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogPickSplit; #define SizeOfSpgxlogPickSplit offsetof(spgxlogPickSplit, offsets) typedef struct spgxlogVacuumLeaf { uint16 nDead; /* number of tuples to become DEAD */ uint16 nPlaceholder; /* number of tuples to become PLACEHOLDER */ uint16 nMove; /* number of tuples to move */ uint16 nChain; /* number of tuples to re-chain */ spgxlogState stateSrc; /*---------- * data follows: * tuple numbers to become DEAD * tuple numbers to become PLACEHOLDER * tuple numbers to move from (and replace with PLACEHOLDER) * tuple numbers to move to (replacing what is there) * tuple numbers to update nextOffset links of * tuple numbers to insert in nextOffset links *---------- */ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogVacuumLeaf; #define SizeOfSpgxlogVacuumLeaf offsetof(spgxlogVacuumLeaf, offsets) typedef struct spgxlogVacuumRoot { /* vacuum a root page when it is also a leaf */ uint16 nDelete; /* number of tuples to delete */ spgxlogState stateSrc; /* offsets of tuples to delete follow */ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogVacuumRoot; #define SizeOfSpgxlogVacuumRoot offsetof(spgxlogVacuumRoot, offsets) typedef struct spgxlogVacuumRedirect { uint16 nToPlaceholder; /* number of redirects to make placeholders */ OffsetNumber firstPlaceholder; /* first placeholder tuple to remove */ TransactionId snapshotConflictHorizon; /* newest XID of removed redirects */ bool isCatalogRel; /* to handle recovery conflict during logical * decoding on standby */ /* offsets of redirect tuples to make placeholders follow */ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; } spgxlogVacuumRedirect; #define SizeOfSpgxlogVacuumRedirect offsetof(spgxlogVacuumRedirect, offsets) extern void spg_redo(XLogReaderState *record); extern void spg_desc(StringInfo buf, XLogReaderState *record); extern const char *spg_identify(uint8 info); extern void spg_xlog_startup(void); extern void spg_xlog_cleanup(void); extern void spg_mask(char *pagedata, BlockNumber blkno); #endif /* SPGXLOG_H */