~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/include/access/nbtree.h

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * nbtree.h
 
4
 *        header file for postgres btree access method implementation.
 
5
 *
 
6
 *
 
7
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
8
 * Portions Copyright (c) 1994, Regents of the University of California
 
9
 *
 
10
 * src/include/access/nbtree.h
 
11
 *
 
12
 *-------------------------------------------------------------------------
 
13
 */
 
14
#ifndef NBTREE_H
 
15
#define NBTREE_H
 
16
 
 
17
#include "access/genam.h"
 
18
#include "access/itup.h"
 
19
#include "access/sdir.h"
 
20
#include "access/xlog.h"
 
21
#include "access/xlogutils.h"
 
22
 
 
23
 
 
24
/* There's room for a 16-bit vacuum cycle ID in BTPageOpaqueData */
 
25
typedef uint16 BTCycleId;
 
26
 
 
27
/*
 
28
 *      BTPageOpaqueData -- At the end of every page, we store a pointer
 
29
 *      to both siblings in the tree.  This is used to do forward/backward
 
30
 *      index scans.  The next-page link is also critical for recovery when
 
31
 *      a search has navigated to the wrong page due to concurrent page splits
 
32
 *      or deletions; see src/backend/access/nbtree/README for more info.
 
33
 *
 
34
 *      In addition, we store the page's btree level (counting upwards from
 
35
 *      zero at a leaf page) as well as some flag bits indicating the page type
 
36
 *      and status.  If the page is deleted, we replace the level with the
 
37
 *      next-transaction-ID value indicating when it is safe to reclaim the page.
 
38
 *
 
39
 *      We also store a "vacuum cycle ID".      When a page is split while VACUUM is
 
40
 *      processing the index, a nonzero value associated with the VACUUM run is
 
41
 *      stored into both halves of the split page.      (If VACUUM is not running,
 
42
 *      both pages receive zero cycleids.)      This allows VACUUM to detect whether
 
43
 *      a page was split since it started, with a small probability of false match
 
44
 *      if the page was last split some exact multiple of MAX_BT_CYCLE_ID VACUUMs
 
45
 *      ago.  Also, during a split, the BTP_SPLIT_END flag is cleared in the left
 
46
 *      (original) page, and set in the right page, but only if the next page
 
47
 *      to its right has a different cycleid.
 
48
 *
 
49
 *      NOTE: the BTP_LEAF flag bit is redundant since level==0 could be tested
 
50
 *      instead.
 
51
 */
 
52
 
 
53
typedef struct BTPageOpaqueData
 
54
{
 
55
        BlockNumber btpo_prev;          /* left sibling, or P_NONE if leftmost */
 
56
        BlockNumber btpo_next;          /* right sibling, or P_NONE if rightmost */
 
57
        union
 
58
        {
 
59
                uint32          level;          /* tree level --- zero for leaf pages */
 
60
                TransactionId xact;             /* next transaction ID, if deleted */
 
61
        }                       btpo;
 
62
        uint16          btpo_flags;             /* flag bits, see below */
 
63
        BTCycleId       btpo_cycleid;   /* vacuum cycle ID of latest split */
 
64
} BTPageOpaqueData;
 
65
 
 
66
typedef BTPageOpaqueData *BTPageOpaque;
 
67
 
 
68
/* Bits defined in btpo_flags */
 
69
#define BTP_LEAF                (1 << 0)        /* leaf page, i.e. not internal page */
 
70
#define BTP_ROOT                (1 << 1)        /* root page (has no parent) */
 
71
#define BTP_DELETED             (1 << 2)        /* page has been deleted from tree */
 
72
#define BTP_META                (1 << 3)        /* meta-page */
 
73
#define BTP_HALF_DEAD   (1 << 4)        /* empty, but still in tree */
 
74
#define BTP_SPLIT_END   (1 << 5)        /* rightmost page of split group */
 
75
#define BTP_HAS_GARBAGE (1 << 6)        /* page has LP_DEAD tuples */
 
76
 
 
77
/*
 
78
 * The max allowed value of a cycle ID is a bit less than 64K.  This is
 
79
 * for convenience of pg_filedump and similar utilities: we want to use
 
80
 * the last 2 bytes of special space as an index type indicator, and
 
81
 * restricting cycle ID lets btree use that space for vacuum cycle IDs
 
82
 * while still allowing index type to be identified.
 
83
 */
 
84
#define MAX_BT_CYCLE_ID         0xFF7F
 
