summaryrefslogtreecommitdiffstats
path: root/src/include/access/spgxlog.h
blob: 63d3c63db2db8d628813d77ff8359b750f436e9b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*-------------------------------------------------------------------------
 *
 * spgxlog.h
 *	  xlog declarations for SP-GiST access method.
 *
 * Portions Copyright (c) 1996-2020, 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 newestRedirectXid;	/* newest XID of removed redirects */

	/* 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 */