]> granicus.if.org Git - postgresql/blob - src/include/access/gist_private.h
1. full functional WAL for GiST
[postgresql] / src / include / access / gist_private.h
1 /*-------------------------------------------------------------------------
2  *
3  * gist_private.h
4  *        private declarations for GiST -- declarations related to the
5  *        internal implementation of GiST, not the public API
6  *
7  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.4 2005/06/20 10:29:36 teodor Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #ifndef GIST_PRIVATE_H
15 #define GIST_PRIVATE_H
16
17 #include "access/itup.h"
18 #include "access/gist.h"
19 #include "access/xlog.h"
20 #include "access/xlogdefs.h"
21 #include "fmgr.h"
22
23 /*
24  * When we descend a tree, we keep a stack of parent pointers. This
25  * allows us to follow a chain of internal node points until we reach
26  * a leaf node, and then back up the stack to re-examine the internal
27  * nodes.
28  *
29  * 'parent' is the previous stack entry -- i.e. the node we arrived
30  * from. 'block' is the node's block number. 'offset' is the offset in
31  * the node's page that we stopped at (i.e. we followed the child
32  * pointer located at the specified offset).
33  */
34 typedef struct GISTSTACK
35 {
36         struct GISTSTACK *parent;
37         OffsetNumber offset;
38         BlockNumber block;
39 } GISTSTACK;
40
41 typedef struct GISTSTATE
42 {
43         FmgrInfo        consistentFn[INDEX_MAX_KEYS];
44         FmgrInfo        unionFn[INDEX_MAX_KEYS];
45         FmgrInfo        compressFn[INDEX_MAX_KEYS];
46         FmgrInfo        decompressFn[INDEX_MAX_KEYS];
47         FmgrInfo        penaltyFn[INDEX_MAX_KEYS];
48         FmgrInfo        picksplitFn[INDEX_MAX_KEYS];
49         FmgrInfo        equalFn[INDEX_MAX_KEYS];
50
51         TupleDesc       tupdesc;
52 } GISTSTATE;
53
54 /*
55  *      When we're doing a scan, we need to keep track of the parent stack
56  *      for the marked and current items.
57  */
58 typedef struct GISTScanOpaqueData
59 {
60         GISTSTACK                       *stack;
61         GISTSTACK                       *markstk;
62         uint16                           flags;
63         GISTSTATE                       *giststate;
64         MemoryContext            tempCxt;
65         Buffer                           curbuf;
66         Buffer                           markbuf;
67 } GISTScanOpaqueData;
68
69 typedef GISTScanOpaqueData *GISTScanOpaque;
70
71 /*
72  * GISTInsertStack used for locking buffers and transfer arguments during
73  * insertion
74  */
75
76 typedef struct GISTInsertStack {
77         /* current page */
78         BlockNumber     blkno;   
79         Buffer          buffer;
80         Page            page;
81         
82         /* child's offset */
83         OffsetNumber    childoffnum;
84
85         /* pointer to parent */
86         struct GISTInsertStack  *parent;
87
88         bool todelete;
89 } GISTInsertStack;
90
91 typedef struct {
92         Relation        r;
93         IndexTuple      *itup; /* in/out, points to compressed entry */
94         int             ituplen; /* length of itup */
95         GISTInsertStack *stack;
96         bool needInsertComplete;
97
98         /* pointer to heap tuple */
99         ItemPointerData key;
100
101         /* path to stroe in XLog */
102         BlockNumber     *path;
103         int             pathlen; 
104 } GISTInsertState;
105
106 /*
107  * When we're doing a scan and updating a tree at the same time, the
108  * updates may affect the scan.  We use the flags entry of the scan's
109  * opaque space to record our actual position in response to updates
110  * that we can't handle simply by adjusting pointers.
111  */
112 #define GS_CURBEFORE    ((uint16) (1 << 0))
113 #define GS_MRKBEFORE    ((uint16) (1 << 1))
114
115 /* root page of a gist index */
116 #define GIST_ROOT_BLKNO                         0
117
118 /*
119  * When we update a relation on which we're doing a scan, we need to
120  * check the scan and fix it if the update affected any of the pages
121  * it touches.  Otherwise, we can miss records that we should see.
122  * The only times we need to do this are for deletions and splits. See
123  * the code in gistscan.c for how the scan is fixed. These two
124  * constants tell us what sort of operation changed the index.
125  */
126 #define GISTOP_DEL              0
127 #define GISTOP_SPLIT    1
128
129 #define ATTSIZE(datum, tupdesc, i, isnull) \
130         ( \
131                 (isnull) ? 0 : \
132                    att_addlength(0, (tupdesc)->attrs[(i)-1]->attlen, (datum)) \
133         ) 
134
135 /* XLog stuff */
136 #define XLOG_GIST_ENTRY_UPDATE  0x00
137 #define XLOG_GIST_ENTRY_DELETE  0x10
138 #define XLOG_GIST_NEW_ROOT      0x20
139
140 typedef struct gistxlogEntryUpdate {
141         RelFileNode     node;
142         BlockNumber     blkno;
143
144         uint16          ntodelete;
145         uint16          pathlen;
146         bool            isemptypage;    
147
148         /* 
149          * It used to identify completeness of insert.
150          * Sets to leaf itup 
151          */ 
152         ItemPointerData key;
153
154         /* follow:
155          * 1. path to root (BlockNumber)
156          * 2. todelete OffsetNumbers 
157          * 3. tuples to insert
158          */ 
159 } gistxlogEntryUpdate;
160
161 #define XLOG_GIST_PAGE_SPLIT    0x30
162
163 typedef struct gistxlogPageSplit {
164         RelFileNode     node;
165         BlockNumber     origblkno; /*splitted page*/
166         uint16          ntodelete;
167         uint16          pathlen;
168         uint16          npage;
169         uint16          nitup;
170
171         /* see comments on gistxlogEntryUpdate */
172         ItemPointerData key;
173  
174         /* follow:
175          * 1. path to root (BlockNumber) 
176          * 2. todelete OffsetNumbers 
177          * 3. tuples to insert
178          * 4. gistxlogPage and array of OffsetNumber per page
179          */ 
180 } gistxlogPageSplit;
181
182 typedef struct gistxlogPage {
183         BlockNumber     blkno;
184         int             num;
185 } gistxlogPage; 
186
187
188 #define XLOG_GIST_INSERT_COMPLETE  0x40
189
190 typedef struct gistxlogInsertComplete {
191         RelFileNode     node;
192         /* follows ItemPointerData key to clean */
193 } gistxlogInsertComplete;
194
195 #define XLOG_GIST_CREATE_INDEX  0x50
196
197 /*
198  * mark tuples on inner pages during recovery
199  */
200 #define TUPLE_IS_VALID          0xffff
201 #define TUPLE_IS_INVALID        0xfffe
202
203 #define  GistTupleIsInvalid(itup)       ( ItemPointerGetOffsetNumber( &((itup)->t_tid) ) == TUPLE_IS_INVALID )
204 #define  GistTupleSetValid(itup)        ItemPointerSetOffsetNumber( &((itup)->t_tid), TUPLE_IS_VALID )
205 #define  GistTupleSetInvalid(itup)      ItemPointerSetOffsetNumber( &((itup)->t_tid), TUPLE_IS_INVALID )
206
207 /* gist.c */
208 extern Datum gistbuild(PG_FUNCTION_ARGS);
209 extern Datum gistinsert(PG_FUNCTION_ARGS);
210 extern MemoryContext createTempGistContext(void);
211 extern void initGISTstate(GISTSTATE *giststate, Relation index);
212 extern void freeGISTstate(GISTSTATE *giststate);
213 extern void gistnewroot(Relation r, IndexTuple *itup, int len, ItemPointer key);
214 extern void gistmakedeal(GISTInsertState *state, GISTSTATE *giststate);
215
216 typedef struct SplitedPageLayout {
217         gistxlogPage    block;
218         OffsetNumber    *list;
219         Buffer          buffer; /* to write after all proceed */
220
221         struct SplitedPageLayout *next;
222 } SplitedPageLayout;
223
224 IndexTuple * gistSplit(Relation r, Buffer buffer, IndexTuple *itup,
225                   int *len, SplitedPageLayout    **dist, GISTSTATE *giststate);
226 /* gistxlog.c */
227 extern void gist_redo(XLogRecPtr lsn, XLogRecord *record);
228 extern void gist_desc(char *buf, uint8 xl_info, char *rec);
229 extern void gist_xlog_startup(void);
230 extern void gist_xlog_cleanup(void);
231 extern IndexTuple gist_form_invalid_tuple(BlockNumber blkno);
232
233 extern XLogRecData* formUpdateRdata(RelFileNode node, BlockNumber blkno,
234                 OffsetNumber *todelete, int ntodelete, bool emptypage,
235                 IndexTuple *itup, int ituplen, ItemPointer key,
236                 BlockNumber *path, int pathlen);
237
238 extern XLogRecData* formSplitRdata(RelFileNode node, BlockNumber blkno,
239                 OffsetNumber *todelete, int ntodelete, 
240                 IndexTuple *itup, int ituplen, ItemPointer key,
241                 BlockNumber *path, int pathlen, SplitedPageLayout *dist );
242
243 extern XLogRecPtr gistxlogInsertCompletion(RelFileNode node, ItemPointerData *keys, int len);
244
245 /* gistget.c */
246 extern Datum gistgettuple(PG_FUNCTION_ARGS);
247 extern Datum gistgetmulti(PG_FUNCTION_ARGS);
248
249 /* gistutil.c */
250 extern  Buffer  gistReadBuffer(Relation r, BlockNumber blkno);
251 extern OffsetNumber gistfillbuffer(Relation r, Page page, IndexTuple *itup,
252                                 int len, OffsetNumber off);
253 extern bool gistnospace(Page page, IndexTuple *itvec, int len);
254 extern IndexTuple * gistextractbuffer(Buffer buffer, int *len /* out */ );
255 extern IndexTuple * gistjoinvector(
256                            IndexTuple *itvec, int *len,
257                            IndexTuple *additvec, int addlen);
258 extern IndexTuple gistunion(Relation r, IndexTuple *itvec,
259                   int len, GISTSTATE *giststate);
260 extern IndexTuple gistgetadjusted(Relation r,
261                                 IndexTuple oldtup,
262                                 IndexTuple addtup,
263                                 GISTSTATE *giststate);
264 extern int gistfindgroup(GISTSTATE *giststate,
265                           GISTENTRY *valvec, GIST_SPLITVEC *spl);
266 extern void gistadjsubkey(Relation r,
267                           IndexTuple *itup, int len,
268                           GIST_SPLITVEC *v,
269                           GISTSTATE *giststate);
270 extern IndexTuple gistFormTuple(GISTSTATE *giststate,
271                         Relation r, Datum *attdata, int *datumsize, bool *isnull);
272
273 extern OffsetNumber gistchoose(Relation r, Page p,
274                    IndexTuple it,
275                    GISTSTATE *giststate);
276 extern void gistcentryinit(GISTSTATE *giststate, int nkey,
277                            GISTENTRY *e, Datum k, 
278                            Relation r, Page pg,
279                            OffsetNumber o, int b, bool l, bool isNull);
280 extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r,
281                               IndexTuple tuple, Page p, OffsetNumber o,
282                               GISTENTRY *attdata, bool *isnull);
283 extern void gistunionsubkey(Relation r, GISTSTATE *giststate, 
284                             IndexTuple *itvec, GIST_SPLITVEC *spl, bool isall);
285 extern void GISTInitBuffer(Buffer b, uint32 f);
286 extern void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
287                            Datum k, Relation r, Page pg, OffsetNumber o,
288                            int b, bool l, bool isNull);
289 void gistUserPicksplit(Relation r, GistEntryVector *entryvec, GIST_SPLITVEC *v,
290                 IndexTuple *itup, int len, GISTSTATE *giststate);
291
292 /* gistvacuum.c */
293 extern Datum gistbulkdelete(PG_FUNCTION_ARGS);
294 extern Datum gistvacuumcleanup(PG_FUNCTION_ARGS);
295
296 #endif  /* GIST_PRIVATE_H */