85
 
 
86
 
 
87
/*
 
88
 * The Meta page is always the first page in the btree index.
 
89
 * Its primary purpose is to point to the location of the btree root page.
 
90
 * We also point to the "fast" root, which is the current effective root;
 
91
 * see README for discussion.
 
92
 */
 
93
 
 
94
typedef struct BTMetaPageData
 
95
{
 
96
        uint32          btm_magic;              /* should contain BTREE_MAGIC */
 
97
        uint32          btm_version;    /* should contain BTREE_VERSION */
 
98
        BlockNumber btm_root;           /* current root location */
 
99
        uint32          btm_level;              /* tree level of the root page */
 
100
        BlockNumber btm_fastroot;       /* current "fast" root location */
 
101
        uint32          btm_fastlevel;  /* tree level of the "fast" root page */
 
102
} BTMetaPageData;
 
103
 
 
104
#define BTPageGetMeta(p) \
 
105
        ((BTMetaPageData *) PageGetContents(p))
 
106
 
 
107
#define BTREE_METAPAGE  0               /* first page is meta */
 
108
#define BTREE_MAGIC             0x053162        /* magic number of btree pages */
 
109
#define BTREE_VERSION   2               /* current version number */
 
110
 
 
111
/*
 
112
 * Maximum size of a btree index entry, including its tuple header.
 
113
 *
 
114
 * We actually need to be able to fit three items on every page,
 
115
 * so restrict any one item to 1/3 the per-page available space.
 
116
 */
 
117
#define BTMaxItemSize(page) \
 
118
        MAXALIGN_DOWN((PageGetPageSize(page) - \
 
119
                                   MAXALIGN(SizeOfPageHeaderData + 3*sizeof(ItemIdData)) - \
 
120
                                   MAXALIGN(sizeof(BTPageOpaqueData))) / 3)
 
121
 
 
122
/*
 
123
 * The leaf-page fillfactor defaults to 90% but is user-adjustable.
 
124
 * For pages above the leaf level, we use a fixed 70% fillfactor.
 
125
 * The fillfactor is applied during index build and when splitting
 
126
 * a rightmost page; when splitting non-rightmost pages we try to
 
127
 * divide the data equally.
 
128
 */
 
129
#define BTREE_MIN_FILLFACTOR            10
 
130
#define BTREE_DEFAULT_FILLFACTOR        90
 
131
#define BTREE_NONLEAF_FILLFACTOR        70
 
132
 
 
133
/*
 
134
 *      Test whether two btree entries are "the same".
 
135
 *
 
136
 *      Old comments:
 
137
 *      In addition, we must guarantee that all tuples in the index are unique,
 
138
 *      in order to satisfy some assumptions in Lehman and Yao.  The way that we
 
139
 *      do this is by generating a new OID for every insertion that we do in the
 
140
 *      tree.  This adds eight bytes to the size of btree index tuples.  Note
 
141
 *      that we do not use the OID as part of a composite key; the OID only
 
142
 *      serves as a unique identifier for a given index tuple (logical position
 
143
 *      within a page).
 
144
 *
 
145
 *      New comments:
 
146
 *      actually, we must guarantee that all tuples in A LEVEL
 
147
 *      are unique, not in ALL INDEX. So, we can use the t_tid
 
148
 *      as unique identifier for a given index tuple (logical position
 
149
 *      within a level). - vadim 04/09/97
 
150
 */
 
151
#define BTTidSame(i1, i2)       \
 
152
        ( (i1).ip_blkid.bi_hi == (i2).ip_blkid.bi_hi && \
 
153
          (i1).ip_blkid.bi_lo == (i2).ip_blkid.bi_lo && \
 
154
          (i1).ip_posid == (i2).ip_posid )
 
155
#define BTEntrySame(i1, i2) \
 
156
        BTTidSame((i1)->t_tid, (i2)->t_tid)
 
157
 
 
158
 
 
159
/*
 
160
 *      In general, the btree code tries to localize its knowledge about
 
161
 *      page layout to a couple of routines.  However, we need a special
 
162
 *      value to indicate "no page number" in those places where we expect
 
163
 *      page numbers.  We can use zero for this because we never need to
 
164
 *      make a pointer to the metadata page.
 
165
 */
 
166
 
 
167
#define P_NONE                  0
 
168
 
 
169
/*
 
170
 * Macros to test whether a page is leftmost or rightmost on its tree level,
 
171
 * as well as other state info kept in the opaque data.
 
172
 */
 
