1
/*****************************************************************************
3
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file include/btr0pcur.h
21
The index tree persistent cursor
23
Created 2/23/1996 Heikki Tuuri
24
*******************************************************/
30
#include "dict0dict.h"
31
#include "data0data.h"
36
#include "btr0types.h"
38
/* Relative positions for a stored cursor position */
40
#define BTR_PCUR_BEFORE 2
41
#define BTR_PCUR_AFTER 3
42
/* Note that if the tree is not empty, btr_pcur_store_position does not
43
use the following, but only uses the above three alternatives, where the
44
position is stored relative to a specific record: this makes implementation
45
of a scroll cursor easier */
46
#define BTR_PCUR_BEFORE_FIRST_IN_TREE 4 /* in an empty tree */
47
#define BTR_PCUR_AFTER_LAST_IN_TREE 5 /* in an empty tree */
49
/**************************************************************//**
50
Allocates memory for a persistent cursor object and initializes the cursor.
51
@return own: persistent cursor */
54
btr_pcur_create_for_mysql(void);
55
/*============================*/
56
/**************************************************************//**
57
Frees the memory for a persistent cursor object. */
60
btr_pcur_free_for_mysql(
61
/*====================*/
62
btr_pcur_t* cursor); /*!< in, own: persistent cursor */
63
/**************************************************************//**
64
Copies the stored position of a pcur to another pcur. */
67
btr_pcur_copy_stored_position(
68
/*==========================*/
69
btr_pcur_t* pcur_receive, /*!< in: pcur which will receive the
71
btr_pcur_t* pcur_donate); /*!< in: pcur from which the info is
73
/**************************************************************//**
74
Sets the old_rec_buf field to NULL. */
79
btr_pcur_t* pcur); /*!< in: persistent cursor */
80
/**************************************************************//**
81
Initializes and opens a persistent cursor to an index tree. It should be
82
closed with btr_pcur_close. */
87
dict_index_t* index, /*!< in: index */
88
const dtuple_t* tuple, /*!< in: tuple on which search done */
89
ulint mode, /*!< in: PAGE_CUR_L, ...;
90
NOTE that if the search is made using a unique
91
prefix of a record, mode should be
92
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
93
may end up on the previous page from the
95
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
96
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
97
const char* file, /*!< in: file name */
98
ulint line, /*!< in: line where called */
99
mtr_t* mtr); /*!< in: mtr */
100
#define btr_pcur_open(i,t,md,l,c,m) \
101
btr_pcur_open_func(i,t,md,l,c,__FILE__,__LINE__,m)
102
/**************************************************************//**
103
Opens an persistent cursor to an index tree without initializing the
107
btr_pcur_open_with_no_init_func(
108
/*============================*/
109
dict_index_t* index, /*!< in: index */
110
const dtuple_t* tuple, /*!< in: tuple on which search done */
111
ulint mode, /*!< in: PAGE_CUR_L, ...;
112
NOTE that if the search is made using a unique
113
prefix of a record, mode should be
114
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
115
may end up on the previous page of the
117
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
118
NOTE that if has_search_latch != 0 then
119
we maybe do not acquire a latch on the cursor
120
page, but assume that the caller uses his
121
btr search latch to protect the record! */
122
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
123
ulint has_search_latch,/*!< in: latch mode the caller
124
currently has on btr_search_latch:
126
const char* file, /*!< in: file name */
127
ulint line, /*!< in: line where called */
128
mtr_t* mtr); /*!< in: mtr */
129
#define btr_pcur_open_with_no_init(ix,t,md,l,cur,has,m) \
130
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,has,__FILE__,__LINE__,m)
132
/*****************************************************************//**
133
Opens a persistent cursor at either end of an index. */
136
btr_pcur_open_at_index_side(
137
/*========================*/
138
ibool from_left, /*!< in: TRUE if open to the low end,
139
FALSE if to the high end */
140
dict_index_t* index, /*!< in: index */
141
ulint latch_mode, /*!< in: latch mode */
142
btr_pcur_t* pcur, /*!< in: cursor */
143
ibool do_init, /*!< in: TRUE if should be initialized */
144
mtr_t* mtr); /*!< in: mtr */
145
/**************************************************************//**
146
Gets the up_match value for a pcur after a search.
147
@return number of matched fields at the cursor or to the right if
148
search mode was PAGE_CUR_GE, otherwise undefined */
151
btr_pcur_get_up_match(
152
/*==================*/
153
const btr_pcur_t* cursor); /*!< in: persistent cursor */
154
/**************************************************************//**
155
Gets the low_match value for a pcur after a search.
156
@return number of matched fields at the cursor or to the right if
157
search mode was PAGE_CUR_LE, otherwise undefined */
160
btr_pcur_get_low_match(
161
/*===================*/
162
const btr_pcur_t* cursor); /*!< in: persistent cursor */
163
/**************************************************************//**
164
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
165
user record satisfying the search condition, in the case PAGE_CUR_L or
166
PAGE_CUR_LE, on the last user record. If no such user record exists, then
167
in the first case sets the cursor after last in tree, and in the latter case
168
before first in tree. The latching mode must be BTR_SEARCH_LEAF or
172
btr_pcur_open_on_user_rec_func(
173
/*===========================*/
174
dict_index_t* index, /*!< in: index */
175
const dtuple_t* tuple, /*!< in: tuple on which search done */
176
ulint mode, /*!< in: PAGE_CUR_L, ... */
177
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
179
btr_pcur_t* cursor, /*!< in: memory buffer for persistent
181
const char* file, /*!< in: file name */
182
ulint line, /*!< in: line where called */
183
mtr_t* mtr); /*!< in: mtr */
184
#define btr_pcur_open_on_user_rec(i,t,md,l,c,m) \
185
btr_pcur_open_on_user_rec_func(i,t,md,l,c,__FILE__,__LINE__,m)
186
/**********************************************************************//**
187
Positions a cursor at a randomly chosen position within a B-tree. */
190
btr_pcur_open_at_rnd_pos_func(
191
/*==========================*/
192
dict_index_t* index, /*!< in: index */
193
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
194
btr_pcur_t* cursor, /*!< in/out: B-tree pcur */
195
const char* file, /*!< in: file name */
196
ulint line, /*!< in: line where called */
197
mtr_t* mtr); /*!< in: mtr */
198
#define btr_pcur_open_at_rnd_pos(i,l,c,m) \
199
btr_pcur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m)
200
/**************************************************************//**
201
Frees the possible old_rec_buf buffer of a persistent cursor and sets the
202
latch mode of the persistent cursor to BTR_NO_LATCHES. */
207
btr_pcur_t* cursor); /*!< in: persistent cursor */
208
/**************************************************************//**
209
The position of the cursor is stored by taking an initial segment of the
210
record the cursor is positioned on, before, or after, and copying it to the
211
cursor data structure, or just setting a flag if the cursor id before the
212
first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
213
page where the cursor is positioned must not be empty if the index tree is
214
not totally empty! */
217
btr_pcur_store_position(
218
/*====================*/
219
btr_pcur_t* cursor, /*!< in: persistent cursor */
220
mtr_t* mtr); /*!< in: mtr */
221
/**************************************************************//**
222
Restores the stored position of a persistent cursor bufferfixing the page and
223
obtaining the specified latches. If the cursor position was saved when the
224
(1) cursor was positioned on a user record: this function restores the position
225
to the last record LESS OR EQUAL to the stored record;
226
(2) cursor was positioned on a page infimum record: restores the position to
227
the last record LESS than the user record which was the successor of the page
229
(3) cursor was positioned on the page supremum: restores to the first record
230
GREATER than the user record which was the predecessor of the supremum.
231
(4) cursor was positioned before the first or after the last in an empty tree:
232
restores to before first or after the last in the tree.
233
@return TRUE if the cursor position was stored when it was on a user
234
record and it can be restored on a user record whose ordering fields
235
are identical to the ones of the original user record */
238
btr_pcur_restore_position_func(
239
/*===========================*/
240
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
241
btr_pcur_t* cursor, /*!< in: detached persistent cursor */
242
const char* file, /*!< in: file name */
243
ulint line, /*!< in: line where called */
244
mtr_t* mtr); /*!< in: mtr */
245
#define btr_pcur_restore_position(l,cur,mtr) \
246
btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr)
247
/*********************************************************//**
248
Gets the rel_pos field for a cursor whose position has been stored.
249
@return BTR_PCUR_ON, ... */
252
btr_pcur_get_rel_pos(
253
/*=================*/
254
const btr_pcur_t* cursor);/*!< in: persistent cursor */
255
/**************************************************************//**
256
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
257
that is, the cursor becomes detached.
258
Function btr_pcur_store_position should be used before calling this,
259
if restoration of cursor is wanted later. */
262
btr_pcur_commit_specify_mtr(
263
/*========================*/
264
btr_pcur_t* pcur, /*!< in: persistent cursor */
265
mtr_t* mtr); /*!< in: mtr to commit */
266
/**************************************************************//**
267
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
268
@return TRUE if detached */
271
btr_pcur_is_detached(
272
/*=================*/
273
btr_pcur_t* pcur); /*!< in: persistent cursor */
274
/*********************************************************//**
275
Moves the persistent cursor to the next record in the tree. If no records are
276
left, the cursor stays 'after last in tree'.
277
@return TRUE if the cursor was not after last in tree */
280
btr_pcur_move_to_next(
281
/*==================*/
282
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
283
function may release the page latch */
284
mtr_t* mtr); /*!< in: mtr */
285
/*********************************************************//**
286
Moves the persistent cursor to the previous record in the tree. If no records
287
are left, the cursor stays 'before first in tree'.
288
@return TRUE if the cursor was not before first in tree */
291
btr_pcur_move_to_prev(
292
/*==================*/
293
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
294
function may release the page latch */
295
mtr_t* mtr); /*!< in: mtr */
296
/*********************************************************//**
297
Moves the persistent cursor to the last record on the same page. */
300
btr_pcur_move_to_last_on_page(
301
/*==========================*/
302
btr_pcur_t* cursor, /*!< in: persistent cursor */
303
mtr_t* mtr); /*!< in: mtr */
304
/*********************************************************//**
305
Moves the persistent cursor to the next user record in the tree. If no user
306
records are left, the cursor ends up 'after last in tree'.
307
@return TRUE if the cursor moved forward, ending on a user record */
310
btr_pcur_move_to_next_user_rec(
311
/*===========================*/
312
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
313
function may release the page latch */
314
mtr_t* mtr); /*!< in: mtr */
315
/*********************************************************//**
316
Moves the persistent cursor to the first record on the next page.
317
Releases the latch on the current page, and bufferunfixes it.
318
Note that there must not be modifications on the current page,
319
as then the x-latch can be released only in mtr_commit. */
322
btr_pcur_move_to_next_page(
323
/*=======================*/
324
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
325
last record of the current page */
326
mtr_t* mtr); /*!< in: mtr */
327
/*********************************************************//**
328
Moves the persistent cursor backward if it is on the first record
329
of the page. Releases the latch on the current page, and bufferunfixes
330
it. Note that to prevent a possible deadlock, the operation first
331
stores the position of the cursor, releases the leaf latch, acquires
332
necessary latches and restores the cursor position again before returning.
333
The alphabetical position of the cursor is guaranteed to be sensible
334
on return, but it may happen that the cursor is not positioned on the
335
last record of any page, because the structure of the tree may have
336
changed while the cursor had no latches. */
339
btr_pcur_move_backward_from_page(
340
/*=============================*/
341
btr_pcur_t* cursor, /*!< in: persistent cursor, must be on the
342
first record of the current page */
343
mtr_t* mtr); /*!< in: mtr */
345
/*********************************************************//**
346
Returns the btr cursor component of a persistent cursor.
347
@return pointer to btr cursor component */
350
btr_pcur_get_btr_cur(
351
/*=================*/
352
const btr_pcur_t* cursor); /*!< in: persistent cursor */
353
/*********************************************************//**
354
Returns the page cursor component of a persistent cursor.
355
@return pointer to page cursor component */
358
btr_pcur_get_page_cur(
359
/*==================*/
360
const btr_pcur_t* cursor); /*!< in: persistent cursor */
361
/*********************************************************//**
362
Returns the page of a persistent cursor.
363
@return pointer to the page */
368
const btr_pcur_t* cursor);/*!< in: persistent cursor */
369
/*********************************************************//**
370
Returns the buffer block of a persistent cursor.
371
@return pointer to the block */
376
const btr_pcur_t* cursor);/*!< in: persistent cursor */
377
/*********************************************************//**
378
Returns the record of a persistent cursor.
379
@return pointer to the record */
384
const btr_pcur_t* cursor);/*!< in: persistent cursor */
385
#else /* UNIV_DEBUG */
386
# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
387
# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
388
# define btr_pcur_get_page(cursor) ((cursor)->btr_cur.page_cur.block->frame)
389
# define btr_pcur_get_block(cursor) ((cursor)->btr_cur.page_cur.block)
390
# define btr_pcur_get_rec(cursor) ((cursor)->btr_cur.page_cur.rec)
391
#endif /* UNIV_DEBUG */
392
/*********************************************************//**
393
Checks if the persistent cursor is on a user record. */
396
btr_pcur_is_on_user_rec(
397
/*====================*/
398
const btr_pcur_t* cursor);/*!< in: persistent cursor */
399
/*********************************************************//**
400
Checks if the persistent cursor is after the last user record on
404
btr_pcur_is_after_last_on_page(
405
/*===========================*/
406
const btr_pcur_t* cursor);/*!< in: persistent cursor */
407
/*********************************************************//**
408
Checks if the persistent cursor is before the first user record on
412
btr_pcur_is_before_first_on_page(
413
/*=============================*/
414
const btr_pcur_t* cursor);/*!< in: persistent cursor */
415
/*********************************************************//**
416
Checks if the persistent cursor is before the first user record in
420
btr_pcur_is_before_first_in_tree(
421
/*=============================*/
422
btr_pcur_t* cursor, /*!< in: persistent cursor */
423
mtr_t* mtr); /*!< in: mtr */
424
/*********************************************************//**
425
Checks if the persistent cursor is after the last user record in
429
btr_pcur_is_after_last_in_tree(
430
/*===========================*/
431
btr_pcur_t* cursor, /*!< in: persistent cursor */
432
mtr_t* mtr); /*!< in: mtr */
433
/*********************************************************//**
434
Moves the persistent cursor to the next record on the same page. */
437
btr_pcur_move_to_next_on_page(
438
/*==========================*/
439
btr_pcur_t* cursor);/*!< in/out: persistent cursor */
440
/*********************************************************//**
441
Moves the persistent cursor to the previous record on the same page. */
444
btr_pcur_move_to_prev_on_page(
445
/*==========================*/
446
btr_pcur_t* cursor);/*!< in/out: persistent cursor */
449
/* The persistent B-tree cursor structure. This is used mainly for SQL
450
selects, updates, and deletes. */
452
struct btr_pcur_struct{
453
btr_cur_t btr_cur; /*!< a B-tree cursor */
454
ulint latch_mode; /*!< see TODO note below!
455
BTR_SEARCH_LEAF, BTR_MODIFY_LEAF,
456
BTR_MODIFY_TREE, or BTR_NO_LATCHES,
457
depending on the latching state of
458
the page and tree where the cursor is
459
positioned; the last value means that
460
the cursor is not currently positioned:
461
we say then that the cursor is
462
detached; it can be restored to
463
attached if the old position was
465
ulint old_stored; /*!< BTR_PCUR_OLD_STORED
466
or BTR_PCUR_OLD_NOT_STORED */
467
rec_t* old_rec; /*!< if cursor position is stored,
468
contains an initial segment of the
469
latest record cursor was positioned
470
either on, before, or after */
471
ulint old_n_fields; /*!< number of fields in old_rec */
472
ulint rel_pos; /*!< BTR_PCUR_ON, BTR_PCUR_BEFORE, or
473
BTR_PCUR_AFTER, depending on whether
474
cursor was on, before, or after the
476
buf_block_t* block_when_stored;/* buffer block when the position was
478
ib_uint64_t modify_clock; /*!< the modify clock value of the
479
buffer block when the cursor position
481
ulint pos_state; /*!< see TODO note below!
482
BTR_PCUR_IS_POSITIONED,
483
BTR_PCUR_WAS_POSITIONED,
484
BTR_PCUR_NOT_POSITIONED */
485
ulint search_mode; /*!< PAGE_CUR_G, ... */
486
trx_t* trx_if_known; /*!< the transaction, if we know it;
487
otherwise this field is not defined;
488
can ONLY BE USED in error prints in
489
fatal assertion failures! */
490
/*-----------------------------*/
491
/* NOTE that the following fields may possess dynamically allocated
492
memory which should be freed if not needed anymore! */
494
byte* old_rec_buf; /*!< NULL, or a dynamically allocated
495
buffer for old_rec */
496
ulint buf_size; /*!< old_rec_buf size if old_rec_buf
500
#define BTR_PCUR_IS_POSITIONED 1997660512 /* TODO: currently, the state
501
can be BTR_PCUR_IS_POSITIONED,
502
though it really should be
503
BTR_PCUR_WAS_POSITIONED,
504
because we have no obligation
505
to commit the cursor with
506
mtr; similarly latch_mode may
507
be out of date. This can
508
lead to problems if btr_pcur
509
is not used the right way;
510
all current code should be
512
#define BTR_PCUR_WAS_POSITIONED 1187549791
513
#define BTR_PCUR_NOT_POSITIONED 1328997689
515
#define BTR_PCUR_OLD_STORED 908467085
516
#define BTR_PCUR_OLD_NOT_STORED 122766467
519
#include "btr0pcur.ic"