173
#define P_LEFTMOST(opaque)              ((opaque)->btpo_prev == P_NONE)
 
174
#define P_RIGHTMOST(opaque)             ((opaque)->btpo_next == P_NONE)
 
175
#define P_ISLEAF(opaque)                ((opaque)->btpo_flags & BTP_LEAF)
 
176
#define P_ISROOT(opaque)                ((opaque)->btpo_flags & BTP_ROOT)
 
177
#define P_ISDELETED(opaque)             ((opaque)->btpo_flags & BTP_DELETED)
 
178
#define P_ISHALFDEAD(opaque)    ((opaque)->btpo_flags & BTP_HALF_DEAD)
 
179
#define P_IGNORE(opaque)                ((opaque)->btpo_flags & (BTP_DELETED|BTP_HALF_DEAD))
 
180
#define P_HAS_GARBAGE(opaque)   ((opaque)->btpo_flags & BTP_HAS_GARBAGE)
 
181
 
 
182
/*
 
183
 *      Lehman and Yao's algorithm requires a ``high key'' on every non-rightmost
 
184
 *      page.  The high key is not a data key, but gives info about what range of
 
185
 *      keys is supposed to be on this page.  The high key on a page is required
 
186
 *      to be greater than or equal to any data key that appears on the page.
 
187
 *      If we find ourselves trying to insert a key > high key, we know we need
 
188
 *      to move right (this should only happen if the page was split since we
 
189
 *      examined the parent page).
 
190
 *
 
191
 *      Our insertion algorithm guarantees that we can use the initial least key
 
192
 *      on our right sibling as the high key.  Once a page is created, its high
 
193
 *      key changes only if the page is split.
 
194
 *
 
195
 *      On a non-rightmost page, the high key lives in item 1 and data items
 
196
 *      start in item 2.  Rightmost pages have no high key, so we store data
 
197
 *      items beginning in item 1.
 
198
 */
 
199
 
 
200
#define P_HIKEY                         ((OffsetNumber) 1)
 
201
#define P_FIRSTKEY                      ((OffsetNumber) 2)
 
202
#define P_FIRSTDATAKEY(opaque)  (P_RIGHTMOST(opaque) ? P_HIKEY : P_FIRSTKEY)
 
203
 
 
204
/*
 
205
 * XLOG records for btree operations
 
206
 *
 
207
 * XLOG allows to store some information in high 4 bits of log
 
208
 * record xl_info field
 
209
 */
 
210
#define XLOG_BTREE_INSERT_LEAF  0x00    /* add index tuple without split */
 
211
#define XLOG_BTREE_INSERT_UPPER 0x10    /* same, on a non-leaf page */
 
212
#define XLOG_BTREE_INSERT_META  0x20    /* same, plus update metapage */
 
213
#define XLOG_BTREE_SPLIT_L              0x30    /* add index tuple with split */
 
214
#define XLOG_BTREE_SPLIT_R              0x40    /* as above, new item on right */
 
215
#define XLOG_BTREE_SPLIT_L_ROOT 0x50    /* add tuple with split of root */
 
216
#define XLOG_BTREE_SPLIT_R_ROOT 0x60    /* as above, new item on right */
 
217
#define XLOG_BTREE_DELETE               0x70    /* delete leaf index tuples for a page */
 
218
#define XLOG_BTREE_DELETE_PAGE  0x80    /* delete an entire page */
 
219
#define XLOG_BTREE_DELETE_PAGE_META 0x90                /* same, and update metapage */
 
220
#define XLOG_BTREE_NEWROOT              0xA0    /* new root page */
 
221
#define XLOG_BTREE_DELETE_PAGE_HALF 0xB0                /* page deletion that makes
 
222
                                                                                                 * parent half-dead */
 
223
#define XLOG_BTREE_VACUUM               0xC0    /* delete entries on a page during
 
224
                                                                                 * vacuum */
 
225
#define XLOG_BTREE_REUSE_PAGE   0xD0    /* old page is about to be reused from
 
226
                                                                                 * FSM */
 
227
 
 
228
/*
 
229
 * All that we need to find changed index tuple
 
230
 */
 
231
typedef struct xl_btreetid
 
232
{
 
233
        RelFileNode node;
 
234
        ItemPointerData tid;            /* changed tuple id */
 
235
} xl_btreetid;
 
236
 
 
237
/*
 
238
 * All that we need to regenerate the meta-data page
 
239
 */
 
240
typedef struct xl_btree_metadata
 
241
{
 
242
        BlockNumber root;
 
243
        uint32          level;
 
244
        BlockNumber fastroot;
 
245
        uint32          fastlevel;
 
246
} xl_btree_metadata;
 
247
 
 
248
/*
 
249
 * This is what we need to know about simple (without split) insert.
 
250
 *
 
251
 * This data record is used for INSERT_LEAF, INSERT_UPPER, INSERT_META.
 
252
 * Note that INSERT_META implies it's not a leaf page.
 
253
 */
 
254
typedef struct xl_btree_insert
 
255
{
 
256
        xl_btreetid target;                     /* inserted tuple id */
 
257
        /* BlockNumber downlink field FOLLOWS IF NOT XLOG_BTREE_INSERT_LEAF */
 
258
        /* xl_btree_metadata FOLLOWS IF XLOG_BTREE_INSERT_META */
 
259
        /* INDEX TUPLE FOLLOWS AT END OF STRUCT */
 
260
} xl_btree_insert;
 
261
 
 
262
#define SizeOfBtreeInsert       (offsetof(xl_btreetid, tid) + SizeOfIptrData)
 
263
 
 
264
/*
 
265
 * On insert with split, we save all the items going into the right sibling
 
266
 * so that we can restore it completely from the log record.  This way takes
 
267
 * less xlog space than the normal approach, because if we did it standardly,
 
268
 * XLogInsert would almost always think the right page is new and store its
 
269
 * whole page image.  The left page, however, is handled in the normal
 
270
 * incremental-update fashion.
 
271
 *
 
272
 * Note: the four XLOG_BTREE_SPLIT xl_info codes all use this data record.
 
273
 * The _L and _R variants indicate whether the inserted tuple went into the
 
274
 * left or right split page (and thus, whether newitemoff and the new item
 
275
 * are stored or not).  The _ROOT variants indicate that we are splitting
 
276
 * the root page, and thus that a newroot record rather than an insert or
 
277
 * split record should follow.  Note that a split record never carries a
 
278
 * metapage update --- we'll do that in the parent-level update.
 
279
 */
 
280
typedef struct xl_btree_split
 
281
{
 
282
        RelFileNode node;
 
283
        BlockNumber leftsib;            /* orig page / new left page */
 
284
        BlockNumber rightsib;           /* new right page */
 
285
        BlockNumber rnext;                      /* next block (orig page's rightlink) */
 
286
        uint32          level;                  /* tree level of page being split */
 
287
        OffsetNumber firstright;        /* first item moved to right page */
 
288
 
 
289
        /*
 
290
         * If level > 0, BlockIdData downlink follows.  (We use BlockIdData rather
 
291
         * than BlockNumber for alignment reasons: SizeOfBtreeSplit is only 16-bit
 
292
         * aligned.)
 
293
         *
 
294
         * If level > 0, an IndexTuple representing the HIKEY of the left page
 
295
         * follows.  We don't need this on leaf pages, because it's the same as
 
296
         * the leftmost key in the new right page.      Also, it's suppressed if
 
297
         * XLogInsert chooses to store the left page's whole page image.
 
298
         *
 
299
         * In the _L variants, next are OffsetNumber newitemoff and the new item.
 
300
         * (In the _R variants, the new item is one of the right page's tuples.)
 
301
         * The new item, but not newitemoff, is suppressed if XLogInsert chooses
 
302
         * to store the left page's whole page image.
 
303
         *
 
304
         * Last are the right page's tuples in the form used by _bt_restore_page.
 
305
         */
 
306
} xl_btree_split;
 
307
 
 
308
#define SizeOfBtreeSplit        (offsetof(xl_btree_split, firstright) + sizeof(OffsetNumber))
 
309
 
 
310
/*
 
311
 * This is what we need to know about delete of individual leaf index tuples.
 
312
 * The WAL record can represent deletion of any number of index tuples on a
 
313
 * single index page when *not* executed by VACUUM.
 
314
 */
 
315
typedef struct xl_btree_delete
 
316
{
 
317
        RelFileNode node;                       /* RelFileNode of the index */
 
318
        BlockNumber block;
 
319
        RelFileNode hnode;                      /* RelFileNode of the heap the index currently
 
320
                                                                 * points at */
 
321
        int                     nitems;
 
322
 
 
323
        /* TARGET OFFSET NUMBERS FOLLOW AT THE END */
 
324
} xl_btree_delete;
 
325
 
 
326
#define SizeOfBtreeDelete       (offsetof(xl_btree_delete, nitems) + sizeof(int))
 
327
 
 
328
/*
 
329
 * This is what we need to know about page reuse within btree.
 
330
 */
 
331
typedef struct xl_btree_reuse_page
 
332
{
 
333
        RelFileNode node;
 
334
        BlockNumber block;
 
335
        TransactionId latestRemovedXid;
 
336
} xl_btree_reuse_page;
 
337
 
 
338
#define SizeOfBtreeReusePage    (sizeof(xl_btree_reuse_page))
 
339
 
 
340
/*
 
341
 * This is what we need to know about vacuum of individual leaf index tuples.
 
342
 * The WAL record can represent deletion of any number of index tuples on a
 
343
 * single index page when executed by VACUUM.
 
344
 *
 
345
 * The correctness requirement for applying these changes during recovery is
 
346
 * that we must do one of these two things for every block in the index:
 
347
 *              * lock the block for cleanup and apply any required changes
 
348
 *              * EnsureBlockUnpinned()
 
349
 * The purpose of this is to ensure that no index scans started before we
 
350
 * finish scanning the index are still running by the time we begin to remove
 
351
 * heap tuples.
 
352
 *
 
353
 * Any changes to any one block are registered on just one WAL record. All
 
354
 * blocks that we need to run EnsureBlockUnpinned() are listed as a block range
 
355
 * starting from the last block vacuumed through until this one. Individual
 
356
 * block numbers aren't given.
 
357
 *
 
358
 * Note that the *last* WAL record in any vacuum of an index is allowed to
 
359
 * have a zero length array of offsets. Earlier records must have at least one.
 
360
 */
 
361
typedef struct xl_btree_vacuum
 
362
{
 
363
        RelFileNode node;
 
364
        BlockNumber block;
 
365
        BlockNumber lastBlockVacuumed;
 
366
 
 
367
        /* TARGET OFFSET NUMBERS FOLLOW */
 
368
} xl_btree_vacuum;
 
369
 
 
370
#define SizeOfBtreeVacuum       (offsetof(xl_btree_vacuum, lastBlockVacuumed) + sizeof(BlockNumber))
 
371
 
 
372
/*
 
373
 * This is what we need to know about deletion of a btree page.  The target
 
374
 * identifies the tuple removed from the parent page (note that we remove
 
375
 * this tuple's downlink and the *following* tuple's key).      Note we do not
 
376
 * store any content for the deleted page --- it is just rewritten as empty
 
377
 * during recovery, apart from resetting the btpo.xact.
 
378
 */
 
379
typedef struct xl_btree_delete_page
 
380
{
 
381
        xl_btreetid target;                     /* deleted tuple id in parent page */
 
382
        BlockNumber deadblk;            /* child block being deleted */
 
383
        BlockNumber leftblk;            /* child block's left sibling, if any */
 
384
        BlockNumber rightblk;           /* child block's right sibling */
 
385
        TransactionId btpo_xact;        /* value of btpo.xact for use in recovery */
 
386
        /* xl_btree_metadata FOLLOWS IF XLOG_BTREE_DELETE_PAGE_META */
 
387
} xl_btree_delete_page;
 
388
 
 
389
#define SizeOfBtreeDeletePage   (offsetof(xl_btree_delete_page, btpo_xact) + sizeof(TransactionId))
 
390
 
 
391
/*
 
392
 * New root log record.  There are zero tuples if this is to establish an
 
393
 * empty root, or two if it is the result of splitting an old root.
 
394
 *
 
395
 * Note that although this implies rewriting the metadata page, we don't need
 
396
 * an xl_btree_metadata record --- the rootblk and level are sufficient.
 
397
 */
 
398
typedef struct xl_btree_newroot
 
399
{
 
400
        RelFileNode node;
 
401
        BlockNumber rootblk;            /* location of new root */
 
402
        uint32          level;                  /* its tree level */
 
403
        /* 0 or 2 INDEX TUPLES FOLLOW AT END OF STRUCT */
 
404
} xl_btree_newroot;
 
405
 
 
406
#define SizeOfBtreeNewroot      (offsetof(xl_btree_newroot, level) + sizeof(uint32))
 
407
 
 
408
 
 
409
/*
 
410
 *      Operator strategy numbers for B-tree have been moved to access/skey.h,
 
411
 *      because many places need to use them in ScanKeyInit() calls.
 
412
 *
 
413
 *      The strategy numbers are chosen so that we can commute them by
 
414
 *      subtraction, thus:
 
415
 */
 
416
#define BTCommuteStrategyNumber(strat)  (BTMaxStrategyNumber + 1 - (strat))
 
417
 
 
418
/*
 
419
 *      When a new operator class is declared, we require that the user
 
420
 *      supply us with an amproc procedure for determining whether, for
 
421
 *      two keys a and b, a < b, a = b, or a > b.  This routine must
 
422
 *      return < 0, 0, > 0, respectively, in these three cases.  Since we
 
423
 *      only have one such proc in amproc, it's number 1.
 
424
 */
 
425
 
 
426
#define BTORDER_PROC    1
 
427
 
 
428
/*
 
429
 *      We need to be able to tell the difference between read and write
 
430
 *      requests for pages, in order to do locking correctly.
 
431
 */
 
432
 
 
433
#define BT_READ                 BUFFER_LOCK_SHARE
 
434
#define BT_WRITE                BUFFER_LOCK_EXCLUSIVE
 
435
 
 
436
/*
 
437
 *      BTStackData -- As we descend a tree, we push the (location, downlink)
 
438
 *      pairs from internal pages onto a private stack.  If we split a
 
439
 *      leaf, we use this stack to walk back up the tree and insert data
 
440
 *      into parent pages (and possibly to split them, too).  Lehman and
 
441
 *      Yao's update algorithm guarantees that under no circumstances can
 
442
 *      our private stack give us an irredeemably bad picture up the tree.
 
443
 *      Again, see the paper for details.
 
444
 */
 
445
 
 
446
typedef struct BTStackData
 
447
{
 
448
        BlockNumber bts_blkno;
 
449
        OffsetNumber bts_offset;
 
450
        IndexTupleData bts_btentry;
 
451
        struct BTStackData *bts_parent;
 
452
} BTStackData;
 
453
 
 
454
typedef BTStackData *BTStack;
 
455
 
 
456
/*
 
457
 * BTScanOpaqueData is the btree-private state needed for an indexscan.
 
458
 * This consists of preprocessed scan keys (see _bt_preprocess_keys() for
 
459
 * details of the preprocessing), information about the current location
 
460
 * of the scan, and information about the marked location, if any.      (We use
 
461
 * BTScanPosData to represent the data needed for each of current and marked
 
462
 * locations.)  In addition we can remember some known-killed index entries
 
463
 * that must be marked before we can move off the current page.
 
464
 *
 
465
 * Index scans work a page at a time: we pin and read-lock the page, identify
 
466
 * all the matching items on the page and save them in BTScanPosData, then
 
467
 * release the read-lock while returning the items to the caller for
 
468
 * processing.  This approach minimizes lock/unlock traffic.  Note that we
 
469
 * keep the pin on the index page until the caller is done with all the items
 
470
 * (this is needed for VACUUM synchronization, see nbtree/README).      When we
 
471
 * are ready to step to the next page, if the caller has told us any of the
 
472
 * items were killed, we re-lock the page to mark them killed, then unlock.
 
473
 * Finally we drop the pin and step to the next page in the appropriate
 
474
 * direction.
 
475
 */
 
476
 
 
477
typedef struct BTScanPosItem    /* what we remember about each match */
 
478
{
 
479
        ItemPointerData heapTid;        /* TID of referenced heap item */
 
480
        OffsetNumber indexOffset;       /* index item's location within page */
 
481
} BTScanPosItem;
 
482
 
 
483
typedef struct BTScanPosData
 
484
{
 
485
        Buffer          buf;                    /* if valid, the buffer is pinned */
 
486
 
 
487
        BlockNumber nextPage;           /* page's right link when we scanned it */
 
488
 
 
489
        /*
 
490
         * moreLeft and moreRight track whether we think there may be matching
 
491
         * index entries to the left and right of the current page, respectively.
 
492
         * We can clear the appropriate one of these flags when _bt_checkkeys()
 
493
         * returns continuescan = false.
 
494
         */
 
495
        bool            moreLeft;
 
496
        bool            moreRight;
 
497
 
 
498
        /*
 
499
         * The items array is always ordered in index order (ie, increasing
 
500
         * indexoffset).  When scanning backwards it is convenient to fill the
 
501
         * array back-to-front, so we start at the last slot and fill downwards.
 
502
         * Hence we need both a first-valid-entry and a last-valid-entry counter.
 
503
         * itemIndex is a cursor showing which entry was last returned to caller.
 
504
         */
 
505
        int                     firstItem;              /* first valid index in items[] */
 
506
        int                     lastItem;               /* last valid index in items[] */
 
507
        int                     itemIndex;              /* current index in items[] */
 
508
 
 
509
        BTScanPosItem items[MaxIndexTuplesPerPage]; /* MUST BE LAST */
 
510
} BTScanPosData;
 
511
 
 
512
typedef BTScanPosData *BTScanPos;
 
513
 
 
514
#define BTScanPosIsValid(scanpos) BufferIsValid((scanpos).buf)
 
515
 
 
516
typedef struct BTScanOpaqueData
 
517
{
 
518
        /* these fields are set by _bt_preprocess_keys(): */
 
519
        bool            qual_ok;                /* false if qual can never be satisfied */
 
520
        int                     numberOfKeys;   /* number of preprocessed scan keys */
 
521
        ScanKey         keyData;                /* array of preprocessed scan keys */
 
522
 
 
523
        /* info about killed items if any (killedItems is NULL if never used) */
 
524
        int                *killedItems;        /* currPos.items indexes of killed items */
 
525
        int                     numKilled;              /* number of currently stored items */
 
526
 
 
527
        /*
 
528
         * If the marked position is on the same page as current position, we
 
529
         * don't use markPos, but just keep the marked itemIndex in markItemIndex
 
530
         * (all the rest of currPos is valid for the mark position). Hence, to
 
531
         * determine if there is a mark, first look at markItemIndex, then at
 
532
         * markPos.
 
533
         */
 
534
        int                     markItemIndex;  /* itemIndex, or -1 if not valid */
 
535
 
 
536
        /* keep these last in struct for efficiency */
 
537
        BTScanPosData currPos;          /* current position data */
 
538
        BTScanPosData markPos;          /* marked position, if any */
 
539
} BTScanOpaqueData;
 
540
 
 
541
typedef BTScanOpaqueData *BTScanOpaque;
 
542
 
 
543
/*
 
544
 * We use some private sk_flags bits in preprocessed scan keys.  We're allowed
 
545
 * to use bits 16-31 (see skey.h).      The uppermost bits are copied from the
 
546
 * index's indoption[] array entry for the index attribute.
 
547
 */
 
548
#define SK_BT_REQFWD    0x00010000              /* required to continue forward scan */
 
549
#define SK_BT_REQBKWD   0x00020000              /* required to continue backward scan */
 
550
#define SK_BT_INDOPTION_SHIFT  24               /* must clear the above bits */
 
551
#define SK_BT_DESC                      (INDOPTION_DESC << SK_BT_INDOPTION_SHIFT)
 
552
#define SK_BT_NULLS_FIRST       (INDOPTION_NULLS_FIRST << SK_BT_INDOPTION_SHIFT)
 
553
 
 
554
/*
 
555
 * prototypes for functions in nbtree.c (external entry points for btree)
 
556
 */
 
557
extern Datum btbuild(PG_FUNCTION_ARGS);
 
558
extern Datum btbuildempty(PG_FUNCTION_ARGS);
 
559
extern Datum btinsert(PG_FUNCTION_ARGS);
 
560
extern Datum btbeginscan(PG_FUNCTION_ARGS);
 
561
extern Datum btgettuple(PG_FUNCTION_ARGS);
 
562
extern Datum btgetbitmap(PG_FUNCTION_ARGS);
 
563
extern Datum btrescan(PG_FUNCTION_ARGS);
 
564
extern Datum btendscan(PG_FUNCTION_ARGS);
 
565
extern Datum btmarkpos(PG_FUNCTION_ARGS);
 
566
extern Datum btrestrpos(PG_FUNCTION_ARGS);
 
567
extern Datum btbulkdelete(PG_FUNCTION_ARGS);
 
568
extern Datum btvacuumcleanup(PG_FUNCTION_ARGS);
 
569
extern Datum btoptions(PG_FUNCTION_ARGS);
 
570
 
 
571
/*
 
572
 * prototypes for functions in nbtinsert.c
 
573
 */
 
574
extern bool _bt_doinsert(Relation rel, IndexTuple itup,
 
575
                         IndexUniqueCheck checkUnique, Relation heapRel);
 
576
extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, int access);
 
577
extern void _bt_insert_parent(Relation rel, Buffer buf, Buffer rbuf,
 
578
                                  BTStack stack, bool is_root, bool is_only);
 
579
 
 
580
/*
 
581
 * prototypes for functions in nbtpage.c
 
582
 */
 
583
extern void _bt_initmetapage(Page page, BlockNumber rootbknum, uint32 level);
 
584
extern Buffer _bt_getroot(Relation rel, int access);
 
585
extern Buffer _bt_gettrueroot(Relation rel);
 
586
extern void _bt_checkpage(Relation rel, Buffer buf);
 
587
extern Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access);
 
588
extern Buffer _bt_relandgetbuf(Relation rel, Buffer obuf,
 
589
                                 BlockNumber blkno, int access);
 
590
extern void _bt_relbuf(Relation rel, Buffer buf);
 
591
extern void _bt_pageinit(Page page, Size size);
 
592
extern bool _bt_page_recyclable(Page page);
 
593
extern void _bt_delitems_delete(Relation rel, Buffer buf,
 
594
                                        OffsetNumber *itemnos, int nitems, Relation heapRel);
 
595
extern void _bt_delitems_vacuum(Relation rel, Buffer buf,
 
596
                   OffsetNumber *itemnos, int nitems, BlockNumber lastBlockVacuumed);
 
597
extern int      _bt_pagedel(Relation rel, Buffer buf, BTStack stack);
 
598
 
 
599
/*
 
600
 * prototypes for functions in nbtsearch.c
 
601
 */
 
602
extern BTStack _bt_search(Relation rel,
 
603
                   int keysz, ScanKey scankey, bool nextkey,
 
604
                   Buffer *bufP, int access);
 
605
extern Buffer _bt_moveright(Relation rel, Buffer buf, int keysz,
 
606
                          ScanKey scankey, bool nextkey, int access);
 
607
extern OffsetNumber _bt_binsrch(Relation rel, Buffer buf, int keysz,
 
608
                        ScanKey scankey, bool nextkey);
 
609
extern int32 _bt_compare(Relation rel, int keysz, ScanKey scankey,
 
610
                        Page page, OffsetNumber offnum);
 
611
extern bool _bt_first(IndexScanDesc scan, ScanDirection dir);
 
612
extern bool _bt_next(IndexScanDesc scan, ScanDirection dir);
 
613
extern Buffer _bt_get_endpoint(Relation rel, uint32 level, bool rightmost);
 
614
 
 
615
/*
 
616
 * prototypes for functions in nbtutils.c
 
617
 */
 
618
extern ScanKey _bt_mkscankey(Relation rel, IndexTuple itup);
 
619
extern ScanKey _bt_mkscankey_nodata(Relation rel);
 
620
extern void _bt_freeskey(ScanKey skey);
 
621
extern void _bt_freestack(BTStack stack);
 
622
extern void _bt_preprocess_keys(IndexScanDesc scan);
 
623
extern bool _bt_checkkeys(IndexScanDesc scan,
 
624
                          Page page, OffsetNumber offnum,
 
625
                          ScanDirection dir, bool *continuescan);
 
626
extern void _bt_killitems(IndexScanDesc scan, bool haveLock);
 
627
extern BTCycleId _bt_vacuum_cycleid(Relation rel);
 
628
extern BTCycleId _bt_start_vacuum(Relation rel);
 
629
extern void _bt_end_vacuum(Relation rel);
 
630
extern void _bt_end_vacuum_callback(int code, Datum arg);
 
631
extern Size BTreeShmemSize(void);
 
632
extern void BTreeShmemInit(void);
 
633
 
 
634
/*
 
635
 * prototypes for functions in nbtsort.c
 
636
 */
 
637
typedef struct BTSpool BTSpool; /* opaque type known only within nbtsort.c */
 
638
 
 
639
extern BTSpool *_bt_spoolinit(Relation index, bool isunique, bool isdead);
 
640
extern void _bt_spooldestroy(BTSpool *btspool);
 
641
extern void _bt_spool(IndexTuple itup, BTSpool *btspool);
 
642
extern void _bt_leafbuild(BTSpool *btspool, BTSpool *spool2);
 
643
 
 
644
/*
 
645
 * prototypes for functions in nbtxlog.c
 
646
 */
 
647
extern void btree_redo(XLogRecPtr lsn, XLogRecord *record);
 
648
extern void btree_desc(StringInfo buf, uint8 xl_info, char *rec);
 
649
extern void btree_xlog_startup(void);
 
650
extern void btree_xlog_cleanup(void);
 
651
extern bool btree_safe_restartpoint(void);
 
652
 
 
653
#endif   /* NBTREE_H */